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