cbe5cf5d81
This is executed curing the build, and usually quite helpful in telling you how the build failed, if it failed. For example, when linking against system libraries, it shows which system lib could not be discovered, the pkg-config path used etc. Not showing it simply removes all this, and trying to parse out the "important" bits and only show these is probably also brittle. The output generally isn't that spammy normally, so let's just `tee` it.
242 lines
9.6 KiB
Nix
242 lines
9.6 KiB
Nix
{ lib, stdenv, echo_colored, noisily, mkRustcDepArgs, mkRustcFeatureArgs }:
|
|
{
|
|
build
|
|
, buildDependencies
|
|
, codegenUnits
|
|
, colors
|
|
, completeBuildDeps
|
|
, completeDeps
|
|
, crateAuthors
|
|
, crateDescription
|
|
, crateFeatures
|
|
, crateHomepage
|
|
, crateLicense
|
|
, crateLicenseFile
|
|
, crateLinks
|
|
, crateName
|
|
, crateType
|
|
, crateReadme
|
|
, crateRenames
|
|
, crateRepository
|
|
, crateRustVersion
|
|
, crateVersion
|
|
, extraLinkFlags
|
|
, extraRustcOptsForBuildRs
|
|
, libName
|
|
, libPath
|
|
, release
|
|
, verbose
|
|
, workspace_member }:
|
|
let version_ = lib.splitString "-" crateVersion;
|
|
versionPre = lib.optionalString (lib.tail version_ != []) (lib.elemAt version_ 1);
|
|
version = lib.splitVersion (lib.head version_);
|
|
rustcOpts = lib.foldl' (opts: opt: opts + " " + opt)
|
|
(if release then "-C opt-level=3" else "-C debuginfo=2")
|
|
(["-C codegen-units=${toString codegenUnits}"] ++ extraRustcOptsForBuildRs);
|
|
buildDeps = mkRustcDepArgs buildDependencies crateRenames;
|
|
authors = lib.concatStringsSep ":" crateAuthors;
|
|
optLevel = if release then 3 else 0;
|
|
completeDepsDir = lib.concatStringsSep " " completeDeps;
|
|
completeBuildDepsDir = lib.concatStringsSep " " completeBuildDeps;
|
|
envFeatures = lib.concatStringsSep " " (
|
|
map (f: lib.replaceStrings ["-"] ["_"] (lib.toUpper f)) crateFeatures
|
|
);
|
|
in ''
|
|
${echo_colored colors}
|
|
${noisily colors verbose}
|
|
source ${./lib.sh}
|
|
|
|
${lib.optionalString (workspace_member != null) ''
|
|
noisily cd "${workspace_member}"
|
|
''}
|
|
${lib.optionalString (workspace_member == null) ''
|
|
echo_colored "Searching for matching Cargo.toml (${crateName})"
|
|
local cargo_toml_dir=$(matching_cargo_toml_dir "${crateName}")
|
|
if [ -z "$cargo_toml_dir" ]; then
|
|
echo_error "ERROR configuring ${crateName}: No matching Cargo.toml in $(pwd) found." >&2
|
|
exit 23
|
|
fi
|
|
noisily cd "$cargo_toml_dir"
|
|
''}
|
|
|
|
runHook preConfigure
|
|
|
|
symlink_dependency() {
|
|
# $1 is the nix-store path of a dependency
|
|
# $2 is the target path
|
|
i=$1
|
|
ln -s -f $i/lib/*.rlib $2 #*/
|
|
ln -s -f $i/lib/*.so $i/lib/*.dylib $2 #*/
|
|
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
|
|
if [ -e "$i/lib/link" ]; then
|
|
cat $i/lib/link >> target/link.build
|
|
fi
|
|
done
|
|
|
|
# Remove duplicate linker flags from the build dependencies.
|
|
if [[ -e target/link.build ]]; then
|
|
sort -uo target/link.build target/link.build
|
|
fi
|
|
|
|
# Remove duplicate linker flags from the dependencies.
|
|
sort -uo target/link target/link
|
|
tr '\n' ' ' < target/link > target/link_
|
|
|
|
# Remove duplicate linker flags from the that are written
|
|
# to the derivation's output.
|
|
sort -uo target/link.final target/link.final
|
|
|
|
EXTRA_BUILD=""
|
|
BUILD_OUT_DIR=""
|
|
|
|
# Set up Cargo Environment variables: https://doc.rust-lang.org/cargo/reference/environment-variables.html
|
|
export CARGO_PKG_NAME=${crateName}
|
|
export CARGO_PKG_VERSION=${crateVersion}
|
|
export CARGO_PKG_AUTHORS="${authors}"
|
|
export CARGO_PKG_DESCRIPTION="${crateDescription}"
|
|
|
|
export CARGO_CFG_TARGET_ARCH=${stdenv.hostPlatform.rust.platform.arch}
|
|
export CARGO_CFG_TARGET_OS=${stdenv.hostPlatform.rust.platform.os}
|
|
export CARGO_CFG_TARGET_FAMILY="unix"
|
|
export CARGO_CFG_UNIX=1
|
|
export CARGO_CFG_TARGET_ENV="gnu"
|
|
export CARGO_CFG_TARGET_ENDIAN=${if stdenv.hostPlatform.parsed.cpu.significantByte.name == "littleEndian" then "little" else "big"}
|
|
export CARGO_CFG_TARGET_POINTER_WIDTH=${with stdenv.hostPlatform; toString (if isILP32 then 32 else parsed.cpu.bits)}
|
|
export CARGO_CFG_TARGET_VENDOR=${stdenv.hostPlatform.parsed.vendor.name}
|
|
|
|
export CARGO_MANIFEST_DIR=$(pwd)
|
|
export CARGO_MANIFEST_LINKS=${crateLinks}
|
|
export DEBUG="${toString (!release)}"
|
|
export OPT_LEVEL="${toString optLevel}"
|
|
export TARGET="${stdenv.hostPlatform.rust.rustcTargetSpec}"
|
|
export HOST="${stdenv.buildPlatform.rust.rustcTargetSpec}"
|
|
export PROFILE=${if release then "release" else "debug"}
|
|
export OUT_DIR=$(pwd)/target/build/${crateName}.out
|
|
export CARGO_PKG_VERSION_MAJOR=${lib.elemAt version 0}
|
|
export CARGO_PKG_VERSION_MINOR=${lib.elemAt version 1}
|
|
export CARGO_PKG_VERSION_PATCH=${lib.elemAt version 2}
|
|
export CARGO_PKG_VERSION_PRE="${versionPre}"
|
|
export CARGO_PKG_HOMEPAGE="${crateHomepage}"
|
|
export CARGO_PKG_LICENSE="${crateLicense}"
|
|
export CARGO_PKG_LICENSE_FILE="${crateLicenseFile}"
|
|
export CARGO_PKG_README="${crateReadme}"
|
|
export CARGO_PKG_REPOSITORY="${crateRepository}"
|
|
export CARGO_PKG_RUST_VERSION="${crateRustVersion}"
|
|
export NUM_JOBS=$NIX_BUILD_CORES
|
|
export RUSTC="rustc"
|
|
export RUSTDOC="rustdoc"
|
|
|
|
BUILD=""
|
|
if [[ ! -z "${build}" ]] ; then
|
|
BUILD=${build}
|
|
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.build ]; then
|
|
EXTRA_BUILD_FLAGS="$EXTRA_BUILD_FLAGS $(tr '\n' ' ' < target/link.build)"
|
|
fi
|
|
noisily rustc --crate-name build_script_build $BUILD --crate-type bin ${rustcOpts} \
|
|
${mkRustcFeatureArgs crateFeatures} --out-dir target/build/${crateName} --emit=dep-info,link \
|
|
-L dependency=target/buildDeps ${buildDeps} --cap-lints allow $EXTRA_BUILD_FLAGS --color ${colors}
|
|
|
|
mkdir -p target/build/${crateName}.out
|
|
export RUST_BACKTRACE=1
|
|
BUILD_OUT_DIR="-L $OUT_DIR"
|
|
mkdir -p $OUT_DIR
|
|
|
|
(
|
|
# Features should be set as environment variable for build scripts:
|
|
# https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
|
|
for feature in ${envFeatures}; do
|
|
export CARGO_FEATURE_$feature=1
|
|
done
|
|
|
|
target/build/${crateName}/build_script_build | tee target/build/${crateName}.opt
|
|
)
|
|
|
|
set +e
|
|
# We want to support the new prefix invocation syntax which uses two colons
|
|
# See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script
|
|
|
|
EXTRA_BUILD=$(sed -n "s/^cargo::\{0,1\}rustc-flags=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u)
|
|
EXTRA_FEATURES=$(sed -n "s/^cargo::\{0,1\}rustc-cfg=\(.*\)/--cfg \1/p" target/build/${crateName}.opt | tr '\n' ' ')
|
|
EXTRA_LINK_ARGS=$(sed -n "s/^cargo::\{0,1\}rustc-link-arg=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ')
|
|
EXTRA_LINK_ARGS_BINS=$(sed -n "s/^cargo::\{0,1\}rustc-link-arg-bins=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ')
|
|
EXTRA_LINK_ARGS_LIB=$(sed -n "s/^cargo::\{0,1\}rustc-link-arg-lib=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ')
|
|
EXTRA_LINK_LIBS=$(sed -n "s/^cargo::\{0,1\}rustc-link-lib=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ')
|
|
EXTRA_LINK_SEARCH=$(sed -n "s/^cargo::\{0,1\}rustc-link-search=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u)
|
|
|
|
${lib.optionalString (lib.elem "cdylib" crateType) ''
|
|
CRATE_TYPE_IS_CDYLIB="true"
|
|
EXTRA_CDYLIB_LINK_ARGS=$(sed -n "s/^cargo::\{0,1\}rustc-cdylib-link-arg=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ')
|
|
''}
|
|
|
|
# We want to read part of every line that has cargo:rustc-env= prefix and
|
|
# export it as environment variables. This turns out tricky if the lines
|
|
# have spaces: we can't wrap the command in double quotes as that captures
|
|
# all the lines in single output. We can't use while read loop because
|
|
# exporting from inside of it doesn't make it to the outside scope. We
|
|
# can't use xargs as export is a built-in and does not work from it. As a
|
|
# last resort then, we change the IFS so that the for loop does not split
|
|
# on spaces and reset it after we are done. See ticket #199298.
|
|
#
|
|
_OLDIFS="$IFS"
|
|
IFS=$'\n'
|
|
for env in $(sed -n "s/^cargo::\{0,1\}rustc-env=\(.*\)/\1/p" target/build/${crateName}.opt); do
|
|
export "$env"
|
|
done
|
|
IFS="$_OLDIFS"
|
|
|
|
CRATENAME=$(echo ${crateName} | sed -e "s/\(.*\)-sys$/\U\1/" -e "s/-/_/g")
|
|
grep -P "^cargo:(?!:?(rustc-|warning=|rerun-if-changed=|rerun-if-env-changed))" target/build/${crateName}.opt \
|
|
| awk -F= "/^cargo::metadata=/ { gsub(/-/, \"_\", \$2); print \"export \" toupper(\"DEP_$(echo $CRATENAME)_\" \$2) \"=\" \"\\\"\"\$3\"\\\"\"; next }
|
|
/^cargo:/ { sub(/^cargo::?/, \"\", \$1); gsub(/-/, \"_\", \$1); print \"export \" toupper(\"DEP_$(echo $CRATENAME)_\" \$1) \"=\" \"\\\"\"\$2\"\\\"\"; next }" > target/env
|
|
set -e
|
|
fi
|
|
runHook postConfigure
|
|
''
|