mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-26 08:53:21 +00:00
6ad22f5b4d
We can get rid of a bunch of workarounds that were in the build script before by just passing on the `crateBin` attribute. Before we converted the list of attributes to a string only to convert it back in bash during the build phase. We can do the entire looping through builds in Nix and thus need no conversion and parsing of attributes over and over again. The big part that still remains bash is the heuristic that cargo introduced and that we can't do at eval time.
150 lines
5.4 KiB
Nix
150 lines
5.4 KiB
Nix
{ lib, stdenv, echo_build_heading, noisily, mkRustcDepArgs, rust }:
|
|
{ crateName,
|
|
dependencies,
|
|
crateFeatures, crateRenames, libName, release, libPath,
|
|
crateType, metadata, crateBin, hasCrateBin,
|
|
extraRustcOpts, verbose, colors }:
|
|
|
|
let
|
|
deps = mkRustcDepArgs dependencies crateRenames;
|
|
rustcOpts =
|
|
lib.foldl' (opts: opt: opts + " " + opt)
|
|
(if release then "-C opt-level=3" else "-C debuginfo=2")
|
|
(["-C codegen-units=$NIX_BUILD_CORES"] ++ extraRustcOpts);
|
|
rustcMeta = "-C metadata=${metadata} -C extra-filename=-${metadata}";
|
|
in ''
|
|
runHook preBuild
|
|
${echo_build_heading colors}
|
|
${noisily colors verbose}
|
|
|
|
build_lib() {
|
|
lib_src=$1
|
|
echo_build_heading $lib_src ${libName}
|
|
|
|
noisily rustc --crate-name $CRATE_NAME $lib_src \
|
|
${lib.strings.concatStrings (map (x: " --crate-type ${x}") crateType)} \
|
|
${rustcOpts} ${rustcMeta} ${crateFeatures} --out-dir target/lib \
|
|
--emit=dep-info,link -L dependency=target/deps ${deps} --cap-lints allow \
|
|
$BUILD_OUT_DIR $EXTRA_BUILD $EXTRA_FEATURES --color ${colors}
|
|
|
|
EXTRA_LIB=" --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-${metadata}.rlib"
|
|
if [ -e target/deps/lib$CRATE_NAME-${metadata}${stdenv.hostPlatform.extensions.sharedLibrary} ]; then
|
|
EXTRA_LIB="$EXTRA_LIB --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-${metadata}${stdenv.hostPlatform.extensions.sharedLibrary}"
|
|
fi
|
|
}
|
|
|
|
build_bin() {
|
|
crate_name=$1
|
|
crate_name_=$(echo $crate_name | tr '-' '_')
|
|
main_file=""
|
|
if [[ ! -z $2 ]]; then
|
|
main_file=$2
|
|
fi
|
|
echo_build_heading $@
|
|
noisily rustc --crate-name $crate_name_ $main_file --crate-type bin ${rustcOpts}\
|
|
${crateFeatures} --out-dir target/bin --emit=dep-info,link -L dependency=target/deps \
|
|
$LINK ${deps}$EXTRA_LIB --cap-lints allow \
|
|
$BUILD_OUT_DIR $EXTRA_BUILD $EXTRA_FEATURES --color ${colors} \
|
|
${if stdenv.hostPlatform != stdenv.buildPlatform then "--target ${rust.toRustTarget stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc" else ""}
|
|
if [ "$crate_name_" != "$crate_name" ]; then
|
|
mv target/bin/$crate_name_ target/bin/$crate_name
|
|
fi
|
|
}
|
|
|
|
|
|
EXTRA_LIB=""
|
|
CRATE_NAME='${lib.replaceStrings ["-"] ["_"] libName}'
|
|
|
|
if [[ -e target/link_ ]]; then
|
|
EXTRA_BUILD="$(cat target/link_) $EXTRA_BUILD"
|
|
fi
|
|
|
|
if [[ -e "${libPath}" ]]; then
|
|
build_lib ${libPath}
|
|
elif [[ -e src/lib.rs ]]; then
|
|
build_lib src/lib.rs
|
|
elif [[ -e src/${libName}.rs ]]; then
|
|
build_lib src/${libName}.rs
|
|
fi
|
|
|
|
echo "$EXTRA_LINK_SEARCH" | while read i; do
|
|
if [[ ! -z "$i" ]]; then
|
|
for library in $i; do
|
|
echo "-L $library" >> target/link
|
|
L=$(echo $library | sed -e "s#$(pwd)/target/build#$lib/lib#")
|
|
echo "-L $L" >> target/link.final
|
|
done
|
|
fi
|
|
done
|
|
echo "$EXTRA_LINK" | while read i; do
|
|
if [[ ! -z "$i" ]]; then
|
|
for library in $i; do
|
|
echo "-l $library" >> target/link
|
|
echo "-l $library" >> target/link.final
|
|
done
|
|
fi
|
|
done
|
|
|
|
if [[ -e target/link ]]; then
|
|
sort -u target/link.final > target/link.final.sorted
|
|
mv target/link.final.sorted target/link.final
|
|
sort -u target/link > target/link.sorted
|
|
mv target/link.sorted target/link
|
|
|
|
tr '\n' ' ' < target/link > target/link_
|
|
LINK=$(cat target/link_)
|
|
fi
|
|
|
|
${lib.optionalString (lib.length crateBin > 0) (lib.concatMapStringsSep "\n" (bin: ''
|
|
mkdir -p target/bin
|
|
BIN_NAME='${bin.name or crateName}'
|
|
${if !bin ? path then ''
|
|
# heuristic to "guess" the correct source file as found in cargo:
|
|
# https://github.com/rust-lang/cargo/blob/90fc9f620190d5fa3c80b0c8c65a1e1361e6b8ae/src/cargo/util/toml/targets.rs#L308-L325
|
|
|
|
# the first two cases are the "new" default IIRC
|
|
BIN_NAME_='${lib.replaceStrings ["-"] ["_"] bin.name}'
|
|
FILES=( "src/bin/$BIN_NAME.rs" "src/bin/$BIN_NAME/main.rs" "src/bin/$BIN_NAME_.rs" "src/bin/$BIN_NAME_/main.rs" "src/bin/main.rs" "src/main.rs" )
|
|
|
|
if ! [ -e "${libPath}" -o -e src/lib.rs -o -e "src/${libName}.rs" ]; then
|
|
# if this is not a library the following path is also valid
|
|
FILES=( "src/$BIN_NAME.rs" "src/$BIN_NAME_.rs" "''${FILES[@]}" )
|
|
fi
|
|
|
|
for file in "''${FILES[@]}";
|
|
do
|
|
echo "checking file $file"
|
|
# first file that exists wins
|
|
if [[ -e "$file" ]]; then
|
|
BIN_PATH="$file"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [[ -z "$BIN_PATH" ]]; then
|
|
echo "failed to find file for binary target: $BIN_NAME" >&2
|
|
exit 1
|
|
fi
|
|
'' else ''
|
|
BIN_PATH='${bin.path}'
|
|
''}
|
|
build_bin "$BIN_NAME" "$BIN_PATH"
|
|
'') crateBin)}
|
|
|
|
# If crateBin is empty and hasCrateBin is not set then we must try to
|
|
# detect some kind of bin target based on some files that might exist.
|
|
${lib.optionalString (lib.length crateBin == 0 && !hasCrateBin) ''
|
|
if [[ -e src/main.rs ]]; then
|
|
mkdir -p target/bin
|
|
build_bin ${crateName} src/main.rs
|
|
fi
|
|
for i in src/bin/*.rs; do #*/
|
|
mkdir -p target/bin
|
|
build_bin "$(basename $i .rs)" "$i"
|
|
done
|
|
''}
|
|
# Remove object files to avoid "wrong ELF type"
|
|
find target -type f -name "*.o" -print0 | xargs -0 rm -f
|
|
runHook postBuild
|
|
''
|