From 841df510dff8c585690e85354998bbcb6695460f Mon Sep 17 00:00:00 2001 From: Wenxuan Date: Wed, 24 Apr 2024 19:07:42 +0800 Subject: [PATCH] Respect target-cpu in RUSTFLAGS (#243) * Respect target-cpu in RUSTFLAGS Signed-off-by: Wish * Raise rustc requirement from 1.70 to 1.74 Signed-off-by: Wish * Fix bindgen errors Signed-off-by: Wish * Fix CI in set -e Signed-off-by: Wish * Use pre-built x86-instruction-set-analyzer Signed-off-by: Wish --------- Signed-off-by: Wish Co-authored-by: messense --- .github/workflows/CI.yml | 39 ++++++- Cargo.lock | 104 ++++++++++++++++++ Cargo.toml | 5 +- src/zig.rs | 203 +++++++++++++++++++++++++++-------- tests/target-cpu/Cargo.lock | 69 ++++++++++++ tests/target-cpu/Cargo.toml | 7 ++ tests/target-cpu/src/main.rs | 5 + 7 files changed, 386 insertions(+), 46 deletions(-) create mode 100644 tests/target-cpu/Cargo.lock create mode 100644 tests/target-cpu/Cargo.toml create mode 100644 tests/target-cpu/src/main.rs diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 20378d8..6fbcd7e 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,11 +32,11 @@ jobs: fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }} matrix: os: [ubuntu-latest, macos-13, windows-latest] - toolchain: [1.70.0, stable, nightly] + toolchain: [1.74.0, stable, nightly] zig: [0.10.1, 0.12.0, master] exclude: # Only test MSRV with zig stable version - - toolchain: 1.70.0 + - toolchain: 1.74.0 zig: master env: RUST_BACKTRACE: "1" @@ -81,6 +81,41 @@ jobs: cargo run zigbuild --manifest-path tests/bindgen-exhaustive/Cargo.toml --target aarch64-unknown-linux-gnu cargo run zigbuild --manifest-path tests/bindgen-exhaustive/Cargo.toml --target x86_64-pc-windows-gnu cargo run zigbuild --manifest-path tests/bindgen-exhaustive/Cargo.toml --target aarch64-apple-darwin + - name: Install x86-instruction-set-analyzer + uses: taiki-e/install-action@v2 + with: + tool: x86-instruction-set-analyzer@0.1.0 + - name: Test RUSTFLAGS + shell: bash + run: | + set -e + cargo build # Build without RUSTFLAGS + + echo "Running -C target_cpu=x86-64..." + echo + export RUSTFLAGS="-C target_cpu=x86-64" + target/debug/cargo-zigbuild zigbuild --manifest-path tests/target-cpu/Cargo.toml --target x86_64-unknown-linux-gnu --release + x86-instruction-set-analyzer tests/target-cpu/target/x86_64-unknown-linux-gnu/release/target-cpu | tee output.txt + echo + if grep -q 'AVX2' output.txt; then + echo "Test fail, should not contain AVX2 instruction set" + false + else + echo "Test pass" + fi + + echo "Running -C target_cpu=x86-64-v4..." + echo + export RUSTFLAGS="-C target_cpu=x86-64-v4" + target/debug/cargo-zigbuild zigbuild --manifest-path tests/target-cpu/Cargo.toml --target x86_64-unknown-linux-gnu --release + x86-instruction-set-analyzer tests/target-cpu/target/x86_64-unknown-linux-gnu/release/target-cpu | tee output.txt + echo + if ! grep -q 'AVX2' output.txt; then + echo "Test fail, should contain AVX2 instruction set" + false + else + echo "Test pass" + fi - name: macOS - Test build run: | cargo run zigbuild --target aarch64-apple-darwin diff --git a/Cargo.lock b/Cargo.lock index 5d073be..45bfef1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,6 +83,18 @@ dependencies = [ "serde", ] +[[package]] +name = "cargo-config2" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d9bdc858a15454c2d0a5138d8dcf4bcabc06fde679abdea8330393fbc0ef05" +dependencies = [ + "home", + "serde", + "serde_derive", + "toml_edit", +] + [[package]] name = "cargo-options" version = "0.7.4" @@ -107,14 +119,17 @@ name = "cargo-zigbuild" version = "0.18.4" dependencies = [ "anyhow", + "cargo-config2", "cargo-options", "cargo_metadata", "clap", + "crc", "dirs", "fat-macho", "fs-err", "path-slash", "rustc_version", + "rustflags", "semver", "serde", "serde_json", @@ -190,6 +205,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "dirs" version = "5.0.1" @@ -217,6 +247,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.8" @@ -267,6 +303,12 @@ dependencies = [ "scroll", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heck" version = "0.4.1" @@ -282,6 +324,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "itoa" version = "1.0.10" @@ -317,6 +369,12 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + [[package]] name = "once_cell" version = "1.19.0" @@ -388,6 +446,12 @@ dependencies = [ "semver", ] +[[package]] +name = "rustflags" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7fc92159fb50a431c5da366f7627751fe7263cf867f8a30f27fa6063ba02ac0" + [[package]] name = "rustix" version = "0.38.30" @@ -467,6 +531,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "shlex" version = "1.3.0" @@ -526,6 +599,28 @@ dependencies = [ "syn", ] +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -688,3 +783,12 @@ name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winnow" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml index 0ca8933..2fbf531 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,20 +7,23 @@ license = "MIT" keywords = ["zig", "cargo"] readme = "README.md" repository = "https://github.com/rust-cross/cargo-zigbuild" -rust-version = "1.70" +rust-version = "1.74" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] anyhow = "1.0.53" +cargo-config2 = "0.1.24" cargo-options = "0.7.4" cargo_metadata = "0.18.0" clap = { version = "4.3.0", features = ["derive", "env", "wrap_help", "unstable-styles"] } +crc = "3.2.1" dirs = "5.0.0" fat-macho = { version = "0.4.6", default-features = false, optional = true } fs-err = "2.6.0" path-slash = "0.2.0" rustc_version = "0.4.0" +rustflags = "0.1.6" semver = "1.0.5" serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.79" diff --git a/src/zig.rs b/src/zig.rs index d4e2336..21db2c9 100644 --- a/src/zig.rs +++ b/src/zig.rs @@ -963,6 +963,43 @@ pub struct ZigWrapper { pub ranlib: PathBuf, } +#[derive(Debug, Clone, Default, PartialEq)] +struct TargetFlags { + pub target_cpu: String, + pub target_feature: String, +} + +impl TargetFlags { + pub fn parse_from_encoded(encoded: &OsStr) -> Result { + let mut parsed = Self::default(); + + let f = rustflags::from_encoded(encoded); + for flag in f { + if let rustflags::Flag::Codegen { opt, value } = flag { + let key = opt.replace('-', "_"); + match key.as_str() { + "target_cpu" => { + if let Some(value) = value { + parsed.target_cpu = value; + } + } + "target_feature" => { + // See https://github.com/rust-lang/rust/blob/7e3ba5b8b7556073ab69822cc36b93d6e74cd8c9/compiler/rustc_session/src/options.rs#L1233 + if let Some(value) = value { + if !parsed.target_feature.is_empty() { + parsed.target_feature.push(','); + } + parsed.target_feature.push_str(&value); + } + } + _ => {} + } + } + } + Ok(parsed) + } +} + /// Prepare wrapper scripts for `zig cc` and `zig c++` and returns their paths /// /// We want to use `zig cc` as linker and c compiler. We want to call `python -m ziglang cc`, but @@ -1003,52 +1040,87 @@ pub fn prepare_zig_linker(target: &str) -> Result { }; let file_ext = if cfg!(windows) { "bat" } else { "sh" }; let file_target = target.trim_end_matches('.'); - let zig_cc = format!("zigcc-{file_target}.{file_ext}"); - let zig_cxx = format!("zigcxx-{file_target}.{file_ext}"); - let cc_args = "-g"; // prevent stripping - let mut cc_args = match triple.operating_system { + + let mut cc_args = vec!["-g".to_owned()]; // prevent stripping + + // TODO: Maybe better to assign mcpu according to: + // rustc --target -Z unstable-options --print target-spec-json + let zig_mcpu_default = match triple.operating_system { OperatingSystem::Linux => { - let (zig_arch, zig_cpu) = match arch.as_str() { + match arch.as_str() { // zig uses _ instead of - in cpu features "arm" => match target_env { - Environment::Gnueabi | Environment::Musleabi => { - ("arm", "-mcpu=generic+v6+strict_align") - } + Environment::Gnueabi | Environment::Musleabi => "generic+v6+strict_align", Environment::Gnueabihf | Environment::Musleabihf => { - ("arm", "-mcpu=generic+v6+strict_align+vfp2-d32") + "generic+v6+strict_align+vfp2-d32" } - _ => ("arm", ""), + _ => "", }, - "armv5te" => ("arm", "-mcpu=generic+soft_float+strict_align"), - "armv7" => ("arm", "-mcpu=generic+v7a+vfp3-d32+thumb2-neon"), + "armv5te" => "generic+soft_float+strict_align", + "armv7" => "generic+v7a+vfp3-d32+thumb2-neon", arch_str @ ("i586" | "i686") => { - let cpu_arg = if arch_str == "i586" { - "-mcpu=pentium" + if arch_str == "i586" { + "pentium" } else { - "-mcpu=pentium4" - }; + "pentium4" + } + } + "riscv64gc" => "generic_rv64+m+a+f+d+c", + "s390x" => "z10-vector", + _ => "", + } + } + _ => "", + }; + + // Override mcpu from RUSTFLAGS if provided. The override happens when + // commands like `cargo-zigbuild build` are invoked. + // Currently we only override according to target_cpu. + let zig_mcpu_override = { + let cargo_config = cargo_config2::Config::load()?; + let rust_flags = cargo_config.rustflags(rust_target)?.unwrap_or_default(); + let encoded_rust_flags = rust_flags.encode()?; + let target_flags = TargetFlags::parse_from_encoded(OsStr::new(&encoded_rust_flags))?; + // Note: zig uses _ instead of - for target_cpu and target_feature + // target_cpu may be empty string, which means target_cpu is not specified. + target_flags.target_cpu.replace('-', "_") + }; + + if !zig_mcpu_override.is_empty() { + cc_args.push(format!("-mcpu={zig_mcpu_override}")); + } else if !zig_mcpu_default.is_empty() { + cc_args.push(format!("-mcpu={zig_mcpu_default}")); + } + + match triple.operating_system { + OperatingSystem::Linux => { + let zig_arch = match arch.as_str() { + // zig uses _ instead of - in cpu features + "arm" => "arm", + "armv5te" => "arm", + "armv7" => "arm", + "i586" | "i686" => { let zig_version = Zig::zig_version()?; - let zig_arch = if zig_version.major == 0 && zig_version.minor >= 11 { + if zig_version.major == 0 && zig_version.minor >= 11 { "x86" } else { "i386" - }; - (zig_arch, cpu_arg) + } } - "riscv64gc" => ("riscv64", "-mcpu=generic_rv64+m+a+f+d+c"), - "s390x" => ("s390x", "-mcpu=z10-vector"), - _ => (arch.as_str(), ""), + "riscv64gc" => "riscv64", + "s390x" => "s390x", + _ => arch.as_str(), }; - format!("-target {zig_arch}-linux-{target_env}{abi_suffix} {zig_cpu} {cc_args}",) + cc_args.push(format!("-target {zig_arch}-linux-{target_env}{abi_suffix}")); } OperatingSystem::MacOSX { .. } | OperatingSystem::Darwin => { let zig_version = Zig::zig_version()?; // Zig 0.10.0 switched macOS ABI to none // see https://github.com/ziglang/zig/pull/11684 if zig_version > semver::Version::new(0, 9, 1) { - format!("-target {arch}-macos-none{abi_suffix} {cc_args}") + cc_args.push(format!("-target {arch}-macos-none{abi_suffix}")); } else { - format!("-target {arch}-macos-gnu{abi_suffix} {cc_args}") + cc_args.push(format!("-target {arch}-macos-gnu{abi_suffix}")); } } OperatingSystem::Windows { .. } => { @@ -1063,15 +1135,21 @@ pub fn prepare_zig_linker(target: &str) -> Result { } arch => arch, }; - format!("-target {zig_arch}-windows-{target_env}{abi_suffix} {cc_args}",) + cc_args.push(format!( + "-target {zig_arch}-windows-{target_env}{abi_suffix}" + )); + } + OperatingSystem::Emscripten => { + cc_args.push(format!("-target {arch}-emscripten{abi_suffix}")); + } + OperatingSystem::Wasi => { + cc_args.push(format!("-target {arch}-wasi{abi_suffix}")); } - OperatingSystem::Emscripten => format!("-target {arch}-emscripten{abi_suffix} {cc_args}"), - OperatingSystem::Wasi => format!("-target {arch}-wasi{abi_suffix} {cc_args}"), OperatingSystem::Unknown => { if triple.architecture == Architecture::Wasm32 || triple.architecture == Architecture::Wasm64 { - format!("-target {arch}-freestanding{abi_suffix} {cc_args}") + cc_args.push(format!("-target {arch}-freestanding{abi_suffix}")); } else { bail!("unsupported target '{rust_target}'") } @@ -1104,7 +1182,6 @@ pub fn prepare_zig_linker(target: &str) -> Result { // See https://github.com/ziglang/zig/issues/9485 if glibc_version < (2, 28) { use crate::linux::{FCNTL_H, FCNTL_MAP}; - use std::fmt::Write as _; let zig_version = Zig::zig_version()?; if zig_version.major == 0 && zig_version.minor < 11 { @@ -1119,13 +1196,8 @@ pub fn prepare_zig_linker(target: &str) -> Result { fs::write(&fcntl_h, FCNTL_H)?; } - write!( - cc_args, - " -Wl,--version-script={} -include {}", - fcntl_map.display(), - fcntl_h.display() - ) - .unwrap(); + cc_args.push(format!("-Wl,--version-script={}", fcntl_map.display())); + cc_args.push(format!("-include {}", fcntl_h.display())); } } } else if matches!( @@ -1136,7 +1208,6 @@ pub fn prepare_zig_linker(target: &str) -> Result { | Environment::Musleabihf ) { use crate::linux::MUSL_WEAK_SYMBOLS_MAPPING_SCRIPT; - use std::fmt::Write as _; let zig_version = Zig::zig_version()?; let rustc_version = rustc_version::version_meta()?.semver; @@ -1151,16 +1222,18 @@ pub fn prepare_zig_linker(target: &str) -> Result { let weak_symbols_map = zig_linker_dir.join("musl_weak_symbols_map.ld"); fs::write(&weak_symbols_map, MUSL_WEAK_SYMBOLS_MAPPING_SCRIPT)?; - write!(cc_args, " -Wl,-T,{}", weak_symbols_map.display()).unwrap() + cc_args.push(format!("-Wl,-T,{}", weak_symbols_map.display())); } } } - let zig_cc = zig_linker_dir.join(zig_cc); - let zig_cxx = zig_linker_dir.join(zig_cxx); + let cc_args_str = cc_args.join(" "); + let hash = crc::Crc::::new(&crc::CRC_16_IBM_SDLC).checksum(cc_args_str.as_bytes()); + let zig_cc = zig_linker_dir.join(format!("zigcc-{file_target}-{:x}.{file_ext}", hash)); + let zig_cxx = zig_linker_dir.join(format!("zigcxx-{file_target}-{:x}.{file_ext}", hash)); let zig_ranlib = zig_linker_dir.join(format!("zigranlib.{file_ext}")); - write_linker_wrapper(&zig_cc, "cc", &cc_args)?; - write_linker_wrapper(&zig_cxx, "c++", &cc_args)?; + write_linker_wrapper(&zig_cc, "cc", &cc_args_str)?; + write_linker_wrapper(&zig_cxx, "c++", &cc_args_str)?; write_linker_wrapper(&zig_ranlib, "ranlib", "")?; let exe_ext = if cfg!(windows) { ".exe" } else { "" }; @@ -1292,3 +1365,47 @@ fn zig_path() -> Result { let zig = env::var("CARGO_ZIGBUILD_ZIG_PATH").unwrap_or_else(|_| "zig".to_string()); Ok(which::which(zig)?) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_target_flags() { + let cases = [ + // Input, TargetCPU, TargetFeature + ("-C target-feature=-crt-static", "", "-crt-static"), + ("-C target-cpu=native", "native", ""), + ( + "--deny warnings --codegen target-feature=+crt-static", + "", + "+crt-static", + ), + ("-C target_cpu=skylake-avx512", "skylake-avx512", ""), + ("-Ctarget_cpu=x86-64-v3", "x86-64-v3", ""), + ( + "-C target-cpu=native --cfg foo -C target-feature=-avx512bf16,-avx512bitalg", + "native", + "-avx512bf16,-avx512bitalg", + ), + ( + "--target x86_64-unknown-linux-gnu --codegen=target-cpu=x --codegen=target-cpu=x86-64", + "x86-64", + "", + ), + ( + "-Ctarget-feature=+crt-static -Ctarget-feature=+avx", + "", + "+crt-static,+avx", + ), + ]; + + for (input, expected_target_cpu, expected_target_feature) in cases.iter() { + let args = cargo_config2::Flags::from_space_separated(input); + let encoded_rust_flags = args.encode().unwrap(); + let flags = TargetFlags::parse_from_encoded(OsStr::new(&encoded_rust_flags)).unwrap(); + assert_eq!(flags.target_cpu, *expected_target_cpu, "{}", input); + assert_eq!(flags.target_feature, *expected_target_feature, "{}", input); + } + } +} diff --git a/tests/target-cpu/Cargo.lock b/tests/target-cpu/Cargo.lock new file mode 100644 index 0000000..3f32098 --- /dev/null +++ b/tests/target-cpu/Cargo.lock @@ -0,0 +1,69 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cc" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "jobserver" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2" +dependencies = [ + "libc", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "target-cpu" +version = "0.1.0" +dependencies = [ + "zstd", +] + +[[package]] +name = "zstd" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.10+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/tests/target-cpu/Cargo.toml b/tests/target-cpu/Cargo.toml new file mode 100644 index 0000000..b9e100c --- /dev/null +++ b/tests/target-cpu/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "target-cpu" +version = "0.1.0" +edition = "2021" + +[dependencies] +zstd = "0.13.1" diff --git a/tests/target-cpu/src/main.rs b/tests/target-cpu/src/main.rs new file mode 100644 index 0000000..a58d7d4 --- /dev/null +++ b/tests/target-cpu/src/main.rs @@ -0,0 +1,5 @@ +use std::io; + +fn main() { + zstd::stream::copy_decode(io::stdin(), io::stdout()).unwrap(); +}