mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
stdbuf: build on Windows (depending on cygwin dll)
This commit is contained in:
committed by
Etienne Cordonnier
parent
a8d51a2cfd
commit
db7b8a6e58
@@ -275,6 +275,7 @@ feat_os_unix_musl = [
|
||||
# "feat_os_windows" == set of utilities which can be built/run on modern/usual windows platforms
|
||||
feat_os_windows = [
|
||||
"feat_Tier1", ## == "feat_os_windows_legacy" + "hostname"
|
||||
"stdbuf",
|
||||
]
|
||||
## (secondary platforms) feature sets
|
||||
# "feat_os_unix_gnueabihf" == set of utilities which can be built/run on the "arm-unknown-linux-gnueabihf" target (ARMv6 Linux [hardfloat])
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ $(info Detected OS = $(OS))
|
||||
ifeq (,$(findstring windows,$(OS)))
|
||||
FEATURE_EXTRACT_UTILS := feat_os_unix
|
||||
else
|
||||
FEATURE_EXTRACT_UTILS := feat_Tier1
|
||||
FEATURE_EXTRACT_UTILS := windows
|
||||
endif
|
||||
PROGS := $(shell cargo tree --depth 1 --features $(FEATURE_EXTRACT_UTILS) --format "{p}" --prefix none | sed -E -n 's/^uu_([^ ]+).*/\1/p')
|
||||
|
||||
|
||||
@@ -22,12 +22,14 @@ doctest = false
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true }
|
||||
libstdbuf = { package = "uu_stdbuf_libstdbuf", version = "0.8.0", path = "src/libstdbuf" }
|
||||
tempfile = { workspace = true }
|
||||
uucore = { workspace = true, features = ["parser-size"] }
|
||||
thiserror = { workspace = true }
|
||||
fluent = { workspace = true }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libstdbuf = { package = "uu_stdbuf_libstdbuf", version = "0.8.0", path = "src/libstdbuf" }
|
||||
|
||||
# "feat_external_libstdbuf": use an external libstdbuf.so for stdbuf instead of embedding it into
|
||||
# the stdbuf binary.
|
||||
# There are 2 use-cases:
|
||||
|
||||
@@ -10,6 +10,11 @@ use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
// do not compile libstdbuf for windows target. The windows stdbuf.exe loads libstdbuf.dll compiled for the cygwin target.
|
||||
if env::var("CARGO_CFG_UNIX").is_err() {
|
||||
println!("cargo:rustc-cfg=feature=\"feat_external_libstdbuf\"");
|
||||
return;
|
||||
}
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed=src/libstdbuf/src/libstdbuf.rs");
|
||||
|
||||
@@ -38,11 +43,7 @@ fn main() {
|
||||
|
||||
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||
let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
|
||||
let target_family = env::var("CARGO_CFG_TARGET_FAMILY").unwrap();
|
||||
|
||||
if target_family != "unix" {
|
||||
return;
|
||||
}
|
||||
let dylib_ext = if target_vendor == "apple" {
|
||||
".dylib"
|
||||
} else if target_os == "cygwin" {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
stdbuf-about = Run COMMAND, with modified buffering operations for its standard streams.
|
||||
stdbuf-about-windows = Run COMMAND linked against cygwin runtime, with modified buffering operations for its standard streams.
|
||||
|
||||
Mandatory arguments to long options are mandatory for short options too.
|
||||
stdbuf-usage = stdbuf [OPTION]... COMMAND
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
// do not compile libstdbuf for windows target. The windows stdbuf.exe loads libstdbuf.dll compiled for the cygwin target.
|
||||
if env::var("CARGO_CFG_UNIX").is_err() {
|
||||
return;
|
||||
}
|
||||
// Make sure we're building position-independent code for use with LD_PRELOAD
|
||||
println!("cargo:rustc-link-arg=-fPIC");
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// file that was distributed with this source code.
|
||||
|
||||
// spell-checker:ignore (ToDO) tempdir dyld dylib optgrps libstdbuf
|
||||
#[cfg(not(unix))]
|
||||
compile_error!("stdbuf is not supported on the target");
|
||||
|
||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||
use std::ffi::OsString;
|
||||
@@ -42,7 +40,10 @@ const STDBUF_INJECT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/libstdbuf
|
||||
#[cfg(all(not(feature = "feat_external_libstdbuf"), target_vendor = "apple"))]
|
||||
const STDBUF_INJECT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/libstdbuf.dylib"));
|
||||
|
||||
#[cfg(all(not(feature = "feat_external_libstdbuf"), target_os = "cygwin"))]
|
||||
#[cfg(all(
|
||||
not(feature = "feat_external_libstdbuf"),
|
||||
any(target_os = "cygwin", target_os = "windows")
|
||||
))]
|
||||
const STDBUF_INJECT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/libstdbuf.dll"));
|
||||
|
||||
enum BufferType {
|
||||
@@ -89,7 +90,7 @@ fn preload_strings() -> (&'static str, &'static str) {
|
||||
("DYLD_LIBRARY_PATH", "dylib")
|
||||
}
|
||||
|
||||
#[cfg(target_os = "cygwin")]
|
||||
#[cfg(any(target_os = "cygwin", windows))]
|
||||
fn preload_strings() -> (&'static str, &'static str) {
|
||||
("LD_PRELOAD", "dll")
|
||||
}
|
||||
@@ -211,7 +212,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
command.args(command_params);
|
||||
|
||||
// Replace the current process with the target program (no fork) using exec.
|
||||
#[cfg(unix)]
|
||||
let e = command.exec();
|
||||
#[cfg(windows)]
|
||||
let e = match command.spawn() {
|
||||
Ok(mut child) => {
|
||||
let status = child.wait().unwrap();
|
||||
process::exit(status.code().unwrap_or(0));
|
||||
}
|
||||
Err(err) => err,
|
||||
};
|
||||
// exec() only returns if there was an error
|
||||
match e.kind() {
|
||||
std::io::ErrorKind::PermissionDenied => Err(USimpleError::new(
|
||||
@@ -230,10 +240,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
}
|
||||
|
||||
pub fn uu_app() -> Command {
|
||||
#[cfg(unix)]
|
||||
let about = translate!("stdbuf-about");
|
||||
#[cfg(windows)]
|
||||
let about = translate!("stdbuf-about-windows");
|
||||
Command::new("stdbuf")
|
||||
.version(uucore::crate_version!())
|
||||
.help_template(uucore::localized_help_template("stdbuf"))
|
||||
.about(translate!("stdbuf-about"))
|
||||
.about(about)
|
||||
.after_help(translate!("stdbuf-after-help"))
|
||||
.override_usage(format_usage(&translate!("stdbuf-usage")))
|
||||
.trailing_var_arg(true)
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
// spell-checker:ignore cmdline dyld dylib PDEATHSIG setvbuf
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use uutests::at_and_ucmd;
|
||||
use uutests::new_ucmd;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use uutests::util::TestScenario;
|
||||
use uutests::util_name;
|
||||
#[cfg(unix)]
|
||||
use uutests::{new_ucmd, util::TestScenario, util_name};
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn invalid_input() {
|
||||
new_ucmd!().arg("-/").fails_with_code(125);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "feat_external_libstdbuf"))]
|
||||
#[cfg(all(unix, not(feature = "feat_external_libstdbuf")))]
|
||||
#[test]
|
||||
fn test_permission() {
|
||||
new_ucmd!()
|
||||
@@ -28,7 +28,7 @@ fn test_permission() {
|
||||
// LD_DEBUG is not available on macOS, OpenBSD, Android, or musl
|
||||
#[cfg(all(
|
||||
feature = "feat_external_libstdbuf",
|
||||
not(target_os = "windows"),
|
||||
unix,
|
||||
not(target_os = "openbsd"),
|
||||
not(target_os = "macos"),
|
||||
not(target_os = "android"),
|
||||
@@ -121,7 +121,7 @@ fn test_stdbuf_search_order_exe_dir_first() {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "feat_external_libstdbuf"))]
|
||||
#[cfg(all(unix, not(feature = "feat_external_libstdbuf")))]
|
||||
#[test]
|
||||
fn test_no_such() {
|
||||
new_ucmd!()
|
||||
@@ -135,7 +135,7 @@ fn test_no_such() {
|
||||
// does not provide musl-compiled system utilities (like head), leading to dynamic linker errors
|
||||
// when preloading musl-compiled libstdbuf.so into glibc-compiled binaries. Same thing for FreeBSD.
|
||||
#[cfg(all(
|
||||
not(target_os = "windows"),
|
||||
unix,
|
||||
not(target_os = "freebsd"),
|
||||
not(target_os = "openbsd"),
|
||||
not(all(target_arch = "x86_64", target_env = "musl"))
|
||||
@@ -157,7 +157,7 @@ fn test_stdbuf_unbuffered_stdout() {
|
||||
// does not provide musl-compiled system utilities (like head), leading to dynamic linker errors
|
||||
// when preloading musl-compiled libstdbuf.so into glibc-compiled binaries. Same thing for FreeBSD.
|
||||
#[cfg(all(
|
||||
not(target_os = "windows"),
|
||||
unix,
|
||||
not(target_os = "freebsd"),
|
||||
not(target_os = "openbsd"),
|
||||
not(all(target_arch = "x86_64", target_env = "musl"))
|
||||
@@ -174,8 +174,8 @@ fn test_stdbuf_line_buffered_stdout() {
|
||||
.stdout_is("The quick brown fox jumps over the lazy dog.");
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_stdbuf_no_buffer_option_fails() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
|
||||
@@ -185,8 +185,8 @@ fn test_stdbuf_no_buffer_option_fails() {
|
||||
.stderr_contains("the following required arguments were not provided:");
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_stdbuf_no_command_fails_with_125() {
|
||||
// Test that missing command fails with exit code 125 (stdbuf error)
|
||||
// This verifies proper error handling without unwrap panic
|
||||
@@ -200,7 +200,7 @@ fn test_stdbuf_no_command_fails_with_125() {
|
||||
// does not provide musl-compiled system utilities (like tail), leading to dynamic linker errors
|
||||
// when preloading musl-compiled libstdbuf.so into glibc-compiled binaries. Same thing for FreeBSD.
|
||||
#[cfg(all(
|
||||
not(target_os = "windows"),
|
||||
unix,
|
||||
not(target_os = "freebsd"),
|
||||
not(target_os = "openbsd"),
|
||||
not(all(target_arch = "x86_64", target_env = "musl"))
|
||||
@@ -214,8 +214,8 @@ fn test_stdbuf_trailing_var_arg() {
|
||||
.stdout_is("jumps over the lazy dog.");
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_stdbuf_line_buffering_stdin_fails() {
|
||||
new_ucmd!()
|
||||
.args(&["-i", "L", "head"])
|
||||
@@ -223,8 +223,8 @@ fn test_stdbuf_line_buffering_stdin_fails() {
|
||||
.usage_error("line buffering stdin is meaningless");
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_stdbuf_invalid_mode_fails() {
|
||||
let options = ["--input", "--output", "--error"];
|
||||
for option in &options {
|
||||
@@ -254,7 +254,7 @@ fn test_stdbuf_invalid_mode_fails() {
|
||||
// and is sometimes disabled. Disable test on Android for now.
|
||||
// musl libc dynamic loader does not support LD_DEBUG, so disable on musl targets as well.
|
||||
#[cfg(all(
|
||||
not(target_os = "windows"),
|
||||
unix,
|
||||
not(target_os = "openbsd"),
|
||||
not(target_os = "macos"),
|
||||
not(target_os = "android"),
|
||||
|
||||
Reference in New Issue
Block a user