1 { go, govers, lib, fetchgit, fetchhg, fetchbzr, rsync
2 , fetchFromGitHub, stdenv }:
5 , nativeBuildInputs ? []
10 # We want parallel builds by default
11 , enableParallelBuilding ? true
13 # Go import path of the package
17 , goPackageAliases ? [ ]
19 # Extra sources to include in the gopath
22 # Extra gopaths containing src subfolder
23 # with sources to include in the gopath
26 # go2nix dependency file
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
44 # needed for buildFlags{,Array} warning
46 , buildFlagsArray ? ""
48 , meta ? {}, ... } @ args:
53 inherit (goDep) goPackagePath;
54 src = if goDep.fetch.type == "git" then
56 inherit (goDep.fetch) url rev sha256;
58 else if goDep.fetch.type == "hg" then
60 inherit (goDep.fetch) url rev sha256;
62 else if goDep.fetch.type == "bzr" then
64 inherit (goDep.fetch) url rev sha256;
66 else if goDep.fetch.type == "FromGitHub" then
68 inherit (goDep.fetch) owner repo rev sha256;
70 else abort "Unrecognized package fetch type: ${goDep.fetch.type}";
73 importGodeps = { depsFile }:
74 map dep2src (import depsFile);
76 goPath = if goDeps != null then importGodeps { depsFile = goDeps; } ++ 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;
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 (''
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"
114 rm -rf "go/src/$goPackagePath/vendor"
116 '' + lib.optionalString (goDeps != null) ''
117 if [ -d "go/src/$goPackagePath/vendor" ]; then
118 echo "vendor folder exists, 'goDeps' is not needed"
121 '' + lib.flip lib.concatMapStrings goPath ({ src, goPackagePath }: ''
123 (cd goPath; unpackFile "${src}")
124 mkdir -p "go/src/$(dirname "${goPackagePath}")"
125 chmod -R u+w goPath/*
126 mv goPath/* "go/src/${goPackagePath}"
129 '') + (lib.optionalString (extraSrcPaths != []) ''
130 ${rsync}/bin/rsync -a ${lib.concatMapStringsSep " " (p: "${p}/src") extraSrcPaths} go
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"
142 runHook postConfigure
145 renameImports = args.renameImports or (
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 (''
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"
168 local cmd="$1" dir="$2"
170 . $TMPDIR/buildFlagsArray
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
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
190 if [ -n "$OUT" ]; then
199 if [ -n "$subPackages" ]; then
200 echo "$subPackages" | sed "s,\(^\| \),\1$goPackagePath/,g"
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"
208 if (( "''${NIX_DEBUG:-0}" >= 1 )); then
209 buildFlagsArray+=(-x)
212 if [ ''${#buildFlagsArray[@]} -ne 0 ]; then
213 declare -p buildFlagsArray > $TMPDIR/buildFlagsArray
215 touch $TMPDIR/buildFlagsArray
217 if [ -z "$enableParallelBuilding" ]; then
218 export NIX_BUILD_CORES=1
220 for pkg in $(getGoDirs ""); do
221 echo "Building subPackage $pkg"
222 buildGoDir install "$pkg"
224 '' + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) ''
225 # normalize cross-compiled builds w.r.t. native builds
227 dir=$NIX_BUILD_TOP/go/bin/${go.GOOS}_${go.GOARCH}
228 if [[ -n "$(shopt -s nullglob; echo $dir/*)" ]]; then
231 if [[ -d $dir ]]; then
239 doCheck = args.doCheck or false;
240 checkPhase = args.checkPhase or ''
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"
252 installPhase = args.installPhase or ''
256 dir="$NIX_BUILD_TOP/go/bin"
257 [ -e "$dir" ] && cp -r $dir $out
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}"
271 export GOPATH=${lib.concatStringsSep ":" ( ["$d"] ++ ["$GOPATH"] ++ ["$PWD"] ++ extraSrcPaths)}
274 disallowedReferences = lib.optional (!allowGoReference) go
275 ++ lib.optional (!dontRenameImports) govers;
277 passthru = passthru //
279 lib.optionalAttrs (goPackageAliases != []) { inherit goPackageAliases; };
282 # Add default meta information
283 homepage = "https://${goPackagePath}";
284 platforms = go.meta.platforms or lib.platforms.all;
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"