xfce.xfce4-notes-plugin: Generate C code with newer Vala (#359006)
[NixPkgs.git] / pkgs / build-support / go / module.nix
blob993e18bd9fcc0876886ad0b10fa7b3716ec9187c
1 { go, cacert, git, lib, stdenv }:
3 { name ? "${args'.pname}-${args'.version}"
4   # The source used to build the derivation.
5 , src
6   # Native build inputs used for the derivation.
7 , nativeBuildInputs ? [ ]
8 , passthru ? { }
9 , patches ? [ ]
11   # A function to override the `goModules` derivation.
12 , overrideModAttrs ? (finalAttrs: previousAttrs: { })
14   # Directory to the `go.mod` and `go.sum` relative to the `src`.
15 , modRoot ? "./"
17   # The SRI hash of the vendored dependencies.
18   # If `vendorHash` is `null`, no dependencies are fetched and
19   # the build relies on the vendor folder within the source.
20 , vendorHash ? throw (
21     if args'?vendorSha256 then
22       "buildGoModule: Expect vendorHash instead of vendorSha256"
23     else
24       "buildGoModule: vendorHash is missing"
25   )
27   # Whether to delete the vendor folder supplied with the source.
28 , deleteVendor ? false
30   # Whether to fetch (go mod download) and proxy the vendor directory.
31   # This is useful if your code depends on c code and go mod tidy does not
32   # include the needed sources to build or if any dependency has case-insensitive
33   # conflicts which will produce platform dependant `vendorHash` checksums.
34 , proxyVendor ? false
36   # We want parallel builds by default.
37 , enableParallelBuilding ? true
39   # Do not enable this without good reason
40   # IE: programs coupled with the compiler.
41 , allowGoReference ? false
43   # Go env. variable to enable CGO.
44 , CGO_ENABLED ? go.CGO_ENABLED
46   # Meta data for the final derivation.
47 , meta ? { }
49   # Go linker flags.
50 , ldflags ? [ ]
51   # Go build flags.
52 , GOFLAGS ? [ ]
54   # Needed for buildFlags{,Array} warning
55 , buildFlags ? "" # deprecated
56 , buildFlagsArray ? "" # deprecated
58 , ...
59 }@args':
61 let
62   args = removeAttrs args' [ "overrideModAttrs" "vendorSha256" ];
64   GO111MODULE = "on";
65   GOTOOLCHAIN = "local";
68 (stdenv.mkDerivation (finalAttrs:
69   args
70   // {
72   inherit modRoot vendorHash deleteVendor proxyVendor;
73   goModules = if (finalAttrs.vendorHash == null) then "" else
74   (stdenv.mkDerivation {
75     name = "${finalAttrs.name or "${finalAttrs.pname}-${finalAttrs.version}"}-go-modules";
77     nativeBuildInputs = (finalAttrs.nativeBuildInputs or [ ]) ++ [ go git cacert ];
79     inherit (finalAttrs) src modRoot;
80     inherit (go) GOOS GOARCH;
81     inherit GO111MODULE GOTOOLCHAIN;
83     # The following inheritance behavior is not trivial to expect, and some may
84     # argue it's not ideal. Changing it may break vendor hashes in Nixpkgs and
85     # out in the wild. In anycase, it's documented in:
86     # doc/languages-frameworks/go.section.md.
87     prePatch = finalAttrs.prePatch or "";
88     patches = finalAttrs.patches or [ ];
89     patchFlags = finalAttrs.patchFlags or [ ];
90     postPatch = finalAttrs.postPatch or "";
91     preBuild = finalAttrs.preBuild or "";
92     postBuild = finalAttrs.modPostBuild or "";
93     sourceRoot = finalAttrs.sourceRoot or "";
94     setSourceRoot = finalAttrs.setSourceRoot or "";
95     env = finalAttrs.env or { };
97     impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
98       "GIT_PROXY_COMMAND"
99       "SOCKS_SERVER"
100       "GOPROXY"
101     ];
103     configurePhase = args.modConfigurePhase or ''
104       runHook preConfigure
105       export GOCACHE=$TMPDIR/go-cache
106       export GOPATH="$TMPDIR/go"
107       cd "$modRoot"
108       runHook postConfigure
109     '';
111     buildPhase = args.modBuildPhase or (''
112       runHook preBuild
113     '' + lib.optionalString finalAttrs.deleteVendor ''
114       if [ ! -d vendor ]; then
115         echo "vendor folder does not exist, 'deleteVendor' is not needed"
116         exit 10
117       else
118         rm -rf vendor
119       fi
120     '' + ''
121       if [ -d vendor ]; then
122         echo "vendor folder exists, please set 'vendorHash = null;' in your expression"
123         exit 10
124       fi
126       export GIT_SSL_CAINFO=$NIX_SSL_CERT_FILE
127       ${if finalAttrs.proxyVendor then ''
128         mkdir -p "''${GOPATH}/pkg/mod/cache/download"
129         go mod download
130       '' else ''
131         if (( "''${NIX_DEBUG:-0}" >= 1 )); then
132           goModVendorFlags+=(-v)
133         fi
134         go mod vendor "''${goModVendorFlags[@]}"
135       ''}
137       mkdir -p vendor
139       runHook postBuild
140     '');
142     installPhase = args.modInstallPhase or ''
143       runHook preInstall
145       ${if finalAttrs.proxyVendor then ''
146         rm -rf "''${GOPATH}/pkg/mod/cache/download/sumdb"
147         cp -r --reflink=auto "''${GOPATH}/pkg/mod/cache/download" $out
148       '' else ''
149         cp -r --reflink=auto vendor $out
150       ''}
152       if ! [ "$(ls -A $out)" ]; then
153         echo "vendor folder is empty, please set 'vendorHash = null;' in your expression"
154         exit 10
155       fi
157       runHook postInstall
158     '';
160     dontFixup = true;
162     outputHashMode = "recursive";
163     outputHash = finalAttrs.vendorHash;
164     # Handle empty `vendorHash`; avoid error:
165     # empty hash requires explicit hash algorithm.
166     outputHashAlgo = if finalAttrs.vendorHash == "" then "sha256" else null;
167     # in case an overlay clears passthru by accident, don't fail evaluation
168   }).overrideAttrs (finalAttrs.passthru.overrideModAttrs or overrideModAttrs);
170     nativeBuildInputs = [ go ] ++ nativeBuildInputs;
172     inherit (go) GOOS GOARCH;
174     GOFLAGS = GOFLAGS
175       ++ lib.warnIf (lib.any (lib.hasPrefix "-mod=") GOFLAGS) "use `proxyVendor` to control Go module/vendor behavior instead of setting `-mod=` in GOFLAGS"
176         (lib.optional (!finalAttrs.proxyVendor) "-mod=vendor")
177       ++ lib.warnIf (builtins.elem "-trimpath" GOFLAGS) "`-trimpath` is added by default to GOFLAGS by buildGoModule when allowGoReference isn't set to true"
178         (lib.optional (!allowGoReference) "-trimpath");
179     inherit CGO_ENABLED enableParallelBuilding GO111MODULE GOTOOLCHAIN;
181     # If not set to an explicit value, set the buildid empty for reproducibility.
182     ldflags = ldflags ++ lib.optional (!lib.any (lib.hasPrefix "-buildid=") ldflags) "-buildid=";
184     configurePhase = args.configurePhase or (''
185       runHook preConfigure
187       export GOCACHE=$TMPDIR/go-cache
188       export GOPATH="$TMPDIR/go"
189       export GOPROXY=off
190       export GOSUMDB=off
191       cd "$modRoot"
192     '' + lib.optionalString (finalAttrs.vendorHash != null) ''
193       ${if finalAttrs.proxyVendor then ''
194         export GOPROXY="file://$goModules"
195       '' else ''
196         rm -rf vendor
197         cp -r --reflink=auto "$goModules" vendor
198       ''}
199     '' + ''
201       # currently pie is only enabled by default in pkgsMusl
202       # this will respect the `hardening{Disable,Enable}` flags if set
203       if [[ $NIX_HARDENING_ENABLE =~ "pie" ]]; then
204         export GOFLAGS="-buildmode=pie $GOFLAGS"
205       fi
207       runHook postConfigure
208     '');
210     buildPhase = args.buildPhase or (
211       lib.warnIf (buildFlags != "" || buildFlagsArray != "")
212         "`buildFlags`/`buildFlagsArray` are deprecated and will be removed in the 24.11 release. Use the `ldflags` and/or `tags` attributes instead of `buildFlags`/`buildFlagsArray`"
213       lib.warnIf (builtins.elem "-buildid=" ldflags)
214         "`-buildid=` is set by default as ldflag by buildGoModule"
215     ''
216       runHook preBuild
218       exclude='\(/_\|examples\|Godeps\|testdata'
219       if [[ -n "$excludedPackages" ]]; then
220         IFS=' ' read -r -a excludedArr <<<$excludedPackages
221         printf -v excludedAlternates '%s\\|' "''${excludedArr[@]}"
222         excludedAlternates=''${excludedAlternates%\\|} # drop final \| added by printf
223         exclude+='\|'"$excludedAlternates"
224       fi
225       exclude+='\)'
227       buildGoDir() {
228         local cmd="$1" dir="$2"
230         declare -ga buildFlagsArray
231         declare -a flags
232         flags+=($buildFlags "''${buildFlagsArray[@]}")
233         flags+=(''${tags:+-tags=''${tags// /,}})
234         flags+=(''${ldflags:+-ldflags="$ldflags"})
235         flags+=("-p" "$NIX_BUILD_CORES")
237         if [ "$cmd" = "test" ]; then
238           flags+=(-vet=off)
239           flags+=($checkFlags)
240         fi
242         local OUT
243         if ! OUT="$(go $cmd "''${flags[@]}" $dir 2>&1)"; then
244           if ! echo "$OUT" | grep -qE '(no( buildable| non-test)?|build constraints exclude all) Go (source )?files'; then
245             echo "$OUT" >&2
246             return 1
247           fi
248         fi
249         if [ -n "$OUT" ]; then
250           echo "$OUT" >&2
251         fi
252         return 0
253       }
255       getGoDirs() {
256         local type;
257         type="$1"
258         if [ -n "$subPackages" ]; then
259           echo "$subPackages" | sed "s,\(^\| \),\1./,g"
260         else
261           find . -type f -name \*$type.go -exec dirname {} \; | grep -v "/vendor/" | sort --unique | grep -v "$exclude"
262         fi
263       }
265       if (( "''${NIX_DEBUG:-0}" >= 1 )); then
266         buildFlagsArray+=(-x)
267       fi
269       if [ -z "$enableParallelBuilding" ]; then
270           export NIX_BUILD_CORES=1
271       fi
272       for pkg in $(getGoDirs ""); do
273         echo "Building subPackage $pkg"
274         buildGoDir install "$pkg"
275       done
276     '' + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) ''
277       # normalize cross-compiled builds w.r.t. native builds
278       (
279         dir=$GOPATH/bin/${go.GOOS}_${go.GOARCH}
280         if [[ -n "$(shopt -s nullglob; echo $dir/*)" ]]; then
281           mv $dir/* $dir/..
282         fi
283         if [[ -d $dir ]]; then
284           rmdir $dir
285         fi
286       )
287     '' + ''
288       runHook postBuild
289     '');
291     doCheck = args.doCheck or true;
292     checkPhase = args.checkPhase or ''
293       runHook preCheck
294       # We do not set trimpath for tests, in case they reference test assets
295       export GOFLAGS=''${GOFLAGS//-trimpath/}
297       for pkg in $(getGoDirs test); do
298         buildGoDir test "$pkg"
299       done
301       runHook postCheck
302     '';
304     installPhase = args.installPhase or ''
305       runHook preInstall
307       mkdir -p $out
308       dir="$GOPATH/bin"
309       [ -e "$dir" ] && cp -r $dir $out
311       runHook postInstall
312     '';
314     strictDeps = true;
316     disallowedReferences = lib.optional (!allowGoReference) go;
318     passthru = {
319       inherit go;
320       # Canonicallize `overrideModAttrs` as an attribute overlay.
321       # `passthru.overrideModAttrs` will be overridden
322       # when users want to override `goModules`.
323       overrideModAttrs = lib.toExtension overrideModAttrs;
324     } // passthru;
326     meta = {
327       # Add default meta information.
328       platforms = go.meta.platforms or lib.platforms.all;
329     } // meta;
330   }