buildRustCrate: set CARGO_BIN_EXE_<name> for integration tests (#502752)
This commit is contained in:
@@ -70,6 +70,25 @@ let
|
||||
binRustcOpts = lib.concatStringsSep " " baseRustcOpts;
|
||||
|
||||
build_bin = if buildTests then "build_bin_test" else "build_bin";
|
||||
|
||||
# Shell snippet that builds a binary target to target/cargo-bin-exe/
|
||||
# so integration tests can exec it via CARGO_BIN_EXE_<name>.
|
||||
buildBinForTests = bin: ''
|
||||
mkdir -p target/cargo-bin-exe
|
||||
BIN_NAME='${bin.name or crateName}'
|
||||
${
|
||||
if !bin ? path then
|
||||
''
|
||||
BIN_PATH=""
|
||||
search_for_bin_path "$BIN_NAME"
|
||||
''
|
||||
else
|
||||
''
|
||||
BIN_PATH='${bin.path}'
|
||||
''
|
||||
}
|
||||
build_bin "$BIN_NAME" "$BIN_PATH" target/cargo-bin-exe
|
||||
'';
|
||||
in
|
||||
''
|
||||
runHook preBuild
|
||||
@@ -88,13 +107,60 @@ in
|
||||
|
||||
if [[ -e "$LIB_PATH" ]]; then
|
||||
build_lib "$LIB_PATH"
|
||||
${lib.optionalString buildTests ''build_lib_test "$LIB_PATH"''}
|
||||
elif [[ -e src/lib.rs ]]; then
|
||||
build_lib src/lib.rs
|
||||
${lib.optionalString buildTests "build_lib_test src/lib.rs"}
|
||||
fi
|
||||
|
||||
${
|
||||
# When building tests, first build the real (non-test) binaries so
|
||||
# integration tests can exec them via CARGO_BIN_EXE_<name>. They go
|
||||
# to target/cargo-bin-exe/ to avoid colliding with the --test
|
||||
# harnesses written to target/bin/. After building, populate the
|
||||
# CARGO_BIN_EXE_ENV array so subsequent rustc invocations see the
|
||||
# env vars (via `env` prefix in lib.sh, which unlike bash `export`
|
||||
# accepts hyphenated names).
|
||||
lib.optionalString buildTests (
|
||||
lib.concatMapStringsSep "\n" (
|
||||
bin:
|
||||
let
|
||||
haveRequiredFeature =
|
||||
if bin ? requiredFeatures then
|
||||
lib.intersectLists bin.requiredFeatures crateFeatures == bin.requiredFeatures
|
||||
else
|
||||
true;
|
||||
in
|
||||
lib.optionalString haveRequiredFeature (buildBinForTests bin)
|
||||
) crateBin
|
||||
+ lib.optionalString (lib.length crateBin == 0 && !hasCrateBin) ''
|
||||
if [[ -e src/main.rs ]]; then
|
||||
mkdir -p target/cargo-bin-exe
|
||||
build_bin ${crateName} src/main.rs target/cargo-bin-exe
|
||||
fi
|
||||
for i in src/bin/*.rs; do
|
||||
[ -e "$i" ] || continue
|
||||
mkdir -p target/cargo-bin-exe
|
||||
build_bin "$(basename $i .rs)" "$i" target/cargo-bin-exe
|
||||
done
|
||||
''
|
||||
+ ''
|
||||
if [ -d target/cargo-bin-exe ]; then
|
||||
for b in target/cargo-bin-exe/*; do
|
||||
[ -x "$b" ] || continue
|
||||
name=$(basename "$b")
|
||||
CARGO_BIN_EXE_ENV+=("CARGO_BIN_EXE_$name=$out/bin/$name")
|
||||
done
|
||||
fi
|
||||
''
|
||||
)
|
||||
}
|
||||
|
||||
${lib.optionalString buildTests ''
|
||||
if [[ -e "$LIB_PATH" ]]; then
|
||||
build_lib_test "$LIB_PATH"
|
||||
elif [[ -e src/lib.rs ]]; then
|
||||
build_lib_test src/lib.rs
|
||||
fi
|
||||
''}
|
||||
|
||||
${lib.optionalString (lib.length crateBin > 0) (
|
||||
lib.concatMapStringsSep "\n" (
|
||||
|
||||
@@ -48,6 +48,12 @@ else
|
||||
-executable \
|
||||
-print0 | xargs --no-run-if-empty --null install --target $out/tests;
|
||||
fi
|
||||
# Real (non-test) binaries that integration tests may exec via
|
||||
# CARGO_BIN_EXE_<name>.
|
||||
if [ -d target/cargo-bin-exe ]; then
|
||||
mkdir -p $out/bin
|
||||
cp -rP target/cargo-bin-exe/* $out/bin
|
||||
fi
|
||||
|
||||
runHook postInstall
|
||||
''
|
||||
|
||||
@@ -10,7 +10,7 @@ build_lib() {
|
||||
lib_src=$1
|
||||
echo_build_heading $lib_src ${libName}
|
||||
|
||||
noisily rustc \
|
||||
noisily env "${CARGO_BIN_EXE_ENV[@]}" rustc \
|
||||
--crate-name $CRATE_NAME \
|
||||
$lib_src \
|
||||
--out-dir target/lib \
|
||||
@@ -36,17 +36,18 @@ build_bin() {
|
||||
local crate_name=$1
|
||||
local crate_name_=$(echo $crate_name | tr '-' '_')
|
||||
local main_file=""
|
||||
local out_dir="${3:-target/bin}"
|
||||
|
||||
if [[ ! -z $2 ]]; then
|
||||
main_file=$2
|
||||
fi
|
||||
echo_build_heading $@
|
||||
noisily rustc \
|
||||
echo_build_heading $crate_name $main_file
|
||||
noisily env "${CARGO_BIN_EXE_ENV[@]}" rustc \
|
||||
--crate-name $crate_name_ \
|
||||
$main_file \
|
||||
--crate-type bin \
|
||||
$BIN_RUSTC_OPTS \
|
||||
--out-dir target/bin \
|
||||
--out-dir "$out_dir" \
|
||||
-L dependency=target/deps \
|
||||
$LINK \
|
||||
$EXTRA_LINK_ARGS \
|
||||
@@ -60,10 +61,10 @@ build_bin() {
|
||||
--color ${colors} \
|
||||
|
||||
if [ "$crate_name_" != "$crate_name" ]; then
|
||||
if [ -f "target/bin/$crate_name_.wasm" ]; then
|
||||
mv target/bin/$crate_name_.wasm target/bin/$crate_name.wasm
|
||||
if [ -f "$out_dir/$crate_name_.wasm" ]; then
|
||||
mv "$out_dir/$crate_name_.wasm" "$out_dir/$crate_name.wasm"
|
||||
else
|
||||
mv target/bin/$crate_name_ target/bin/$crate_name
|
||||
mv "$out_dir/$crate_name_" "$out_dir/$crate_name"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -458,6 +458,74 @@ rec {
|
||||
"test flat_test ... ok"
|
||||
];
|
||||
};
|
||||
rustBinTestsCargoBinExe = {
|
||||
# Integration tests locate the crate's own binary via
|
||||
# `env!("CARGO_BIN_EXE_<name>")`, which cargo sets automatically.
|
||||
crateName = "my-crate";
|
||||
src = symlinkJoin {
|
||||
name = "rust-bin-tests-cargo-bin-exe";
|
||||
paths = [
|
||||
(mkFile "src/main.rs" ''
|
||||
fn main() { println!("hello from my-crate"); }
|
||||
'')
|
||||
(mkFile "tests/run_bin.rs" ''
|
||||
#[test]
|
||||
fn runs_binary() {
|
||||
let bin = env!("CARGO_BIN_EXE_my-crate");
|
||||
let out = std::process::Command::new(bin)
|
||||
.output()
|
||||
.expect("spawn");
|
||||
assert!(out.status.success());
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(&out.stdout).trim(),
|
||||
"hello from my-crate"
|
||||
);
|
||||
}
|
||||
'')
|
||||
];
|
||||
};
|
||||
buildTests = true;
|
||||
expectedTestOutputs = [
|
||||
"test runs_binary ... ok"
|
||||
];
|
||||
};
|
||||
rustBinTestsCargoBinExeAutoDetect = {
|
||||
# Verify CARGO_BIN_EXE_<name> is also set for auto-detected
|
||||
# src/bin/*.rs binaries, not just src/main.rs or explicit
|
||||
# crateBin entries.
|
||||
crateName = "multi-bin";
|
||||
src = symlinkJoin {
|
||||
name = "rust-bin-tests-cargo-bin-exe-auto";
|
||||
paths = [
|
||||
(mkFile "src/lib.rs" "")
|
||||
(mkFile "src/bin/tool-a.rs" ''
|
||||
fn main() { println!("tool-a ran"); }
|
||||
'')
|
||||
(mkFile "src/bin/tool-b.rs" ''
|
||||
fn main() { println!("tool-b ran"); }
|
||||
'')
|
||||
(mkFile "tests/run_tools.rs" ''
|
||||
#[test]
|
||||
fn runs_both() {
|
||||
for (bin, want) in [
|
||||
(env!("CARGO_BIN_EXE_tool-a"), "tool-a ran"),
|
||||
(env!("CARGO_BIN_EXE_tool-b"), "tool-b ran"),
|
||||
] {
|
||||
let out = std::process::Command::new(bin)
|
||||
.output()
|
||||
.expect("spawn");
|
||||
assert!(out.status.success());
|
||||
assert_eq!(String::from_utf8_lossy(&out.stdout).trim(), want);
|
||||
}
|
||||
}
|
||||
'')
|
||||
];
|
||||
};
|
||||
buildTests = true;
|
||||
expectedTestOutputs = [
|
||||
"test runs_both ... ok"
|
||||
];
|
||||
};
|
||||
linkAgainstRlibCrate = {
|
||||
crateName = "foo";
|
||||
src = mkFile "src/main.rs" ''
|
||||
|
||||
Reference in New Issue
Block a user