mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +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]
|
||||
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
|
||||
# https://github.com/rust-lang/rust/issues/82193
|
||||
|
|
|
@ -37,6 +37,9 @@ test_risky_names = []
|
|||
# * only build `uudoc` when `--feature uudoc` is activated
|
||||
uudoc = ["zip", "dep:uuhelp_parser"]
|
||||
## 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`)
|
||||
# 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.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# spell-checker:ignore dpkg
|
||||
[package]
|
||||
name = "uu_stdbuf"
|
||||
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 }
|
||||
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]]
|
||||
name = "stdbuf"
|
||||
path = "src/main.rs"
|
||||
|
|
|
@ -29,6 +29,26 @@ fn main() {
|
|||
println!("cargo:rerun-if-changed=build.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 target = env::var("TARGET").unwrap_or_else(|_| "unknown".to_string());
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
// spell-checker:ignore (ToDO) tempdir dyld dylib optgrps libstdbuf
|
||||
|
||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::os::unix::process::ExitStatusExt;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
|
@ -29,16 +27,19 @@ mod options {
|
|||
pub const COMMAND: &str = "command";
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "dragonfly"
|
||||
#[cfg(all(
|
||||
not(feature = "feat_external_libstdbuf"),
|
||||
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")]
|
||||
#[cfg(all(not(feature = "feat_external_libstdbuf"), target_vendor = "apple"))]
|
||||
const STDBUF_INJECT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/libstdbuf.dylib"));
|
||||
|
||||
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)> {
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
|
||||
let (preload, extension) = preload_strings()?;
|
||||
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))
|
||||
}
|
||||
|
||||
#[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]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue