···1-{ lib, stdenv, echo_build_heading, noisily, mkRustcDepArgs }:
2{ build
3, buildDependencies
4, colors
···31 completeDepsDir = lib.concatStringsSep " " completeDeps;
32 completeBuildDepsDir = lib.concatStringsSep " " completeBuildDeps;
33in ''
34- cd ${workspace_member}
000000000000000035 runHook preConfigure
36- ${echo_build_heading colors}
37- ${noisily colors verbose}
38 symlink_dependency() {
39 # $1 is the nix-store path of a dependency
40 # $2 is the target path
41 i=$1
42 ln -s -f $i/lib/*.rlib $2 #*/
43 ln -s -f $i/lib/*.so $i/lib/*.dylib $2 #*/
44- if [ -e "$i/lib/link" ]; then
45- cat $i/lib/link >> target/link
46- cat $i/lib/link >> target/link.final
47- fi
48 if [ -e $i/env ]; then
49 source $i/env
50 fi
51 }
520000000000000000053 mkdir -p target/{deps,lib,build,buildDeps}
54 chmod uga+w target -R
55 echo ${extraLinkFlags} > target/link
56 echo ${extraLinkFlags} > target/link.final
0057 for i in ${completeDepsDir}; do
58 symlink_dependency $i target/deps
000059 done
0060 for i in ${completeBuildDepsDir}; do
61- symlink_dependency $i target/buildDeps
00062 done
63- if [[ -e target/link ]]; then
64- sort -u target/link > target/link.sorted
65- mv target/link.sorted target/link
66- sort -u target/link.final > target/link.final.sorted
67- mv target/link.final.sorted target/link.final
68- tr '\n' ' ' < target/link > target/link_
69 fi
00000000070 EXTRA_BUILD=""
71 BUILD_OUT_DIR=""
72 export CARGO_PKG_NAME=${crateName}
···105 elif [[ -e "build.rs" ]]; then
106 BUILD="build.rs"
107 fi
00108 if [[ ! -z "$BUILD" ]] ; then
109 echo_build_heading "$BUILD" ${libName}
110 mkdir -p target/build/${crateName}
111 EXTRA_BUILD_FLAGS=""
112- if [ -e target/link_ ]; then
113- EXTRA_BUILD_FLAGS=$(cat target/link_)
114- fi
115 if [ -e target/link.build ]; then
116- EXTRA_BUILD_FLAGS="$EXTRA_BUILD_FLAGS $(cat target/link.build)"
117 fi
118 noisily rustc --crate-name build_script_build $BUILD --crate-type bin ${rustcOpts} \
119 ${crateFeatures} --out-dir target/build/${crateName} --emit=dep-info,link \
···127 set +e
128 EXTRA_BUILD=$(sed -n "s/^cargo:rustc-flags=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u)
129 EXTRA_FEATURES=$(sed -n "s/^cargo:rustc-cfg=\(.*\)/--cfg \1/p" target/build/${crateName}.opt | tr '\n' ' ')
130- EXTRA_LINK=$(sed -n "s/^cargo:rustc-link-lib=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u)
131 EXTRA_LINK_SEARCH=$(sed -n "s/^cargo:rustc-link-search=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u)
132133 for env in $(sed -n "s/^cargo:rustc-env=\(.*\)/\1/p" target/build/${crateName}.opt); do
···1+{ lib, stdenv, echo_colored, noisily, mkRustcDepArgs }:
2{ build
3, buildDependencies
4, colors
···31 completeDepsDir = lib.concatStringsSep " " completeDeps;
32 completeBuildDepsDir = lib.concatStringsSep " " completeBuildDeps;
33in ''
34+ ${echo_colored colors}
35+ ${noisily colors verbose}
36+ source ${./lib.sh}
37+38+ ${lib.optionalString (workspace_member != null) ''
39+ noisily cd "${workspace_member}"
40+''}
41+ ${lib.optionalString (workspace_member == null) ''
42+ echo_colored "Searching for matching Cargo.toml (${crateName})"
43+ local cargo_toml_dir=$(matching_cargo_toml_dir "${crateName}")
44+ if [ -z "$cargo_toml_dir" ]; then
45+ echo_error "ERROR configuring ${crateName}: No matching Cargo.toml in $(pwd) found." >&2
46+ exit 23
47+ fi
48+ noisily cd "$cargo_toml_dir"
49+''}
50+51 runHook preConfigure
52+053 symlink_dependency() {
54 # $1 is the nix-store path of a dependency
55 # $2 is the target path
56 i=$1
57 ln -s -f $i/lib/*.rlib $2 #*/
58 ln -s -f $i/lib/*.so $i/lib/*.dylib $2 #*/
000059 if [ -e $i/env ]; then
60 source $i/env
61 fi
62 }
6364+ # The following steps set up the dependencies of the crate. Two
65+ # kinds of dependencies are distinguished: build dependencies
66+ # (used by the build script) and crate dependencies. For each
67+ # dependency we have to:
68+ #
69+ # - Make its Rust library available to rustc. This is done by
70+ # symlinking all library dependencies into a directory that
71+ # can be provided to rustc.
72+ # - Accumulate linking flags. These flags are largely used for
73+ # linking native libraries.
74+ #
75+ # The crate link flags are added to the `link` and `link.final`
76+ # files. The `link` file is used for linkage in the current
77+ # crate. The `link.final` file will be copied to the output and can
78+ # be used by downstream crates to get the linker flags of this
79+ # crate.
80+81 mkdir -p target/{deps,lib,build,buildDeps}
82 chmod uga+w target -R
83 echo ${extraLinkFlags} > target/link
84 echo ${extraLinkFlags} > target/link.final
85+86+ # Prepare crate dependencies
87 for i in ${completeDepsDir}; do
88 symlink_dependency $i target/deps
89+ if [ -e "$i/lib/link" ]; then
90+ cat $i/lib/link >> target/link
91+ cat $i/lib/link >> target/link.final
92+ fi
93 done
94+95+ # Prepare crate build dependencies that are used for the build script.
96 for i in ${completeBuildDepsDir}; do
97+ symlink_dependency $i target/buildDeps
98+ if [ -e "$i/lib/link" ]; then
99+ cat $i/lib/link >> target/link.build
100+ fi
101 done
102+103+ # Remove duplicate linker flags from the build dependencies.
104+ if [[ -e target/link.build ]]; then
105+ sort -uo target/link.build target/link.build
00106 fi
107+108+ # Remove duplicate linker flags from the dependencies.
109+ sort -uo target/link target/link
110+ tr '\n' ' ' < target/link > target/link_
111+112+ # Remove duplicate linker flags from the that are written
113+ # to the derivation's output.
114+ sort -uo target/link.final target/link.final
115+116 EXTRA_BUILD=""
117 BUILD_OUT_DIR=""
118 export CARGO_PKG_NAME=${crateName}
···151 elif [[ -e "build.rs" ]]; then
152 BUILD="build.rs"
153 fi
154+155+ # Compile and run the build script, when available.
156 if [[ ! -z "$BUILD" ]] ; then
157 echo_build_heading "$BUILD" ${libName}
158 mkdir -p target/build/${crateName}
159 EXTRA_BUILD_FLAGS=""
000160 if [ -e target/link.build ]; then
161+ EXTRA_BUILD_FLAGS="$EXTRA_BUILD_FLAGS $(tr '\n' ' ' < target/link.build)"
162 fi
163 noisily rustc --crate-name build_script_build $BUILD --crate-type bin ${rustcOpts} \
164 ${crateFeatures} --out-dir target/build/${crateName} --emit=dep-info,link \
···172 set +e
173 EXTRA_BUILD=$(sed -n "s/^cargo:rustc-flags=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u)
174 EXTRA_FEATURES=$(sed -n "s/^cargo:rustc-cfg=\(.*\)/--cfg \1/p" target/build/${crateName}.opt | tr '\n' ' ')
175+ EXTRA_LINK=$(sed -n "s/^cargo:rustc-link-lib=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ')
176 EXTRA_LINK_SEARCH=$(sed -n "s/^cargo:rustc-link-search=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u)
177178 for env in $(sed -n "s/^cargo:rustc-env=\(.*\)/\1/p" target/build/${crateName}.opt); do
···14 fi
15 if [[ "$(ls -A target/lib)" ]]; then
16 mkdir -p $lib/lib
17- cp target/lib/* $lib/lib #*/
18 for library in $lib/lib/*.so $lib/lib/*.dylib; do #*/
19 ln -s $library $(echo $library | sed -e "s/-${metadata}//")
20 done
···26 if [[ -d target/bin ]]; then
27 if [[ "$(ls -A target/bin)" ]]; then
28 mkdir -p $out/bin
29- cp -P target/bin/* $out/bin # */
30 fi
31 fi
32 runHook postInstall
···14 fi
15 if [[ "$(ls -A target/lib)" ]]; then
16 mkdir -p $lib/lib
17+ cp -r target/lib/* $lib/lib #*/
18 for library in $lib/lib/*.so $lib/lib/*.dylib; do #*/
19 ln -s $library $(echo $library | sed -e "s/-${metadata}//")
20 done
···26 if [[ -d target/bin ]]; then
27 if [[ "$(ls -A target/bin)" ]]; then
28 mkdir -p $out/bin
29+ cp -rP target/bin/* $out/bin # */
30 fi
31 fi
32 runHook postInstall
···1+echo_build_heading() {
2+ if (( $# == 1 )); then
3+ echo_colored "Building $1"
4+ else
5+ echo_colored "Building $1 ($2)"
6+ fi
7+}
8+9build_lib() {
10 lib_src=$1
11 echo_build_heading $lib_src ${libName}
···14 --crate-name $CRATE_NAME \
15 $lib_src \
16 --out-dir target/lib \
017 -L dependency=target/deps \
18 --cap-lints allow \
19 $LIB_RUSTC_OPTS \
···44 --crate-type bin \
45 $BIN_RUSTC_OPTS \
46 --out-dir target/bin \
047 -L dependency=target/deps \
48 $LINK \
49 $EXTRA_LIB \
···77 build_bin_test "$derived_crate_name" "$file"
78}
7980+# Add additional link options that were provided by the build script.
81setup_link_paths() {
82 EXTRA_LIB=""
83 if [[ -e target/link_ ]]; then
···103 done
104105 if [[ -e target/link ]]; then
00000106 tr '\n' ' ' < target/link > target/link_
107 LINK=$(cat target/link_)
108 fi
···134 done
135136 if [[ -z "$BIN_PATH" ]]; then
137+ echo_error "ERROR: failed to find file for binary target: $BIN_NAME" >&2
138 exit 1
139 fi
140}
141+142+# Extracts cargo_toml_path of the matching crate.
143+matching_cargo_toml_path() {
144+ local manifest_path="$1"
145+ local expected_crate_name="$2"
146+147+ # If the Cargo.toml is not a workspace root,
148+ # it will only contain one package in ".packages"
149+ # because "--no-deps" suppressed dependency resolution.
150+ #
151+ # But to make it more general, we search for a matching
152+ # crate in all packages and use the manifest path that
153+ # is referenced there.
154+ cargo metadata --no-deps --format-version 1 \
155+ --manifest-path "$manifest_path" \
156+ | jq -r '.packages[]
157+ | select( .name == "'$expected_crate_name'")
158+ | .manifest_path'
159+}
160+161+# Find a Cargo.toml in the current or any sub directory
162+# with a matching crate name.
163+matching_cargo_toml_dir() {
164+ local expected_crate_name="$1"
165+166+ find -L -name Cargo.toml | sort | while read manifest_path; do
167+ echo "...checking manifest_path $manifest_path" >&2
168+ local matching_path="$(matching_cargo_toml_path "$manifest_path" "$expected_crate_name")"
169+ if [ -n "${matching_path}" ]; then
170+ echo "$(dirname $matching_path)"
171+ break
172+ fi
173+ done
174+}
···1{ lib }:
2+3+let echo_colored_body = start_escape:
4+ # Body of a function that behaves like "echo" but
5+ # has the output colored by the given start_escape
6+ # sequence. E.g.
7+ #
8+ # * echo_x "Building ..."
9+ # * echo_x -n "Running "
10+ #
11+ # This is more complicated than apparent at first sight
12+ # because:
13+ # * The color markers and the text must be print
14+ # in the same echo statement. Otherise, other
15+ # intermingled text from concurrent builds will
16+ # be colored as well.
17+ # * We need to preserve the trailing newline of the
18+ # echo if and only if it is present. Bash likes
19+ # to strip those if we capture the output of echo
20+ # in a variable.
21+ # * Leading "-" will be interpreted by test as an
22+ # option for itself. Therefore, we prefix it with
23+ # an x in `[[ "x$1" =~ ^x- ]]`.
24+ ''
25+ local echo_args="";
26+ while [[ "x$1" =~ ^x- ]]; do
27+ echo_args+=" $1"
28+ shift
29+ done
30+31+ local start_escape="$(printf '${start_escape}')"
32+ local reset="$(printf '\033[0m')"
33+ echo $echo_args $start_escape"$@"$reset
34+ '';
35+ echo_conditional_colored_body = colors: start_escape:
36+ if colors == "always"
37+ then (echo_colored_body start_escape)
38+ else ''echo "$@"'';
39+in {
40+ echo_colored = colors: ''
41+ echo_colored() {
42+ ${echo_conditional_colored_body colors ''\033[0;1;32m''}
43 }
44+45+ echo_error() {
46+ ${echo_conditional_colored_body colors ''\033[0;1;31m''}
47+ }
48+ '';
49+50 noisily = colors: verbose: ''
51 noisily() {
00000052 ${lib.optionalString verbose ''
53+ echo_colored -n "Running "
54 echo $@
55 ''}
56 $@