aboutsummaryrefslogtreecommitdiff
path: root/infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test
diff options
context:
space:
mode:
authorMx Kookie <kookie@spacekookie.de>2020-10-31 19:35:09 +0100
committerMx Kookie <kookie@spacekookie.de>2020-10-31 19:35:09 +0100
commitc4625b175f8200f643fd6e11010932ea44c78433 (patch)
treebce3f89888c8ac3991fa5569a878a9eab6801ccc /infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test
parent49f735974dd103039ddc4cb576bb76555164a9e7 (diff)
parentd661aa56a8843e991261510c1bb28fdc2f6975ae (diff)
Add 'infra/libkookie/' from commit 'd661aa56a8843e991261510c1bb28fdc2f6975ae'
git-subtree-dir: infra/libkookie git-subtree-mainline: 49f735974dd103039ddc4cb576bb76555164a9e7 git-subtree-split: d661aa56a8843e991261510c1bb28fdc2f6975ae
Diffstat (limited to 'infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test')
-rw-r--r--infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/brotli-crates.nix95
-rw-r--r--infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix651
2 files changed, 746 insertions, 0 deletions
diff --git a/infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/brotli-crates.nix b/infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/brotli-crates.nix
new file mode 100644
index 000000000000..ab9b0a13ae77
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/brotli-crates.nix
@@ -0,0 +1,95 @@
+{ lib, buildPlatform, buildRustCrate, fetchgit }:
+let kernel = buildPlatform.parsed.kernel.name;
+ abi = buildPlatform.parsed.abi.name;
+ include = includedFiles: src: builtins.filterSource (path: type:
+ lib.lists.any (f:
+ let p = toString (src + ("/" + f)); in
+ (path == p) || (type == "directory" && lib.strings.hasPrefix path p)
+ ) includedFiles
+ ) src;
+ updateFeatures = f: up: functions: builtins.deepSeq f (lib.lists.foldl' (features: fun: fun features) (lib.attrsets.recursiveUpdate f up) functions);
+ mapFeatures = features: map (fun: fun { features = features; });
+ mkFeatures = feat: lib.lists.foldl (features: featureName:
+ if feat.${featureName} or false then
+ [ featureName ] ++ features
+ else
+ features
+ ) [] (builtins.attrNames feat);
+in
+rec {
+ alloc_no_stdlib_1_3_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+ crateName = "alloc-no-stdlib";
+ version = "1.3.0";
+ authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ];
+ sha256 = "1jcp27pzmqdszgp80y484g4kwbjbg7x8a589drcwbxg0i8xwkir9";
+ crateBin = [ { name = "example"; } ];
+ inherit dependencies buildDependencies features;
+ };
+ brotli_2_5_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+ crateName = "brotli";
+ version = "2.5.0";
+ authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" "The Brotli Authors" ];
+ sha256 = "1ynw4hkdwnp0kj30p86ls44ahv4s99258s019bqrq4mya8hlsb5b";
+ crateBin = [ { name = "brotli"; } ];
+ inherit dependencies buildDependencies features;
+ };
+ brotli_decompressor_1_3_1_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
+ crateName = "brotli-decompressor";
+ version = "1.3.1";
+ authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" "The Brotli Authors" ];
+ sha256 = "022g69q1xzwdj0130qm3fa4qwpn4q1jx3lc8yz0v0v201p7bm8fb";
+ crateBin = [ { name = "brotli-decompressor"; } ];
+ inherit dependencies buildDependencies features;
+ };
+ alloc_no_stdlib_1_3_0 = { features?(alloc_no_stdlib_1_3_0_features {}) }: alloc_no_stdlib_1_3_0_ {
+ features = mkFeatures (features.alloc_no_stdlib_1_3_0 or {});
+ };
+ alloc_no_stdlib_1_3_0_features = f: updateFeatures f ({
+ alloc_no_stdlib_1_3_0.default = (f.alloc_no_stdlib_1_3_0.default or true);
+ }) [];
+ brotli_2_5_0 = { features?(brotli_2_5_0_features {}) }: brotli_2_5_0_ {
+ dependencies = mapFeatures features ([ alloc_no_stdlib_1_3_0 brotli_decompressor_1_3_1 ]);
+ features = mkFeatures (features.brotli_2_5_0 or {});
+ };
+ brotli_2_5_0_features = f: updateFeatures f (rec {
+ alloc_no_stdlib_1_3_0.no-stdlib =
+ (f.alloc_no_stdlib_1_3_0.no-stdlib or false) ||
+ (brotli_2_5_0.no-stdlib or false) ||
+ (f.brotli_2_5_0.no-stdlib or false);
+ alloc_no_stdlib_1_3_0.default = true;
+ brotli_2_5_0.default = (f.brotli_2_5_0.default or true);
+ brotli_decompressor_1_3_1.disable-timer =
+ (f.brotli_decompressor_1_3_1.disable-timer or false) ||
+ (brotli_2_5_0.disable-timer or false) ||
+ (f.brotli_2_5_0.disable-timer or false);
+ brotli_decompressor_1_3_1.no-stdlib =
+ (f.brotli_decompressor_1_3_1.no-stdlib or false) ||
+ (brotli_2_5_0.no-stdlib or false) ||
+ (f.brotli_2_5_0.no-stdlib or false);
+ brotli_decompressor_1_3_1.benchmark =
+ (f.brotli_decompressor_1_3_1.benchmark or false) ||
+ (brotli_2_5_0.benchmark or false) ||
+ (f.brotli_2_5_0.benchmark or false);
+ brotli_decompressor_1_3_1.default = true;
+ brotli_decompressor_1_3_1.seccomp =
+ (f.brotli_decompressor_1_3_1.seccomp or false) ||
+ (brotli_2_5_0.seccomp or false) ||
+ (f.brotli_2_5_0.seccomp or false);
+ }) [ alloc_no_stdlib_1_3_0_features brotli_decompressor_1_3_1_features ];
+ brotli_decompressor_1_3_1 = { features?(brotli_decompressor_1_3_1_features {}) }: brotli_decompressor_1_3_1_ {
+ dependencies = mapFeatures features ([ alloc_no_stdlib_1_3_0 ]);
+ features = mkFeatures (features.brotli_decompressor_1_3_1 or {});
+ };
+ brotli_decompressor_1_3_1_features = f: updateFeatures f (rec {
+ alloc_no_stdlib_1_3_0.no-stdlib =
+ (f.alloc_no_stdlib_1_3_0.no-stdlib or false) ||
+ (brotli_decompressor_1_3_1.no-stdlib or false) ||
+ (f.brotli_decompressor_1_3_1.no-stdlib or false);
+ alloc_no_stdlib_1_3_0.default = true;
+ alloc_no_stdlib_1_3_0.unsafe =
+ (f.alloc_no_stdlib_1_3_0.unsafe or false) ||
+ (brotli_decompressor_1_3_1.unsafe or false) ||
+ (f.brotli_decompressor_1_3_1.unsafe or false);
+ brotli_decompressor_1_3_1.default = (f.brotli_decompressor_1_3_1.default or true);
+ }) [ alloc_no_stdlib_1_3_0_features ];
+}
diff --git a/infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix b/infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix
new file mode 100644
index 000000000000..f6cd54c4ee3e
--- /dev/null
+++ b/infra/libkookie/nixpkgs/pkgs/build-support/rust/build-rust-crate/test/default.nix
@@ -0,0 +1,651 @@
+{ lib
+, buildPackages
+, buildRustCrate
+, callPackage
+, releaseTools
+, runCommand
+, runCommandCC
+, stdenv
+, symlinkJoin
+, writeTextFile
+}:
+
+let
+ mkCrate = buildRustCrate: args: let
+ p = {
+ crateName = "nixtestcrate";
+ version = "0.1.0";
+ authors = [ "Test <test@example.com>" ];
+ } // args;
+ in buildRustCrate p;
+ mkHostCrate = mkCrate buildRustCrate;
+
+ mkCargoToml =
+ { name, crateVersion ? "0.1.0", path ? "Cargo.toml" }:
+ mkFile path ''
+ [package]
+ name = ${builtins.toJSON name}
+ version = ${builtins.toJSON crateVersion}
+ '';
+
+ mkFile = destination: text: writeTextFile {
+ name = "src";
+ destination = "/${destination}";
+ inherit text;
+ };
+
+ mkBin = name: mkFile name ''
+ use std::env;
+ fn main() {
+ let name: String = env::args().nth(0).unwrap();
+ println!("executed {}", name);
+ }
+ '';
+
+ mkBinExtern = name: extern: mkFile name ''
+ extern crate ${extern};
+ fn main() {
+ assert_eq!(${extern}::test(), 23);
+ }
+ '';
+
+ mkTestFile = name: functionName: mkFile name ''
+ #[cfg(test)]
+ #[test]
+ fn ${functionName}() {
+ assert!(true);
+ }
+ '';
+ mkTestFileWithMain = name: functionName: mkFile name ''
+ #[cfg(test)]
+ #[test]
+ fn ${functionName}() {
+ assert!(true);
+ }
+
+ fn main() {}
+ '';
+
+
+ mkLib = name: mkFile name "pub fn test() -> i32 { return 23; }";
+
+ mkTest = crateArgs: let
+ crate = mkHostCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
+ hasTests = crateArgs.buildTests or false;
+ expectedTestOutputs = crateArgs.expectedTestOutputs or null;
+ binaries = map (v: lib.escapeShellArg v.name) (crateArgs.crateBin or []);
+ isLib = crateArgs ? libName || crateArgs ? libPath;
+ crateName = crateArgs.crateName or "nixtestcrate";
+ libName = crateArgs.libName or crateName;
+
+ libTestBinary = if !isLib then null else mkHostCrate {
+ crateName = "run-test-${crateName}";
+ dependencies = [ crate ];
+ src = mkBinExtern "src/main.rs" libName;
+ };
+
+ in
+ assert expectedTestOutputs != null -> hasTests;
+ assert hasTests -> expectedTestOutputs != null;
+
+ runCommand "run-buildRustCrate-${crateName}-test" {
+ nativeBuildInputs = [ crate ];
+ } (if !hasTests then ''
+ ${lib.concatMapStringsSep "\n" (binary:
+ # Can't actually run the binary when cross-compiling
+ (lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "type ") + binary
+ ) binaries}
+ ${lib.optionalString isLib ''
+ test -e ${crate}/lib/*.rlib || exit 1
+ ${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "test -x "} \
+ ${libTestBinary}/bin/run-test-${crateName}
+ ''}
+ touch $out
+ '' else if stdenv.hostPlatform == stdenv.buildPlatform then ''
+ for file in ${crate}/tests/*; do
+ $file 2>&1 >> $out
+ done
+ set -e
+ ${lib.concatMapStringsSep "\n" (o: "grep '${o}' $out || { echo 'output \"${o}\" not found in:'; cat $out; exit 23; }") expectedTestOutputs}
+ '' else ''
+ for file in ${crate}/tests/*; do
+ test -x "$file"
+ done
+ touch "$out"
+ ''
+ );
+
+ /* Returns a derivation that asserts that the crate specified by `crateArgs`
+ has the specified files as output.
+
+ `name` is used as part of the derivation name that performs the checking.
+
+ `crateArgs` is passed to `mkHostCrate` to build the crate with `buildRustCrate`.
+
+ `expectedFiles` contains a list of expected file paths in the output. E.g.
+ `[ "./bin/my_binary" ]`.
+
+ `output` specifies the name of the output to use. By default, the default
+ output is used but e.g. `output = "lib";` will cause the lib output
+ to be checked instead. You do not need to specify any directories.
+ */
+ assertOutputs = { name, crateArgs, expectedFiles, output? null }:
+ assert (builtins.isString name);
+ assert (builtins.isAttrs crateArgs);
+ assert (builtins.isList expectedFiles);
+
+ let
+ crate = mkHostCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
+ crateOutput = if output == null then crate else crate."${output}";
+ expectedFilesFile = writeTextFile {
+ name = "expected-files-${name}";
+ text =
+ let sorted = builtins.sort (a: b: a<b) expectedFiles;
+ concatenated = builtins.concatStringsSep "\n" sorted;
+ in "${concatenated}\n";
+ };
+ in
+ runCommand "assert-outputs-${name}" {
+ } ''
+ local actualFiles=$(mktemp)
+
+ cd "${crateOutput}"
+ find . -type f | sort >$actualFiles
+ diff -q ${expectedFilesFile} $actualFiles >/dev/null || {
+ echo -e "\033[0;1;31mERROR: Difference in expected output files in ${crateOutput} \033[0m" >&2
+ echo === Got:
+ sed -e 's/^/ /' $actualFiles
+ echo === Expected:
+ sed -e 's/^/ /' ${expectedFilesFile}
+ echo === Diff:
+ diff -u ${expectedFilesFile} $actualFiles |\
+ tail -n +3 |\
+ sed -e 's/^/ /'
+ exit 1
+ }
+ touch $out
+ ''
+ ;
+
+ in rec {
+
+ tests = let
+ cases = rec {
+ libPath = { libPath = "src/my_lib.rs"; src = mkLib "src/my_lib.rs"; };
+ srcLib = { src = mkLib "src/lib.rs"; };
+
+ # This used to be supported by cargo but as of 1.40.0 I can't make it work like that with just cargo anymore.
+ # This might be a regression or deprecated thing they finally removed…
+ # customLibName = { libName = "test_lib"; src = mkLib "src/test_lib.rs"; };
+ # rustLibTestsCustomLibName = {
+ # libName = "test_lib";
+ # src = mkTestFile "src/test_lib.rs" "foo";
+ # buildTests = true;
+ # expectedTestOutputs = [ "test foo ... ok" ];
+ # };
+
+ customLibNameAndLibPath = { libName = "test_lib"; libPath = "src/best-lib.rs"; src = mkLib "src/best-lib.rs"; };
+ crateBinWithPath = { crateBin = [{ name = "test_binary1"; path = "src/foobar.rs"; }]; src = mkBin "src/foobar.rs"; };
+ crateBinNoPath1 = { crateBin = [{ name = "my-binary2"; }]; src = mkBin "src/my_binary2.rs"; };
+ crateBinNoPath2 = {
+ crateBin = [{ name = "my-binary3"; } { name = "my-binary4"; }];
+ src = symlinkJoin {
+ name = "buildRustCrateMultipleBinariesCase";
+ paths = [ (mkBin "src/bin/my_binary3.rs") (mkBin "src/bin/my_binary4.rs") ];
+ };
+ };
+ crateBinNoPath3 = { crateBin = [{ name = "my-binary5"; }]; src = mkBin "src/bin/main.rs"; };
+ crateBinNoPath4 = { crateBin = [{ name = "my-binary6"; }]; src = mkBin "src/main.rs";};
+ crateBinRename1 = {
+ crateBin = [{ name = "my-binary-rename1"; }];
+ src = mkBinExtern "src/main.rs" "foo_renamed";
+ dependencies = [ (mkHostCrate { crateName = "foo"; src = mkLib "src/lib.rs"; }) ];
+ crateRenames = { "foo" = "foo_renamed"; };
+ };
+ crateBinRename2 = {
+ crateBin = [{ name = "my-binary-rename2"; }];
+ src = mkBinExtern "src/main.rs" "foo_renamed";
+ dependencies = [ (mkHostCrate { crateName = "foo"; libName = "foolib"; src = mkLib "src/lib.rs"; }) ];
+ crateRenames = { "foo" = "foo_renamed"; };
+ };
+ crateBinRenameMultiVersion = let
+ crateWithVersion = version: mkHostCrate {
+ crateName = "my_lib";
+ inherit version;
+ src = mkFile "src/lib.rs" ''
+ pub const version: &str = "${version}";
+ '';
+ };
+ depCrate01 = crateWithVersion "0.1.2";
+ depCrate02 = crateWithVersion "0.2.1";
+ in {
+ crateName = "my_bin";
+ src = symlinkJoin {
+ name = "my_bin_src";
+ paths = [
+ (mkFile "src/main.rs" ''
+ #[test]
+ fn my_lib_01() { assert_eq!(lib01::version, "0.1.2"); }
+
+ #[test]
+ fn my_lib_02() { assert_eq!(lib02::version, "0.2.1"); }
+
+ fn main() { }
+ '')
+ ];
+ };
+ dependencies = [ depCrate01 depCrate02 ];
+ crateRenames = {
+ "my_lib" = [
+ {
+ version = "0.1.2";
+ rename = "lib01";
+ }
+ {
+ version = "0.2.1";
+ rename = "lib02";
+ }
+ ];
+ };
+ buildTests = true;
+ expectedTestOutputs = [
+ "test my_lib_01 ... ok"
+ "test my_lib_02 ... ok"
+ ];
+ };
+ rustLibTestsDefault = {
+ src = mkTestFile "src/lib.rs" "baz";
+ buildTests = true;
+ expectedTestOutputs = [ "test baz ... ok" ];
+ };
+ rustLibTestsCustomLibPath = {
+ libPath = "src/test_path.rs";
+ src = mkTestFile "src/test_path.rs" "bar";
+ buildTests = true;
+ expectedTestOutputs = [ "test bar ... ok" ];
+ };
+ rustLibTestsCustomLibPathWithTests = {
+ libPath = "src/test_path.rs";
+ src = symlinkJoin {
+ name = "rust-lib-tests-custom-lib-path-with-tests-dir";
+ paths = [
+ (mkTestFile "src/test_path.rs" "bar")
+ (mkTestFile "tests/something.rs" "something")
+ ];
+ };
+ buildTests = true;
+ expectedTestOutputs = [
+ "test bar ... ok"
+ "test something ... ok"
+ ];
+ };
+ rustBinTestsCombined = {
+ src = symlinkJoin {
+ name = "rust-bin-tests-combined";
+ paths = [
+ (mkTestFileWithMain "src/main.rs" "src_main")
+ (mkTestFile "tests/foo.rs" "tests_foo")
+ (mkTestFile "tests/bar.rs" "tests_bar")
+ ];
+ };
+ buildTests = true;
+ expectedTestOutputs = [
+ "test src_main ... ok"
+ "test tests_foo ... ok"
+ "test tests_bar ... ok"
+ ];
+ };
+ rustBinTestsSubdirCombined = {
+ src = symlinkJoin {
+ name = "rust-bin-tests-subdir-combined";
+ paths = [
+ (mkTestFileWithMain "src/main.rs" "src_main")
+ (mkTestFile "tests/foo/main.rs" "tests_foo")
+ (mkTestFile "tests/bar/main.rs" "tests_bar")
+ ];
+ };
+ buildTests = true;
+ expectedTestOutputs = [
+ "test src_main ... ok"
+ "test tests_foo ... ok"
+ "test tests_bar ... ok"
+ ];
+ };
+ linkAgainstRlibCrate = {
+ crateName = "foo";
+ src = mkFile "src/main.rs" ''
+ extern crate somerlib;
+ fn main() {}
+ '';
+ dependencies = [
+ (mkHostCrate {
+ crateName = "somerlib";
+ type = [ "rlib" ];
+ src = mkLib "src/lib.rs";
+ })
+ ];
+ };
+ buildScriptDeps = let
+ depCrate = buildRustCrate: boolVal: mkCrate buildRustCrate {
+ crateName = "bar";
+ src = mkFile "src/lib.rs" ''
+ pub const baz: bool = ${boolVal};
+ '';
+ };
+ in {
+ crateName = "foo";
+ src = symlinkJoin {
+ name = "build-script-and-main";
+ paths = [
+ (mkFile "src/main.rs" ''
+ extern crate bar;
+ #[cfg(test)]
+ #[test]
+ fn baz_false() { assert!(!bar::baz); }
+ fn main() { }
+ '')
+ (mkFile "build.rs" ''
+ extern crate bar;
+ fn main() { assert!(bar::baz); }
+ '')
+ ];
+ };
+ buildDependencies = [ (depCrate buildPackages.buildRustCrate "true") ];
+ dependencies = [ (depCrate buildRustCrate "false") ];
+ buildTests = true;
+ expectedTestOutputs = [ "test baz_false ... ok" ];
+ };
+ buildScriptFeatureEnv = {
+ crateName = "build-script-feature-env";
+ features = [ "some-feature" "crate/another_feature" ];
+ src = symlinkJoin {
+ name = "build-script-feature-env";
+ paths = [
+ (mkFile "src/main.rs" ''
+ #[cfg(test)]
+ #[test]
+ fn feature_not_visible() {
+ assert!(std::env::var("CARGO_FEATURE_SOME_FEATURE").is_err());
+ assert!(option_env!("CARGO_FEATURE_SOME_FEATURE").is_none());
+ }
+ fn main() {}
+ '')
+ (mkFile "build.rs" ''
+ fn main() {
+ assert!(std::env::var("CARGO_FEATURE_SOME_FEATURE").is_ok());
+ assert!(option_env!("CARGO_FEATURE_SOME_FEATURE").is_none());
+ }
+ '')
+ ];
+ };
+ buildTests = true;
+ expectedTestOutputs = [ "test feature_not_visible ... ok" ];
+ };
+ # Regression test for https://github.com/NixOS/nixpkgs/pull/88054
+ # Build script output should be rewritten as valid env vars.
+ buildScriptIncludeDirDeps = let
+ depCrate = mkHostCrate {
+ crateName = "bar";
+ src = symlinkJoin {
+ name = "build-script-and-include-dir-bar";
+ paths = [
+ (mkFile "src/lib.rs" ''
+ fn main() { }
+ '')
+ (mkFile "build.rs" ''
+ use std::path::PathBuf;
+ fn main() { println!("cargo:include-dir={}/src", std::env::current_dir().unwrap_or(PathBuf::from(".")).to_str().unwrap()); }
+ '')
+ ];
+ };
+ };
+ in {
+ crateName = "foo";
+ src = symlinkJoin {
+ name = "build-script-and-include-dir-foo";
+ paths = [
+ (mkFile "src/main.rs" ''
+ fn main() { }
+ '')
+ (mkFile "build.rs" ''
+ fn main() { assert!(std::env::var_os("DEP_BAR_INCLUDE_DIR").is_some()); }
+ '')
+ ];
+ };
+ buildDependencies = [ depCrate ];
+ dependencies = [ depCrate ];
+ };
+ # Regression test for https://github.com/NixOS/nixpkgs/issues/74071
+ # Whenevever a build.rs file is generating files those should not be overlayed onto the actual source dir
+ buildRsOutDirOverlay = {
+ src = symlinkJoin {
+ name = "buildrs-out-dir-overlay";
+ paths = [
+ (mkLib "src/lib.rs")
+ (mkFile "build.rs" ''
+ use std::env;
+ use std::ffi::OsString;
+ use std::fs;
+ use std::path::Path;
+ fn main() {
+ let out_dir = env::var_os("OUT_DIR").expect("OUT_DIR not set");
+ let out_file = Path::new(&out_dir).join("lib.rs");
+ fs::write(out_file, "invalid rust code!").expect("failed to write lib.rs");
+ }
+ '')
+ ];
+ };
+ };
+ # Regression test for https://github.com/NixOS/nixpkgs/pull/83379
+ # link flag order should be preserved
+ linkOrder = {
+ src = symlinkJoin {
+ name = "buildrs-out-dir-overlay";
+ paths = [
+ (mkFile "build.rs" ''
+ fn main() {
+ // in the other order, linkage will fail
+ println!("cargo:rustc-link-lib=b");
+ println!("cargo:rustc-link-lib=a");
+ }
+ '')
+ (mkFile "src/main.rs" ''
+ extern "C" {
+ fn hello_world();
+ }
+ fn main() {
+ unsafe {
+ hello_world();
+ }
+ }
+ '')
+ ];
+ };
+ buildInputs = let
+ compile = name: text: let
+ src = writeTextFile {
+ name = "${name}-src.c";
+ inherit text;
+ };
+ in runCommandCC name {} ''
+ mkdir -p $out/lib
+ # Note: On darwin (which defaults to clang) we have to add
+ # `-undefined dynamic_lookup` as otherwise the compilation fails.
+ $CC -shared \
+ ${lib.optionalString stdenv.isDarwin "-undefined dynamic_lookup"} \
+ -o $out/lib/${name}${stdenv.hostPlatform.extensions.sharedLibrary} ${src}
+ '';
+ b = compile "libb" ''
+ #include <stdio.h>
+
+ void hello();
+
+ void hello_world() {
+ hello();
+ printf(" world!\n");
+ }
+ '';
+ a = compile "liba" ''
+ #include <stdio.h>
+
+ void hello() {
+ printf("hello");
+ }
+ '';
+ in [ a b ];
+ };
+ rustCargoTomlInSubDir = {
+ # The "workspace_member" can be set to the sub directory with the crate to build.
+ # By default ".", meaning the top level directory is assumed.
+ # Using null will trigger a search.
+ workspace_member = null;
+ src = symlinkJoin rec {
+ name = "find-cargo-toml";
+ paths = [
+ (mkCargoToml { name = "ignoreMe"; })
+ (mkTestFileWithMain "src/main.rs" "ignore_main")
+
+ (mkCargoToml { name = "rustCargoTomlInSubDir"; path = "subdir/Cargo.toml"; })
+ (mkTestFileWithMain "subdir/src/main.rs" "src_main")
+ (mkTestFile "subdir/tests/foo/main.rs" "tests_foo")
+ (mkTestFile "subdir/tests/bar/main.rs" "tests_bar")
+ ];
+ };
+ buildTests = true;
+ expectedTestOutputs = [
+ "test src_main ... ok"
+ "test tests_foo ... ok"
+ "test tests_bar ... ok"
+ ];
+ };
+
+ rustCargoTomlInTopDir =
+ let
+ withoutCargoTomlSearch = builtins.removeAttrs rustCargoTomlInSubDir [ "workspace_member" ];
+ in
+ withoutCargoTomlSearch // {
+ expectedTestOutputs = [
+ "test ignore_main ... ok"
+ ];
+ };
+ procMacroInPrelude = {
+ procMacro = true;
+ edition = "2018";
+ src = symlinkJoin {
+ name = "proc-macro-in-prelude";
+ paths = [
+ (mkFile "src/lib.rs" ''
+ use proc_macro::TokenTree;
+ '')
+ ];
+ };
+ };
+ };
+ brotliCrates = (callPackage ./brotli-crates.nix {});
+ tests = lib.mapAttrs (key: value: mkTest (value // lib.optionalAttrs (!value?crateName) { crateName = key; })) cases;
+ in tests // rec {
+
+ crateBinWithPathOutputs = assertOutputs {
+ name="crateBinWithPath";
+ crateArgs = {
+ crateBin = [{ name = "test_binary1"; path = "src/foobar.rs"; }];
+ src = mkBin "src/foobar.rs";
+ };
+ expectedFiles = [
+ "./bin/test_binary1"
+ ];
+ };
+
+ crateBinWithPathOutputsDebug = assertOutputs {
+ name="crateBinWithPath";
+ crateArgs = {
+ release = false;
+ crateBin = [{ name = "test_binary1"; path = "src/foobar.rs"; }];
+ src = mkBin "src/foobar.rs";
+ };
+ expectedFiles = [
+ "./bin/test_binary1"
+ ] ++ lib.optionals stdenv.isDarwin [
+ # On Darwin, the debug symbols are in a seperate directory.
+ "./bin/test_binary1.dSYM/Contents/Info.plist"
+ "./bin/test_binary1.dSYM/Contents/Resources/DWARF/test_binary1"
+ ];
+ };
+
+ crateBinNoPath1Outputs = assertOutputs {
+ name="crateBinNoPath1";
+ crateArgs = {
+ crateBin = [{ name = "my-binary2"; }];
+ src = mkBin "src/my_binary2.rs";
+ };
+ expectedFiles = [
+ "./bin/my-binary2"
+ ];
+ };
+
+ crateLibOutputs = assertOutputs {
+ name="crateLib";
+ output="lib";
+ crateArgs = {
+ libName = "test_lib";
+ type = [ "rlib" ];
+ libPath = "src/lib.rs";
+ src = mkLib "src/lib.rs";
+ };
+ expectedFiles = [
+ "./nix-support/propagated-build-inputs"
+ "./lib/libtest_lib-042a1fdbef.rlib"
+ "./lib/link"
+ ];
+ };
+
+ crateLibOutputsDebug = assertOutputs {
+ name="crateLib";
+ output="lib";
+ crateArgs = {
+ release = false;
+ libName = "test_lib";
+ type = [ "rlib" ];
+ libPath = "src/lib.rs";
+ src = mkLib "src/lib.rs";
+ };
+ expectedFiles = [
+ "./nix-support/propagated-build-inputs"
+ "./lib/libtest_lib-042a1fdbef.rlib"
+ "./lib/link"
+ ];
+ };
+
+ brotliTest = let
+ pkg = brotliCrates.brotli_2_5_0 {};
+ in runCommand "run-brotli-test-cmd" {
+ nativeBuildInputs = [ pkg ];
+ } (if stdenv.hostPlatform == stdenv.buildPlatform then ''
+ ${pkg}/bin/brotli -c ${pkg}/bin/brotli > /dev/null && touch $out
+ '' else ''
+ test -x '${pkg}/bin/brotli' && touch $out
+ '');
+ allocNoStdLibTest = let
+ pkg = brotliCrates.alloc_no_stdlib_1_3_0 {};
+ in runCommand "run-alloc-no-stdlib-test-cmd" {
+ nativeBuildInputs = [ pkg ];
+ } ''
+ test -e ${pkg}/bin/example && touch $out
+ '';
+ brotliDecompressorTest = let
+ pkg = brotliCrates.brotli_decompressor_1_3_1 {};
+ in runCommand "run-brotli-decompressor-test-cmd" {
+ nativeBuildInputs = [ pkg ];
+ } ''
+ test -e ${pkg}/bin/brotli-decompressor && touch $out
+ '';
+ };
+ test = releaseTools.aggregate {
+ name = "buildRustCrate-tests";
+ meta = {
+ description = "Test cases for buildRustCrate";
+ maintainers = [ lib.maintainers.andir ];
+ };
+ constituents = builtins.attrValues tests;
+ };
+}