nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at devShellTools-shell 259 lines 10 kB view raw
1{ 2 lib, 3 stdenv, 4 echo_colored, 5 noisily, 6 mkRustcDepArgs, 7 mkRustcFeatureArgs, 8}: 9{ 10 build, 11 buildDependencies, 12 codegenUnits, 13 colors, 14 completeBuildDeps, 15 completeDeps, 16 crateAuthors, 17 crateDescription, 18 crateFeatures, 19 crateHomepage, 20 crateLicense, 21 crateLicenseFile, 22 crateLinks, 23 crateName, 24 crateType, 25 crateReadme, 26 crateRenames, 27 crateRepository, 28 crateRustVersion, 29 crateVersion, 30 extraLinkFlags, 31 extraRustcOptsForBuildRs, 32 libName, 33 libPath, 34 release, 35 verbose, 36 workspace_member, 37}: 38let 39 version_ = lib.splitString "-" crateVersion; 40 versionPre = lib.optionalString (lib.tail version_ != [ ]) (lib.elemAt version_ 1); 41 version = lib.splitVersion (lib.head version_); 42 rustcOpts = lib.foldl' (opts: opt: opts + " " + opt) ( 43 if release then "-C opt-level=3" else "-C debuginfo=2" 44 ) ([ "-C codegen-units=${toString codegenUnits}" ] ++ extraRustcOptsForBuildRs); 45 buildDeps = mkRustcDepArgs buildDependencies crateRenames; 46 authors = lib.concatStringsSep ":" crateAuthors; 47 optLevel = if release then 3 else 0; 48 completeDepsDir = lib.concatStringsSep " " completeDeps; 49 completeBuildDepsDir = lib.concatStringsSep " " completeBuildDeps; 50 envFeatures = lib.concatStringsSep " " ( 51 map (f: lib.replaceStrings [ "-" ] [ "_" ] (lib.toUpper f)) crateFeatures 52 ); 53in 54'' 55 ${echo_colored colors} 56 ${noisily colors verbose} 57 source ${./lib.sh} 58 59 ${lib.optionalString (workspace_member != null) '' 60 noisily cd "${workspace_member}" 61 ''} 62 ${lib.optionalString (workspace_member == null) '' 63 echo_colored "Searching for matching Cargo.toml (${crateName})" 64 local cargo_toml_dir=$(matching_cargo_toml_dir "${crateName}") 65 if [ -z "$cargo_toml_dir" ]; then 66 echo_error "ERROR configuring ${crateName}: No matching Cargo.toml in $(pwd) found." >&2 67 exit 23 68 fi 69 noisily cd "$cargo_toml_dir" 70 ''} 71 72 runHook preConfigure 73 74 symlink_dependency() { 75 # $1 is the nix-store path of a dependency 76 # $2 is the target path 77 i=$1 78 ln -s -f $i/lib/*.rlib $2 #*/ 79 ln -s -f $i/lib/*.so $i/lib/*.dylib $2 #*/ 80 if [ -e $i/env ]; then 81 source $i/env 82 fi 83 } 84 85 # The following steps set up the dependencies of the crate. Two 86 # kinds of dependencies are distinguished: build dependencies 87 # (used by the build script) and crate dependencies. For each 88 # dependency we have to: 89 # 90 # - Make its Rust library available to rustc. This is done by 91 # symlinking all library dependencies into a directory that 92 # can be provided to rustc. 93 # - Accumulate linking flags. These flags are largely used for 94 # linking native libraries. 95 # 96 # The crate link flags are added to the `link` and `link.final` 97 # files. The `link` file is used for linkage in the current 98 # crate. The `link.final` file will be copied to the output and can 99 # be used by downstream crates to get the linker flags of this 100 # crate. 101 102 mkdir -p target/{deps,lib,build,buildDeps} 103 chmod uga+w target -R 104 echo ${extraLinkFlags} > target/link 105 echo ${extraLinkFlags} > target/link.final 106 107 # Prepare crate dependencies 108 for i in ${completeDepsDir}; do 109 symlink_dependency $i target/deps 110 if [ -e "$i/lib/link" ]; then 111 cat $i/lib/link >> target/link 112 cat $i/lib/link >> target/link.final 113 fi 114 done 115 116 # Prepare crate build dependencies that are used for the build script. 117 for i in ${completeBuildDepsDir}; do 118 symlink_dependency $i target/buildDeps 119 if [ -e "$i/lib/link" ]; then 120 cat $i/lib/link >> target/link.build 121 fi 122 done 123 124 # Remove duplicate linker flags from the build dependencies. 125 if [[ -e target/link.build ]]; then 126 sort -uo target/link.build target/link.build 127 fi 128 129 # Remove duplicate linker flags from the dependencies. 130 sort -uo target/link target/link 131 tr '\n' ' ' < target/link > target/link_ 132 133 # Remove duplicate linker flags from the that are written 134 # to the derivation's output. 135 sort -uo target/link.final target/link.final 136 137 EXTRA_BUILD="" 138 BUILD_OUT_DIR="" 139 140 # Set up Cargo Environment variables: https://doc.rust-lang.org/cargo/reference/environment-variables.html 141 export CARGO_PKG_NAME=${crateName} 142 export CARGO_PKG_VERSION=${crateVersion} 143 export CARGO_PKG_AUTHORS="${authors}" 144 export CARGO_PKG_DESCRIPTION="${crateDescription}" 145 146 export CARGO_CFG_TARGET_ARCH=${stdenv.hostPlatform.rust.platform.arch} 147 export CARGO_CFG_TARGET_OS=${stdenv.hostPlatform.rust.platform.os} 148 export CARGO_CFG_TARGET_FAMILY="unix" 149 export CARGO_CFG_UNIX=1 150 export CARGO_CFG_TARGET_ENV="gnu" 151 export CARGO_CFG_TARGET_ENDIAN=${ 152 if stdenv.hostPlatform.parsed.cpu.significantByte.name == "littleEndian" then "little" else "big" 153 } 154 export CARGO_CFG_TARGET_POINTER_WIDTH=${ 155 with stdenv.hostPlatform; toString (if isILP32 then 32 else parsed.cpu.bits) 156 } 157 export CARGO_CFG_TARGET_VENDOR=${stdenv.hostPlatform.parsed.vendor.name} 158 159 export CARGO_MANIFEST_DIR=$(pwd) 160 export CARGO_MANIFEST_LINKS=${crateLinks} 161 export DEBUG="${toString (!release)}" 162 export OPT_LEVEL="${toString optLevel}" 163 export TARGET="${stdenv.hostPlatform.rust.rustcTargetSpec}" 164 export HOST="${stdenv.buildPlatform.rust.rustcTargetSpec}" 165 export PROFILE=${if release then "release" else "debug"} 166 export OUT_DIR=$(pwd)/target/build/${crateName}.out 167 export CARGO_PKG_VERSION_MAJOR=${lib.elemAt version 0} 168 export CARGO_PKG_VERSION_MINOR=${lib.elemAt version 1} 169 export CARGO_PKG_VERSION_PATCH=${lib.elemAt version 2} 170 export CARGO_PKG_VERSION_PRE="${versionPre}" 171 export CARGO_PKG_HOMEPAGE="${crateHomepage}" 172 export CARGO_PKG_LICENSE="${crateLicense}" 173 export CARGO_PKG_LICENSE_FILE="${crateLicenseFile}" 174 export CARGO_PKG_README="${crateReadme}" 175 export CARGO_PKG_REPOSITORY="${crateRepository}" 176 export CARGO_PKG_RUST_VERSION="${crateRustVersion}" 177 export NUM_JOBS=$NIX_BUILD_CORES 178 export RUSTC="rustc" 179 export RUSTDOC="rustdoc" 180 181 BUILD="" 182 if [[ ! -z "${build}" ]] ; then 183 BUILD=${build} 184 elif [[ -e "build.rs" ]]; then 185 BUILD="build.rs" 186 fi 187 188 # Compile and run the build script, when available. 189 if [[ ! -z "$BUILD" ]] ; then 190 echo_build_heading "$BUILD" ${libName} 191 mkdir -p target/build/${crateName} 192 EXTRA_BUILD_FLAGS="" 193 if [ -e target/link.build ]; then 194 EXTRA_BUILD_FLAGS="$EXTRA_BUILD_FLAGS $(tr '\n' ' ' < target/link.build)" 195 fi 196 noisily rustc --crate-name build_script_build $BUILD --crate-type bin ${rustcOpts} \ 197 ${mkRustcFeatureArgs crateFeatures} --out-dir target/build/${crateName} --emit=dep-info,link \ 198 -L dependency=target/buildDeps ${buildDeps} --cap-lints allow $EXTRA_BUILD_FLAGS --color ${colors} 199 200 mkdir -p target/build/${crateName}.out 201 export RUST_BACKTRACE=1 202 BUILD_OUT_DIR="-L $OUT_DIR" 203 mkdir -p $OUT_DIR 204 205 ( 206 # Features should be set as environment variable for build scripts: 207 # https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts 208 for feature in ${envFeatures}; do 209 export CARGO_FEATURE_$feature=1 210 done 211 212 target/build/${crateName}/build_script_build | tee target/build/${crateName}.opt 213 ) 214 215 set +e 216 # We want to support the new prefix invocation syntax which uses two colons 217 # See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script 218 219 EXTRA_BUILD=$(sed -n "s/^cargo::\{0,1\}rustc-flags=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u) 220 EXTRA_FEATURES=$(sed -n "s/^cargo::\{0,1\}rustc-cfg=\(.*\)/--cfg \1/p" target/build/${crateName}.opt | tr '\n' ' ') 221 EXTRA_LINK_ARGS=$(sed -n "s/^cargo::\{0,1\}rustc-link-arg=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ') 222 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' ' ') 223 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' ' ') 224 EXTRA_LINK_LIBS=$(sed -n "s/^cargo::\{0,1\}rustc-link-lib=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ') 225 EXTRA_LINK_SEARCH=$(sed -n "s/^cargo::\{0,1\}rustc-link-search=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u) 226 227 ${lib.optionalString (lib.elem "cdylib" crateType) '' 228 CRATE_TYPE_IS_CDYLIB="true" 229 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' ' ') 230 ''} 231 232 # We want to read part of every line that has cargo:rustc-env= prefix and 233 # export it as environment variables. This turns out tricky if the lines 234 # have spaces: we can't wrap the command in double quotes as that captures 235 # all the lines in single output. We can't use while read loop because 236 # exporting from inside of it doesn't make it to the outside scope. We 237 # can't use xargs as export is a built-in and does not work from it. As a 238 # last resort then, we change the IFS so that the for loop does not split 239 # on spaces and reset it after we are done. See ticket #199298. 240 # 241 _OLDIFS="$IFS" 242 IFS=$'\n' 243 for env in $(sed -n "s/^cargo::\{0,1\}rustc-env=\(.*\)/\1/p" target/build/${crateName}.opt); do 244 export "$env" 245 done 246 IFS="$_OLDIFS" 247 248 CRATENAME=$(echo ${crateName} | sed -e "s/\(.*\)-sys$/\U\1/" -e "s/-/_/g") 249 # SemVer allows version numbers to contain alphanumeric characters and `.+-` 250 # which aren't legal bash identifiers. 251 # https://semver.org/#backusnaur-form-grammar-for-valid-semver-versions 252 CRATEVERSION=$(echo ${crateVersion} | sed -e "s/[\.\+-]/_/g") 253 grep -P "^cargo:(?!:?(rustc-|warning=|rerun-if-changed=|rerun-if-env-changed))" target/build/${crateName}.opt \ 254 | awk -F= "/^cargo::metadata=/ { gsub(/-/, \"_\", \$2); print \"export \" toupper(\"DEP_$(echo $CRATENAME)_\" \$2) \"=\" \"\\\"\"\$3\"\\\"\"; next } 255 /^cargo:/ { sub(/^cargo::?/, \"\", \$1); gsub(/-/, \"_\", \$1); print \"export \" toupper(\"DEP_$(echo $CRATENAME)_\" \$1) \"=\" \"\\\"\"\$2\"\\\"\"; print \"export \" toupper(\"DEP_$(echo $CRATENAME)_$(echo $CRATEVERSION)_\" \$1) \"=\" \"\\\"\"\$2\"\\\"\"; next }" > target/env 256 set -e 257 fi 258 runHook postConfigure 259''