From 2eaaf7aafd861c4e92b1ae89b7edbfb383d28a4a Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Thu, 12 Dec 2019 13:55:04 +0100 Subject: [PATCH] buildRustCrate: move common build functions to a dedicated file This means we aren't rebuilding hat file for each crate we are building and the buildPhase expression is a lot easier to comprehent. --- .../rust/build-rust-crate/build-crate.nix | 139 +++++------------- .../rust/build-rust-crate/lib.sh | 117 +++++++++++++++ 2 files changed, 155 insertions(+), 101 deletions(-) create mode 100644 pkgs/build-support/rust/build-rust-crate/lib.sh diff --git a/pkgs/build-support/rust/build-rust-crate/build-crate.nix b/pkgs/build-support/rust/build-rust-crate/build-crate.nix index 70bd84c83466..9f1930fa62b6 100644 --- a/pkgs/build-support/rust/build-rust-crate/build-crate.nix +++ b/pkgs/build-support/rust/build-rust-crate/build-crate.nix @@ -3,128 +3,65 @@ dependencies, crateFeatures, crateRenames, libName, release, libPath, crateType, metadata, crateBin, hasCrateBin, - extraRustcOpts, verbose, colors }: + 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); + baseRustcOpts = + [(if release then "-C opt-level=3" else "-C debuginfo=2")] + ++ ["-C codegen-units=$NIX_BUILD_CORES"] + ++ [(mkRustcDepArgs dependencies crateRenames)] + ++ [crateFeatures] + ++ extraRustcOpts + ++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) "--target ${rust.toRustTarget stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc" + ; rustcMeta = "-C metadata=${metadata} -C extra-filename=-${metadata}"; + + + # build the final rustc arguments that can be different between different + # crates + libRustcOpts = lib.concatStringsSep " " ( + baseRustcOpts + ++ [rustcMeta] + ++ (map (x: "--crate-type ${x}") crateType) + ); + + binRustcOpts = lib.concatStringsSep " " ( + baseRustcOpts + ); + in '' runHook preBuild ${echo_build_heading colors} ${noisily colors verbose} - build_lib() { - lib_src=$1 - echo_build_heading $lib_src ${libName} + # configure & source common build functions + LIB_RUSTC_OPTS="${libRustcOpts}" + BIN_RUSTC_OPTS="${binRustcOpts}" + LIB_EXT="${stdenv.hostPlatform.extensions.sharedLibrary}" + LIB_PATH="${libPath}" + LIB_NAME="${libName}" + source ${./lib.sh} - 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 + setup_link_paths - if [[ -e "${libPath}" ]]; then - build_lib ${libPath} + if [[ -e "$LIB_PATH" ]]; then + build_lib $LIB_PATH elif [[ -e src/lib.rs ]]; then build_lib src/lib.rs - elif [[ -e src/${libName}.rs ]]; then - build_lib src/${libName}.rs + elif [[ -e "src/$LIB_NAME.rs" ]]; then + build_lib src/$LIB_NAME.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 + BIN_PATH="" + search_for_bin_path "$BIN_NAME" '' else '' BIN_PATH='${bin.path}' ''} diff --git a/pkgs/build-support/rust/build-rust-crate/lib.sh b/pkgs/build-support/rust/build-rust-crate/lib.sh new file mode 100644 index 000000000000..24c712468ea6 --- /dev/null +++ b/pkgs/build-support/rust/build-rust-crate/lib.sh @@ -0,0 +1,117 @@ +build_lib() { + lib_src=$1 + echo_build_heading $lib_src ${libName} + + noisily rustc \ + --crate-name $CRATE_NAME \ + $lib_src \ + --out-dir target/lib \ + --emit=dep-info,link \ + -L dependency=target/deps \ + --cap-lints allow \ + $LIB_RUSTC_OPTS \ + $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$LIB_EXT ]; then + EXTRA_LIB="$EXTRA_LIB --extern $CRATE_NAME=target/lib/lib$CRATE_NAME-$metadata$LIB_EXT" + 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 \ + $BIN_RUSTC_OPTS \ + --out-dir target/bin \ + --emit=dep-info,link \ + -L dependency=target/deps \ + $LINK \ + $EXTRA_LIB \ + --cap-lints allow \ + $BUILD_OUT_DIR \ + $EXTRA_BUILD \ + $EXTRA_FEATURES \ + --color ${colors} \ + + if [ "$crate_name_" != "$crate_name" ]; then + mv target/bin/$crate_name_ target/bin/$crate_name + fi +} + +setup_link_paths() { + EXTRA_LIB="" + if [[ -e target/link_ ]]; then + EXTRA_BUILD="$(cat target/link_) $EXTRA_BUILD" + 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 +} + +search_for_bin_path() { + # 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 + + BIN_NAME=$1 + BIN_NAME_=$(echo $BIN_NAME | tr '-' '_') + + # the first two cases are the "new" default IIRC + 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 "$LIB_PATH" -o -e src/lib.rs -o -e "src/$LIB_NAME.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 +}