buildDotnetModule: fix structured attributes support
This change refactors internal hooks used by buildDotnetModule to support derivations with structured attributes. Note that this changes variable names that the internal hooks expect.
···11-declare -a projectFile testProjectFile
22-33-# Inherit arguments from derivation
44-dotnetFlags=( ${dotnetFlags[@]-} )
55-dotnetRestoreFlags=( ${dotnetRestoreFlags[@]-} )
66-71dotnetConfigureHook() {
82 echo "Executing dotnetConfigureHook"
93104 runHook preConfigure
1151212- if [ -z "${enableParallelBuilding-}" ]; then
66+ if [[ -z ${nugetSource-} ]]; then
77+ echo
88+ echo "ERROR: no dependencies were specified"
99+ echo 'Hint: set `nugetSource` if using these hooks individually. If this is happening with `buildDotnetModule`, please open an issue.'
1010+ echo
1111+1212+ exit 1
1313+ fi
1414+1515+ local nugetSourceSedQuoted="${nugetSource//[\/\\&$'\n']/\\&}"
1616+ local nugetSourceXMLQuoted="$nugetSource"
1717+ nugetSourceXMLQuoted="${nugetSource//&/\&}"
1818+ nugetSourceXMLQuoted="${nugetSourceXMLQuoted//\"/\"}"
1919+2020+ local -r hostRuntimeId=@runtimeId@
2121+ local -r dynamicLinker=@dynamicLinker@
2222+ local -r libPath=@libPath@
2323+ local -r dotnetRuntimeId="${dotnetRuntimeId-$hostRuntimeId}"
2424+2525+ if [[ -n $__structuredAttrs ]]; then
2626+ local dotnetProjectFilesArray=( "${dotnetProjectFiles[@]}" )
2727+ local dotnetTestProjectFilesArray=( "${dotnetTestProjectFiles[@]}" )
2828+ local dotnetFlagsArray=( "${dotnetFlags[@]}" )
2929+ local dotnetRestoreFlagsArray=( "${dotnetRestoreFlags[@]}" )
3030+ else
3131+ local dotnetProjectFilesArray=($dotnetProjectFiles)
3232+ local dotnetTestProjectFilesArray=($dotnetTestProjectFiles)
3333+ local dotnetFlagsArray=($dotnetFlags)
3434+ local dotnetRestoreFlagsArray=($dotnetRestoreFlags)
3535+ fi
3636+3737+ if [[ -z ${enableParallelBuilding-} ]]; then
1338 local -r parallelFlag="--disable-parallel"
1439 fi
15401641 dotnetRestore() {
1717- local -r project="${1-}"
1818- dotnet restore ${project-} \
4242+ local -r projectFile="${1-}"
4343+ dotnet restore ${1+"$projectFile"} \
1944 -p:ContinuousIntegrationBuild=true \
2045 -p:Deterministic=true \
2121- --runtime "@runtimeId@" \
2222- --source "@nugetSource@/lib" \
4646+ --runtime "$dotnetRuntimeId" \
4747+ --source "$nugetSource/lib" \
2348 ${parallelFlag-} \
2424- ${dotnetRestoreFlags[@]} \
2525- ${dotnetFlags[@]}
4949+ "${dotnetRestoreFlagsArray[@]}" \
5050+ "${dotnetFlagsArray[@]}"
2651 }
27522853 # Generate a NuGet.config file to make sure everything,
2954 # including things like <Sdk /> dependencies, is restored from the proper source
3030-cat <<EOF > "./NuGet.config"
5555+ cat >NuGet.config <<EOF
3156<?xml version="1.0" encoding="utf-8"?>
3257<configuration>
3358 <packageSources>
3459 <clear />
3535- <add key="nugetSource" value="@nugetSource@/lib" />
6060+ <add key="nugetSource" value="$nugetSourceXMLQuoted/lib" />
3661 </packageSources>
3762</configuration>
3863EOF
39644040- # Patch paket.dependencies and paket.lock (if found) to use the proper source. This ensures
4141- # paket restore works correctly
4242- # We use + instead of / in sed to avoid problems with slashes
4343- find -name paket.dependencies -exec sed -i 's+source .*+source @nugetSource@/lib+g' {} \;
4444- find -name paket.lock -exec sed -i 's+remote:.*+remote: @nugetSource@/lib+g' {} \;
6565+ # Patch paket.dependencies and paket.lock (if found) to use the proper
6666+ # source. This ensures paket restore works correctly. Note that the
6767+ # nugetSourceSedQuoted abomination below safely escapes nugetSource string
6868+ # for use as a sed replacement string to avoid issues with slashes and other
6969+ # special characters ('&', '\\' and '\n').
7070+ find -name paket.dependencies -exec sed -i "s/source .*/source $nugetSourceSedQuoted\/lib/g" {} \;
7171+ find -name paket.lock -exec sed -i "s/remote:.*/remote: $nugetSourceSedQuoted\/lib/g" {} \;
45724646- dotnet tool restore --add-source "@nugetSource@/lib"
7373+ dotnet tool restore --add-source "$nugetSource/lib"
47744848- (( "${#projectFile[@]}" == 0 )) && dotnetRestore
7575+ # dotnetGlobalTool is set in buildDotnetGlobalTool to patch dependencies but
7676+ # avoid other project-specific logic. This is a hack, but the old behavior
7777+ # is worse as it relied on a bug: setting projectFile to an empty string
7878+ # made the hooks actually skip all project-specific logic. It’s hard to keep
7979+ # backwards compatibility with this odd behavior now since we are using
8080+ # arrays, so instead we just pass a variable to indicate that we don’t have
8181+ # projects.
8282+ if [[ -z ${dotnetGlobalTool-} ]]; then
8383+ if (( ${#dotnetProjectFilesArray[@]} == 0 )); then
8484+ dotnetRestore
8585+ fi
49865050- for project in ${projectFile[@]} ${testProjectFile[@]-}; do
5151- dotnetRestore "$project"
5252- done
8787+ local projectFile
8888+ for projectFile in "${dotnetProjectFilesArray[@]}" "${dotnetTestProjectFilesArray[@]}"; do
8989+ dotnetRestore "$projectFile"
9090+ done
9191+ fi
53925493 echo "Fixing up native binaries..."
5594 # Find all native binaries and nuget libraries, and fix them up,
5695 # by setting the proper interpreter and rpath to some commonly used libraries
9696+ local binary
5797 for binary in $(find "$HOME/.nuget/packages/" -type f -executable); do
5898 if patchelf --print-interpreter "$binary" >/dev/null 2>/dev/null; then
5999 echo "Found binary: $binary, fixing it up..."
6060- patchelf --set-interpreter "$(cat "@dynamicLinker@")" "$binary"
100100+ patchelf --set-interpreter "$(cat "$dynamicLinker")" "$binary"
6110162102 # This makes sure that if the binary requires some specific runtime dependencies, it can find it.
63103 # This fixes dotnet-built binaries like crossgen2
···68108 --add-needed libssl.so \
69109 "$binary"
701107171- patchelf --set-rpath "@libPath@" "$binary"
111111+ patchelf --set-rpath "$libPath" "$binary"
72112 fi
73113 done
74114
···11-# Inherit arguments from the derivation
22-declare -a derivationMakeWrapperArgs="( ${makeWrapperArgs-} )"
33-makeWrapperArgs=( "${derivationMakeWrapperArgs[@]}" )
44-51# First argument is the executable you want to wrap,
62# the second is the destination for the wrapper.
73wrapDotnetProgram() {
88- local dotnetRootFlags=()
44+ local -r dotnetRuntime=@dotnetRuntime@
55+ local -r wrapperPath=@wrapperPath@
66+77+ local -r dotnetFromEnvScript='dotnetFromEnv() {
88+ local dotnetPath
99+ if command -v dotnet 2>&1 >/dev/null; then
1010+ dotnetPath=$(which dotnet) && \
1111+ dotnetPath=$(realpath "$dotnetPath") && \
1212+ dotnetPath=$(dirname "$dotnetPath") && \
1313+ export DOTNET_ROOT="$dotnetPath"
1414+ fi
1515+}
1616+dotnetFromEnv'
1717+1818+ if [[ -n $__structuredAttrs ]]; then
1919+ local -r dotnetRuntimeDepsArray=( "${dotnetRuntimeDeps[@]}" )
2020+ local -r makeWrapperArgsArray=( "${makeWrapperArgs[@]}" )
2121+ else
2222+ local -r dotnetRuntimeDepsArray=($dotnetRuntimeDeps)
2323+ local -r makeWrapperArgsArray=($makeWrapperArgs)
2424+ fi
9251010- if [ ! "${selfContainedBuild-}" ]; then
1111- if [ "${useDotnetFromEnv-}" ]; then
2626+ local dotnetRuntimeDepsFlags=()
2727+ if (( ${#dotnetRuntimeDepsArray[@]} > 0 )); then
2828+ local libraryPathArray=("${dotnetRuntimeDepsArray[@]/%//lib}")
2929+ local OLDIFS="$IFS" IFS=':'
3030+ dotnetRuntimeDepsFlags+=("--suffix" "LD_LIBRARY_PATH" ":" "${libraryPathArray[*]}")
3131+ IFS="$OLDIFS"
3232+ fi
3333+3434+ local dotnetRootFlagsArray=()
3535+ if [[ -z ${dotnetSelfContainedBuild-} ]]; then
3636+ if [[ -n ${useDotnetFromEnv-} ]]; then
1237 # if dotnet CLI is available, set DOTNET_ROOT based on it. Otherwise set to default .NET runtime
1313- dotnetRootFlags+=("--run" 'command -v dotnet &>/dev/null && export DOTNET_ROOT="$(@dirname@ "$(@realpath@ "$(@which@ dotnet)")")" || export DOTNET_ROOT="@dotnetRuntime@"')
1414- dotnetRootFlags+=("--suffix" "PATH" ":" "@dotnetRuntime@/bin")
3838+ dotnetRootFlagsArray+=("--suffix" "PATH" ":" "$wrapperPath")
3939+ dotnetRootFlagsArray+=("--run" "$dotnetFromEnvScript")
4040+ dotnetRootFlagsArray+=("--set-default" "DOTNET_ROOT" "$dotnetRuntime")
4141+ dotnetRootFlagsArray+=("--suffix" "PATH" ":" "$dotnetRuntime/bin")
1542 else
1616- dotnetRootFlags+=("--set" "DOTNET_ROOT" "@dotnetRuntime@")
1717- dotnetRootFlags+=("--prefix" "PATH" ":" "@dotnetRuntime@/bin")
4343+ dotnetRootFlagsArray+=("--set" "DOTNET_ROOT" "$dotnetRuntime")
4444+ dotnetRootFlagsArray+=("--prefix" "PATH" ":" "$dotnetRuntime/bin")
1845 fi
1946 fi
20472148 makeWrapper "$1" "$2" \
2222- --suffix "LD_LIBRARY_PATH" : "@runtimeDeps@" \
2323- "${dotnetRootFlags[@]}" \
4949+ "${dotnetRuntimeDepsFlags[@]}" \
5050+ "${dotnetRootFlagsArray[@]}" \
2451 "${gappsWrapperArgs[@]}" \
2525- "${makeWrapperArgs[@]}"
5252+ "${makeWrapperArgsArray[@]}"
26532754 echo "installed wrapper to "$2""
2855}
···3057dotnetFixupHook() {
3158 echo "Executing dotnetFixupPhase"
32593333- # check if executables is declared (including empty values, in which case we generate no executables)
3434- if declare -p executables &>/dev/null; then
3535- for executable in ${executables[@]}; do
3636- path="${installPath-$out/lib/$pname}/$executable"
6060+ local -r dotnetInstallPath="${dotnetInstallPath-$out/lib/$pname}"
6161+6262+ local executable executableBasename
6363+6464+ # check if dotnetExecutables is declared (including empty values, in which case we generate no executables)
6565+ if declare -p dotnetExecutables &>/dev/null; then
6666+ if [[ -n $__structuredAttrs ]]; then
6767+ local dotnetExecutablesArray=( "${dotnetExecutables[@]}" )
6868+ else
6969+ local dotnetExecutablesArray=($dotnetExecutables)
7070+ fi
7171+ for executable in "${dotnetExecutablesArray[@]}"; do
7272+ executableBasename=$(basename "$executable")
7373+7474+ local path="$dotnetInstallPath/$executable"
37753876 if test -x "$path"; then
3939- wrapDotnetProgram "$path" "$out/bin/$(basename "$executable")"
7777+ wrapDotnetProgram "$path" "$out/bin/$executableBasename"
4078 else
4179 echo "Specified binary \"$executable\" is either not an executable or does not exist!"
4280 echo "Looked in $path"
···4583 done
4684 else
4785 while IFS= read -d '' executable; do
4848- wrapDotnetProgram "$executable" "$out/bin/$(basename "$executable")" \;
4949- done < <(find "${installPath-$out/lib/$pname}" ! -name "*.dll" -executable -type f -print0)
8686+ executableBasename=$(basename "$executable")
8787+ wrapDotnetProgram "$executable" "$out/bin/$executableBasename" \;
8888+ done < <(find "$dotnetInstallPath" ! -name "*.dll" -executable -type f -print0)
5089 fi
51905291 echo "Finished dotnetFixupPhase"
···11+# This file was automatically generated by passthru.fetch-deps.
22+# Please dont edit it manually, your changes might get overwritten!
33+44+{ fetchNuGet }: [
55+]
···11+# This file was automatically generated by passthru.fetch-deps.
22+# Please dont edit it manually, your changes might get overwritten!
33+44+{ fetchNuGet }: [
55+]