nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{ go, cacert, git, lib, stdenv }:
2
3{ name ? "${args'.pname}-${args'.version}"
4, src
5, buildInputs ? []
6, nativeBuildInputs ? []
7, passthru ? {}
8, patches ? []
9
10# Go linker flags, passed to go via -ldflags
11, ldflags ? []
12
13# Go tags, passed to go via -tag
14, tags ? []
15
16# A function to override the go-modules derivation
17, overrideModAttrs ? (_oldAttrs : {})
18
19# path to go.mod and go.sum directory
20, modRoot ? "./"
21
22# vendorSha256 is the sha256 of the vendored dependencies
23#
24# if vendorSha256 is null, then we won't fetch any dependencies and
25# rely on the vendor folder within the source.
26, vendorSha256
27# Whether to delete the vendor folder supplied with the source.
28, deleteVendor ? false
29# Whether to fetch (go mod download) and proxy the vendor directory.
30# This is useful if your code depends on c code and go mod tidy does not
31# include the needed sources to build or if any dependency has case-insensitive
32# conflicts which will produce platform dependant `vendorSha256` checksums.
33, proxyVendor ? false
34
35# We want parallel builds by default
36, enableParallelBuilding ? true
37
38# Do not enable this without good reason
39# IE: programs coupled with the compiler
40, allowGoReference ? false
41
42, meta ? {}
43
44# disabled
45, runVend ? false
46
47# Not needed with buildGoModule
48, goPackagePath ? ""
49
50# needed for buildFlags{,Array} warning
51, buildFlags ? ""
52, buildFlagsArray ? ""
53
54, ... }@args':
55
56with builtins;
57
58assert runVend != false -> throw "`runVend` has been replaced by `proxyVendor`";
59
60assert goPackagePath != "" -> throw "`goPackagePath` is not needed with `buildGoModule`";
61
62let
63 args = removeAttrs args' [ "overrideModAttrs" "vendorSha256" ];
64
65 go-modules = if vendorSha256 != null then stdenv.mkDerivation (let modArgs = {
66
67 name = "${name}-go-modules";
68
69 nativeBuildInputs = (args.nativeBuildInputs or []) ++ [ go git cacert ];
70
71 inherit (args) src;
72 inherit (go) GOOS GOARCH;
73
74 patches = args.patches or [];
75 patchFlags = args.patchFlags or [];
76 preBuild = args.preBuild or "";
77 sourceRoot = args.sourceRoot or "";
78
79 GO111MODULE = "on";
80
81 impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
82 "GIT_PROXY_COMMAND" "SOCKS_SERVER" "GOPROXY"
83 ];
84
85 configurePhase = args.modConfigurePhase or ''
86 runHook preConfigure
87 export GOCACHE=$TMPDIR/go-cache
88 export GOPATH="$TMPDIR/go"
89 cd "${modRoot}"
90 runHook postConfigure
91 '';
92
93 buildPhase = args.modBuildPhase or ''
94 runHook preBuild
95 '' + lib.optionalString (deleteVendor == true) ''
96 if [ ! -d vendor ]; then
97 echo "vendor folder does not exist, 'deleteVendor' is not needed"
98 exit 10
99 else
100 rm -rf vendor
101 fi
102 '' + ''
103 if [ -d vendor ]; then
104 echo "vendor folder exists, please set 'vendorSha256 = null;' in your expression"
105 exit 10
106 fi
107
108 ${if proxyVendor then ''
109 mkdir -p "''${GOPATH}/pkg/mod/cache/download"
110 go mod download
111 '' else ''
112 go mod vendor
113 ''}
114
115 mkdir -p vendor
116
117 runHook postBuild
118 '';
119
120 installPhase = args.modInstallPhase or ''
121 runHook preInstall
122
123 ${if proxyVendor then ''
124 rm -rf "''${GOPATH}/pkg/mod/cache/download/sumdb"
125 cp -r --reflink=auto "''${GOPATH}/pkg/mod/cache/download" $out
126 '' else ''
127 cp -r --reflink=auto vendor $out
128 ''}
129
130 runHook postInstall
131 '';
132
133 dontFixup = true;
134 }; in modArgs // (
135 {
136 outputHashMode = "recursive";
137 outputHashAlgo = "sha256";
138 outputHash = vendorSha256;
139 }
140 ) // overrideModAttrs modArgs) else "";
141
142 package = stdenv.mkDerivation (args // {
143 nativeBuildInputs = [ go ] ++ nativeBuildInputs;
144
145 inherit (go) GOOS GOARCH;
146
147 GO111MODULE = "on";
148 GOFLAGS = lib.optionals (!proxyVendor) [ "-mod=vendor" ] ++ lib.optionals (!allowGoReference) [ "-trimpath" ];
149
150 configurePhase = args.configurePhase or ''
151 runHook preConfigure
152
153 export GOCACHE=$TMPDIR/go-cache
154 export GOPATH="$TMPDIR/go"
155 export GOPROXY=off
156 export GOSUMDB=off
157 cd "$modRoot"
158 '' + lib.optionalString (vendorSha256 != null) ''
159 ${if proxyVendor then ''
160 export GOPROXY=file://${go-modules}
161 '' else ''
162 rm -rf vendor
163 cp -r --reflink=auto ${go-modules} vendor
164 ''}
165 '' + ''
166
167 runHook postConfigure
168 '';
169
170 buildPhase = args.buildPhase or ''
171 runHook preBuild
172
173 exclude='\(/_\|examples\|Godeps\|testdata'
174 if [[ -n "$excludedPackages" ]]; then
175 IFS=' ' read -r -a excludedArr <<<$excludedPackages
176 printf -v excludedAlternates '%s\\|' "''${excludedArr[@]}"
177 excludedAlternates=''${excludedAlternates%\\|} # drop final \| added by printf
178 exclude+='\|'"$excludedAlternates"
179 fi
180 exclude+='\)'
181
182 buildGoDir() {
183 local d; local cmd;
184 cmd="$1"
185 d="$2"
186 . $TMPDIR/buildFlagsArray
187 local OUT
188 if ! OUT="$(go $cmd $buildFlags "''${buildFlagsArray[@]}" ''${tags:+-tags=${lib.concatStringsSep "," tags}} ''${ldflags:+-ldflags="$ldflags"} -v -p $NIX_BUILD_CORES $d 2>&1)"; then
189 if ! echo "$OUT" | grep -qE '(no( buildable| non-test)?|build constraints exclude all) Go (source )?files'; then
190 echo "$OUT" >&2
191 return 1
192 fi
193 fi
194 if [ -n "$OUT" ]; then
195 echo "$OUT" >&2
196 fi
197 return 0
198 }
199
200 getGoDirs() {
201 local type;
202 type="$1"
203 if [ -n "$subPackages" ]; then
204 echo "$subPackages" | sed "s,\(^\| \),\1./,g"
205 else
206 find . -type f -name \*$type.go -exec dirname {} \; | grep -v "/vendor/" | sort --unique | grep -v "$exclude"
207 fi
208 }
209
210 if (( "''${NIX_DEBUG:-0}" >= 1 )); then
211 buildFlagsArray+=(-x)
212 fi
213
214 if [ ''${#buildFlagsArray[@]} -ne 0 ]; then
215 declare -p buildFlagsArray > $TMPDIR/buildFlagsArray
216 else
217 touch $TMPDIR/buildFlagsArray
218 fi
219 if [ -z "$enableParallelBuilding" ]; then
220 export NIX_BUILD_CORES=1
221 fi
222 for pkg in $(getGoDirs ""); do
223 echo "Building subPackage $pkg"
224 buildGoDir install "$pkg"
225 done
226 '' + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) ''
227 # normalize cross-compiled builds w.r.t. native builds
228 (
229 dir=$GOPATH/bin/${go.GOOS}_${go.GOARCH}
230 if [[ -n "$(shopt -s nullglob; echo $dir/*)" ]]; then
231 mv $dir/* $dir/..
232 fi
233 if [[ -d $dir ]]; then
234 rmdir $dir
235 fi
236 )
237 '' + ''
238 runHook postBuild
239 '';
240
241 doCheck = args.doCheck or true;
242 checkPhase = args.checkPhase or ''
243 runHook preCheck
244
245 for pkg in $(getGoDirs test); do
246 buildGoDir test $checkFlags "$pkg"
247 done
248
249 runHook postCheck
250 '';
251
252 installPhase = args.installPhase or ''
253 runHook preInstall
254
255 mkdir -p $out
256 dir="$GOPATH/bin"
257 [ -e "$dir" ] && cp -r $dir $out
258
259 runHook postInstall
260 '';
261
262 strictDeps = true;
263
264 disallowedReferences = lib.optional (!allowGoReference) go;
265
266 passthru = passthru // { inherit go go-modules vendorSha256 ; };
267
268 enableParallelBuilding = enableParallelBuilding;
269
270 meta = {
271 # Add default meta information
272 platforms = go.meta.platforms or lib.platforms.all;
273 } // meta // {
274 # add an extra maintainer to every package
275 maintainers = (meta.maintainers or []) ++
276 [ lib.maintainers.kalbasit ];
277 };
278 });
279in
280lib.warnIf (buildFlags != "" || buildFlagsArray != "")
281 "Use the `ldflags` and/or `tags` attributes instead of `buildFlags`/`buildFlagsArray`"
282 package