nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 412 lines 14 kB view raw
1{ 2 go, 3 cacert, 4 gitMinimal, 5 lib, 6 stdenv, 7}: 8 9lib.extendMkDerivation { 10 constructDrv = stdenv.mkDerivation; 11 excludeDrvArgNames = [ 12 "overrideModAttrs" 13 ]; 14 extendDrvArgs = 15 finalAttrs: 16 { 17 nativeBuildInputs ? [ ], # Native build inputs used for the derivation. 18 passthru ? { }, 19 20 # A function to override the `goModules` derivation. 21 overrideModAttrs ? (finalAttrs: previousAttrs: { }), 22 23 # Directory to the `go.mod` and `go.sum` relative to the `src`. 24 modRoot ? "./", 25 26 # The SRI hash of the vendored dependencies. 27 # If `null`, it means the project either has no external dependencies 28 # or the vendored dependencies are already present in the source tree. 29 vendorHash ? throw ( 30 if args ? vendorSha256 then 31 "buildGoModule: Expect vendorHash instead of vendorSha256" 32 else 33 "buildGoModule: vendorHash is missing" 34 ), 35 36 # The go.sum file to track which can cause rebuilds. 37 goSum ? null, 38 39 # Whether to delete the vendor folder supplied with the source. 40 deleteVendor ? false, 41 42 # Whether to fetch (go mod download) and proxy the vendor directory. 43 # This is useful if your code depends on c code and go mod tidy does not 44 # include the needed sources to build or if any dependency has case-insensitive 45 # conflicts which will produce platform dependant `vendorHash` checksums. 46 proxyVendor ? false, 47 48 # We want parallel builds by default. 49 enableParallelBuilding ? true, 50 51 # Do not enable this without good reason 52 # IE: programs coupled with the compiler. 53 allowGoReference ? false, 54 55 # Meta data for the final derivation. 56 meta ? { }, 57 58 # Go linker flags. 59 ldflags ? [ ], 60 # Go build flags. 61 GOFLAGS ? [ ], 62 63 # Instead of building binary targets with 'go install', build test binaries with 'go test'. 64 # The binaries found in $out/bin can be executed as go tests outside of the sandbox. 65 # This is mostly useful outside of nixpkgs, for example to build integration/e2e tests 66 # that won't run within the sandbox. 67 buildTestBinaries ? false, 68 69 ... 70 }@args: 71 { 72 inherit 73 modRoot 74 vendorHash 75 deleteVendor 76 proxyVendor 77 goSum 78 ; 79 goModules = 80 if (finalAttrs.vendorHash == null) then 81 "" 82 else 83 (stdenv.mkDerivation { 84 name = 85 let 86 prefix = "${finalAttrs.name or "${finalAttrs.pname}-${finalAttrs.version}"}-"; 87 88 # If "goSum" is supplied then it can cause "goModules" to rebuild. 89 # Attach the hash name of the "go.sum" file so we can rebuild when it changes. 90 suffix = lib.optionalString ( 91 finalAttrs.goSum != null 92 ) "-${(lib.removeSuffix "-go.sum" (lib.removePrefix "${builtins.storeDir}/" finalAttrs.goSum))}"; 93 in 94 "${prefix}go-modules${suffix}"; 95 96 nativeBuildInputs = (finalAttrs.nativeBuildInputs or [ ]) ++ [ 97 go 98 gitMinimal 99 cacert 100 ]; 101 102 inherit (finalAttrs) src modRoot goSum; 103 104 # The following inheritance behavior is not trivial to expect, and some may 105 # argue it's not ideal. Changing it may break vendor hashes in Nixpkgs and 106 # out in the wild. In anycase, it's documented in: 107 # doc/languages-frameworks/go.section.md. 108 prePatch = finalAttrs.prePatch or ""; 109 patches = finalAttrs.patches or [ ]; 110 patchFlags = finalAttrs.patchFlags or [ ]; 111 postPatch = finalAttrs.postPatch or ""; 112 preBuild = finalAttrs.preBuild or ""; 113 postBuild = finalAttrs.modPostBuild or ""; 114 sourceRoot = finalAttrs.sourceRoot or ""; 115 setSourceRoot = finalAttrs.setSourceRoot or ""; 116 env = finalAttrs.env or { }; 117 118 impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [ 119 "GIT_PROXY_COMMAND" 120 "SOCKS_SERVER" 121 "GOPROXY" 122 ]; 123 124 configurePhase = 125 args.modConfigurePhase or '' 126 runHook preConfigure 127 export GOCACHE=$TMPDIR/go-cache 128 export GOPATH="$TMPDIR/go" 129 cd "$modRoot" 130 runHook postConfigure 131 ''; 132 133 buildPhase = 134 args.modBuildPhase or ( 135 '' 136 runHook preBuild 137 '' 138 + lib.optionalString finalAttrs.deleteVendor '' 139 if [ ! -d vendor ]; then 140 echo "vendor folder does not exist, 'deleteVendor' is not needed" 141 exit 10 142 else 143 rm -rf vendor 144 fi 145 '' 146 + '' 147 if [ -d vendor ]; then 148 echo "vendor folder exists, please set 'vendorHash = null;' in your expression" 149 exit 10 150 fi 151 152 export GIT_SSL_CAINFO=$NIX_SSL_CERT_FILE 153 ${ 154 if finalAttrs.proxyVendor then 155 '' 156 mkdir -p "$GOPATH/pkg/mod/cache/download" 157 go mod download 158 '' 159 else 160 '' 161 if (( "''${NIX_DEBUG:-0}" >= 1 )); then 162 goModVendorFlags+=(-v) 163 fi 164 go mod vendor "''${goModVendorFlags[@]}" 165 '' 166 } 167 168 mkdir -p vendor 169 170 runHook postBuild 171 '' 172 ); 173 174 installPhase = 175 args.modInstallPhase or '' 176 runHook preInstall 177 178 ${ 179 if finalAttrs.proxyVendor then 180 '' 181 rm -rf "$GOPATH/pkg/mod/cache/download/sumdb" 182 cp -r --reflink=auto "$GOPATH/pkg/mod/cache/download" $out 183 '' 184 else 185 '' 186 cp -r --reflink=auto vendor $out 187 '' 188 } 189 190 if ! [ "$(ls -A $out)" ]; then 191 echo "vendor folder is empty, please set 'vendorHash = null;' in your expression" 192 exit 10 193 fi 194 195 runHook postInstall 196 ''; 197 198 dontFixup = true; 199 200 outputHashMode = "recursive"; 201 outputHash = finalAttrs.vendorHash; 202 # Handle empty `vendorHash`; avoid error: 203 # empty hash requires explicit hash algorithm. 204 outputHashAlgo = if finalAttrs.vendorHash == "" then "sha256" else null; 205 # in case an overlay clears passthru by accident, don't fail evaluation 206 }).overrideAttrs 207 ( 208 let 209 pos = builtins.unsafeGetAttrPos "passthru" finalAttrs; 210 posString = 211 if pos == null then "unknown" else "${pos.file}:${toString pos.line}:${toString pos.column}"; 212 in 213 finalAttrs.passthru.overrideModAttrs 214 or (lib.warn "buildGoModule: ${finalAttrs.name or finalAttrs.pname}: passthru.overrideModAttrs missing after overrideAttrs. Last overridden at ${posString}." overrideModAttrs) 215 ); 216 217 nativeBuildInputs = [ go ] ++ nativeBuildInputs; 218 219 env = args.env or { } // { 220 inherit (go) GOOS GOARCH; 221 222 GO111MODULE = "on"; 223 GOTOOLCHAIN = "local"; 224 225 CGO_ENABLED = args.env.CGO_ENABLED or go.CGO_ENABLED; 226 227 GOFLAGS = toString ( 228 GOFLAGS 229 ++ 230 lib.warnIf (lib.any (lib.hasPrefix "-mod=") GOFLAGS) 231 "use `proxyVendor` to control Go module/vendor behavior instead of setting `-mod=` in GOFLAGS" 232 (lib.optional (!finalAttrs.proxyVendor) "-mod=vendor") 233 ++ 234 lib.warnIf (builtins.elem "-trimpath" GOFLAGS) 235 "`-trimpath` is added by default to GOFLAGS by buildGoModule when allowGoReference isn't set to true" 236 (lib.optional (!finalAttrs.allowGoReference) "-trimpath") 237 ); 238 }; 239 240 inherit enableParallelBuilding; 241 242 # If not set to an explicit value, set the buildid empty for reproducibility. 243 ldflags = ldflags ++ lib.optional (!lib.any (lib.hasPrefix "-buildid=") ldflags) "-buildid="; 244 245 configurePhase = 246 args.configurePhase or ( 247 '' 248 runHook preConfigure 249 250 export GOCACHE=$TMPDIR/go-cache 251 export GOPATH="$TMPDIR/go" 252 export GOPROXY=off 253 export GOSUMDB=off 254 if [ -f "$NIX_CC_FOR_TARGET/nix-support/dynamic-linker" ]; then 255 export GO_LDSO=$(cat $NIX_CC_FOR_TARGET/nix-support/dynamic-linker) 256 fi 257 cd "$modRoot" 258 '' 259 + lib.optionalString (finalAttrs.vendorHash != null) '' 260 ${ 261 if finalAttrs.proxyVendor then 262 '' 263 export GOPROXY="file://$goModules" 264 '' 265 else 266 '' 267 rm -rf vendor 268 cp -r --reflink=auto "$goModules" vendor 269 '' 270 } 271 '' 272 + '' 273 runHook postConfigure 274 '' 275 ); 276 277 buildPhase = 278 args.buildPhase or ( 279 lib.warnIf (builtins.elem "-buildid=" ldflags) 280 "`-buildid=` is set by default as ldflag by buildGoModule" 281 '' 282 runHook preBuild 283 284 exclude='\(/_\|examples\|Godeps\|testdata' 285 if [[ -n "$excludedPackages" ]]; then 286 IFS=' ' read -r -a excludedArr <<<$excludedPackages 287 printf -v excludedAlternates '%s\\|' "''${excludedArr[@]}" 288 excludedAlternates=''${excludedAlternates%\\|} # drop final \| added by printf 289 exclude+='\|'"$excludedAlternates" 290 fi 291 exclude+='\)' 292 293 buildGoDir() { 294 local cmd="$1" dir="$2" 295 296 declare -a flags 297 flags+=(''${tags:+-tags=$(concatStringsSep "," tags)}) 298 flags+=(''${ldflags:+-ldflags="''${ldflags[*]}"}) 299 flags+=("-p" "$NIX_BUILD_CORES") 300 if (( "''${NIX_DEBUG:-0}" >= 1 )); then 301 flags+=(-x) 302 fi 303 304 if [ "$cmd" = "test" ]; then 305 flags+=(-vet=off) 306 flags+=($checkFlags) 307 fi 308 309 local OUT 310 if ! OUT="$(go $cmd "''${flags[@]}" $dir 2>&1)"; then 311 if ! echo "$OUT" | grep -qE '(no( buildable| non-test)?|build constraints exclude all) Go (source )?files'; then 312 echo "$OUT" >&2 313 return 1 314 fi 315 fi 316 if [ -n "$OUT" ]; then 317 echo "$OUT" >&2 318 fi 319 return 0 320 } 321 322 getGoDirs() { 323 local type; 324 type="$1" 325 if [ -n "$subPackages" ]; then 326 echo "$subPackages" | sed "s,\(^\| \),\1./,g" 327 else 328 find . -type f -name \*$type.go -exec dirname {} \; | grep -v "/vendor/" | sort --unique | grep -v "$exclude" 329 fi 330 } 331 332 if [ -z "$enableParallelBuilding" ]; then 333 export NIX_BUILD_CORES=1 334 fi 335 for pkg in $(getGoDirs ""); do 336 ${ 337 if buildTestBinaries then 338 '' 339 echo "Building test binary for $pkg" 340 buildGoDir "test -c -o $GOPATH/bin/" "$pkg" 341 '' 342 else 343 '' 344 echo "Building subPackage $pkg" 345 buildGoDir install "$pkg" 346 '' 347 } 348 done 349 '' 350 + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) '' 351 # normalize cross-compiled builds w.r.t. native builds 352 ( 353 dir=$GOPATH/bin/''${GOOS}_''${GOARCH} 354 if [[ -n "$(shopt -s nullglob; echo $dir/*)" ]]; then 355 mv $dir/* $dir/.. 356 fi 357 if [[ -d $dir ]]; then 358 rmdir $dir 359 fi 360 ) 361 '' 362 + '' 363 runHook postBuild 364 '' 365 ); 366 367 doCheck = args.doCheck or (!buildTestBinaries); 368 checkPhase = 369 args.checkPhase or '' 370 runHook preCheck 371 # We do not set trimpath for tests, in case they reference test assets 372 export GOFLAGS=''${GOFLAGS//-trimpath/} 373 374 for pkg in $(getGoDirs test); do 375 buildGoDir test "$pkg" 376 done 377 378 runHook postCheck 379 ''; 380 381 installPhase = 382 args.installPhase or '' 383 runHook preInstall 384 385 mkdir -p $out 386 dir="$GOPATH/bin" 387 [ -e "$dir" ] && cp -r $dir $out 388 389 runHook postInstall 390 ''; 391 392 strictDeps = true; 393 394 inherit allowGoReference; 395 disallowedReferences = lib.optional (!finalAttrs.allowGoReference) go; 396 397 passthru = { 398 inherit go; 399 # Canonicallize `overrideModAttrs` as an attribute overlay. 400 # `passthru.overrideModAttrs` will be overridden 401 # when users want to override `goModules`. 402 overrideModAttrs = lib.toExtension overrideModAttrs; 403 } 404 // passthru; 405 406 meta = { 407 # Add default meta information. 408 platforms = go.meta.platforms or lib.platforms.all; 409 } 410 // meta; 411 }; 412}