@@ -485,16 +485,18 @@ def _go_tool_binary_impl(ctx):
485485 name += ".exe"
486486
487487 out = ctx .actions .declare_file (name )
488+
489+ # Using pre-declared directory for temporary output to avoid needing to use shell to create it.
490+ gotmp = ctx .actions .declare_directory (name + "_gotmp" )
488491 if sdk .goos == "windows" :
489- # Using pre-declared directory for temporary output as there is no safe
490- # way under Windows to create unique temporary dir.
491- gotmp = ctx .actions .declare_directory ("gotmp" )
492492 cmd = """@echo off
493493set GOMAXPROCS=1
494494set GOCACHE=%cd%\\ {gotmp}\\ gocache
495495set GOPATH=%cd%"\\ {gotmp}\\ gopath
496496set GOTOOLCHAIN=local
497497set GO111MODULE=off
498+ set GOTELEMETRY=off
499+ set GOENV=off
498500{go} build -o {out} -trimpath -ldflags \" -buildid='' {ldflags}\" {srcs}
499501set GO_EXIT_CODE=%ERRORLEVEL%
500502RMDIR /S /Q "{gotmp}"
@@ -523,30 +525,44 @@ exit /b %GO_EXIT_CODE%
523525 mnemonic = "GoToolchainBinaryBuild" ,
524526 )
525527 else :
526- # Note: GOPATH is needed for Go 1.16.
527- cmd = """
528- GOTMP=$(mktemp -d)
529- trap "rm -rf \" $GOTMP\" " EXIT
530- GOMAXPROCS=1 \
531- GOCACHE="$GOTMP"/gocache \
532- GOPATH="$GOTMP"/gopath \
533- GOTOOLCHAIN=local \
534- GO111MODULE=off \
535- {go} build -o {out} -trimpath -ldflags '-buildid="" {ldflags}' {srcs}
536- """ .format (
537- go = sdk .go .path ,
538- out = out .path ,
539- srcs = " " .join ([f .path for f in ctx .files .srcs ]),
540- ldflags = ctx .attr .ldflags ,
528+ # A dummy action to generate `gotmp`; this way the compilation below can avoid listing it in `outputs`.
529+ # The net effect is to avoid copying out the GOCACHE when actions run sandboxed.
530+ # Incidentally, this makes the reproducibility test pass.
531+ ctx .actions .write (
532+ output = gotmp ,
533+ content = "" ,
541534 )
542- ctx .actions .run_shell (
543- command = cmd ,
544- tools = depset (
545- ctx .files .srcs + [sdk .go ],
535+
536+ # In case actions are running unsandboxed, GOCACHE in `gotmp` may have been polluted.
537+ # -a flag forces a rebuild so we are not affected by it.
538+ args = ctx .actions .args ()
539+ args .add ("build" )
540+ args .add ("-a" )
541+ args .add ("-o" , out )
542+ args .add ("-trimpath" )
543+ args .add ("-ldflags" , ctx .attr .ldflags , format = '-buildid="" %s' )
544+ args .add_all (ctx .files .srcs )
545+
546+ ctx .actions .run (
547+ executable = sdk .go ,
548+ arguments = [args ],
549+ env = {
550+ "GOMAXPROCS" : "1" ,
551+ "GOTOOLCHAIN" : "local" ,
552+ "GO111MODULE" : "off" ,
553+ "GOTELEMETRY" : "off" ,
554+ "GOENV" : "off" ,
555+ # GOCACHE and GOPATH will default themselves to locations under $HOME.
556+ # Otherwise we would need to set them explicitly, in which case they must be absolute paths.
557+ # That would require a wrapper script/shell dependency.
558+ "HOME" : gotmp .path ,
559+ },
560+ inputs = depset (
561+ ctx .files .srcs ,
546562 transitive = [sdk .headers , sdk .srcs , sdk .libs , sdk .tools ],
547563 ),
548- toolchain = None ,
549564 outputs = [out ],
565+ toolchain = None ,
550566 mnemonic = "GoToolchainBinaryBuild" ,
551567 )
552568
0 commit comments