at master 450 lines 13 kB view raw
1# shellcheck shell=bash 2 3_dotnetIsSolution() { 4 dotnet sln ${1:+"$1"} list 2>/dev/null 5} 6 7dotnetConfigurePhase() { 8 echo "Executing dotnetConfigureHook" 9 10 runHook preConfigure 11 12 local -a projectFiles flags runtimeIds 13 concatTo projectFiles dotnetProjectFiles dotnetTestProjectFiles 14 concatTo flags dotnetFlags dotnetRestoreFlags 15 concatTo runtimeIds dotnetRuntimeIds 16 17 if [[ -z ${enableParallelBuilding-} ]]; then 18 flags+=(--disable-parallel) 19 fi 20 21 if [[ -v dotnetSelfContainedBuild ]]; then 22 if [[ -n $dotnetSelfContainedBuild ]]; then 23 flags+=("-p:SelfContained=true") 24 else 25 flags+=("-p:SelfContained=false") 26 fi 27 fi 28 29 dotnetRestore() { 30 local -r projectFile="${1-}" 31 for runtimeId in "${runtimeIds[@]}"; do 32 dotnet restore ${1+"$projectFile"} \ 33 -p:ContinuousIntegrationBuild=true \ 34 -p:Deterministic=true \ 35 -p:NuGetAudit=false \ 36 --runtime "$runtimeId" \ 37 "${flags[@]}" 38 done 39 } 40 41 if [[ -f .config/dotnet-tools.json || -f dotnet-tools.json ]]; then 42 dotnet tool restore 43 fi 44 45 # dotnetGlobalTool is set in buildDotnetGlobalTool to patch dependencies but 46 # avoid other project-specific logic. This is a hack, but the old behavior 47 # is worse as it relied on a bug: setting projectFile to an empty string 48 # made the hooks actually skip all project-specific logic. It’s hard to keep 49 # backwards compatibility with this odd behavior now since we are using 50 # arrays, so instead we just pass a variable to indicate that we don’t have 51 # projects. 52 if [[ -z ${dotnetGlobalTool-} ]]; then 53 if (( ${#projectFiles[@]} == 0 )); then 54 dotnetRestore 55 fi 56 57 local projectFile 58 for projectFile in "${projectFiles[@]}"; do 59 dotnetRestore "$projectFile" 60 done 61 fi 62 63 runHook postConfigure 64 65 echo "Finished dotnetConfigureHook" 66} 67 68if [[ -z "${dontDotnetConfigure-}" && -z "${configurePhase-}" ]]; then 69 configurePhase=dotnetConfigurePhase 70fi 71 72dotnetBuildPhase() { 73 echo "Executing dotnetBuildHook" 74 75 runHook preBuild 76 77 local -r dotnetBuildType="${dotnetBuildType-Release}" 78 79 local -a projectFiles flags runtimeIds 80 concatTo projectFiles dotnetProjectFiles dotnetTestProjectFiles 81 concatTo flags dotnetFlags dotnetBuildFlags 82 concatTo runtimeIds dotnetRuntimeIds 83 84 if [[ -n "${enableParallelBuilding-}" ]]; then 85 local -r maxCpuFlag="$NIX_BUILD_CORES" 86 local -r parallelBuildFlag="true" 87 else 88 local -r maxCpuFlag="1" 89 local -r parallelBuildFlag="false" 90 fi 91 92 if [[ -v dotnetSelfContainedBuild ]]; then 93 if [[ -n $dotnetSelfContainedBuild ]]; then 94 flags+=("-p:SelfContained=true") 95 else 96 flags+=("-p:SelfContained=false") 97 fi 98 fi 99 100 if [[ -n ${dotnetUseAppHost-} ]]; then 101 flags+=("-p:UseAppHost=true") 102 fi 103 104 if [[ -n ${version-} ]]; then 105 flags+=("-p:InformationalVersion=$version") 106 fi 107 108 if [[ -n ${versionForDotnet-} ]]; then 109 flags+=("-p:Version=$versionForDotnet") 110 fi 111 112 dotnetBuild() { 113 local -r projectFile="${1-}" 114 115 local useRuntime= 116 _dotnetIsSolution "$projectFile" || useRuntime=1 117 118 for runtimeId in "${runtimeIds[@]}"; do 119 local runtimeIdFlags=() 120 if [[ -n $useRuntime ]]; then 121 runtimeIdFlags+=("--runtime" "$runtimeId") 122 fi 123 124 dotnet build ${1+"$projectFile"} \ 125 -maxcpucount:"$maxCpuFlag" \ 126 -p:BuildInParallel="$parallelBuildFlag" \ 127 -p:ContinuousIntegrationBuild=true \ 128 -p:Deterministic=true \ 129 -p:OverwriteReadOnlyFiles=true \ 130 --configuration "$dotnetBuildType" \ 131 --no-restore \ 132 "${runtimeIdFlags[@]}" \ 133 "${flags[@]}" 134 done 135 } 136 137 if (( ${#projectFiles[@]} == 0 )); then 138 dotnetBuild 139 fi 140 141 local projectFile 142 for projectFile in "${projectFiles[@]}"; do 143 dotnetBuild "$projectFile" 144 done 145 146 runHook postBuild 147 148 echo "Finished dotnetBuildHook" 149} 150 151if [[ -z ${dontDotnetBuild-} && -z ${buildPhase-} ]]; then 152 buildPhase=dotnetBuildPhase 153fi 154 155dotnetCheckPhase() { 156 echo "Executing dotnetCheckHook" 157 158 runHook preCheck 159 160 local -r dotnetBuildType="${dotnetBuildType-Release}" 161 162 local -a projectFiles testProjectFiles testFilters disabledTests flags runtimeIds runtimeDeps 163 concatTo projectFiles dotnetProjectFiles 164 concatTo testProjectFiles dotnetTestProjectFiles 165 concatTo testFilters dotnetTestFilters 166 concatTo disabledTests dotnetDisabledTests 167 concatTo flags dotnetFlags dotnetTestFlags 168 concatTo runtimeIds dotnetRuntimeIds 169 concatTo runtimeDeps dotnetRuntimeDeps 170 171 if (( ${#disabledTests[@]} > 0 )); then 172 local disabledTestsFilters=("${disabledTests[@]/#/FullyQualifiedName!=}") 173 testFilters=( "${testFilters[@]}" "${disabledTestsFilters[@]//,/%2C}" ) 174 fi 175 176 if (( ${#testFilters[@]} > 0 )); then 177 local OLDIFS="$IFS" IFS='&' 178 flags+=("--filter:${testFilters[*]}") 179 IFS="$OLDIFS" 180 fi 181 182 local libraryPath="${LD_LIBRARY_PATH-}" 183 if (( ${#runtimeDeps[@]} > 0 )); then 184 local libraryPaths=("${runtimeDeps[@]/%//lib}") 185 local OLDIFS="$IFS" IFS=':' 186 libraryPath="${libraryPaths[*]}${libraryPath:+':'}$libraryPath" 187 IFS="$OLDIFS" 188 fi 189 190 if [[ -n ${enableParallelBuilding-} ]]; then 191 local -r maxCpuFlag="$NIX_BUILD_CORES" 192 else 193 local -r maxCpuFlag="1" 194 fi 195 196 local projectFile runtimeId 197 for projectFile in "${testProjectFiles[@]-${projectFiles[@]}}"; do 198 local useRuntime= 199 _dotnetIsSolution "$projectFile" || useRuntime=1 200 201 for runtimeId in "${runtimeIds[@]}"; do 202 local runtimeIdFlags=() 203 if [[ -n $useRuntime ]]; then 204 runtimeIdFlags=("--runtime" "$runtimeId") 205 fi 206 207 LD_LIBRARY_PATH=$libraryPath \ 208 dotnet test "$projectFile" \ 209 -maxcpucount:"$maxCpuFlag" \ 210 -p:ContinuousIntegrationBuild=true \ 211 -p:Deterministic=true \ 212 --configuration "$dotnetBuildType" \ 213 --no-restore \ 214 --no-build \ 215 --logger "console;verbosity=normal" \ 216 "${runtimeIdFlags[@]}" \ 217 "${flags[@]}" 218 done 219 done 220 221 runHook postCheck 222 223 echo "Finished dotnetCheckHook" 224} 225 226if [[ -z "${dontDotnetCheck-}" && -z "${checkPhase-}" ]]; then 227 checkPhase=dotnetCheckPhase 228fi 229 230# For compatibility, convert makeWrapperArgs to an array unless we are using 231# structured attributes. That is, we ensure that makeWrapperArgs is always an 232# array. 233# See https://github.com/NixOS/nixpkgs/blob/858f4db3048c5be3527e183470e93c1a72c5727c/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-fixup-hook.sh#L1-L3 234# and https://github.com/NixOS/nixpkgs/pull/313005#issuecomment-2175482920 235# shellcheck disable=2206 236if [[ -z $__structuredAttrs ]]; then 237 makeWrapperArgs=( ${makeWrapperArgs-} ) 238fi 239 240# First argument is the executable you want to wrap, 241# the second is the destination for the wrapper. 242wrapDotnetProgram() { 243 local -r dotnetRuntime=@dotnetRuntime@ 244 local -r wrapperPath=@wrapperPath@ 245 246 # shellcheck disable=2016 247 local -r dotnetFromEnvScript='dotnetFromEnv() { 248 local dotnetPath 249 if command -v dotnet 2>&1 >/dev/null; then 250 dotnetPath=$(which dotnet) && \ 251 dotnetPath=$(realpath "$dotnetPath") && \ 252 dotnetPath=$(dirname "$dotnetPath") && \ 253 export DOTNET_ROOT="$dotnetPath" 254 fi 255} 256dotnetFromEnv' 257 258 # shellcheck disable=2206 259 local -a runtimeDeps 260 concatTo runtimeDeps dotnetRuntimeDeps 261 262 local wrapperFlags=() 263 if (( ${#runtimeDeps[@]} > 0 )); then 264 local libraryPath=("${runtimeDeps[@]/%//lib}") 265 local OLDIFS="$IFS" IFS=':' 266 wrapperFlags+=("--suffix" "LD_LIBRARY_PATH" ":" "${libraryPath[*]}") 267 IFS="$OLDIFS" 268 fi 269 270 if [[ -z ${dotnetSelfContainedBuild-} ]]; then 271 if [[ -n ${useDotnetFromEnv-} ]]; then 272 # if dotnet CLI is available, set DOTNET_ROOT based on it. Otherwise set to default .NET runtime 273 wrapperFlags+=("--suffix" "PATH" ":" "$wrapperPath") 274 wrapperFlags+=("--run" "$dotnetFromEnvScript") 275 if [[ -n $dotnetRuntime ]]; then 276 wrapperFlags+=("--set-default" "DOTNET_ROOT" "$dotnetRuntime/share/dotnet") 277 wrapperFlags+=("--suffix" "PATH" ":" "$dotnetRuntime/bin") 278 fi 279 elif [[ -n $dotnetRuntime ]]; then 280 wrapperFlags+=("--set" "DOTNET_ROOT" "$dotnetRuntime/share/dotnet") 281 wrapperFlags+=("--prefix" "PATH" ":" "$dotnetRuntime/bin") 282 fi 283 fi 284 285 # shellcheck disable=2154 286 makeWrapper "$1" "$2" \ 287 "${wrapperFlags[@]}" \ 288 "${gappsWrapperArgs[@]}" \ 289 "${makeWrapperArgs[@]}" 290 291 echo "installed wrapper to $2" 292} 293 294dotnetFixupPhase() { 295 local -r dotnetInstallPath="${dotnetInstallPath-$out/lib/$pname}" 296 297 local executable executableBasename 298 299 # check if dotnetExecutables is declared (including empty values, in which case we generate no executables) 300 # shellcheck disable=2154 301 if declare -p dotnetExecutables &>/dev/null; then 302 # shellcheck disable=2206 303 local -a executables 304 concatTo executables dotnetExecutables 305 for executable in "${executables[@]}"; do 306 executableBasename=$(basename "$executable") 307 308 local path="$dotnetInstallPath/$executable" 309 310 if test -x "$path"; then 311 wrapDotnetProgram "$path" "$out/bin/$executableBasename" 312 else 313 echo "Specified binary \"$executable\" is either not an executable or does not exist!" 314 echo "Looked in $path" 315 exit 1 316 fi 317 done 318 else 319 while IFS= read -r -d '' executable; do 320 executableBasename=$(basename "$executable") 321 wrapDotnetProgram "$executable" "$out/bin/$executableBasename" \; 322 done < <(find "$dotnetInstallPath" ! -name "*.dll" -executable -type f -print0) 323 fi 324} 325 326if [[ -z "${dontFixup-}" && -z "${dontDotnetFixup-}" ]]; then 327 appendToVar preFixupPhases dotnetFixupPhase 328fi 329 330dotnetInstallPhase() { 331 echo "Executing dotnetInstallHook" 332 333 runHook preInstall 334 335 local -r dotnetInstallPath="${dotnetInstallPath-$out/lib/$pname}" 336 local -r dotnetBuildType="${dotnetBuildType-Release}" 337 338 local -a projectFiles flags installFlags packFlags runtimeIds 339 concatTo projectFiles dotnetProjectFiles 340 concatTo flags dotnetFlags 341 concatTo installFlags dotnetInstallFlags 342 concatTo packFlags dotnetPackFlags 343 concatTo runtimeIds dotnetRuntimeIds 344 345 if [[ -v dotnetSelfContainedBuild ]]; then 346 if [[ -n $dotnetSelfContainedBuild ]]; then 347 installFlags+=("--self-contained") 348 else 349 installFlags+=("--no-self-contained") 350 # https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained 351 # Trimming is only available for self-contained build, so force disable it here 352 installFlags+=("-p:PublishTrimmed=false") 353 fi 354 fi 355 356 if [[ -n ${dotnetUseAppHost-} ]]; then 357 installFlags+=("-p:UseAppHost=true") 358 fi 359 360 if [[ -n ${enableParallelBuilding-} ]]; then 361 local -r maxCpuFlag="$NIX_BUILD_CORES" 362 else 363 local -r maxCpuFlag="1" 364 fi 365 366 dotnetPublish() { 367 local -r projectFile="${1-}" 368 369 local useRuntime= 370 _dotnetIsSolution "$projectFile" || useRuntime=1 371 372 for runtimeId in "${runtimeIds[@]}"; do 373 local runtimeIdFlags=() 374 if [[ -n $useRuntime ]]; then 375 runtimeIdFlags+=("--runtime" "$runtimeId") 376 fi 377 378 dotnet publish ${1+"$projectFile"} \ 379 -maxcpucount:"$maxCpuFlag" \ 380 -p:ContinuousIntegrationBuild=true \ 381 -p:Deterministic=true \ 382 -p:OverwriteReadOnlyFiles=true \ 383 --output "$dotnetInstallPath" \ 384 --configuration "$dotnetBuildType" \ 385 --no-restore \ 386 --no-build \ 387 "${runtimeIdFlags[@]}" \ 388 "${flags[@]}" \ 389 "${installFlags[@]}" 390 done 391 } 392 393 dotnetPack() { 394 local -r projectFile="${1-}" 395 396 local useRuntime= 397 _dotnetIsSolution "$projectFile" || useRuntime=1 398 399 for runtimeId in "${runtimeIds[@]}"; do 400 local runtimeIdFlags=() 401 if [[ -n $useRuntime ]]; then 402 runtimeIdFlags+=("--runtime" "$runtimeId") 403 # set RuntimeIdentifier because --runtime is broken: 404 # https://github.com/dotnet/sdk/issues/13983 405 runtimeIdFlags+=(-p:RuntimeIdentifier="$runtimeId") 406 fi 407 408 dotnet pack ${1+"$projectFile"} \ 409 -maxcpucount:"$maxCpuFlag" \ 410 -p:ContinuousIntegrationBuild=true \ 411 -p:Deterministic=true \ 412 -p:OverwriteReadOnlyFiles=true \ 413 --output "$out/share/nuget/source" \ 414 --configuration "$dotnetBuildType" \ 415 --no-restore \ 416 --no-build \ 417 "${runtimeIdFlags[@]}" \ 418 "${flags[@]}" \ 419 "${packFlags[@]}" 420 done 421 } 422 423 if (( ${#projectFiles[@]} == 0 )); then 424 dotnetPublish 425 else 426 local projectFile 427 for projectFile in "${projectFiles[@]}"; do 428 dotnetPublish "$projectFile" 429 done 430 fi 431 432 if [[ -n ${packNupkg-} ]]; then 433 if (( ${#projectFiles[@]} == 0 )); then 434 dotnetPack 435 else 436 local projectFile 437 for projectFile in "${projectFiles[@]}"; do 438 dotnetPack "$projectFile" 439 done 440 fi 441 fi 442 443 runHook postInstall 444 445 echo "Finished dotnetInstallHook" 446} 447 448if [[ -z "${dontDotnetInstall-}" && -z "${installPhase-}" ]]; then 449 installPhase=dotnetInstallPhase 450fi