mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
Merge pull request #8104 from Ecordonnier/eco/stdbuf-external
stdbuf: add feat_external_libstdbuf
This commit is contained in:
commit
ba1833d39b
5 changed files with 82 additions and 9 deletions
|
@ -3,6 +3,8 @@ linker = "x86_64-unknown-redox-gcc"
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
PROJECT_NAME_FOR_VERSION_STRING = "uutils coreutils"
|
PROJECT_NAME_FOR_VERSION_STRING = "uutils coreutils"
|
||||||
|
# See feat_external_libstdbuf in src/uu/stdbuf/Cargo.toml
|
||||||
|
LIBSTDBUF_DIR = "/usr/lib"
|
||||||
|
|
||||||
# libstdbuf must be a shared library, so musl libc can't be linked statically
|
# libstdbuf must be a shared library, so musl libc can't be linked statically
|
||||||
# https://github.com/rust-lang/rust/issues/82193
|
# https://github.com/rust-lang/rust/issues/82193
|
||||||
|
|
|
@ -37,6 +37,9 @@ test_risky_names = []
|
||||||
# * only build `uudoc` when `--feature uudoc` is activated
|
# * only build `uudoc` when `--feature uudoc` is activated
|
||||||
uudoc = ["zip", "dep:uuhelp_parser"]
|
uudoc = ["zip", "dep:uuhelp_parser"]
|
||||||
## features
|
## features
|
||||||
|
## Optional feature for stdbuf
|
||||||
|
# "feat_external_libstdbuf" == use an external libstdbuf.so for stdbuf instead of embedding it
|
||||||
|
feat_external_libstdbuf = ["stdbuf/feat_external_libstdbuf"]
|
||||||
# "feat_acl" == enable support for ACLs (access control lists; by using`--features feat_acl`)
|
# "feat_acl" == enable support for ACLs (access control lists; by using`--features feat_acl`)
|
||||||
# NOTE:
|
# NOTE:
|
||||||
# * On linux, the posix-acl/acl-sys crate requires `libacl` headers and shared library to be accessible in the C toolchain at compile time.
|
# * On linux, the posix-acl/acl-sys crate requires `libacl` headers and shared library to be accessible in the C toolchain at compile time.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# spell-checker:ignore dpkg
|
||||||
[package]
|
[package]
|
||||||
name = "uu_stdbuf"
|
name = "uu_stdbuf"
|
||||||
description = "stdbuf ~ (uutils) run COMMAND with modified standard stream buffering"
|
description = "stdbuf ~ (uutils) run COMMAND with modified standard stream buffering"
|
||||||
|
@ -23,6 +24,25 @@ libstdbuf = { package = "uu_stdbuf_libstdbuf", path = "src/libstdbuf" }
|
||||||
tempfile = { workspace = true }
|
tempfile = { workspace = true }
|
||||||
uucore = { workspace = true, features = ["parser"] }
|
uucore = { workspace = true, features = ["parser"] }
|
||||||
|
|
||||||
|
# "feat_external_libstdbuf": use an external libstdbuf.so for stdbuf instead of embedding it into
|
||||||
|
# the stdbuf binary.
|
||||||
|
# There are 2 use-cases:
|
||||||
|
# 1. Installation of uutils-coreutils using cargo install (e.g. from crates.io
|
||||||
|
# which supports only "cargo install" as installation method). In this case,
|
||||||
|
# installing libstdbuf.so is impossible, because "cargo install" installs
|
||||||
|
# only binary programs (no cdylib), thus libstdbuf.so must be embedded into
|
||||||
|
# stdbuf and written to /tmp at runtime. This is a hack, and may not work
|
||||||
|
# on some platforms, e.g. because the SELinux permissions may not allow
|
||||||
|
# stdbuf to write to /tmp, /tmp may be read-only, libstdbuf.so may not work
|
||||||
|
# at all without SELinux labels, etc.
|
||||||
|
#
|
||||||
|
# 2. Installation of uutils-coreutils using an external tool, e.g. dpkg/apt on
|
||||||
|
# debian. In this case, libstdbuf.so should be installed separately to its
|
||||||
|
# correct location and the environment variable LIBSTDBUF_DIR configures the
|
||||||
|
# installation directory during the build. E.g. LIBSTDBUF_DIR="/usr/lib"
|
||||||
|
[features]
|
||||||
|
feat_external_libstdbuf = []
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "stdbuf"
|
name = "stdbuf"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
|
@ -29,6 +29,26 @@ fn main() {
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
println!("cargo:rerun-if-changed=src/libstdbuf/src/libstdbuf.rs");
|
println!("cargo:rerun-if-changed=src/libstdbuf/src/libstdbuf.rs");
|
||||||
|
|
||||||
|
// Check for external stdbuf feature requirements
|
||||||
|
#[cfg(feature = "feat_external_libstdbuf")]
|
||||||
|
{
|
||||||
|
if env::var("LIBSTDBUF_DIR").is_err() {
|
||||||
|
eprintln!(
|
||||||
|
"\n\x1b[31mError:\x1b[0m The 'feat_external_libstdbuf' feature requires the LIBSTDBUF_DIR environment variable to be set."
|
||||||
|
);
|
||||||
|
eprintln!(
|
||||||
|
"\x1b[33mUsage:\x1b[0m LIBSTDBUF_DIR=/path/to/lib/directory cargo build --features feat_external_libstdbuf"
|
||||||
|
);
|
||||||
|
eprintln!(
|
||||||
|
"\x1b[33mExample:\x1b[0m LIBSTDBUF_DIR=/usr/lib cargo build --features feat_external_libstdbuf"
|
||||||
|
);
|
||||||
|
eprintln!(
|
||||||
|
"\nThis directory should point to where libstdbuf.so / libstdbuf.dylib will be installed on the target system."
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let out_dir = env::var("OUT_DIR").expect("OUT_DIR not set");
|
let out_dir = env::var("OUT_DIR").expect("OUT_DIR not set");
|
||||||
let target = env::var("TARGET").unwrap_or_else(|_| "unknown".to_string());
|
let target = env::var("TARGET").unwrap_or_else(|_| "unknown".to_string());
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
// spell-checker:ignore (ToDO) tempdir dyld dylib optgrps libstdbuf
|
// spell-checker:ignore (ToDO) tempdir dyld dylib optgrps libstdbuf
|
||||||
|
|
||||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::os::unix::process::ExitStatusExt;
|
use std::os::unix::process::ExitStatusExt;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
@ -29,16 +27,19 @@ mod options {
|
||||||
pub const COMMAND: &str = "command";
|
pub const COMMAND: &str = "command";
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(all(
|
||||||
|
not(feature = "feat_external_libstdbuf"),
|
||||||
|
any(
|
||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
target_os = "android",
|
target_os = "android",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
target_os = "netbsd",
|
target_os = "netbsd",
|
||||||
target_os = "dragonfly"
|
target_os = "dragonfly"
|
||||||
|
)
|
||||||
))]
|
))]
|
||||||
const STDBUF_INJECT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/libstdbuf.so"));
|
const STDBUF_INJECT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/libstdbuf.so"));
|
||||||
|
|
||||||
#[cfg(target_vendor = "apple")]
|
#[cfg(all(not(feature = "feat_external_libstdbuf"), target_vendor = "apple"))]
|
||||||
const STDBUF_INJECT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/libstdbuf.dylib"));
|
const STDBUF_INJECT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/libstdbuf.dylib"));
|
||||||
|
|
||||||
enum BufferType {
|
enum BufferType {
|
||||||
|
@ -137,7 +138,11 @@ fn set_command_env(command: &mut process::Command, buffer_name: &str, buffer_typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "feat_external_libstdbuf"))]
|
||||||
fn get_preload_env(tmp_dir: &TempDir) -> UResult<(String, PathBuf)> {
|
fn get_preload_env(tmp_dir: &TempDir) -> UResult<(String, PathBuf)> {
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
let (preload, extension) = preload_strings()?;
|
let (preload, extension) = preload_strings()?;
|
||||||
let inject_path = tmp_dir.path().join("libstdbuf").with_extension(extension);
|
let inject_path = tmp_dir.path().join("libstdbuf").with_extension(extension);
|
||||||
|
|
||||||
|
@ -147,6 +152,29 @@ fn get_preload_env(tmp_dir: &TempDir) -> UResult<(String, PathBuf)> {
|
||||||
Ok((preload.to_owned(), inject_path))
|
Ok((preload.to_owned(), inject_path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "feat_external_libstdbuf")]
|
||||||
|
fn get_preload_env(_tmp_dir: &TempDir) -> UResult<(String, PathBuf)> {
|
||||||
|
let (preload, extension) = preload_strings()?;
|
||||||
|
|
||||||
|
// Use the directory provided at compile time via LIBSTDBUF_DIR environment variable
|
||||||
|
// This will fail to compile if LIBSTDBUF_DIR is not set, which is the desired behavior
|
||||||
|
const LIBSTDBUF_DIR: &str = env!("LIBSTDBUF_DIR");
|
||||||
|
let path_buf = PathBuf::from(LIBSTDBUF_DIR)
|
||||||
|
.join("libstdbuf")
|
||||||
|
.with_extension(extension);
|
||||||
|
if path_buf.exists() {
|
||||||
|
return Ok((preload.to_owned(), path_buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(USimpleError::new(
|
||||||
|
1,
|
||||||
|
format!(
|
||||||
|
"External libstdbuf not found at configured path: {}",
|
||||||
|
path_buf.display()
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?;
|
let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue