From 35634b46a0acfc9028743bf023c133a4d0135f13 Mon Sep 17 00:00:00 2001 From: Etienne Cordonnier Date: Wed, 7 May 2025 20:01:49 +0200 Subject: [PATCH] stdbuf: fix cross-compilation Summary: Partial fix for https://github.com/uutils/coreutils/issues/6591 The current code declare libstdbuf as a build-dependency of stdbuf as a workaround to enforce that libstdbuf is compiled before stdbuf. This breaks cross-compilation, because build-dependencies were compiled for the host architecture, and not for the target architecture. The reason this workaround is necessary is that bindeps is available only in nightly at the moment: https://rust-lang.github.io/rfcs/3028-cargo-binary-dependencies.html This commit replaces the "build-dependency" workaround with another workaround: calling cargo manually to build libstdbuf in the build.rs of stdbuf, in order to ensure that libstdbuf is built before stdbuf. Changes: - Removed cpp/cpp_build dependencies: The cpp, cpp_build, and related dependencies were removed because they made cross-compilation in a build.rs file very complex, since you need to pass proper CXX env variables for cross-compilation, whereas cross-compiling rust code using cargo is quite simple. Provided Rust implementations for getting stdin, stdout, and stderr pointers. Switched from C++/cpp macro-based initialization to using the Rust ctor crate for library initialization. - Remove "feat_require_crate_cpp" which is not needed any more, since stdbuf was the only utility using the cpp crate. Tests: This commit fixes e.g. this test: cross test --target aarch64-unknown-linux-gnu --features stdbuf test_stdbuf::test_libstdbuf_preload -- --nocapture - The "i686" build of stdbuf was also broken (stdbuf 32 bits, but libstdbuf 64 bits) and test_stdbuf::test_libstdbuf_preload of the i686 builds in github CI serves as regression test for this issue, no need to add a cross-rs test for aarch64. - The x86_64 musl build of stdbuf was also broken and was passing tests in CI only because it was compiled with the wrong libc (glibc instead of musl) Signed-off-by: Etienne Cordonnier --- .cargo/config.toml | 5 + Cargo.lock | 379 ++++++++++--------- Cargo.toml | 11 +- deny.toml | 38 +- src/uu/stdbuf/Cargo.toml | 4 +- src/uu/stdbuf/build.rs | 106 ++++-- src/uu/stdbuf/src/libstdbuf/Cargo.toml | 10 +- src/uu/stdbuf/src/libstdbuf/build.rs | 14 +- src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs | 88 ++++- src/uu/stdbuf/src/stdbuf.rs | 10 + tests/by-util/test_stdbuf.rs | 78 +++- 11 files changed, 476 insertions(+), 267 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index c6aa20761..02550b267 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,3 +3,8 @@ linker = "x86_64-unknown-redox-gcc" [env] PROJECT_NAME_FOR_VERSION_STRING = "uutils coreutils" + +# libstdbuf must be a shared library, so musl libc can't be linked statically +# https://github.com/rust-lang/rust/issues/82193 +[build] +rustflags = [ "-C", "target-feature=-crt-static" ] diff --git a/Cargo.lock b/Cargo.lock index 4e2b95dbd..1e9ebde10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,12 +88,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys 0.59.0", ] @@ -172,7 +172,7 @@ version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cexpr", "clang-sys", "itertools 0.13.0", @@ -194,9 +194,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bitvec" @@ -274,9 +274,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.2.16" +version = "1.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "d0fc897dc1e865cc67c0e05a836d9d3f1df3cbe442aa4a9473b18e12624a4951" dependencies = [ "shlex", ] @@ -412,7 +412,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "once_cell", "tiny-keccak", ] @@ -579,56 +579,6 @@ dependencies = [ "zip", ] -[[package]] -name = "cpp" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bcac3d8234c1fb813358e83d1bb6b0290a3d2b3b5efc6b88bfeaf9d8eec17" -dependencies = [ - "cpp_macros", -] - -[[package]] -name = "cpp_build" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f8638c97fbd79cc6fc80b616e0e74b49bac21014faed590bbc89b7e2676c90" -dependencies = [ - "cc", - "cpp_common", - "lazy_static", - "proc-macro2", - "regex", - "syn", - "unicode-xid", -] - -[[package]] -name = "cpp_common" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25fcfea2ee05889597d35e986c2ad0169694320ae5cc8f6d2640a4bb8a884560" -dependencies = [ - "lazy_static", - "proc-macro2", - "syn", -] - -[[package]] -name = "cpp_macros" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d156158fe86e274820f5a53bc9edb0885a6e7113909497aa8d883b69dd171871" -dependencies = [ - "aho-corasick", - "byteorder", - "cpp_common", - "lazy_static", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "cpufeatures" version = "0.2.17" @@ -678,7 +628,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "crossterm_winapi", "derive_more", "document-features", @@ -907,9 +857,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys 0.59.0", @@ -921,7 +871,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22be12de19decddab85d09f251ec8363f060ccb22ec9c81bc157c0c8433946d8" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "log", "scopeguard", "uuid", @@ -1026,9 +976,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "fs_extra" @@ -1122,9 +1072,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -1133,14 +1083,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -1167,9 +1117,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" dependencies = [ "allocator-api2", "equivalent", @@ -1225,12 +1175,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.3", ] [[package]] @@ -1252,7 +1202,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "inotify-sys", "libc", ] @@ -1317,9 +1267,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27e77966151130221b079bcec80f1f34a9e414fa489d99152a201c07fd2182bc" +checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93" dependencies = [ "jiff-static", "jiff-tzdb-platform", @@ -1332,9 +1282,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97265751f8a9a4228476f2fc17874a9e7e70e96b893368e42619880fe143b48a" +checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" dependencies = [ "proc-macro2", "quote", @@ -1377,9 +1327,9 @@ dependencies = [ [[package]] name = "kqueue" -version = "1.0.8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" dependencies = [ "kqueue-sys", "libc", @@ -1395,12 +1345,6 @@ dependencies = [ "libc", ] -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "libc" version = "0.2.172" @@ -1409,19 +1353,19 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.53.0", ] [[package]] name = "libm" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" @@ -1429,7 +1373,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "libc", "redox_syscall", ] @@ -1457,25 +1401,19 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", ] -[[package]] -name = "lockfree-object-pool" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" - [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "lru" @@ -1483,7 +1421,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.3", ] [[package]] @@ -1529,23 +1467,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1554,7 +1492,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "cfg-if", "cfg_aliases", "libc", @@ -1585,7 +1523,7 @@ version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "filetime", "fsevent-sys", "inotify", @@ -1692,9 +1630,15 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "onig" @@ -1702,7 +1646,7 @@ version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "libc", "once_cell", "onig_sys", @@ -1739,9 +1683,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -1749,9 +1693,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", @@ -1860,11 +1804,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy", + "zerocopy 0.8.25", ] [[package]] @@ -1879,9 +1823,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.30" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" +checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" dependencies = [ "proc-macro2", "syn", @@ -1920,6 +1864,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "radium" version = "0.7.0" @@ -1973,7 +1923,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -1982,7 +1932,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", + "getrandom 0.3.3", ] [[package]] @@ -2007,11 +1957,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -2122,11 +2072,11 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.1" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dade4812df5c384711475be5fcd8c162555352945401aed22a35bffeab61f657" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys", @@ -2135,9 +2085,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "same-file" @@ -2166,7 +2116,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e37f432dfe840521abd9a72fefdf88ed7ad0f43bbea7d9d1d3d80383e9f4ad13" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", "libc", "once_cell", "parking_lot", @@ -2282,9 +2232,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -2333,9 +2283,9 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2349,9 +2299,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.99" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -2371,7 +2321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", - "getrandom 0.3.1", + "getrandom 0.3.3", "once_cell", "rustix", "windows-sys 0.59.0", @@ -2577,12 +2527,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "unindent" version = "0.2.4" @@ -2612,7 +2556,7 @@ dependencies = [ "thiserror 1.0.69", "time", "utmp-classic-raw", - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -2622,7 +2566,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22c226537a3d6e01c440c1926ca0256dbee2d19b2229ede6fc4863a6493dd831" dependencies = [ "cfg-if", - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -3399,8 +3343,7 @@ dependencies = [ name = "uu_stdbuf_libstdbuf" version = "0.1.0" dependencies = [ - "cpp", - "cpp_build", + "ctor", "libc", ] @@ -3709,9 +3652,13 @@ version = "0.1.0" [[package]] name = "uuid" -version = "1.15.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "uutests" @@ -3770,9 +3717,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] @@ -3876,7 +3823,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -3887,9 +3834,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.60.1" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca21a92a9cae9bf4ccae5cf8368dce0837100ddf6e6d57936749e85f152f6247" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", @@ -3900,9 +3847,9 @@ dependencies = [ [[package]] name = "windows-implement" -version = "0.59.0" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", @@ -3928,18 +3875,18 @@ checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" [[package]] name = "windows-result" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] @@ -3995,13 +3942,29 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -4014,6 +3977,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -4026,6 +3995,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -4038,12 +4013,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -4056,6 +4043,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -4068,6 +4061,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -4080,6 +4079,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -4092,6 +4097,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.7.10" @@ -4103,11 +4114,11 @@ dependencies = [ [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.1", ] [[package]] @@ -4148,7 +4159,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +dependencies = [ + "zerocopy-derive 0.8.25", ] [[package]] @@ -4162,6 +4182,17 @@ dependencies = [ "syn", ] +[[package]] +name = "zerocopy-derive" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zerofrom" version = "0.1.6" @@ -4199,14 +4230,12 @@ checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8" [[package]] name = "zopfli" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" dependencies = [ "bumpalo", "crc32fast", - "lockfree-object-pool", "log", - "once_cell", "simd-adler32", ] diff --git a/Cargo.toml b/Cargo.toml index cec7ae21c..a69100fea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -158,7 +158,6 @@ feat_os_macos = [ feat_os_unix = [ "feat_Tier1", # - "feat_require_crate_cpp", "feat_require_unix", "feat_require_unix_utmpx", "feat_require_unix_hostid", @@ -185,9 +184,7 @@ feat_os_unix_android = [ # # ** NOTE: these `feat_require_...` sets should be minimized as much as possible to encourage cross-platform availability of utilities # -# "feat_require_crate_cpp" == set of utilities requiring the `cpp` crate (which fail to compile on several platforms; as of 2020-04-23) -feat_require_crate_cpp = ["stdbuf"] -# "feat_require_unix" == set of utilities requiring support which is only available on unix platforms (as of 2020-04-23) +# "feat_require_unix" == set of utilities requiring support which is only available on unix platforms feat_require_unix = [ "chgrp", "chmod", @@ -204,6 +201,7 @@ feat_require_unix = [ "nohup", "pathchk", "stat", + "stdbuf", "stty", "timeout", "tty", @@ -220,8 +218,6 @@ feat_require_selinux = ["chcon", "runcon"] feat_os_unix_fuchsia = [ "feat_common_core", # - "feat_require_crate_cpp", - # "chgrp", "chmod", "chown", @@ -287,6 +283,7 @@ clap_complete = "4.4" clap_mangen = "0.2" compare = "0.1.0" crossterm = "0.29.0" +ctor = "0.4.1" ctrlc = { version = "3.4.7", features = ["termination"] } dns-lookup = { version = "2.0.4" } exacl = "0.12.0" @@ -502,6 +499,7 @@ yes = { optional = true, version = "0.1.0", package = "uu_yes", path = "src/uu/y [dev-dependencies] chrono = { workspace = true } +ctor = { workspace = true } filetime = { workspace = true } glob = { workspace = true } libc = { workspace = true } @@ -524,7 +522,6 @@ uucore = { workspace = true, features = [ walkdir = { workspace = true } hex-literal = "1.0.0" rstest = { workspace = true } -ctor = "0.4.1" [target.'cfg(unix)'.dev-dependencies] nix = { workspace = true, features = ["process", "signal", "user", "term"] } diff --git a/deny.toml b/deny.toml index 1b1700dcd..c15502149 100644 --- a/deny.toml +++ b/deny.toml @@ -58,22 +58,42 @@ skip = [ { name = "windows-sys", version = "0.48.0" }, # mio, nu-ansi-term, socket2 { name = "windows-sys", version = "0.52.0" }, + # anstyle-query + { name = "windows-sys", version = "0.59.0" }, # windows-sys - { name = "windows-targets", version = "0.48.0" }, + { name = "windows-targets", version = "0.48.5" }, + # parking_lot_core + { name = "windows-targets", version = "0.52.6" }, # windows-targets - { name = "windows_aarch64_gnullvm", version = "0.48.0" }, + { name = "windows_aarch64_gnullvm", version = "0.48.5" }, # windows-targets - { name = "windows_aarch64_msvc", version = "0.48.0" }, + { name = "windows_aarch64_gnullvm", version = "0.52.6" }, # windows-targets - { name = "windows_i686_gnu", version = "0.48.0" }, + { name = "windows_aarch64_msvc", version = "0.48.5" }, # windows-targets - { name = "windows_i686_msvc", version = "0.48.0" }, + { name = "windows_aarch64_msvc", version = "0.52.6" }, # windows-targets - { name = "windows_x86_64_gnu", version = "0.48.0" }, + { name = "windows_i686_gnu", version = "0.48.5" }, # windows-targets - { name = "windows_x86_64_gnullvm", version = "0.48.0" }, + { name = "windows_i686_gnu", version = "0.52.6" }, # windows-targets - { name = "windows_x86_64_msvc", version = "0.48.0" }, + { name = "windows_i686_gnullvm", version = "0.52.6" }, + # windows-targets + { name = "windows_i686_msvc", version = "0.48.5" }, + # windows-targets + { name = "windows_i686_msvc", version = "0.52.6" }, + # windows-targets + { name = "windows_x86_64_gnu", version = "0.48.5" }, + # windows-targets + { name = "windows_x86_64_gnu", version = "0.52.6" }, + # windows-targets + { name = "windows_x86_64_gnullvm", version = "0.48.5" }, + # windows-targets + { name = "windows_x86_64_gnullvm", version = "0.52.6" }, + # windows-targets + { name = "windows_x86_64_msvc", version = "0.48.5" }, + # windows-targets + { name = "windows_x86_64_msvc", version = "0.52.6" }, # kqueue-sys, onig { name = "bitflags", version = "1.3.2" }, # ansi-width @@ -98,6 +118,8 @@ skip = [ { name = "rand_chacha", version = "0.3.1" }, # rand { name = "rand_core", version = "0.6.4" }, + # utmp-classic + { name = "zerocopy", version = "0.7.35" }, ] # spell-checker: enable diff --git a/src/uu/stdbuf/Cargo.toml b/src/uu/stdbuf/Cargo.toml index 5f9e8ffd7..bcfc9fb94 100644 --- a/src/uu/stdbuf/Cargo.toml +++ b/src/uu/stdbuf/Cargo.toml @@ -19,12 +19,10 @@ path = "src/stdbuf.rs" [dependencies] clap = { workspace = true } +libstdbuf = { package = "uu_stdbuf_libstdbuf", path = "src/libstdbuf" } tempfile = { workspace = true } uucore = { workspace = true, features = ["parser"] } -[build-dependencies] -libstdbuf = { version = "0.1.0", package = "uu_stdbuf_libstdbuf", path = "src/libstdbuf" } - [[bin]] name = "stdbuf" path = "src/main.rs" diff --git a/src/uu/stdbuf/build.rs b/src/uu/stdbuf/build.rs index b31a32235..abb4069ad 100644 --- a/src/uu/stdbuf/build.rs +++ b/src/uu/stdbuf/build.rs @@ -2,14 +2,20 @@ // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (ToDO) dylib libstdbuf deps liblibstdbuf +// spell-checker:ignore (ToDO) bindeps dylib libstdbuf deps liblibstdbuf use std::env; -use std::env::current_exe; use std::fs; use std::path::Path; +use std::process::Command; -#[cfg(not(any(target_vendor = "apple", target_os = "windows")))] +#[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + target_os = "netbsd", + target_os = "dragonfly" +))] mod platform { pub const DYLIB_EXT: &str = ".so"; } @@ -19,31 +25,83 @@ mod platform { pub const DYLIB_EXT: &str = ".dylib"; } -#[cfg(target_os = "windows")] -mod platform { - pub const DYLIB_EXT: &str = ".dll"; -} - fn main() { - let current_exe = current_exe().unwrap(); + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=src/libstdbuf/src/libstdbuf.rs"); - let out_dir_string = env::var("OUT_DIR").unwrap(); - let out_dir = Path::new(&out_dir_string); + let out_dir = env::var("OUT_DIR").expect("OUT_DIR not set"); + let target = env::var("TARGET").unwrap_or_else(|_| "unknown".to_string()); - let deps_dir = current_exe.ancestors().nth(3).unwrap().join("deps"); - dbg!(&deps_dir); + // Create a separate build directory for libstdbuf to avoid conflicts + let build_dir = Path::new(&out_dir).join("libstdbuf-build"); + fs::create_dir_all(&build_dir).expect("Failed to create build directory"); - let libstdbuf = deps_dir - .read_dir() - .unwrap() - .flatten() - .find(|entry| { - let n = entry.file_name(); - let name = n.to_string_lossy(); + // Get the cargo executable + let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); - name.starts_with("liblibstdbuf") && name.ends_with(platform::DYLIB_EXT) - }) - .expect("unable to find libstdbuf"); + // This manual cargo call ensures that libstdbuf is built before stdbuf.rs is compiled, which is necessary + // for include_bytes!(..."/libstdbuf.so") to work. + // In the future, "bindeps" should be used to simplify the code and avoid the manual cargo call, + // however this is available only in cargo nightly at the moment. + // See the tracking issue: https://github.com/rust-lang/cargo/issues/9096 + let mut cmd = Command::new(&cargo); + cmd.env_clear().envs(env::vars()); + cmd.current_dir(Path::new("src/libstdbuf")).args([ + "build", + "--target-dir", + build_dir.to_str().unwrap(), + ]); - fs::copy(libstdbuf.path(), out_dir.join("libstdbuf.so")).unwrap(); + // Get the current profile + let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_string()); + + // Pass the release flag if we're in release mode + if profile == "release" || profile == "bench" { + cmd.arg("--release"); + } + + // Pass the target architecture if we're cross-compiling + if !target.is_empty() && target != "unknown" { + cmd.arg("--target").arg(&target); + } + + let status = cmd.status().expect("Failed to build libstdbuf"); + assert!(status.success(), "Failed to build libstdbuf"); + + // Copy the built library to OUT_DIR for include_bytes! to find + let lib_name = format!("liblibstdbuf{}", platform::DYLIB_EXT); + let dest_path = Path::new(&out_dir).join(format!("libstdbuf{}", platform::DYLIB_EXT)); + + // Check multiple possible locations for the built library + let possible_paths = if !target.is_empty() && target != "unknown" { + vec![ + build_dir.join(&target).join(&profile).join(&lib_name), + build_dir + .join(&target) + .join(&profile) + .join("deps") + .join(&lib_name), + ] + } else { + vec![ + build_dir.join(&profile).join(&lib_name), + build_dir.join(&profile).join("deps").join(&lib_name), + ] + }; + + // Try to find the library in any of the possible locations + let mut found = false; + for source_path in &possible_paths { + if source_path.exists() { + fs::copy(source_path, &dest_path).expect("Failed to copy libstdbuf library"); + found = true; + break; + } + } + + assert!( + found, + "Could not find built libstdbuf library. Searched in: {:?}.", + possible_paths + ); } diff --git a/src/uu/stdbuf/src/libstdbuf/Cargo.toml b/src/uu/stdbuf/src/libstdbuf/Cargo.toml index 3f8511ffa..01dd3a49d 100644 --- a/src/uu/stdbuf/src/libstdbuf/Cargo.toml +++ b/src/uu/stdbuf/src/libstdbuf/Cargo.toml @@ -13,14 +13,8 @@ edition.workspace = true [lib] name = "libstdbuf" path = "src/libstdbuf.rs" -crate-type = [ - "cdylib", - "rlib", -] # XXX: note: the rlib is just to prevent Cargo from spitting out a warning +crate-type = ["cdylib"] [dependencies] -cpp = "0.5.10" +ctor = { workspace = true } libc = { workspace = true } - -[build-dependencies] -cpp_build = "0.5.10" diff --git a/src/uu/stdbuf/src/libstdbuf/build.rs b/src/uu/stdbuf/src/libstdbuf/build.rs index 6dcd6a869..505cdf68a 100644 --- a/src/uu/stdbuf/src/libstdbuf/build.rs +++ b/src/uu/stdbuf/src/libstdbuf/build.rs @@ -4,8 +4,18 @@ // file that was distributed with this source code. // spell-checker:ignore (ToDO) libstdbuf -use cpp_build::Config; +use std::env; fn main() { - Config::new().pic(true).build("src/libstdbuf.rs"); + // Make sure we're building position-independent code for use with LD_PRELOAD + println!("cargo:rustc-link-arg=-fPIC"); + + let target = env::var("TARGET").unwrap_or_else(|_| "unknown".to_string()); + // Ensure the library doesn't have any undefined symbols (-z flag not supported on macOS) + if !target.contains("apple-darwin") { + println!("cargo:rustc-link-arg=-z"); + println!("cargo:rustc-link-arg=defs"); + } + + println!("cargo:rerun-if-changed=src/libstdbuf.rs"); } diff --git a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs index b151ce686..d99509880 100644 --- a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs +++ b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs @@ -2,34 +2,80 @@ // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (ToDO) IOFBF IOLBF IONBF cstdio setvbuf +// spell-checker:ignore (ToDO) IOFBF IOLBF IONBF setvbuf stderrp stdinp stdoutp -use cpp::cpp; +use ctor::ctor; use libc::{_IOFBF, _IOLBF, _IONBF, FILE, c_char, c_int, fileno, size_t}; use std::env; use std::ptr; -cpp! {{ - #include +// This runs automatically when the library is loaded via LD_PRELOAD +#[ctor] +fn init() { + unsafe { __stdbuf() }; +} - extern "C" { - void __stdbuf(void); - - void __attribute((constructor)) - __stdbuf_init(void) { - __stdbuf(); +/// # Safety +/// This function is unsafe because it calls a C API +#[unsafe(no_mangle)] +pub unsafe extern "C" fn __stdbuf_get_stdin() -> *mut FILE { + #[cfg(any(target_os = "macos", target_os = "freebsd"))] + { + unsafe extern "C" { + fn __stdinp() -> *mut FILE; } - - FILE *__stdbuf_get_stdin() { return stdin; } - FILE *__stdbuf_get_stdout() { return stdout; } - FILE *__stdbuf_get_stderr() { return stderr; } + unsafe { __stdinp() } } -}} -unsafe extern "C" { - fn __stdbuf_get_stdin() -> *mut FILE; - fn __stdbuf_get_stdout() -> *mut FILE; - fn __stdbuf_get_stderr() -> *mut FILE; + #[cfg(not(any(target_os = "macos", target_os = "freebsd")))] + { + unsafe extern "C" { + static mut stdin: *mut FILE; + } + unsafe { stdin } + } +} + +/// # Safety +/// This function is unsafe because it calls a C API +#[unsafe(no_mangle)] +pub unsafe extern "C" fn __stdbuf_get_stdout() -> *mut FILE { + #[cfg(any(target_os = "macos", target_os = "freebsd"))] + { + unsafe extern "C" { + fn __stdoutp() -> *mut FILE; + } + unsafe { __stdoutp() } + } + + #[cfg(not(any(target_os = "macos", target_os = "freebsd")))] + { + unsafe extern "C" { + static mut stdout: *mut FILE; + } + unsafe { stdout } + } +} + +/// # Safety +/// This function is unsafe because it calls a C API +#[unsafe(no_mangle)] +pub unsafe extern "C" fn __stdbuf_get_stderr() -> *mut FILE { + #[cfg(any(target_os = "macos", target_os = "freebsd"))] + { + unsafe extern "C" { + fn __stderrp() -> *mut FILE; + } + unsafe { __stderrp() } + } + + #[cfg(not(any(target_os = "macos", target_os = "freebsd")))] + { + unsafe extern "C" { + static mut stderr: *mut FILE; + } + unsafe { stderr } + } } fn set_buffer(stream: *mut FILE, value: &str) { @@ -61,7 +107,9 @@ fn set_buffer(stream: *mut FILE, value: &str) { } /// # Safety -/// ToDO ... (safety note) +/// This function is intended to be called automatically when the library is loaded via LD_PRELOAD. +/// It assumes that the standard streams are valid and that calling setvbuf on them is safe. +/// The caller must ensure this function is only called in a compatible runtime environment. #[unsafe(no_mangle)] pub unsafe extern "C" fn __stdbuf() { if let Ok(val) = env::var("_STDBUF_E") { diff --git a/src/uu/stdbuf/src/stdbuf.rs b/src/uu/stdbuf/src/stdbuf.rs index 3b5c3fb9d..fa6b2e630 100644 --- a/src/uu/stdbuf/src/stdbuf.rs +++ b/src/uu/stdbuf/src/stdbuf.rs @@ -31,8 +31,18 @@ mod options { pub const COMMAND: &str = "command"; } +#[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + target_os = "netbsd", + target_os = "dragonfly" +))] const STDBUF_INJECT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/libstdbuf.so")); +#[cfg(target_vendor = "apple")] +const STDBUF_INJECT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/libstdbuf.dylib")); + enum BufferType { Default, Line, diff --git a/tests/by-util/test_stdbuf.rs b/tests/by-util/test_stdbuf.rs index cbd0a5c2b..dec6bfe64 100644 --- a/tests/by-util/test_stdbuf.rs +++ b/tests/by-util/test_stdbuf.rs @@ -3,12 +3,6 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. // spell-checker:ignore dyld dylib setvbuf -#[cfg(all( - not(target_os = "windows"), - not(target_os = "openbsd"), - not(target_os = "macos") -))] -use std::process::Command; use uutests::new_ucmd; #[cfg(not(target_os = "windows"))] use uutests::util::TestScenario; @@ -37,7 +31,15 @@ fn test_no_such() { .stderr_contains("No such file or directory"); } -#[cfg(all(not(target_os = "windows"), not(target_os = "openbsd")))] +// Disabled on x86_64-unknown-linux-musl because the cross-rs Docker image for this target +// 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"), + not(target_os = "freebsd"), + not(target_os = "openbsd"), + not(all(target_arch = "x86_64", target_env = "musl")) +))] #[test] fn test_stdbuf_unbuffered_stdout() { // This is a basic smoke test @@ -51,7 +53,15 @@ fn test_stdbuf_unbuffered_stdout() { .stdout_is("The quick brown fox jumps over the lazy dog."); } -#[cfg(all(not(target_os = "windows"), not(target_os = "openbsd")))] +// Disabled on x86_64-unknown-linux-musl because the cross-rs Docker image for this target +// 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"), + not(target_os = "freebsd"), + not(target_os = "openbsd"), + not(all(target_arch = "x86_64", target_env = "musl")) +))] #[test] fn test_stdbuf_line_buffered_stdout() { // Note: This test only verifies that stdbuf does not crash and that output is passed through as expected @@ -75,7 +85,15 @@ fn test_stdbuf_no_buffer_option_fails() { .stderr_contains("the following required arguments were not provided:"); } -#[cfg(all(not(target_os = "windows"), not(target_os = "openbsd")))] +// Disabled on x86_64-unknown-linux-musl because the cross-rs Docker image for this target +// 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"), + not(target_os = "freebsd"), + not(target_os = "openbsd"), + not(all(target_arch = "x86_64", target_env = "musl")) +))] #[test] fn test_stdbuf_trailing_var_arg() { new_ucmd!() @@ -119,16 +137,25 @@ fn test_stdbuf_invalid_mode_fails() { } } -// macos uses DYLD_PRINT_LIBRARIES, not LD_DEBUG, so disable on macos at the moment +// macos uses DYLD_PRINT_LIBRARIES, not LD_DEBUG, so disable on macos at the moment. +// On modern Android (Bionic, API 37+), LD_DEBUG is supported and behaves similarly to glibc. +// On older Android versions (Bionic, API < 37), LD_DEBUG uses integer values instead of strings +// 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"), not(target_os = "openbsd"), - not(target_os = "macos") + not(target_os = "macos"), + not(target_os = "android"), + not(target_env = "musl") ))] #[test] -fn test_setvbuf_resolution() { - // Run a simple program with LD_DEBUG=symbols to see which setvbuf is being used - // Written in a way that it can run with cross-rs and be used as regression test +fn test_libstdbuf_preload() { + use std::process::Command; + + // Run a simple program with LD_DEBUG=symbols to verify that libstdbuf is loaded correctly + // and that there are no architecture mismatches when preloading the library. + // Note: This does not check which setvbuf implementation is used, as our libstdbuf does not override setvbuf. // for https://github.com/uutils/coreutils/issues/6591 let scene = TestScenario::new(util_name!()); @@ -149,13 +176,24 @@ fn test_setvbuf_resolution() { let uutils_debug = String::from_utf8_lossy(&uutils_output.stdout); - // Check if libstdbuf.so / libstdbuf.dylib is in the lookup path. The log should contain something like this: - // "symbol=setvbuf; lookup in file=/tmp/.tmp0mfmCg/libstdbuf.so [0]" - let libstdbuf_in_path = uutils_debug.contains("symbol=setvbuf") - && uutils_debug.contains("lookup in file=") - && uutils_debug.contains("libstdbuf"); + // Check if libstdbuf.so / libstdbuf.dylib is in the lookup path. + // With GLIBC, the log should contain something like: + // "symbol=setvbuf; lookup in file=/tmp/.tmp0mfmCg/libstdbuf.so [0]" + // With FreeBSD dynamic loader, the log should contain something like: + // cspell:disable-next-line + // "calling init function for /tmp/.tmpu11rhP/libstdbuf.so at ..." + let libstdbuf_in_path = if cfg!(target_os = "freebsd") { + uutils_debug + .lines() + .any(|line| line.contains("calling init function") && line.contains("libstdbuf")) + } else { + uutils_debug.contains("symbol=setvbuf") + && uutils_debug.contains("lookup in file=") + && uutils_debug.contains("libstdbuf") + }; - // Check for lack of architecture mismatch error. The potential error message is: + // Check for lack of architecture mismatch error. The potential error message with GLIBC is: + // cspell:disable-next-line // "ERROR: ld.so: object '/tmp/.tmpCLq8jl/libstdbuf.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored." let arch_mismatch_line = uutils_debug .lines()