@@ -497,7 +497,10 @@ set GOTOOLCHAIN=local
497497set GO111MODULE=off
498498set GOTELEMETRY=off
499499set GOENV=off
500- {go} build -o {out} -trimpath -ldflags \" -buildid='' {ldflags}\" {srcs}
500+ {go} build -o {out_pack} -trimpath -ldflags \" -buildid='' {ldflags}\" cmd/pack
501+ if %ERRORLEVEL% EQ 0 (
502+ {go} build -o {out} -trimpath -ldflags \" -buildid='' {ldflags}\" {srcs}
503+ )
501504set GO_EXIT_CODE=%ERRORLEVEL%
502505RMDIR /S /Q "{gotmp}"
503506MKDIR "{gotmp}"
@@ -506,6 +509,7 @@ exit /b %GO_EXIT_CODE%
506509 gotmp = gotmp .path .replace ("/" , "\\ " ),
507510 go = sdk .go .path .replace ("/" , "\\ " ),
508511 out = out .path ,
512+ out_pack = ctx .outputs .out_pack .path ,
509513 srcs = " " .join ([f .path for f in ctx .files .srcs ]),
510514 ldflags = ctx .attr .ldflags ,
511515 )
@@ -521,32 +525,35 @@ exit /b %GO_EXIT_CODE%
521525 transitive = [sdk .headers , sdk .srcs , sdk .tools ],
522526 ),
523527 toolchain = None ,
524- outputs = [out , gotmp ],
528+ outputs = [out , ctx . outputs . out_pack , gotmp ],
525529 mnemonic = "GoToolchainBinaryBuild" ,
526530 )
527531 else :
528- # -a flag instructs the compiler to not read from GOCACHE and force a rebuild.
529- # This provides extra safety in cases of unsandboxed execution .
532+ # We do not use -a here as the cache drastically reduces the time spent
533+ # on the second go build (roughly 50% faster) .
530534 args = ctx .actions .args ()
531- args .add ("build" )
532- args .add ("-a" )
533- args .add ("-o" , out )
534- args .add ("-trimpath" )
535- args .add ("-ldflags" , ctx .attr .ldflags , format = '-buildid="" %s' )
535+ args .add (ctx .outputs .out_pack )
536+ args .add (out )
536537 args .add_all (ctx .files .srcs )
537538
538539 ctx .actions .run_shell (
539540 command = """
540- trap "HOME={HOME} GOROOT={GOROOT} {go} clean -cache" EXIT;
541- HOME={HOME} {go} "$@" """ .format (
541+ set -eu
542+ export HOME={HOME}
543+ trap "{go} clean -cache" EXIT;
544+ {go} build -trimpath -ldflags='-buildid="" {ldflags}' -o "$1" cmd/pack
545+ shift
546+ {go} build -trimpath -ldflags='-buildid="" {ldflags}' -o "$@"
547+ """ .format (
542548 go = sdk .go .path ,
543- GOROOT = sdk . root_file . dirname ,
549+ ldflags = ctx . attr . ldflags ,
544550 # The value of GOCACHE/GOPATH are determined from HOME.
545551 # We place them in the execroot to avoid dependency on `mktemp` and because we don't know
546552 # a safe scratch space on all systems. Note that HOME must be an absolute path, otherwise the
547553 # Go toolchain will write some outputs to the wrong place and the result will be uncacheable.
548- # We use a hardcoded UUID to prevent collisions with anything else under unsandboxed strategy.
549- HOME = "$(pwd)/_go_tool_binary-fake-home-85e96dea-541b-4188-8d13-5c2c42bdbd06" ,
554+ # We include the output path of this action to prevent collisions with anything else,
555+ # including differently configured versions of the same target, under an unsandboxed strategy.
556+ HOME = "$(pwd)/_go_tool_binary-fake-home-" + out .path .replace ("/" , "_" ),
550557 ),
551558 arguments = [args ],
552559 tools = [sdk .go ],
@@ -562,7 +569,7 @@ HOME={HOME} {go} "$@" """.format(
562569 transitive = [sdk .headers , sdk .srcs , sdk .libs , sdk .tools ],
563570 ),
564571 toolchain = None ,
565- outputs = [out ],
572+ outputs = [out , ctx . outputs . out_pack ],
566573 mnemonic = "GoToolchainBinaryBuild" ,
567574 )
568575
@@ -586,6 +593,7 @@ go_tool_binary = rule(
586593 "ldflags" : attr .string (
587594 doc = "Raw value to pass to go build via -ldflags without tokenization" ,
588595 ),
596+ "out_pack" : attr .output (),
589597 },
590598 executable = True ,
591599 doc = """Used instead of go_binary for executables used in the toolchain.
@@ -594,6 +602,11 @@ go_tool_binary depends on tools and libraries that are part of the Go SDK.
594602It does not depend on other toolchains. It can only compile binaries that
595603just have a main package and only depend on the standard library and don't
596604require build constraints.
605+
606+ It is currently only used to build the `builder` tool maintained as part of
607+ rules_go as well as the `pack` tool provided by the Go SDK in source form
608+ only as of Go 1.25. Combining both builds into a single action drastically
609+ reduces the overall build time due to Go's own caching mechanism.
597610""" ,
598611)
599612
0 commit comments