summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniël de Kok <me@danieldk.eu>2020-03-12 12:29:31 +0100
committerDaniël de Kok <me@danieldk.eu>2020-03-13 11:13:27 +0100
commitea6e048c37eff63e057f767410acd8fc911ba078 (patch)
tree0277a5ab69de09afae345f72a68e4e2dd753441c
parentbe80721e747b3ea3d89b3a945cb85669f4f8ddce (diff)
downloadnixpkgs-ea6e048c37eff63e057f767410acd8fc911ba078.tar
nixpkgs-ea6e048c37eff63e057f767410acd8fc911ba078.tar.gz
nixpkgs-ea6e048c37eff63e057f767410acd8fc911ba078.tar.bz2
nixpkgs-ea6e048c37eff63e057f767410acd8fc911ba078.tar.lz
nixpkgs-ea6e048c37eff63e057f767410acd8fc911ba078.tar.xz
nixpkgs-ea6e048c37eff63e057f767410acd8fc911ba078.tar.zst
nixpkgs-ea6e048c37eff63e057f767410acd8fc911ba078.zip
buildRustCrate: only link build deps into build script
According to the Cargo documentation:

> The build script does not have access to the dependencies listed in
> the dependencies or dev-dependencies section (they’re not built
> yet!). Also, build dependencies are not available to the package
> itself unless also explicitly added in the [dependencies] table.

https://doc.rust-lang.org/cargo/reference/build-scripts.html

This change separates linkage of regular dependencies and build
dependencies.
-rw-r--r--pkgs/build-support/rust/build-rust-crate/configure-crate.nix63
-rw-r--r--pkgs/build-support/rust/build-rust-crate/lib.sh1
-rw-r--r--pkgs/build-support/rust/build-rust-crate/test/default.nix30
3 files changed, 79 insertions, 15 deletions
diff --git a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
index 013b99a77b4..2f7d3b77f39 100644
--- a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
+++ b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
@@ -56,32 +56,66 @@ in ''
     i=$1
     ln -s -f $i/lib/*.rlib $2 #*/
     ln -s -f $i/lib/*.so $i/lib/*.dylib $2 #*/
-    if [ -e "$i/lib/link" ]; then
-        cat $i/lib/link >> target/link
-        cat $i/lib/link >> target/link.final
-    fi
     if [ -e $i/env ]; then
         source $i/env
     fi
   }
 
+  # The following steps set up the dependencies of the crate. Two
+  # kinds of dependencies are distinguished: build dependencies
+  # (used by the build script) and crate dependencies. For each
+  # dependency we have to:
+  #
+  # - Make its Rust library available to rustc. This is done by
+  #   symlinking all library dependencies into a directory that
+  #   can be provided to rustc.
+  # - Accumulate linking flags. These flags are largely used for
+  #   linking native libraries.
+  #
+  # The crate link flags are added to the `link` and `link.final`
+  # files. The `link` file is used for linkage in the current
+  # crate. The `link.final` file will be copied to the output and can
+  # be used by downstream crates to get the linker flags of this
+  # crate.
+
   mkdir -p target/{deps,lib,build,buildDeps}
   chmod uga+w target -R
   echo ${extraLinkFlags} > target/link
   echo ${extraLinkFlags} > target/link.final
+
+  # Prepare crate dependencies
   for i in ${completeDepsDir}; do
     symlink_dependency $i target/deps
+    if [ -e "$i/lib/link" ]; then
+      cat $i/lib/link >> target/link
+      cat $i/lib/link >> target/link.final
+    fi
   done
+
+  # Prepare crate build dependencies that are used for the build script.
   for i in ${completeBuildDepsDir}; do
-     symlink_dependency $i target/buildDeps
+    symlink_dependency $i target/buildDeps
+    if [ -e "$i/lib/link" ]; then
+      cat $i/lib/link >> target/link.build
+    fi
   done
-  if [[ -e target/link ]]; then
-    sort -u target/link > target/link.sorted
-    mv target/link.sorted target/link
-    sort -u target/link.final > target/link.final.sorted
-    mv target/link.final.sorted target/link.final
-    tr '\n' ' ' < target/link > target/link_
+
+  # Remove duplicate linker flags from the build dependencies.
+  if [[ -e target/link.build ]]; then
+    sort -u target/link.build > target/link.build.sorted
+    mv target/link.build.sorted target/link.build
   fi
+
+  # Remove duplicate linker flags from the dependencies.
+  sort -u target/link > target/link.sorted
+  mv target/link.sorted target/link
+  tr '\n' ' ' < target/link > target/link_
+
+  # Remove duplicate linker flags from the that are written
+  # to the derivation's output.
+  sort -u target/link.final > target/link.final.sorted
+  mv target/link.final.sorted target/link.final
+
   EXTRA_BUILD=""
   BUILD_OUT_DIR=""
   export CARGO_PKG_NAME=${crateName}
@@ -120,15 +154,14 @@ in ''
   elif [[ -e "build.rs" ]]; then
      BUILD="build.rs"
   fi
+
+  # Compile and run the build script, when available.
   if [[ ! -z "$BUILD" ]] ; then
      echo_build_heading "$BUILD" ${libName}
      mkdir -p target/build/${crateName}
      EXTRA_BUILD_FLAGS=""
-     if [ -e target/link_ ]; then
-       EXTRA_BUILD_FLAGS=$(cat target/link_)
-     fi
      if [ -e target/link.build ]; then
-       EXTRA_BUILD_FLAGS="$EXTRA_BUILD_FLAGS $(cat target/link.build)"
+       EXTRA_BUILD_FLAGS="$EXTRA_BUILD_FLAGS $(tr '\n' ' ' < target/link.build)"
      fi
      noisily rustc --crate-name build_script_build $BUILD --crate-type bin ${rustcOpts} \
        ${crateFeatures} --out-dir target/build/${crateName} --emit=dep-info,link \
diff --git a/pkgs/build-support/rust/build-rust-crate/lib.sh b/pkgs/build-support/rust/build-rust-crate/lib.sh
index 0f08c133e55..5843ee98b0d 100644
--- a/pkgs/build-support/rust/build-rust-crate/lib.sh
+++ b/pkgs/build-support/rust/build-rust-crate/lib.sh
@@ -79,6 +79,7 @@ build_bin_test_file() {
     build_bin_test "$derived_crate_name" "$file"
 }
 
+# Add additional link options that were provided by the build script.
 setup_link_paths() {
   EXTRA_LIB=""
   if [[ -e target/link_ ]]; then
diff --git a/pkgs/build-support/rust/build-rust-crate/test/default.nix b/pkgs/build-support/rust/build-rust-crate/test/default.nix
index 71004566468..f24583c41fc 100644
--- a/pkgs/build-support/rust/build-rust-crate/test/default.nix
+++ b/pkgs/build-support/rust/build-rust-crate/test/default.nix
@@ -207,6 +207,36 @@ let
           })
         ];
       };
+      buildScriptDeps = let
+        depCrate = boolVal: mkCrate {
+          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 "true") ];
+        dependencies = [ (depCrate "false") ];
+        buildTests = true;
+        expectedTestOutputs = [ "test baz_false ... ok" ];
+      };
       # 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 = {