sdrangel: fix build on x86_64-darwin
[NixPkgs.git] / pkgs / build-support / go / package.nix
blob58a242a2535c24b6d44f52204a5cbd6cd1f2e13c
1 { go, govers, lib, fetchgit, fetchhg, fetchbzr, rsync
2 , fetchFromGitHub, stdenv }:
4 { buildInputs ? []
5 , nativeBuildInputs ? []
6 , passthru ? {}
7 , preFixup ? ""
8 , shellHook ? ""
10 # We want parallel builds by default
11 , enableParallelBuilding ? true
13 # Go import path of the package
14 , goPackagePath
16 # Go package aliases
17 , goPackageAliases ? [ ]
19 # Extra sources to include in the gopath
20 , extraSrcs ? [ ]
22 # Extra gopaths containing src subfolder
23 # with sources to include in the gopath
24 , extraSrcPaths ? [ ]
26 # go2nix dependency file
27 , goDeps ? null
29 # Whether to delete the vendor folder supplied with the source.
30 , deleteVendor ? false
32 , dontRenameImports ? false
34 # Do not enable this without good reason
35 # IE: programs coupled with the compiler
36 , allowGoReference ? false
38 , CGO_ENABLED ? go.CGO_ENABLED
40 , ldflags ? [ ]
42 , GOFLAGS ? [ ]
44 # needed for buildFlags{,Array} warning
45 , buildFlags ? ""
46 , buildFlagsArray ? ""
48 , meta ? {}, ... } @ args:
50 let
51   dep2src = goDep:
52     {
53       inherit (goDep) goPackagePath;
54       src = if goDep.fetch.type == "git" then
55         fetchgit {
56           inherit (goDep.fetch) url rev sha256;
57         }
58       else if goDep.fetch.type == "hg" then
59         fetchhg {
60           inherit (goDep.fetch) url rev sha256;
61         }
62       else if goDep.fetch.type == "bzr" then
63         fetchbzr {
64           inherit (goDep.fetch) url rev sha256;
65         }
66       else if goDep.fetch.type == "FromGitHub" then
67         fetchFromGitHub {
68           inherit (goDep.fetch) owner repo rev sha256;
69         }
70       else abort "Unrecognized package fetch type: ${goDep.fetch.type}";
71     };
73   importGodeps = { depsFile }:
74     map dep2src (import depsFile);
76   goPath = if goDeps != null then importGodeps { depsFile = goDeps; } ++ extraSrcs
77                              else extraSrcs;
78   package = stdenv.mkDerivation (
79     (builtins.removeAttrs args [ "goPackageAliases" "disabled" "extraSrcs"]) // {
81     nativeBuildInputs = [ go ]
82       ++ (lib.optional (!dontRenameImports) govers) ++ nativeBuildInputs;
83     buildInputs = buildInputs;
85     inherit (go) GOOS GOARCH GO386;
87     GOHOSTARCH = go.GOHOSTARCH or null;
88     GOHOSTOS = go.GOHOSTOS or null;
90     inherit CGO_ENABLED enableParallelBuilding;
92     GO111MODULE = "off";
93     GOTOOLCHAIN = "local";
94     GOFLAGS = GOFLAGS ++ lib.optional (!allowGoReference)  "-trimpath" ;
96     GOARM = toString (lib.intersectLists [(stdenv.hostPlatform.parsed.cpu.version or "")] ["5" "6" "7"]);
98     # If not set to an explicit value, set the buildid empty for reproducibility.
99     ldflags = ldflags ++ lib.optional (!lib.any (lib.hasPrefix "-buildid=") ldflags) "-buildid=";
101     configurePhase = args.configurePhase or (''
102       runHook preConfigure
104       # Extract the source
105       cd "$NIX_BUILD_TOP"
106       mkdir -p "go/src/$(dirname "$goPackagePath")"
107       mv "$sourceRoot" "go/src/$goPackagePath"
109     '' + lib.optionalString deleteVendor ''
110       if [ ! -d "go/src/$goPackagePath/vendor" ]; then
111         echo "vendor folder does not exist, 'deleteVendor' is not needed"
112         exit 10
113       else
114         rm -rf "go/src/$goPackagePath/vendor"
115       fi
116     '' + lib.optionalString (goDeps != null) ''
117       if [ -d "go/src/$goPackagePath/vendor" ]; then
118         echo "vendor folder exists, 'goDeps' is not needed"
119         exit 10
120       fi
121     '' + lib.flip lib.concatMapStrings goPath ({ src, goPackagePath }: ''
122       mkdir goPath
123       (cd goPath; unpackFile "${src}")
124       mkdir -p "go/src/$(dirname "${goPackagePath}")"
125       chmod -R u+w goPath/*
126       mv goPath/* "go/src/${goPackagePath}"
127       rmdir goPath
129     '') + (lib.optionalString (extraSrcPaths != []) ''
130       ${rsync}/bin/rsync -a ${lib.concatMapStringsSep " " (p: "${p}/src") extraSrcPaths} go
132     '') + ''
133       export GOPATH=$NIX_BUILD_TOP/go:$GOPATH
134       export GOCACHE=$TMPDIR/go-cache
136       # currently pie is only enabled by default in pkgsMusl
137       # this will respect the `hardening{Disable,Enable}` flags if set
138       if [[ $NIX_HARDENING_ENABLE =~ "pie" ]]; then
139         export GOFLAGS="-buildmode=pie $GOFLAGS"
140       fi
142       runHook postConfigure
143     '');
145     renameImports = args.renameImports or (
146       let
147         inputsWithAliases = lib.filter (x: x ? goPackageAliases)
148           (buildInputs ++ (args.propagatedBuildInputs or [ ]));
149         rename = to: from: "echo Renaming '${from}' to '${to}'; govers -d -m ${from} ${to}";
150         renames = p: lib.concatMapStringsSep "\n" (rename p.goPackagePath) p.goPackageAliases;
151       in lib.concatMapStringsSep "\n" renames inputsWithAliases);
153     buildPhase = args.buildPhase or (''
154       runHook preBuild
156       runHook renameImports
158       exclude='\(/_\|examples\|Godeps\|testdata'
159       if [[ -n "$excludedPackages" ]]; then
160         IFS=' ' read -r -a excludedArr <<<$excludedPackages
161         printf -v excludedAlternates '%s\\|' "''${excludedArr[@]}"
162         excludedAlternates=''${excludedAlternates%\\|} # drop final \| added by printf
163         exclude+='\|'"$excludedAlternates"
164       fi
165       exclude+='\)'
167       buildGoDir() {
168         local cmd="$1" dir="$2"
170         . $TMPDIR/buildFlagsArray
172         declare -a flags
173         flags+=($buildFlags "''${buildFlagsArray[@]}")
174         flags+=(''${tags:+-tags=''${tags// /,}})
175         flags+=(''${ldflags:+-ldflags="$ldflags"})
176         flags+=("-p" "$NIX_BUILD_CORES")
178         if [ "$cmd" = "test" ]; then
179           flags+=(-vet=off)
180           flags+=($checkFlags)
181         fi
183         local OUT
184         if ! OUT="$(go $cmd "''${flags[@]}" $dir 2>&1)"; then
185           if ! echo "$OUT" | grep -qE '(no( buildable| non-test)?|build constraints exclude all) Go (source )?files'; then
186             echo "$OUT" >&2
187             return 1
188           fi
189         fi
190         if [ -n "$OUT" ]; then
191           echo "$OUT" >&2
192         fi
193         return 0
194       }
196       getGoDirs() {
197         local type;
198         type="$1"
199         if [ -n "$subPackages" ]; then
200           echo "$subPackages" | sed "s,\(^\| \),\1$goPackagePath/,g"
201         else
202           pushd "$NIX_BUILD_TOP/go/src" >/dev/null
203           find "$goPackagePath" -type f -name \*$type.go -exec dirname {} \; | grep -v "/vendor/" | sort | uniq | grep -v "$exclude"
204           popd >/dev/null
205         fi
206       }
208       if (( "''${NIX_DEBUG:-0}" >= 1 )); then
209         buildFlagsArray+=(-x)
210       fi
212       if [ ''${#buildFlagsArray[@]} -ne 0 ]; then
213         declare -p buildFlagsArray > $TMPDIR/buildFlagsArray
214       else
215         touch $TMPDIR/buildFlagsArray
216       fi
217       if [ -z "$enableParallelBuilding" ]; then
218           export NIX_BUILD_CORES=1
219       fi
220       for pkg in $(getGoDirs ""); do
221         echo "Building subPackage $pkg"
222         buildGoDir install "$pkg"
223       done
224     '' + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) ''
225       # normalize cross-compiled builds w.r.t. native builds
226       (
227         dir=$NIX_BUILD_TOP/go/bin/${go.GOOS}_${go.GOARCH}
228         if [[ -n "$(shopt -s nullglob; echo $dir/*)" ]]; then
229           mv $dir/* $dir/..
230         fi
231         if [[ -d $dir ]]; then
232           rmdir $dir
233         fi
234       )
235     '' + ''
236       runHook postBuild
237     '');
239     doCheck = args.doCheck or false;
240     checkPhase = args.checkPhase or ''
241       runHook preCheck
242       # We do not set trimpath for tests, in case they reference test assets
243       export GOFLAGS=''${GOFLAGS//-trimpath/}
245       for pkg in $(getGoDirs test); do
246         buildGoDir test "$pkg"
247       done
249       runHook postCheck
250     '';
252     installPhase = args.installPhase or ''
253       runHook preInstall
255       mkdir -p $out
256       dir="$NIX_BUILD_TOP/go/bin"
257       [ -e "$dir" ] && cp -r $dir $out
259       runHook postInstall
260     '';
262     strictDeps = true;
264     shellHook = ''
265       d=$(mktemp -d "--suffix=-$name")
266     '' + toString (map (dep: ''
267        mkdir -p "$d/src/$(dirname "${dep.goPackagePath}")"
268        ln -s "${dep.src}" "$d/src/${dep.goPackagePath}"
269     ''
270     ) goPath) + ''
271       export GOPATH=${lib.concatStringsSep ":" ( ["$d"] ++ ["$GOPATH"] ++ ["$PWD"] ++ extraSrcPaths)}
272     '' + shellHook;
274     disallowedReferences = lib.optional (!allowGoReference) go
275       ++ lib.optional (!dontRenameImports) govers;
277     passthru = passthru //
278       { inherit go; } //
279       lib.optionalAttrs (goPackageAliases != []) { inherit goPackageAliases; };
281     meta = {
282       # Add default meta information
283       homepage = "https://${goPackagePath}";
284       platforms = go.meta.platforms or lib.platforms.all;
285     } // meta;
286   });
288 lib.warnIf (buildFlags != "" || buildFlagsArray != "")
289   "`buildFlags`/`buildFlagsArray` are deprecated and will be removed in the 24.11 release. Use the `ldflags` and/or `tags` attributes instead"
290 lib.warnIf (builtins.elem "-buildid=" ldflags) "`-buildid=` is set by default as ldflag by buildGoModule"
291 lib.warnIf (builtins.elem "-trimpath" GOFLAGS) "`-trimpath` is added by default to GOFLAGS by buildGoModule when allowGoReference isn't set to true"
292   package