buildRustCrate: add lib output

This cuts down the dependency tree on some rust builds where a crate not
just exposes a binary but also a library. `$out/lib` contained a bunch
of extra support files that among other information carry linker flags
(including the full path to link-time dependencies). Worst case this led
to some binary outputs depending on the full build closure of rust
crates.

Moving all the `$out/lib` files to `$lib/lib` solves this nicely.

`lib` might be a bit weird here as they are most of the time just rlib
files (rust libraries). Those are essential only required during
compilation but they can also be shared objects (like with traditional
C-style packages). Which is why I went with `lib` for the new output.

One of the caveats we are running into here is that we do not (always)
know ahead of time of a crate produces just a library or just a binary.
Cargo allows for some ambiguity regarding whether or not a crate
provides one, two, … binaries and libraries as it's outputs. Ideally we
would be able to rely on the `crateType` entirely but so far that isn't
the case. More work on that area might show how difficult that actually
is.
This commit is contained in:
Andreas Rammhold 2019-11-20 07:30:06 +01:00
parent 5b2b82c821
commit 1b748554d5
No known key found for this signature in database
GPG Key ID: E432E410B5E48C86
4 changed files with 31 additions and 20 deletions

View File

@ -193,6 +193,12 @@
The aforementioned option was added this release. The aforementioned option was added this release.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
The <literal>buildRustCrate</literal> infrastructure now produces <literal>lib</literal> outputs in addition to the <literal>out</literal> output.
This has led to drastically reduced closed sizes for some rust crates since development dependencies are now in the <literal>lib</literal> output.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>

View File

@ -91,18 +91,18 @@
echo "$EXTRA_LINK_SEARCH" | while read i; do echo "$EXTRA_LINK_SEARCH" | while read i; do
if [[ ! -z "$i" ]]; then if [[ ! -z "$i" ]]; then
for lib in $i; do for library in $i; do
echo "-L $lib" >> target/link echo "-L $library" >> target/link
L=$(echo $lib | sed -e "s#$(pwd)/target/build#$out/lib#") L=$(echo $library | sed -e "s#$(pwd)/target/build#$lib/lib#")
echo "-L $L" >> target/link.final echo "-L $L" >> target/link.final
done done
fi fi
done done
echo "$EXTRA_LINK" | while read i; do echo "$EXTRA_LINK" | while read i; do
if [[ ! -z "$i" ]]; then if [[ ! -z "$i" ]]; then
for lib in $i; do for library in $i; do
echo "-l $lib" >> target/link echo "-l $library" >> target/link
echo "-l $lib" >> target/link.final echo "-l $library" >> target/link.final
done done
fi fi
done done

View File

@ -22,9 +22,9 @@ let
else else
extern; extern;
in (if lib.lists.any (x: x == "lib") dep.crateType then in (if lib.lists.any (x: x == "lib") dep.crateType then
" --extern ${name}=${dep.out}/lib/lib${extern}-${dep.metadata}.rlib" " --extern ${name}=${dep.lib}/lib/lib${extern}-${dep.metadata}.rlib"
else else
" --extern ${name}=${dep.out}/lib/lib${extern}-${dep.metadata}${stdenv.hostPlatform.extensions.sharedLibrary}") " --extern ${name}=${dep.lib}/lib/lib${extern}-${dep.metadata}${stdenv.hostPlatform.extensions.sharedLibrary}")
) dependencies); ) dependencies);
echo_build_heading = colors: '' echo_build_heading = colors: ''
@ -96,12 +96,12 @@ stdenv.mkDerivation (rec {
buildInputs = (crate.buildInputs or []) ++ buildInputs_; buildInputs = (crate.buildInputs or []) ++ buildInputs_;
dependencies = dependencies =
builtins.map builtins.map
(dep: dep.override { rust = rust; release = release; verbose = verbose; crateOverrides = crateOverrides; }) (dep: lib.getLib (dep.override { rust = rust; release = release; verbose = verbose; crateOverrides = crateOverrides; }))
dependencies_; dependencies_;
buildDependencies = buildDependencies =
builtins.map builtins.map
(dep: dep.override { rust = rust; release = release; verbose = verbose; crateOverrides = crateOverrides; }) (dep: lib.getLib (dep.override { rust = rust; release = release; verbose = verbose; crateOverrides = crateOverrides; }))
buildDependencies_; buildDependencies_;
completeDeps = lib.lists.unique (dependencies ++ lib.lists.concatMap (dep: dep.completeDeps) dependencies); completeDeps = lib.lists.unique (dependencies ++ lib.lists.concatMap (dep: dep.completeDeps) dependencies);
@ -160,6 +160,9 @@ stdenv.mkDerivation (rec {
}; };
installPhase = installCrate crateName metadata; installPhase = installCrate crateName metadata;
outputs = [ "out" "lib" ];
outputDev = [ "lib" ];
} // extraDerivationAttrs } // extraDerivationAttrs
)) { )) {
rust = rustc; rust = rustc;

View File

@ -1,24 +1,26 @@
crateName: metadata: crateName: metadata:
'' ''
runHook preInstall runHook preInstall
mkdir -p $out # always create $out even if we do not have binaries. We are detecting binary targets during compilation, if those are missing there is no way to only have $lib
mkdir $out
if [[ -s target/env ]]; then if [[ -s target/env ]]; then
cp target/env $out/env mkdir -p $lib
cp target/env $lib/env
fi fi
if [[ -s target/link.final ]]; then if [[ -s target/link.final ]]; then
mkdir -p $out/lib mkdir -p $lib/lib
cp target/link.final $out/lib/link cp target/link.final $lib/lib/link
fi fi
if [[ "$(ls -A target/lib)" ]]; then if [[ "$(ls -A target/lib)" ]]; then
mkdir -p $out/lib mkdir -p $lib/lib
cp target/lib/* $out/lib #*/ cp target/lib/* $lib/lib #*/
for lib in $out/lib/*.so $out/lib/*.dylib; do #*/ for library in $lib/lib/*.so $lib/lib/*.dylib; do #*/
ln -s $lib $(echo $lib | sed -e "s/-${metadata}//") ln -s $library $(echo $library | sed -e "s/-${metadata}//")
done done
fi fi
if [[ "$(ls -A target/build)" ]]; then # */ if [[ "$(ls -A target/build)" ]]; then # */
mkdir -p $out/lib mkdir -p $lib/lib
cp -r target/build/* $out/lib # */ cp -r target/build/* $lib/lib # */
fi fi
if [[ -d target/bin ]]; then if [[ -d target/bin ]]; then
if [[ "$(ls -A target/bin)" ]]; then if [[ "$(ls -A target/bin)" ]]; then