Source file src/pkg/cmd/go/internal/work/exec.go
     1	
     2	
     3	
     4	
     5	
     6	
     7	package work
     8	
     9	import (
    10		"bytes"
    11		"cmd/go/internal/base"
    12		"cmd/go/internal/cache"
    13		"cmd/go/internal/cfg"
    14		"cmd/go/internal/load"
    15		"cmd/go/internal/str"
    16		"encoding/json"
    17		"errors"
    18		"fmt"
    19		"internal/lazyregexp"
    20		"io"
    21		"io/ioutil"
    22		"log"
    23		"math/rand"
    24		"os"
    25		"os/exec"
    26		"path/filepath"
    27		"regexp"
    28		"runtime"
    29		"strconv"
    30		"strings"
    31		"sync"
    32		"time"
    33	)
    34	
    35	
    36	
    37	func actionList(root *Action) []*Action {
    38		seen := map[*Action]bool{}
    39		all := []*Action{}
    40		var walk func(*Action)
    41		walk = func(a *Action) {
    42			if seen[a] {
    43				return
    44			}
    45			seen[a] = true
    46			for _, a1 := range a.Deps {
    47				walk(a1)
    48			}
    49			all = append(all, a)
    50		}
    51		walk(root)
    52		return all
    53	}
    54	
    55	
    56	func (b *Builder) Do(root *Action) {
    57		if c := cache.Default(); c != nil && !b.IsCmdList {
    58			
    59			defer c.Trim()
    60		}
    61	
    62		
    63		
    64		
    65		
    66		
    67		
    68		
    69		
    70		
    71		
    72		
    73		all := actionList(root)
    74		for i, a := range all {
    75			a.priority = i
    76		}
    77	
    78		
    79		writeActionGraph := func() {
    80			if file := cfg.DebugActiongraph; file != "" {
    81				if strings.HasSuffix(file, ".go") {
    82					
    83					
    84					base.Fatalf("go: refusing to write action graph to %v\n", file)
    85				}
    86				js := actionGraphJSON(root)
    87				if err := ioutil.WriteFile(file, []byte(js), 0666); err != nil {
    88					fmt.Fprintf(os.Stderr, "go: writing action graph: %v\n", err)
    89					base.SetExitStatus(1)
    90				}
    91			}
    92		}
    93		writeActionGraph()
    94	
    95		b.readySema = make(chan bool, len(all))
    96	
    97		
    98		for _, a := range all {
    99			for _, a1 := range a.Deps {
   100				a1.triggers = append(a1.triggers, a)
   101			}
   102			a.pending = len(a.Deps)
   103			if a.pending == 0 {
   104				b.ready.push(a)
   105				b.readySema <- true
   106			}
   107		}
   108	
   109		
   110		
   111		handle := func(a *Action) {
   112			if a.json != nil {
   113				a.json.TimeStart = time.Now()
   114			}
   115			var err error
   116			if a.Func != nil && (!a.Failed || a.IgnoreFail) {
   117				err = a.Func(b, a)
   118			}
   119			if a.json != nil {
   120				a.json.TimeDone = time.Now()
   121			}
   122	
   123			
   124			
   125			b.exec.Lock()
   126			defer b.exec.Unlock()
   127	
   128			if err != nil {
   129				if err == errPrintedOutput {
   130					base.SetExitStatus(2)
   131				} else {
   132					base.Errorf("%s", err)
   133				}
   134				a.Failed = true
   135			}
   136	
   137			for _, a0 := range a.triggers {
   138				if a.Failed {
   139					a0.Failed = true
   140				}
   141				if a0.pending--; a0.pending == 0 {
   142					b.ready.push(a0)
   143					b.readySema <- true
   144				}
   145			}
   146	
   147			if a == root {
   148				close(b.readySema)
   149			}
   150		}
   151	
   152		var wg sync.WaitGroup
   153	
   154		
   155		
   156		
   157		
   158		par := cfg.BuildP
   159		if cfg.BuildN {
   160			par = 1
   161		}
   162		for i := 0; i < par; i++ {
   163			wg.Add(1)
   164			go func() {
   165				defer wg.Done()
   166				for {
   167					select {
   168					case _, ok := <-b.readySema:
   169						if !ok {
   170							return
   171						}
   172						
   173						
   174						b.exec.Lock()
   175						a := b.ready.pop()
   176						b.exec.Unlock()
   177						handle(a)
   178					case <-base.Interrupted:
   179						base.SetExitStatus(1)
   180						return
   181					}
   182				}
   183			}()
   184		}
   185	
   186		wg.Wait()
   187	
   188		
   189		writeActionGraph()
   190	}
   191	
   192	
   193	func (b *Builder) buildActionID(a *Action) cache.ActionID {
   194		p := a.Package
   195		h := cache.NewHash("build " + p.ImportPath)
   196	
   197		
   198		
   199		
   200		
   201		
   202		fmt.Fprintf(h, "compile\n")
   203		
   204		
   205		
   206		
   207		
   208		if !p.Goroot && !cfg.BuildTrimpath && !strings.HasPrefix(p.Dir, b.WorkDir) {
   209			fmt.Fprintf(h, "dir %s\n", p.Dir)
   210		}
   211		fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch)
   212		fmt.Fprintf(h, "import %q\n", p.ImportPath)
   213		fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix)
   214		if cfg.BuildTrimpath {
   215			fmt.Fprintln(h, "trimpath")
   216		}
   217		if p.Internal.ForceLibrary {
   218			fmt.Fprintf(h, "forcelibrary\n")
   219		}
   220		if len(p.CgoFiles)+len(p.SwigFiles) > 0 {
   221			fmt.Fprintf(h, "cgo %q\n", b.toolID("cgo"))
   222			cppflags, cflags, cxxflags, fflags, ldflags, _ := b.CFlags(p)
   223			fmt.Fprintf(h, "CC=%q %q %q %q\n", b.ccExe(), cppflags, cflags, ldflags)
   224			if len(p.CXXFiles)+len(p.SwigFiles) > 0 {
   225				fmt.Fprintf(h, "CXX=%q %q\n", b.cxxExe(), cxxflags)
   226			}
   227			if len(p.FFiles) > 0 {
   228				fmt.Fprintf(h, "FC=%q %q\n", b.fcExe(), fflags)
   229			}
   230			
   231		}
   232		if p.Internal.CoverMode != "" {
   233			fmt.Fprintf(h, "cover %q %q\n", p.Internal.CoverMode, b.toolID("cover"))
   234		}
   235		fmt.Fprintf(h, "modinfo %q\n", p.Internal.BuildInfo)
   236	
   237		
   238		switch cfg.BuildToolchainName {
   239		default:
   240			base.Fatalf("buildActionID: unknown build toolchain %q", cfg.BuildToolchainName)
   241		case "gc":
   242			fmt.Fprintf(h, "compile %s %q %q\n", b.toolID("compile"), forcedGcflags, p.Internal.Gcflags)
   243			if len(p.SFiles) > 0 {
   244				fmt.Fprintf(h, "asm %q %q %q\n", b.toolID("asm"), forcedAsmflags, p.Internal.Asmflags)
   245			}
   246	
   247			
   248			key, val := cfg.GetArchEnv()
   249			fmt.Fprintf(h, "%s=%s\n", key, val)
   250	
   251			
   252			
   253			
   254			
   255			
   256			magic := []string{
   257				"GOCLOBBERDEADHASH",
   258				"GOSSAFUNC",
   259				"GO_SSA_PHI_LOC_CUTOFF",
   260				"GOSSAHASH",
   261			}
   262			for _, env := range magic {
   263				if x := os.Getenv(env); x != "" {
   264					fmt.Fprintf(h, "magic %s=%s\n", env, x)
   265				}
   266			}
   267			if os.Getenv("GOSSAHASH") != "" {
   268				for i := 0; ; i++ {
   269					env := fmt.Sprintf("GOSSAHASH%d", i)
   270					x := os.Getenv(env)
   271					if x == "" {
   272						break
   273					}
   274					fmt.Fprintf(h, "magic %s=%s\n", env, x)
   275				}
   276			}
   277			if os.Getenv("GSHS_LOGFILE") != "" {
   278				
   279				
   280				
   281				
   282				fmt.Fprintf(h, "nocache %d\n", time.Now().UnixNano())
   283			}
   284	
   285		case "gccgo":
   286			id, err := b.gccgoToolID(BuildToolchain.compiler(), "go")
   287			if err != nil {
   288				base.Fatalf("%v", err)
   289			}
   290			fmt.Fprintf(h, "compile %s %q %q\n", id, forcedGccgoflags, p.Internal.Gccgoflags)
   291			fmt.Fprintf(h, "pkgpath %s\n", gccgoPkgpath(p))
   292			fmt.Fprintf(h, "ar %q\n", BuildToolchain.(gccgoToolchain).ar())
   293			if len(p.SFiles) > 0 {
   294				id, _ = b.gccgoToolID(BuildToolchain.compiler(), "assembler-with-cpp")
   295				
   296				
   297				fmt.Fprintf(h, "asm %q\n", id)
   298			}
   299		}
   300	
   301		
   302		inputFiles := str.StringList(
   303			p.GoFiles,
   304			p.CgoFiles,
   305			p.CFiles,
   306			p.CXXFiles,
   307			p.FFiles,
   308			p.MFiles,
   309			p.HFiles,
   310			p.SFiles,
   311			p.SysoFiles,
   312			p.SwigFiles,
   313			p.SwigCXXFiles,
   314		)
   315		for _, file := range inputFiles {
   316			fmt.Fprintf(h, "file %s %s\n", file, b.fileHash(filepath.Join(p.Dir, file)))
   317		}
   318		for _, a1 := range a.Deps {
   319			p1 := a1.Package
   320			if p1 != nil {
   321				fmt.Fprintf(h, "import %s %s\n", p1.ImportPath, contentID(a1.buildID))
   322			}
   323		}
   324	
   325		return h.Sum()
   326	}
   327	
   328	
   329	
   330	func (b *Builder) needCgoHdr(a *Action) bool {
   331		
   332		if !b.IsCmdList && (a.Package.UsesCgo() || a.Package.UsesSwig()) && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
   333			for _, t1 := range a.triggers {
   334				if t1.Mode == "install header" {
   335					return true
   336				}
   337			}
   338			for _, t1 := range a.triggers {
   339				for _, t2 := range t1.triggers {
   340					if t2.Mode == "install header" {
   341						return true
   342					}
   343				}
   344			}
   345		}
   346		return false
   347	}
   348	
   349	
   350	
   351	
   352	func allowedVersion(v string) bool {
   353		
   354		if v == "" {
   355			return true
   356		}
   357		
   358		if v == "1.0" {
   359			return true
   360		}
   361		
   362		for _, tag := range cfg.BuildContext.ReleaseTags {
   363			if strings.HasPrefix(tag, "go") && tag[2:] == v {
   364				return true
   365			}
   366		}
   367		return false
   368	}
   369	
   370	const (
   371		needBuild uint32 = 1 << iota
   372		needCgoHdr
   373		needVet
   374		needCompiledGoFiles
   375		needStale
   376	)
   377	
   378	
   379	
   380	func (b *Builder) build(a *Action) (err error) {
   381		p := a.Package
   382	
   383		bit := func(x uint32, b bool) uint32 {
   384			if b {
   385				return x
   386			}
   387			return 0
   388		}
   389	
   390		cachedBuild := false
   391		need := bit(needBuild, !b.IsCmdList && a.needBuild || b.NeedExport) |
   392			bit(needCgoHdr, b.needCgoHdr(a)) |
   393			bit(needVet, a.needVet) |
   394			bit(needCompiledGoFiles, b.NeedCompiledGoFiles)
   395	
   396		if !p.BinaryOnly {
   397			if b.useCache(a, p, b.buildActionID(a), p.Target) {
   398				
   399				
   400				
   401				
   402				
   403				cachedBuild = true
   404				a.output = []byte{} 
   405				need &^= needBuild
   406				if b.NeedExport {
   407					p.Export = a.built
   408				}
   409				if need&needCompiledGoFiles != 0 && b.loadCachedSrcFiles(a) {
   410					need &^= needCompiledGoFiles
   411				}
   412			}
   413	
   414			
   415			
   416			if !cachedBuild && need&needCompiledGoFiles != 0 && b.loadCachedSrcFiles(a) {
   417				need &^= needCompiledGoFiles
   418			}
   419	
   420			if need == 0 {
   421				return nil
   422			}
   423			defer b.flushOutput(a)
   424		}
   425	
   426		defer func() {
   427			if err != nil && err != errPrintedOutput {
   428				err = fmt.Errorf("go build %s: %v", a.Package.ImportPath, err)
   429			}
   430			if err != nil && b.IsCmdList && b.NeedError && p.Error == nil {
   431				p.Error = &load.PackageError{Err: err.Error()}
   432			}
   433		}()
   434		if cfg.BuildN {
   435			
   436			
   437			
   438			
   439			
   440			b.Print("\n#\n# " + a.Package.ImportPath + "\n#\n\n")
   441		}
   442	
   443		if cfg.BuildV {
   444			b.Print(a.Package.ImportPath + "\n")
   445		}
   446	
   447		if a.Package.BinaryOnly {
   448			p.Stale = true
   449			p.StaleReason = "binary-only packages are no longer supported"
   450			if b.IsCmdList {
   451				return nil
   452			}
   453			return errors.New("binary-only packages are no longer supported")
   454		}
   455	
   456		if err := b.Mkdir(a.Objdir); err != nil {
   457			return err
   458		}
   459		objdir := a.Objdir
   460	
   461		
   462		if cachedBuild && need&needCgoHdr != 0 && b.loadCachedCgoHdr(a) {
   463			need &^= needCgoHdr
   464		}
   465	
   466		
   467		
   468		
   469		
   470		if need == needVet && b.loadCachedVet(a) {
   471			need &^= needVet
   472		}
   473		if need == 0 {
   474			return nil
   475		}
   476	
   477		
   478		dir, _ := filepath.Split(a.Target)
   479		if dir != "" {
   480			if err := b.Mkdir(dir); err != nil {
   481				return err
   482			}
   483		}
   484	
   485		gofiles := str.StringList(a.Package.GoFiles)
   486		cgofiles := str.StringList(a.Package.CgoFiles)
   487		cfiles := str.StringList(a.Package.CFiles)
   488		sfiles := str.StringList(a.Package.SFiles)
   489		cxxfiles := str.StringList(a.Package.CXXFiles)
   490		var objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string
   491	
   492		if a.Package.UsesCgo() || a.Package.UsesSwig() {
   493			if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.Package); err != nil {
   494				return
   495			}
   496		}
   497	
   498		
   499		
   500		
   501		if a.Package.UsesSwig() {
   502			outGo, outC, outCXX, err := b.swig(a, a.Package, objdir, pcCFLAGS)
   503			if err != nil {
   504				return err
   505			}
   506			cgofiles = append(cgofiles, outGo...)
   507			cfiles = append(cfiles, outC...)
   508			cxxfiles = append(cxxfiles, outCXX...)
   509		}
   510	
   511		
   512		if a.Package.Internal.CoverMode != "" {
   513			for i, file := range str.StringList(gofiles, cgofiles) {
   514				var sourceFile string
   515				var coverFile string
   516				var key string
   517				if strings.HasSuffix(file, ".cgo1.go") {
   518					
   519					base := filepath.Base(file)
   520					sourceFile = file
   521					coverFile = objdir + base
   522					key = strings.TrimSuffix(base, ".cgo1.go") + ".go"
   523				} else {
   524					sourceFile = filepath.Join(a.Package.Dir, file)
   525					coverFile = objdir + file
   526					key = file
   527				}
   528				coverFile = strings.TrimSuffix(coverFile, ".go") + ".cover.go"
   529				cover := a.Package.Internal.CoverVars[key]
   530				if cover == nil || base.IsTestFile(file) {
   531					
   532					continue
   533				}
   534				if err := b.cover(a, coverFile, sourceFile, cover.Var); err != nil {
   535					return err
   536				}
   537				if i < len(gofiles) {
   538					gofiles[i] = coverFile
   539				} else {
   540					cgofiles[i-len(gofiles)] = coverFile
   541				}
   542			}
   543		}
   544	
   545		
   546		if a.Package.UsesCgo() || a.Package.UsesSwig() {
   547			
   548			
   549			
   550			
   551			var gccfiles []string
   552			gccfiles = append(gccfiles, cfiles...)
   553			cfiles = nil
   554			if a.Package.Standard && a.Package.ImportPath == "runtime/cgo" {
   555				filter := func(files, nongcc, gcc []string) ([]string, []string) {
   556					for _, f := range files {
   557						if strings.HasPrefix(f, "gcc_") {
   558							gcc = append(gcc, f)
   559						} else {
   560							nongcc = append(nongcc, f)
   561						}
   562					}
   563					return nongcc, gcc
   564				}
   565				sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
   566			} else {
   567				for _, sfile := range sfiles {
   568					data, err := ioutil.ReadFile(filepath.Join(a.Package.Dir, sfile))
   569					if err == nil {
   570						if bytes.HasPrefix(data, []byte("TEXT")) || bytes.Contains(data, []byte("\nTEXT")) ||
   571							bytes.HasPrefix(data, []byte("DATA")) || bytes.Contains(data, []byte("\nDATA")) ||
   572							bytes.HasPrefix(data, []byte("GLOBL")) || bytes.Contains(data, []byte("\nGLOBL")) {
   573							return fmt.Errorf("package using cgo has Go assembly file %s", sfile)
   574						}
   575					}
   576				}
   577				gccfiles = append(gccfiles, sfiles...)
   578				sfiles = nil
   579			}
   580	
   581			outGo, outObj, err := b.cgo(a, base.Tool("cgo"), objdir, pcCFLAGS, pcLDFLAGS, mkAbsFiles(a.Package.Dir, cgofiles), gccfiles, cxxfiles, a.Package.MFiles, a.Package.FFiles)
   582			if err != nil {
   583				return err
   584			}
   585			if cfg.BuildToolchainName == "gccgo" {
   586				cgoObjects = append(cgoObjects, a.Objdir+"_cgo_flags")
   587			}
   588			cgoObjects = append(cgoObjects, outObj...)
   589			gofiles = append(gofiles, outGo...)
   590	
   591			switch cfg.BuildBuildmode {
   592			case "c-archive", "c-shared":
   593				b.cacheCgoHdr(a)
   594			}
   595		}
   596	
   597		var srcfiles []string 
   598		srcfiles = append(srcfiles, gofiles...)
   599		srcfiles = append(srcfiles, sfiles...)
   600		srcfiles = append(srcfiles, cfiles...)
   601		srcfiles = append(srcfiles, cxxfiles...)
   602		b.cacheSrcFiles(a, srcfiles)
   603	
   604		
   605		need &^= needCgoHdr
   606	
   607		
   608		if len(gofiles) == 0 {
   609			return &load.NoGoError{Package: a.Package}
   610		}
   611	
   612		
   613		if need&needVet != 0 {
   614			buildVetConfig(a, srcfiles)
   615			need &^= needVet
   616		}
   617		if need&needCompiledGoFiles != 0 {
   618			if !b.loadCachedSrcFiles(a) {
   619				return fmt.Errorf("failed to cache compiled Go files")
   620			}
   621			need &^= needCompiledGoFiles
   622		}
   623		if need == 0 {
   624			
   625			return nil
   626		}
   627	
   628		
   629		symabis, err := BuildToolchain.symabis(b, a, sfiles)
   630		if err != nil {
   631			return err
   632		}
   633	
   634		
   635		
   636		
   637		
   638		
   639		
   640		var icfg bytes.Buffer
   641		fmt.Fprintf(&icfg, "# import config\n")
   642		for i, raw := range a.Package.Internal.RawImports {
   643			final := a.Package.Imports[i]
   644			if final != raw {
   645				fmt.Fprintf(&icfg, "importmap %s=%s\n", raw, final)
   646			}
   647		}
   648		for _, a1 := range a.Deps {
   649			p1 := a1.Package
   650			if p1 == nil || p1.ImportPath == "" || a1.built == "" {
   651				continue
   652			}
   653			fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built)
   654		}
   655	
   656		if p.Internal.BuildInfo != "" && cfg.ModulesEnabled {
   657			if err := b.writeFile(objdir+"_gomod_.go", load.ModInfoProg(p.Internal.BuildInfo)); err != nil {
   658				return err
   659			}
   660			gofiles = append(gofiles, objdir+"_gomod_.go")
   661		}
   662	
   663		
   664		objpkg := objdir + "_pkg_.a"
   665		ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), symabis, len(sfiles) > 0, gofiles)
   666		if len(out) > 0 {
   667			output := b.processOutput(out)
   668			if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
   669				output += "note: module requires Go " + p.Module.GoVersion + "\n"
   670			}
   671			b.showOutput(a, a.Package.Dir, a.Package.Desc(), output)
   672			if err != nil {
   673				return errPrintedOutput
   674			}
   675		}
   676		if err != nil {
   677			if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
   678				b.showOutput(a, a.Package.Dir, a.Package.Desc(), "note: module requires Go "+p.Module.GoVersion)
   679			}
   680			return err
   681		}
   682		if ofile != objpkg {
   683			objects = append(objects, ofile)
   684		}
   685	
   686		
   687		
   688		
   689		_goos_goarch := "_" + cfg.Goos + "_" + cfg.Goarch
   690		_goos := "_" + cfg.Goos
   691		_goarch := "_" + cfg.Goarch
   692		for _, file := range a.Package.HFiles {
   693			name, ext := fileExtSplit(file)
   694			switch {
   695			case strings.HasSuffix(name, _goos_goarch):
   696				targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext
   697				if err := b.copyFile(objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil {
   698					return err
   699				}
   700			case strings.HasSuffix(name, _goarch):
   701				targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext
   702				if err := b.copyFile(objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil {
   703					return err
   704				}
   705			case strings.HasSuffix(name, _goos):
   706				targ := file[:len(name)-len(_goos)] + "_GOOS." + ext
   707				if err := b.copyFile(objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil {
   708					return err
   709				}
   710			}
   711		}
   712	
   713		for _, file := range cfiles {
   714			out := file[:len(file)-len(".c")] + ".o"
   715			if err := BuildToolchain.cc(b, a, objdir+out, file); err != nil {
   716				return err
   717			}
   718			objects = append(objects, out)
   719		}
   720	
   721		
   722		if len(sfiles) > 0 {
   723			ofiles, err := BuildToolchain.asm(b, a, sfiles)
   724			if err != nil {
   725				return err
   726			}
   727			objects = append(objects, ofiles...)
   728		}
   729	
   730		
   731		
   732		
   733		if a.buildID != "" && cfg.BuildToolchainName == "gccgo" {
   734			switch cfg.Goos {
   735			case "aix", "android", "dragonfly", "freebsd", "illumos", "linux", "netbsd", "openbsd", "solaris":
   736				asmfile, err := b.gccgoBuildIDFile(a)
   737				if err != nil {
   738					return err
   739				}
   740				ofiles, err := BuildToolchain.asm(b, a, []string{asmfile})
   741				if err != nil {
   742					return err
   743				}
   744				objects = append(objects, ofiles...)
   745			}
   746		}
   747	
   748		
   749		
   750		
   751		
   752		objects = append(objects, cgoObjects...)
   753	
   754		
   755		for _, syso := range a.Package.SysoFiles {
   756			objects = append(objects, filepath.Join(a.Package.Dir, syso))
   757		}
   758	
   759		
   760		
   761		
   762		
   763		
   764		if len(objects) > 0 {
   765			if err := BuildToolchain.pack(b, a, objpkg, objects); err != nil {
   766				return err
   767			}
   768		}
   769	
   770		if err := b.updateBuildID(a, objpkg, true); err != nil {
   771			return err
   772		}
   773	
   774		a.built = objpkg
   775		return nil
   776	}
   777	
   778	func (b *Builder) cacheObjdirFile(a *Action, c *cache.Cache, name string) error {
   779		f, err := os.Open(a.Objdir + name)
   780		if err != nil {
   781			return err
   782		}
   783		defer f.Close()
   784		_, _, err = c.Put(cache.Subkey(a.actionID, name), f)
   785		return err
   786	}
   787	
   788	func (b *Builder) findCachedObjdirFile(a *Action, c *cache.Cache, name string) (string, error) {
   789		file, _, err := c.GetFile(cache.Subkey(a.actionID, name))
   790		if err != nil {
   791			return "", err
   792		}
   793		return file, nil
   794	}
   795	
   796	func (b *Builder) loadCachedObjdirFile(a *Action, c *cache.Cache, name string) error {
   797		cached, err := b.findCachedObjdirFile(a, c, name)
   798		if err != nil {
   799			return err
   800		}
   801		return b.copyFile(a.Objdir+name, cached, 0666, true)
   802	}
   803	
   804	func (b *Builder) cacheCgoHdr(a *Action) {
   805		c := cache.Default()
   806		if c == nil {
   807			return
   808		}
   809		b.cacheObjdirFile(a, c, "_cgo_install.h")
   810	}
   811	
   812	func (b *Builder) loadCachedCgoHdr(a *Action) bool {
   813		c := cache.Default()
   814		if c == nil {
   815			return false
   816		}
   817		err := b.loadCachedObjdirFile(a, c, "_cgo_install.h")
   818		return err == nil
   819	}
   820	
   821	func (b *Builder) cacheSrcFiles(a *Action, srcfiles []string) {
   822		c := cache.Default()
   823		if c == nil {
   824			return
   825		}
   826		var buf bytes.Buffer
   827		for _, file := range srcfiles {
   828			if !strings.HasPrefix(file, a.Objdir) {
   829				
   830				buf.WriteString("./")
   831				buf.WriteString(file)
   832				buf.WriteString("\n")
   833				continue
   834			}
   835			name := file[len(a.Objdir):]
   836			buf.WriteString(name)
   837			buf.WriteString("\n")
   838			if err := b.cacheObjdirFile(a, c, name); err != nil {
   839				return
   840			}
   841		}
   842		c.PutBytes(cache.Subkey(a.actionID, "srcfiles"), buf.Bytes())
   843	}
   844	
   845	func (b *Builder) loadCachedVet(a *Action) bool {
   846		c := cache.Default()
   847		if c == nil {
   848			return false
   849		}
   850		list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles"))
   851		if err != nil {
   852			return false
   853		}
   854		var srcfiles []string
   855		for _, name := range strings.Split(string(list), "\n") {
   856			if name == "" { 
   857				continue
   858			}
   859			if strings.HasPrefix(name, "./") {
   860				srcfiles = append(srcfiles, name[2:])
   861				continue
   862			}
   863			if err := b.loadCachedObjdirFile(a, c, name); err != nil {
   864				return false
   865			}
   866			srcfiles = append(srcfiles, a.Objdir+name)
   867		}
   868		buildVetConfig(a, srcfiles)
   869		return true
   870	}
   871	
   872	func (b *Builder) loadCachedSrcFiles(a *Action) bool {
   873		c := cache.Default()
   874		if c == nil {
   875			return false
   876		}
   877		list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles"))
   878		if err != nil {
   879			return false
   880		}
   881		var files []string
   882		for _, name := range strings.Split(string(list), "\n") {
   883			if name == "" { 
   884				continue
   885			}
   886			if strings.HasPrefix(name, "./") {
   887				files = append(files, name[len("./"):])
   888				continue
   889			}
   890			file, err := b.findCachedObjdirFile(a, c, name)
   891			if err != nil {
   892				return false
   893			}
   894			files = append(files, file)
   895		}
   896		a.Package.CompiledGoFiles = files
   897		return true
   898	}
   899	
   900	
   901	type vetConfig struct {
   902		ID         string   
   903		Compiler   string   
   904		Dir        string   
   905		ImportPath string   
   906		GoFiles    []string 
   907		NonGoFiles []string 
   908	
   909		ImportMap   map[string]string 
   910		PackageFile map[string]string 
   911		Standard    map[string]bool   
   912		PackageVetx map[string]string 
   913		VetxOnly    bool              
   914		VetxOutput  string            
   915	
   916		SucceedOnTypecheckFailure bool 
   917	}
   918	
   919	func buildVetConfig(a *Action, srcfiles []string) {
   920		
   921		
   922		var gofiles, nongofiles []string
   923		for _, name := range srcfiles {
   924			if strings.HasSuffix(name, ".go") {
   925				gofiles = append(gofiles, name)
   926			} else {
   927				nongofiles = append(nongofiles, name)
   928			}
   929		}
   930	
   931		
   932		
   933		
   934		
   935		vcfg := &vetConfig{
   936			ID:          a.Package.ImportPath,
   937			Compiler:    cfg.BuildToolchainName,
   938			Dir:         a.Package.Dir,
   939			GoFiles:     mkAbsFiles(a.Package.Dir, gofiles),
   940			NonGoFiles:  mkAbsFiles(a.Package.Dir, nongofiles),
   941			ImportPath:  a.Package.ImportPath,
   942			ImportMap:   make(map[string]string),
   943			PackageFile: make(map[string]string),
   944			Standard:    make(map[string]bool),
   945		}
   946		a.vetCfg = vcfg
   947		for i, raw := range a.Package.Internal.RawImports {
   948			final := a.Package.Imports[i]
   949			vcfg.ImportMap[raw] = final
   950		}
   951	
   952		
   953		
   954		vcfgMapped := make(map[string]bool)
   955		for _, p := range vcfg.ImportMap {
   956			vcfgMapped[p] = true
   957		}
   958	
   959		for _, a1 := range a.Deps {
   960			p1 := a1.Package
   961			if p1 == nil || p1.ImportPath == "" {
   962				continue
   963			}
   964			
   965			
   966			if !vcfgMapped[p1.ImportPath] {
   967				vcfg.ImportMap[p1.ImportPath] = p1.ImportPath
   968			}
   969			if a1.built != "" {
   970				vcfg.PackageFile[p1.ImportPath] = a1.built
   971			}
   972			if p1.Standard {
   973				vcfg.Standard[p1.ImportPath] = true
   974			}
   975		}
   976	}
   977	
   978	
   979	
   980	var VetTool string
   981	
   982	
   983	
   984	var VetFlags []string
   985	
   986	
   987	var VetExplicit bool
   988	
   989	func (b *Builder) vet(a *Action) error {
   990		
   991		
   992	
   993		a.Failed = false 
   994	
   995		if a.Deps[0].Failed {
   996			
   997			
   998			
   999			return nil
  1000		}
  1001	
  1002		vcfg := a.Deps[0].vetCfg
  1003		if vcfg == nil {
  1004			
  1005			return fmt.Errorf("vet config not found")
  1006		}
  1007	
  1008		vcfg.VetxOnly = a.VetxOnly
  1009		vcfg.VetxOutput = a.Objdir + "vet.out"
  1010		vcfg.PackageVetx = make(map[string]string)
  1011	
  1012		h := cache.NewHash("vet " + a.Package.ImportPath)
  1013		fmt.Fprintf(h, "vet %q\n", b.toolID("vet"))
  1014	
  1015		vetFlags := VetFlags
  1016	
  1017		
  1018		
  1019		
  1020		
  1021		
  1022		
  1023		
  1024		
  1025		
  1026		
  1027		
  1028		
  1029		
  1030		
  1031		
  1032		
  1033		if a.Package.Goroot && !VetExplicit && VetTool == "" {
  1034			
  1035			
  1036			
  1037			
  1038			
  1039			
  1040			
  1041			
  1042			vetFlags = []string{"-unsafeptr=false"}
  1043		}
  1044	
  1045		
  1046		
  1047		
  1048		
  1049		
  1050		fmt.Fprintf(h, "vetflags %q\n", vetFlags)
  1051	
  1052		fmt.Fprintf(h, "pkg %q\n", a.Deps[0].actionID)
  1053		for _, a1 := range a.Deps {
  1054			if a1.Mode == "vet" && a1.built != "" {
  1055				fmt.Fprintf(h, "vetout %q %s\n", a1.Package.ImportPath, b.fileHash(a1.built))
  1056				vcfg.PackageVetx[a1.Package.ImportPath] = a1.built
  1057			}
  1058		}
  1059		key := cache.ActionID(h.Sum())
  1060	
  1061		if vcfg.VetxOnly {
  1062			if c := cache.Default(); c != nil && !cfg.BuildA {
  1063				if file, _, err := c.GetFile(key); err == nil {
  1064					a.built = file
  1065					return nil
  1066				}
  1067			}
  1068		}
  1069	
  1070		js, err := json.MarshalIndent(vcfg, "", "\t")
  1071		if err != nil {
  1072			return fmt.Errorf("internal error marshaling vet config: %v", err)
  1073		}
  1074		js = append(js, '\n')
  1075		if err := b.writeFile(a.Objdir+"vet.cfg", js); err != nil {
  1076			return err
  1077		}
  1078	
  1079		env := b.cCompilerEnv()
  1080		if cfg.BuildToolchainName == "gccgo" {
  1081			env = append(env, "GCCGO="+BuildToolchain.compiler())
  1082		}
  1083	
  1084		p := a.Package
  1085		tool := VetTool
  1086		if tool == "" {
  1087			tool = base.Tool("vet")
  1088		}
  1089		runErr := b.run(a, p.Dir, p.ImportPath, env, cfg.BuildToolexec, tool, vetFlags, a.Objdir+"vet.cfg")
  1090	
  1091		
  1092		if f, err := os.Open(vcfg.VetxOutput); err == nil {
  1093			a.built = vcfg.VetxOutput
  1094			if c := cache.Default(); c != nil {
  1095				c.Put(key, f)
  1096			}
  1097			f.Close()
  1098		}
  1099	
  1100		return runErr
  1101	}
  1102	
  1103	
  1104	func (b *Builder) linkActionID(a *Action) cache.ActionID {
  1105		p := a.Package
  1106		h := cache.NewHash("link " + p.ImportPath)
  1107	
  1108		
  1109		fmt.Fprintf(h, "link\n")
  1110		fmt.Fprintf(h, "buildmode %s goos %s goarch %s\n", cfg.BuildBuildmode, cfg.Goos, cfg.Goarch)
  1111		fmt.Fprintf(h, "import %q\n", p.ImportPath)
  1112		fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix)
  1113		if cfg.BuildTrimpath {
  1114			fmt.Fprintln(h, "trimpath")
  1115		}
  1116	
  1117		
  1118		b.printLinkerConfig(h, p)
  1119	
  1120		
  1121		for _, a1 := range a.Deps {
  1122			p1 := a1.Package
  1123			if p1 != nil {
  1124				if a1.built != "" || a1.buildID != "" {
  1125					buildID := a1.buildID
  1126					if buildID == "" {
  1127						buildID = b.buildID(a1.built)
  1128					}
  1129					fmt.Fprintf(h, "packagefile %s=%s\n", p1.ImportPath, contentID(buildID))
  1130				}
  1131				
  1132				
  1133				if p1.Name == "main" {
  1134					fmt.Fprintf(h, "packagemain %s\n", a1.buildID)
  1135				}
  1136				if p1.Shlib != "" {
  1137					fmt.Fprintf(h, "packageshlib %s=%s\n", p1.ImportPath, contentID(b.buildID(p1.Shlib)))
  1138				}
  1139			}
  1140		}
  1141	
  1142		return h.Sum()
  1143	}
  1144	
  1145	
  1146	
  1147	func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) {
  1148		switch cfg.BuildToolchainName {
  1149		default:
  1150			base.Fatalf("linkActionID: unknown toolchain %q", cfg.BuildToolchainName)
  1151	
  1152		case "gc":
  1153			fmt.Fprintf(h, "link %s %q %s\n", b.toolID("link"), forcedLdflags, ldBuildmode)
  1154			if p != nil {
  1155				fmt.Fprintf(h, "linkflags %q\n", p.Internal.Ldflags)
  1156			}
  1157	
  1158			
  1159			key, val := cfg.GetArchEnv()
  1160			fmt.Fprintf(h, "%s=%s\n", key, val)
  1161	
  1162			
  1163			fmt.Fprintf(h, "GOROOT=%s\n", cfg.GOROOT_FINAL)
  1164	
  1165			
  1166			fmt.Fprintf(h, "GO_EXTLINK_ENABLED=%s\n", cfg.Getenv("GO_EXTLINK_ENABLED"))
  1167	
  1168			
  1169			
  1170	
  1171		case "gccgo":
  1172			id, err := b.gccgoToolID(BuildToolchain.linker(), "go")
  1173			if err != nil {
  1174				base.Fatalf("%v", err)
  1175			}
  1176			fmt.Fprintf(h, "link %s %s\n", id, ldBuildmode)
  1177			
  1178		}
  1179	}
  1180	
  1181	
  1182	
  1183	func (b *Builder) link(a *Action) (err error) {
  1184		if b.useCache(a, a.Package, b.linkActionID(a), a.Package.Target) || b.IsCmdList {
  1185			return nil
  1186		}
  1187		defer b.flushOutput(a)
  1188	
  1189		if err := b.Mkdir(a.Objdir); err != nil {
  1190			return err
  1191		}
  1192	
  1193		importcfg := a.Objdir + "importcfg.link"
  1194		if err := b.writeLinkImportcfg(a, importcfg); err != nil {
  1195			return err
  1196		}
  1197	
  1198		
  1199		dir, _ := filepath.Split(a.Target)
  1200		if dir != "" {
  1201			if err := b.Mkdir(dir); err != nil {
  1202				return err
  1203			}
  1204		}
  1205	
  1206		if err := BuildToolchain.ld(b, a, a.Target, importcfg, a.Deps[0].built); err != nil {
  1207			return err
  1208		}
  1209	
  1210		
  1211		
  1212		
  1213		
  1214		
  1215		
  1216		
  1217		
  1218		
  1219		
  1220		
  1221		
  1222		
  1223		
  1224		
  1225		
  1226		if err := b.updateBuildID(a, a.Target, !a.Package.Internal.OmitDebug); err != nil {
  1227			return err
  1228		}
  1229	
  1230		a.built = a.Target
  1231		return nil
  1232	}
  1233	
  1234	func (b *Builder) writeLinkImportcfg(a *Action, file string) error {
  1235		
  1236		var icfg bytes.Buffer
  1237		for _, a1 := range a.Deps {
  1238			p1 := a1.Package
  1239			if p1 == nil {
  1240				continue
  1241			}
  1242			fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built)
  1243			if p1.Shlib != "" {
  1244				fmt.Fprintf(&icfg, "packageshlib %s=%s\n", p1.ImportPath, p1.Shlib)
  1245			}
  1246		}
  1247		return b.writeFile(file, icfg.Bytes())
  1248	}
  1249	
  1250	
  1251	
  1252	func (b *Builder) PkgconfigCmd() string {
  1253		return envList("PKG_CONFIG", cfg.DefaultPkgConfig)[0]
  1254	}
  1255	
  1256	
  1257	
  1258	func splitPkgConfigOutput(out []byte) ([]string, error) {
  1259		if len(out) == 0 {
  1260			return nil, nil
  1261		}
  1262		var flags []string
  1263		flag := make([]byte, 0, len(out))
  1264		escaped := false
  1265		quote := byte(0)
  1266	
  1267		for _, c := range out {
  1268			if escaped {
  1269				if quote != 0 {
  1270					switch c {
  1271					case '$', '`', '"', '\\':
  1272					default:
  1273						flag = append(flag, '\\')
  1274					}
  1275					flag = append(flag, c)
  1276				} else {
  1277					flag = append(flag, c)
  1278				}
  1279				escaped = false
  1280			} else if quote != 0 {
  1281				if c == quote {
  1282					quote = 0
  1283				} else {
  1284					switch c {
  1285					case '\\':
  1286						escaped = true
  1287					default:
  1288						flag = append(flag, c)
  1289					}
  1290				}
  1291			} else if strings.IndexByte(" \t\n\v\f\r", c) < 0 {
  1292				switch c {
  1293				case '\\':
  1294					escaped = true
  1295				case '\'', '"':
  1296					quote = c
  1297				default:
  1298					flag = append(flag, c)
  1299				}
  1300			} else if len(flag) != 0 {
  1301				flags = append(flags, string(flag))
  1302				flag = flag[:0]
  1303			}
  1304		}
  1305		if escaped {
  1306			return nil, errors.New("broken character escaping in pkgconf output ")
  1307		}
  1308		if quote != 0 {
  1309			return nil, errors.New("unterminated quoted string in pkgconf output ")
  1310		} else if len(flag) != 0 {
  1311			flags = append(flags, string(flag))
  1312		}
  1313	
  1314		return flags, nil
  1315	}
  1316	
  1317	
  1318	func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, err error) {
  1319		if pcargs := p.CgoPkgConfig; len(pcargs) > 0 {
  1320			
  1321			
  1322			var pcflags []string
  1323			var pkgs []string
  1324			for _, pcarg := range pcargs {
  1325				if pcarg == "--" {
  1326					
  1327				} else if strings.HasPrefix(pcarg, "--") {
  1328					pcflags = append(pcflags, pcarg)
  1329				} else {
  1330					pkgs = append(pkgs, pcarg)
  1331				}
  1332			}
  1333			for _, pkg := range pkgs {
  1334				if !load.SafeArg(pkg) {
  1335					return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg)
  1336				}
  1337			}
  1338			var out []byte
  1339			out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs)
  1340			if err != nil {
  1341				b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
  1342				b.Print(err.Error() + "\n")
  1343				return nil, nil, errPrintedOutput
  1344			}
  1345			if len(out) > 0 {
  1346				cflags, err = splitPkgConfigOutput(out)
  1347				if err != nil {
  1348					return nil, nil, err
  1349				}
  1350				if err := checkCompilerFlags("CFLAGS", "pkg-config --cflags", cflags); err != nil {
  1351					return nil, nil, err
  1352				}
  1353			}
  1354			out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs)
  1355			if err != nil {
  1356				b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
  1357				b.Print(err.Error() + "\n")
  1358				return nil, nil, errPrintedOutput
  1359			}
  1360			if len(out) > 0 {
  1361				ldflags = strings.Fields(string(out))
  1362				if err := checkLinkerFlags("LDFLAGS", "pkg-config --libs", ldflags); err != nil {
  1363					return nil, nil, err
  1364				}
  1365			}
  1366		}
  1367	
  1368		return
  1369	}
  1370	
  1371	func (b *Builder) installShlibname(a *Action) error {
  1372		
  1373		a1 := a.Deps[0]
  1374		err := ioutil.WriteFile(a.Target, []byte(filepath.Base(a1.Target)+"\n"), 0666)
  1375		if err != nil {
  1376			return err
  1377		}
  1378		if cfg.BuildX {
  1379			b.Showcmd("", "echo '%s' > %s # internal", filepath.Base(a1.Target), a.Target)
  1380		}
  1381		return nil
  1382	}
  1383	
  1384	func (b *Builder) linkSharedActionID(a *Action) cache.ActionID {
  1385		h := cache.NewHash("linkShared")
  1386	
  1387		
  1388		fmt.Fprintf(h, "linkShared\n")
  1389		fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch)
  1390	
  1391		
  1392		b.printLinkerConfig(h, nil)
  1393	
  1394		
  1395		for _, a1 := range a.Deps {
  1396			p1 := a1.Package
  1397			if a1.built == "" {
  1398				continue
  1399			}
  1400			if p1 != nil {
  1401				fmt.Fprintf(h, "packagefile %s=%s\n", p1.ImportPath, contentID(b.buildID(a1.built)))
  1402				if p1.Shlib != "" {
  1403					fmt.Fprintf(h, "packageshlib %s=%s\n", p1.ImportPath, contentID(b.buildID(p1.Shlib)))
  1404				}
  1405			}
  1406		}
  1407		
  1408		for _, a1 := range a.Deps[0].Deps {
  1409			p1 := a1.Package
  1410			fmt.Fprintf(h, "top %s=%s\n", p1.ImportPath, contentID(b.buildID(a1.built)))
  1411		}
  1412	
  1413		return h.Sum()
  1414	}
  1415	
  1416	func (b *Builder) linkShared(a *Action) (err error) {
  1417		if b.useCache(a, nil, b.linkSharedActionID(a), a.Target) || b.IsCmdList {
  1418			return nil
  1419		}
  1420		defer b.flushOutput(a)
  1421	
  1422		if err := b.Mkdir(a.Objdir); err != nil {
  1423			return err
  1424		}
  1425	
  1426		importcfg := a.Objdir + "importcfg.link"
  1427		if err := b.writeLinkImportcfg(a, importcfg); err != nil {
  1428			return err
  1429		}
  1430	
  1431		
  1432		
  1433		a.built = a.Target
  1434		return BuildToolchain.ldShared(b, a, a.Deps[0].Deps, a.Target, importcfg, a.Deps)
  1435	}
  1436	
  1437	
  1438	func BuildInstallFunc(b *Builder, a *Action) (err error) {
  1439		defer func() {
  1440			if err != nil && err != errPrintedOutput {
  1441				
  1442				
  1443				
  1444				sep, path := "", ""
  1445				if a.Package != nil {
  1446					sep, path = " ", a.Package.ImportPath
  1447				}
  1448				err = fmt.Errorf("go %s%s%s: %v", cfg.CmdName, sep, path, err)
  1449			}
  1450		}()
  1451	
  1452		a1 := a.Deps[0]
  1453		a.buildID = a1.buildID
  1454		if a.json != nil {
  1455			a.json.BuildID = a.buildID
  1456		}
  1457	
  1458		
  1459		
  1460		
  1461		
  1462		
  1463		if a1.built == a.Target {
  1464			a.built = a.Target
  1465			if !a.buggyInstall {
  1466				b.cleanup(a1)
  1467			}
  1468			
  1469			
  1470			
  1471			
  1472			
  1473			
  1474			
  1475			
  1476			
  1477			
  1478			
  1479			
  1480			
  1481			
  1482			
  1483			
  1484			
  1485			
  1486			if !a.buggyInstall && !b.IsCmdList {
  1487				now := time.Now()
  1488				os.Chtimes(a.Target, now, now)
  1489			}
  1490			return nil
  1491		}
  1492	
  1493		
  1494		
  1495		if b.IsCmdList {
  1496			a.built = a1.built
  1497			return nil
  1498		}
  1499	
  1500		if err := b.Mkdir(a.Objdir); err != nil {
  1501			return err
  1502		}
  1503	
  1504		perm := os.FileMode(0666)
  1505		if a1.Mode == "link" {
  1506			switch cfg.BuildBuildmode {
  1507			case "c-archive", "c-shared", "plugin":
  1508			default:
  1509				perm = 0777
  1510			}
  1511		}
  1512	
  1513		
  1514		dir, _ := filepath.Split(a.Target)
  1515		if dir != "" {
  1516			if err := b.Mkdir(dir); err != nil {
  1517				return err
  1518			}
  1519		}
  1520	
  1521		if !a.buggyInstall {
  1522			defer b.cleanup(a1)
  1523		}
  1524	
  1525		return b.moveOrCopyFile(a.Target, a1.built, perm, false)
  1526	}
  1527	
  1528	
  1529	
  1530	
  1531	
  1532	func (b *Builder) cleanup(a *Action) {
  1533		if !cfg.BuildWork {
  1534			if cfg.BuildX {
  1535				
  1536				
  1537				if _, err := os.Stat(a.Objdir); err == nil || cfg.BuildN {
  1538					b.Showcmd("", "rm -r %s", a.Objdir)
  1539				}
  1540			}
  1541			os.RemoveAll(a.Objdir)
  1542		}
  1543	}
  1544	
  1545	
  1546	func (b *Builder) moveOrCopyFile(dst, src string, perm os.FileMode, force bool) error {
  1547		if cfg.BuildN {
  1548			b.Showcmd("", "mv %s %s", src, dst)
  1549			return nil
  1550		}
  1551	
  1552		
  1553		
  1554	
  1555		
  1556		if strings.HasPrefix(src, cache.DefaultDir()) {
  1557			return b.copyFile(dst, src, perm, force)
  1558		}
  1559	
  1560		
  1561		
  1562		
  1563		
  1564		if runtime.GOOS == "windows" {
  1565			return b.copyFile(dst, src, perm, force)
  1566		}
  1567	
  1568		
  1569		
  1570		
  1571		if fi, err := os.Stat(filepath.Dir(dst)); err == nil {
  1572			if fi.IsDir() && (fi.Mode()&os.ModeSetgid) != 0 {
  1573				return b.copyFile(dst, src, perm, force)
  1574			}
  1575		}
  1576	
  1577		
  1578		
  1579		
  1580		
  1581		
  1582		mode := perm
  1583		f, err := os.OpenFile(filepath.Clean(dst)+"-go-tmp-umask", os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
  1584		if err == nil {
  1585			fi, err := f.Stat()
  1586			if err == nil {
  1587				mode = fi.Mode() & 0777
  1588			}
  1589			name := f.Name()
  1590			f.Close()
  1591			os.Remove(name)
  1592		}
  1593	
  1594		if err := os.Chmod(src, mode); err == nil {
  1595			if err := os.Rename(src, dst); err == nil {
  1596				if cfg.BuildX {
  1597					b.Showcmd("", "mv %s %s", src, dst)
  1598				}
  1599				return nil
  1600			}
  1601		}
  1602	
  1603		return b.copyFile(dst, src, perm, force)
  1604	}
  1605	
  1606	
  1607	func (b *Builder) copyFile(dst, src string, perm os.FileMode, force bool) error {
  1608		if cfg.BuildN || cfg.BuildX {
  1609			b.Showcmd("", "cp %s %s", src, dst)
  1610			if cfg.BuildN {
  1611				return nil
  1612			}
  1613		}
  1614	
  1615		sf, err := os.Open(src)
  1616		if err != nil {
  1617			return err
  1618		}
  1619		defer sf.Close()
  1620	
  1621		
  1622		
  1623		
  1624		if fi, err := os.Stat(dst); err == nil {
  1625			if fi.IsDir() {
  1626				return fmt.Errorf("build output %q already exists and is a directory", dst)
  1627			}
  1628			if !force && fi.Mode().IsRegular() && !isObject(dst) {
  1629				return fmt.Errorf("build output %q already exists and is not an object file", dst)
  1630			}
  1631		}
  1632	
  1633		
  1634		if base.ToolIsWindows {
  1635			if _, err := os.Stat(dst + "~"); err == nil {
  1636				os.Remove(dst + "~")
  1637			}
  1638		}
  1639	
  1640		mayberemovefile(dst)
  1641		df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
  1642		if err != nil && base.ToolIsWindows {
  1643			
  1644			
  1645			
  1646			
  1647			if err := os.Rename(dst, dst+"~"); err == nil {
  1648				os.Remove(dst + "~")
  1649			}
  1650			df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
  1651		}
  1652		if err != nil {
  1653			return err
  1654		}
  1655	
  1656		_, err = io.Copy(df, sf)
  1657		df.Close()
  1658		if err != nil {
  1659			mayberemovefile(dst)
  1660			return fmt.Errorf("copying %s to %s: %v", src, dst, err)
  1661		}
  1662		return nil
  1663	}
  1664	
  1665	
  1666	func (b *Builder) writeFile(file string, text []byte) error {
  1667		if cfg.BuildN || cfg.BuildX {
  1668			b.Showcmd("", "cat >%s << 'EOF' # internal\n%sEOF", file, text)
  1669		}
  1670		if cfg.BuildN {
  1671			return nil
  1672		}
  1673		return ioutil.WriteFile(file, text, 0666)
  1674	}
  1675	
  1676	
  1677	func (b *Builder) installHeader(a *Action) error {
  1678		src := a.Objdir + "_cgo_install.h"
  1679		if _, err := os.Stat(src); os.IsNotExist(err) {
  1680			
  1681			
  1682			
  1683			
  1684			
  1685			if cfg.BuildX {
  1686				b.Showcmd("", "# %s not created", src)
  1687			}
  1688			return nil
  1689		}
  1690	
  1691		dir, _ := filepath.Split(a.Target)
  1692		if dir != "" {
  1693			if err := b.Mkdir(dir); err != nil {
  1694				return err
  1695			}
  1696		}
  1697	
  1698		return b.moveOrCopyFile(a.Target, src, 0666, true)
  1699	}
  1700	
  1701	
  1702	
  1703	func (b *Builder) cover(a *Action, dst, src string, varName string) error {
  1704		return b.run(a, a.Objdir, "cover "+a.Package.ImportPath, nil,
  1705			cfg.BuildToolexec,
  1706			base.Tool("cover"),
  1707			"-mode", a.Package.Internal.CoverMode,
  1708			"-var", varName,
  1709			"-o", dst,
  1710			src)
  1711	}
  1712	
  1713	var objectMagic = [][]byte{
  1714		{'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}, 
  1715		{'<', 'b', 'i', 'g', 'a', 'f', '>', '\n'}, 
  1716		{'\x7F', 'E', 'L', 'F'},                   
  1717		{0xFE, 0xED, 0xFA, 0xCE},                  
  1718		{0xFE, 0xED, 0xFA, 0xCF},                  
  1719		{0xCE, 0xFA, 0xED, 0xFE},                  
  1720		{0xCF, 0xFA, 0xED, 0xFE},                  
  1721		{0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00},      
  1722		{0x00, 0x00, 0x01, 0xEB},                  
  1723		{0x00, 0x00, 0x8a, 0x97},                  
  1724		{0x00, 0x00, 0x06, 0x47},                  
  1725		{0x00, 0x61, 0x73, 0x6D},                  
  1726		{0x01, 0xDF},                              
  1727		{0x01, 0xF7},                              
  1728	}
  1729	
  1730	func isObject(s string) bool {
  1731		f, err := os.Open(s)
  1732		if err != nil {
  1733			return false
  1734		}
  1735		defer f.Close()
  1736		buf := make([]byte, 64)
  1737		io.ReadFull(f, buf)
  1738		for _, magic := range objectMagic {
  1739			if bytes.HasPrefix(buf, magic) {
  1740				return true
  1741			}
  1742		}
  1743		return false
  1744	}
  1745	
  1746	
  1747	
  1748	
  1749	func mayberemovefile(s string) {
  1750		if fi, err := os.Lstat(s); err == nil && !fi.Mode().IsRegular() {
  1751			return
  1752		}
  1753		os.Remove(s)
  1754	}
  1755	
  1756	
  1757	
  1758	
  1759	
  1760	
  1761	
  1762	
  1763	
  1764	
  1765	
  1766	
  1767	
  1768	func (b *Builder) fmtcmd(dir string, format string, args ...interface{}) string {
  1769		cmd := fmt.Sprintf(format, args...)
  1770		if dir != "" && dir != "/" {
  1771			dot := " ."
  1772			if dir[len(dir)-1] == filepath.Separator {
  1773				dot += string(filepath.Separator)
  1774			}
  1775			cmd = strings.ReplaceAll(" "+cmd, " "+dir, dot)[1:]
  1776			if b.scriptDir != dir {
  1777				b.scriptDir = dir
  1778				cmd = "cd " + dir + "\n" + cmd
  1779			}
  1780		}
  1781		if b.WorkDir != "" {
  1782			cmd = strings.ReplaceAll(cmd, b.WorkDir, "$WORK")
  1783		}
  1784		return cmd
  1785	}
  1786	
  1787	
  1788	
  1789	func (b *Builder) Showcmd(dir string, format string, args ...interface{}) {
  1790		b.output.Lock()
  1791		defer b.output.Unlock()
  1792		b.Print(b.fmtcmd(dir, format, args...) + "\n")
  1793	}
  1794	
  1795	
  1796	
  1797	
  1798	
  1799	
  1800	
  1801	
  1802	
  1803	
  1804	
  1805	
  1806	
  1807	
  1808	
  1809	
  1810	
  1811	
  1812	
  1813	
  1814	
  1815	
  1816	
  1817	
  1818	
  1819	
  1820	func (b *Builder) showOutput(a *Action, dir, desc, out string) {
  1821		prefix := "# " + desc
  1822		suffix := "\n" + out
  1823		if reldir := base.ShortPath(dir); reldir != dir {
  1824			suffix = strings.ReplaceAll(suffix, " "+dir, " "+reldir)
  1825			suffix = strings.ReplaceAll(suffix, "\n"+dir, "\n"+reldir)
  1826		}
  1827		suffix = strings.ReplaceAll(suffix, " "+b.WorkDir, " $WORK")
  1828	
  1829		if a != nil && a.output != nil {
  1830			a.output = append(a.output, prefix...)
  1831			a.output = append(a.output, suffix...)
  1832			return
  1833		}
  1834	
  1835		b.output.Lock()
  1836		defer b.output.Unlock()
  1837		b.Print(prefix, suffix)
  1838	}
  1839	
  1840	
  1841	
  1842	
  1843	
  1844	
  1845	var errPrintedOutput = errors.New("already printed output - no need to show error")
  1846	
  1847	var cgoLine = lazyregexp.New(`\[[^\[\]]+\.(cgo1|cover)\.go:[0-9]+(:[0-9]+)?\]`)
  1848	var cgoTypeSigRe = lazyregexp.New(`\b_C2?(type|func|var|macro)_\B`)
  1849	
  1850	
  1851	
  1852	
  1853	func (b *Builder) run(a *Action, dir string, desc string, env []string, cmdargs ...interface{}) error {
  1854		out, err := b.runOut(a, dir, env, cmdargs...)
  1855		if len(out) > 0 {
  1856			if desc == "" {
  1857				desc = b.fmtcmd(dir, "%s", strings.Join(str.StringList(cmdargs...), " "))
  1858			}
  1859			b.showOutput(a, dir, desc, b.processOutput(out))
  1860			if err != nil {
  1861				err = errPrintedOutput
  1862			}
  1863		}
  1864		return err
  1865	}
  1866	
  1867	
  1868	func (b *Builder) processOutput(out []byte) string {
  1869		if out[len(out)-1] != '\n' {
  1870			out = append(out, '\n')
  1871		}
  1872		messages := string(out)
  1873		
  1874		
  1875		
  1876		
  1877		if !cfg.BuildX && cgoLine.MatchString(messages) {
  1878			messages = cgoLine.ReplaceAllString(messages, "")
  1879			messages = cgoTypeSigRe.ReplaceAllString(messages, "C.")
  1880		}
  1881		return messages
  1882	}
  1883	
  1884	
  1885	
  1886	
  1887	func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...interface{}) ([]byte, error) {
  1888		cmdline := str.StringList(cmdargs...)
  1889	
  1890		for _, arg := range cmdline {
  1891			
  1892			
  1893			
  1894			
  1895			if strings.HasPrefix(arg, "@") {
  1896				return nil, fmt.Errorf("invalid command-line argument %s in command: %s", arg, joinUnambiguously(cmdline))
  1897			}
  1898		}
  1899	
  1900		if cfg.BuildN || cfg.BuildX {
  1901			var envcmdline string
  1902			for _, e := range env {
  1903				if j := strings.IndexByte(e, '='); j != -1 {
  1904					if strings.ContainsRune(e[j+1:], '\'') {
  1905						envcmdline += fmt.Sprintf("%s=%q", e[:j], e[j+1:])
  1906					} else {
  1907						envcmdline += fmt.Sprintf("%s='%s'", e[:j], e[j+1:])
  1908					}
  1909					envcmdline += " "
  1910				}
  1911			}
  1912			envcmdline += joinUnambiguously(cmdline)
  1913			b.Showcmd(dir, "%s", envcmdline)
  1914			if cfg.BuildN {
  1915				return nil, nil
  1916			}
  1917		}
  1918	
  1919		var buf bytes.Buffer
  1920		cmd := exec.Command(cmdline[0], cmdline[1:]...)
  1921		cmd.Stdout = &buf
  1922		cmd.Stderr = &buf
  1923		cleanup := passLongArgsInResponseFiles(cmd)
  1924		defer cleanup()
  1925		cmd.Dir = dir
  1926		cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
  1927		cmd.Env = append(cmd.Env, env...)
  1928		start := time.Now()
  1929		err := cmd.Run()
  1930		if a != nil && a.json != nil {
  1931			aj := a.json
  1932			aj.Cmd = append(aj.Cmd, joinUnambiguously(cmdline))
  1933			aj.CmdReal += time.Since(start)
  1934			if ps := cmd.ProcessState; ps != nil {
  1935				aj.CmdUser += ps.UserTime()
  1936				aj.CmdSys += ps.SystemTime()
  1937			}
  1938		}
  1939	
  1940		
  1941		
  1942		
  1943		
  1944		
  1945		if err != nil {
  1946			err = errors.New(cmdline[0] + ": " + err.Error())
  1947		}
  1948		return buf.Bytes(), err
  1949	}
  1950	
  1951	
  1952	
  1953	
  1954	func joinUnambiguously(a []string) string {
  1955		var buf bytes.Buffer
  1956		for i, s := range a {
  1957			if i > 0 {
  1958				buf.WriteByte(' ')
  1959			}
  1960			q := strconv.Quote(s)
  1961			
  1962			
  1963			
  1964			if s == "" || strings.ContainsAny(s, " ()>;") || len(q) > len(s)+2 {
  1965				buf.WriteString(q)
  1966			} else {
  1967				buf.WriteString(s)
  1968			}
  1969		}
  1970		return buf.String()
  1971	}
  1972	
  1973	
  1974	
  1975	
  1976	func (b *Builder) cCompilerEnv() []string {
  1977		return []string{"TERM=dumb"}
  1978	}
  1979	
  1980	
  1981	func (b *Builder) Mkdir(dir string) error {
  1982		
  1983		if dir == "" {
  1984			return nil
  1985		}
  1986	
  1987		b.exec.Lock()
  1988		defer b.exec.Unlock()
  1989		
  1990		
  1991		if b.mkdirCache[dir] {
  1992			return nil
  1993		}
  1994		b.mkdirCache[dir] = true
  1995	
  1996		if cfg.BuildN || cfg.BuildX {
  1997			b.Showcmd("", "mkdir -p %s", dir)
  1998			if cfg.BuildN {
  1999				return nil
  2000			}
  2001		}
  2002	
  2003		if err := os.MkdirAll(dir, 0777); err != nil {
  2004			return err
  2005		}
  2006		return nil
  2007	}
  2008	
  2009	
  2010	func (b *Builder) Symlink(oldname, newname string) error {
  2011		
  2012		if link, err := os.Readlink(newname); err == nil && link == oldname {
  2013			return nil
  2014		}
  2015	
  2016		if cfg.BuildN || cfg.BuildX {
  2017			b.Showcmd("", "ln -s %s %s", oldname, newname)
  2018			if cfg.BuildN {
  2019				return nil
  2020			}
  2021		}
  2022		return os.Symlink(oldname, newname)
  2023	}
  2024	
  2025	
  2026	
  2027	
  2028	
  2029	
  2030	func mkAbs(dir, f string) string {
  2031		
  2032		
  2033		
  2034		
  2035		if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") {
  2036			return f
  2037		}
  2038		return filepath.Join(dir, f)
  2039	}
  2040	
  2041	type toolchain interface {
  2042		
  2043		
  2044		
  2045		
  2046		gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error)
  2047		
  2048		
  2049		cc(b *Builder, a *Action, ofile, cfile string) error
  2050		
  2051		
  2052		asm(b *Builder, a *Action, sfiles []string) ([]string, error)
  2053		
  2054		
  2055		symabis(b *Builder, a *Action, sfiles []string) (string, error)
  2056		
  2057		
  2058		
  2059		pack(b *Builder, a *Action, afile string, ofiles []string) error
  2060		
  2061		ld(b *Builder, root *Action, out, importcfg, mainpkg string) error
  2062		
  2063		ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error
  2064	
  2065		compiler() string
  2066		linker() string
  2067	}
  2068	
  2069	type noToolchain struct{}
  2070	
  2071	func noCompiler() error {
  2072		log.Fatalf("unknown compiler %q", cfg.BuildContext.Compiler)
  2073		return nil
  2074	}
  2075	
  2076	func (noToolchain) compiler() string {
  2077		noCompiler()
  2078		return ""
  2079	}
  2080	
  2081	func (noToolchain) linker() string {
  2082		noCompiler()
  2083		return ""
  2084	}
  2085	
  2086	func (noToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) {
  2087		return "", nil, noCompiler()
  2088	}
  2089	
  2090	func (noToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) {
  2091		return nil, noCompiler()
  2092	}
  2093	
  2094	func (noToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
  2095		return "", noCompiler()
  2096	}
  2097	
  2098	func (noToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error {
  2099		return noCompiler()
  2100	}
  2101	
  2102	func (noToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string) error {
  2103		return noCompiler()
  2104	}
  2105	
  2106	func (noToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
  2107		return noCompiler()
  2108	}
  2109	
  2110	func (noToolchain) cc(b *Builder, a *Action, ofile, cfile string) error {
  2111		return noCompiler()
  2112	}
  2113	
  2114	
  2115	func (b *Builder) gcc(a *Action, p *load.Package, workdir, out string, flags []string, cfile string) error {
  2116		return b.ccompile(a, p, out, flags, cfile, b.GccCmd(p.Dir, workdir))
  2117	}
  2118	
  2119	
  2120	func (b *Builder) gxx(a *Action, p *load.Package, workdir, out string, flags []string, cxxfile string) error {
  2121		return b.ccompile(a, p, out, flags, cxxfile, b.GxxCmd(p.Dir, workdir))
  2122	}
  2123	
  2124	
  2125	func (b *Builder) gfortran(a *Action, p *load.Package, workdir, out string, flags []string, ffile string) error {
  2126		return b.ccompile(a, p, out, flags, ffile, b.gfortranCmd(p.Dir, workdir))
  2127	}
  2128	
  2129	
  2130	func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []string, file string, compiler []string) error {
  2131		file = mkAbs(p.Dir, file)
  2132		desc := p.ImportPath
  2133		if !filepath.IsAbs(outfile) {
  2134			outfile = filepath.Join(p.Dir, outfile)
  2135		}
  2136		output, err := b.runOut(a, filepath.Dir(file), b.cCompilerEnv(), compiler, flags, "-o", outfile, "-c", filepath.Base(file))
  2137		if len(output) > 0 {
  2138			
  2139			
  2140			
  2141			
  2142			
  2143			
  2144			
  2145			
  2146			if bytes.Contains(output, []byte("DWARF2 only supports one section per compilation unit")) {
  2147				newFlags := make([]string, 0, len(flags))
  2148				for _, f := range flags {
  2149					if !strings.HasPrefix(f, "-g") {
  2150						newFlags = append(newFlags, f)
  2151					}
  2152				}
  2153				if len(newFlags) < len(flags) {
  2154					return b.ccompile(a, p, outfile, newFlags, file, compiler)
  2155				}
  2156			}
  2157	
  2158			b.showOutput(a, p.Dir, desc, b.processOutput(output))
  2159			if err != nil {
  2160				err = errPrintedOutput
  2161			} else if os.Getenv("GO_BUILDER_NAME") != "" {
  2162				return errors.New("C compiler warning promoted to error on Go builders")
  2163			}
  2164		}
  2165		return err
  2166	}
  2167	
  2168	
  2169	func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flags []string, objs []string) error {
  2170		var cmd []string
  2171		if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 {
  2172			cmd = b.GxxCmd(p.Dir, objdir)
  2173		} else {
  2174			cmd = b.GccCmd(p.Dir, objdir)
  2175		}
  2176	
  2177		cmdargs := []interface{}{cmd, "-o", outfile, objs, flags}
  2178		dir := p.Dir
  2179		out, err := b.runOut(a, dir, b.cCompilerEnv(), cmdargs...)
  2180		if len(out) > 0 {
  2181			
  2182			
  2183			var save [][]byte
  2184			var skipLines int
  2185			for _, line := range bytes.SplitAfter(out, []byte("\n")) {
  2186				
  2187				if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
  2188					continue
  2189				}
  2190	
  2191				if skipLines > 0 {
  2192					skipLines--
  2193					continue
  2194				}
  2195	
  2196				
  2197				
  2198				
  2199				
  2200				
  2201				
  2202				
  2203				
  2204				
  2205				if p.ImportPath == "runtime/cgo" && bytes.Contains(line, []byte("ld: 0711-224 WARNING: Duplicate symbol: .main")) {
  2206					skipLines = 1
  2207					continue
  2208				}
  2209	
  2210				save = append(save, line)
  2211			}
  2212			out = bytes.Join(save, nil)
  2213			if len(out) > 0 {
  2214				b.showOutput(nil, dir, p.ImportPath, b.processOutput(out))
  2215				if err != nil {
  2216					err = errPrintedOutput
  2217				}
  2218			}
  2219		}
  2220		return err
  2221	}
  2222	
  2223	
  2224	var (
  2225		origCC  = cfg.Getenv("CC")
  2226		origCXX = cfg.Getenv("CXX")
  2227	)
  2228	
  2229	
  2230	
  2231	func (b *Builder) GccCmd(incdir, workdir string) []string {
  2232		return b.compilerCmd(b.ccExe(), incdir, workdir)
  2233	}
  2234	
  2235	
  2236	
  2237	func (b *Builder) GxxCmd(incdir, workdir string) []string {
  2238		return b.compilerCmd(b.cxxExe(), incdir, workdir)
  2239	}
  2240	
  2241	
  2242	func (b *Builder) gfortranCmd(incdir, workdir string) []string {
  2243		return b.compilerCmd(b.fcExe(), incdir, workdir)
  2244	}
  2245	
  2246	
  2247	func (b *Builder) ccExe() []string {
  2248		return b.compilerExe(origCC, cfg.DefaultCC(cfg.Goos, cfg.Goarch))
  2249	}
  2250	
  2251	
  2252	func (b *Builder) cxxExe() []string {
  2253		return b.compilerExe(origCXX, cfg.DefaultCXX(cfg.Goos, cfg.Goarch))
  2254	}
  2255	
  2256	
  2257	func (b *Builder) fcExe() []string {
  2258		return b.compilerExe(cfg.Getenv("FC"), "gfortran")
  2259	}
  2260	
  2261	
  2262	
  2263	
  2264	
  2265	
  2266	
  2267	func (b *Builder) compilerExe(envValue string, def string) []string {
  2268		compiler := strings.Fields(envValue)
  2269		if len(compiler) == 0 {
  2270			compiler = []string{def}
  2271		}
  2272		return compiler
  2273	}
  2274	
  2275	
  2276	
  2277	func (b *Builder) compilerCmd(compiler []string, incdir, workdir string) []string {
  2278		
  2279		
  2280		a := []string{compiler[0], "-I", incdir}
  2281		a = append(a, compiler[1:]...)
  2282	
  2283		
  2284		
  2285		if cfg.Goos != "windows" {
  2286			a = append(a, "-fPIC")
  2287		}
  2288		a = append(a, b.gccArchArgs()...)
  2289		
  2290		
  2291		if cfg.BuildContext.CgoEnabled {
  2292			switch cfg.Goos {
  2293			case "windows":
  2294				a = append(a, "-mthreads")
  2295			default:
  2296				a = append(a, "-pthread")
  2297			}
  2298		}
  2299	
  2300		if cfg.Goos == "aix" {
  2301			
  2302			a = append(a, "-mcmodel=large")
  2303		}
  2304	
  2305		
  2306		if b.gccSupportsFlag(compiler, "-fno-caret-diagnostics") {
  2307			a = append(a, "-fno-caret-diagnostics")
  2308		}
  2309		
  2310		if b.gccSupportsFlag(compiler, "-Qunused-arguments") {
  2311			a = append(a, "-Qunused-arguments")
  2312		}
  2313	
  2314		
  2315		a = append(a, "-fmessage-length=0")
  2316	
  2317		
  2318		if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") {
  2319			if workdir == "" {
  2320				workdir = b.WorkDir
  2321			}
  2322			workdir = strings.TrimSuffix(workdir, string(filepath.Separator))
  2323			a = append(a, "-fdebug-prefix-map="+workdir+"=/tmp/go-build")
  2324		}
  2325	
  2326		
  2327		
  2328		if b.gccSupportsFlag(compiler, "-gno-record-gcc-switches") {
  2329			a = append(a, "-gno-record-gcc-switches")
  2330		}
  2331	
  2332		
  2333		
  2334		
  2335		if cfg.Goos == "darwin" {
  2336			a = append(a, "-fno-common")
  2337		}
  2338	
  2339		return a
  2340	}
  2341	
  2342	
  2343	
  2344	
  2345	
  2346	func (b *Builder) gccNoPie(linker []string) string {
  2347		if b.gccSupportsFlag(linker, "-no-pie") {
  2348			return "-no-pie"
  2349		}
  2350		if b.gccSupportsFlag(linker, "-nopie") {
  2351			return "-nopie"
  2352		}
  2353		return ""
  2354	}
  2355	
  2356	
  2357	func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
  2358		key := [2]string{compiler[0], flag}
  2359	
  2360		b.exec.Lock()
  2361		defer b.exec.Unlock()
  2362		if b, ok := b.flagCache[key]; ok {
  2363			return b
  2364		}
  2365		if b.flagCache == nil {
  2366			b.flagCache = make(map[[2]string]bool)
  2367		}
  2368		
  2369		
  2370		
  2371		
  2372		
  2373		
  2374		cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-", "-o", os.DevNull)
  2375		if cfg.BuildN || cfg.BuildX {
  2376			b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs))
  2377			if cfg.BuildN {
  2378				return false
  2379			}
  2380		}
  2381		cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
  2382		cmd.Dir = b.WorkDir
  2383		cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
  2384		cmd.Env = append(cmd.Env, "LC_ALL=C")
  2385		out, _ := cmd.CombinedOutput()
  2386		
  2387		
  2388		
  2389		
  2390		supported := !bytes.Contains(out, []byte("unrecognized")) &&
  2391			!bytes.Contains(out, []byte("unknown")) &&
  2392			!bytes.Contains(out, []byte("unrecognised")) &&
  2393			!bytes.Contains(out, []byte("is not supported"))
  2394		b.flagCache[key] = supported
  2395		return supported
  2396	}
  2397	
  2398	
  2399	func (b *Builder) gccArchArgs() []string {
  2400		switch cfg.Goarch {
  2401		case "386":
  2402			return []string{"-m32"}
  2403		case "amd64", "amd64p32":
  2404			return []string{"-m64"}
  2405		case "arm":
  2406			return []string{"-marm"} 
  2407		case "s390x":
  2408			return []string{"-m64", "-march=z196"}
  2409		case "mips64", "mips64le":
  2410			return []string{"-mabi=64"}
  2411		case "mips", "mipsle":
  2412			return []string{"-mabi=32", "-march=mips32"}
  2413		case "ppc64":
  2414			if cfg.Goos == "aix" {
  2415				return []string{"-maix64"}
  2416			}
  2417		}
  2418		return nil
  2419	}
  2420	
  2421	
  2422	
  2423	func envList(key, def string) []string {
  2424		v := cfg.Getenv(key)
  2425		if v == "" {
  2426			v = def
  2427		}
  2428		return strings.Fields(v)
  2429	}
  2430	
  2431	
  2432	func (b *Builder) CFlags(p *load.Package) (cppflags, cflags, cxxflags, fflags, ldflags []string, err error) {
  2433		defaults := "-g -O2"
  2434	
  2435		if cppflags, err = buildFlags("CPPFLAGS", "", p.CgoCPPFLAGS, checkCompilerFlags); err != nil {
  2436			return
  2437		}
  2438		if cflags, err = buildFlags("CFLAGS", defaults, p.CgoCFLAGS, checkCompilerFlags); err != nil {
  2439			return
  2440		}
  2441		if cxxflags, err = buildFlags("CXXFLAGS", defaults, p.CgoCXXFLAGS, checkCompilerFlags); err != nil {
  2442			return
  2443		}
  2444		if fflags, err = buildFlags("FFLAGS", defaults, p.CgoFFLAGS, checkCompilerFlags); err != nil {
  2445			return
  2446		}
  2447		if ldflags, err = buildFlags("LDFLAGS", defaults, p.CgoLDFLAGS, checkLinkerFlags); err != nil {
  2448			return
  2449		}
  2450	
  2451		return
  2452	}
  2453	
  2454	func buildFlags(name, defaults string, fromPackage []string, check func(string, string, []string) error) ([]string, error) {
  2455		if err := check(name, "#cgo "+name, fromPackage); err != nil {
  2456			return nil, err
  2457		}
  2458		return str.StringList(envList("CGO_"+name, defaults), fromPackage), nil
  2459	}
  2460	
  2461	var cgoRe = lazyregexp.New(`[/\\:]`)
  2462	
  2463	func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) {
  2464		p := a.Package
  2465		cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS, err := b.CFlags(p)
  2466		if err != nil {
  2467			return nil, nil, err
  2468		}
  2469	
  2470		cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
  2471		cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
  2472		
  2473		if len(mfiles) > 0 {
  2474			cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc")
  2475		}
  2476	
  2477		
  2478		
  2479		
  2480		if len(ffiles) > 0 {
  2481			fc := cfg.Getenv("FC")
  2482			if fc == "" {
  2483				fc = "gfortran"
  2484			}
  2485			if strings.Contains(fc, "gfortran") {
  2486				cgoLDFLAGS = append(cgoLDFLAGS, "-lgfortran")
  2487			}
  2488		}
  2489	
  2490		if cfg.BuildMSan {
  2491			cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
  2492			cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...)
  2493		}
  2494	
  2495		
  2496		cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", objdir)
  2497	
  2498		
  2499		
  2500		gofiles := []string{objdir + "_cgo_gotypes.go"}
  2501		cfiles := []string{"_cgo_export.c"}
  2502		for _, fn := range cgofiles {
  2503			f := strings.TrimSuffix(filepath.Base(fn), ".go")
  2504			gofiles = append(gofiles, objdir+f+".cgo1.go")
  2505			cfiles = append(cfiles, f+".cgo2.c")
  2506		}
  2507	
  2508		
  2509	
  2510		cgoflags := []string{}
  2511		if p.Standard && p.ImportPath == "runtime/cgo" {
  2512			cgoflags = append(cgoflags, "-import_runtime_cgo=false")
  2513		}
  2514		if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/msan" || p.ImportPath == "runtime/cgo") {
  2515			cgoflags = append(cgoflags, "-import_syscall=false")
  2516		}
  2517	
  2518		
  2519		
  2520		
  2521		
  2522		
  2523		
  2524		
  2525		cgoenv := b.cCompilerEnv()
  2526		if len(cgoLDFLAGS) > 0 {
  2527			flags := make([]string, len(cgoLDFLAGS))
  2528			for i, f := range cgoLDFLAGS {
  2529				flags[i] = strconv.Quote(f)
  2530			}
  2531			cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
  2532		}
  2533	
  2534		if cfg.BuildToolchainName == "gccgo" {
  2535			if b.gccSupportsFlag([]string{BuildToolchain.compiler()}, "-fsplit-stack") {
  2536				cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack")
  2537			}
  2538			cgoflags = append(cgoflags, "-gccgo")
  2539			if pkgpath := gccgoPkgpath(p); pkgpath != "" {
  2540				cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath)
  2541			}
  2542		}
  2543	
  2544		switch cfg.BuildBuildmode {
  2545		case "c-archive", "c-shared":
  2546			
  2547			
  2548			
  2549			cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h")
  2550		}
  2551	
  2552		if err := b.run(a, p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
  2553			return nil, nil, err
  2554		}
  2555		outGo = append(outGo, gofiles...)
  2556	
  2557		
  2558		
  2559		
  2560		
  2561		
  2562		
  2563		oseq := 0
  2564		nextOfile := func() string {
  2565			oseq++
  2566			return objdir + fmt.Sprintf("_x%03d.o", oseq)
  2567		}
  2568	
  2569		
  2570		cflags := str.StringList(cgoCPPFLAGS, cgoCFLAGS)
  2571		for _, cfile := range cfiles {
  2572			ofile := nextOfile()
  2573			if err := b.gcc(a, p, a.Objdir, ofile, cflags, objdir+cfile); err != nil {
  2574				return nil, nil, err
  2575			}
  2576			outObj = append(outObj, ofile)
  2577		}
  2578	
  2579		for _, file := range gccfiles {
  2580			ofile := nextOfile()
  2581			if err := b.gcc(a, p, a.Objdir, ofile, cflags, file); err != nil {
  2582				return nil, nil, err
  2583			}
  2584			outObj = append(outObj, ofile)
  2585		}
  2586	
  2587		cxxflags := str.StringList(cgoCPPFLAGS, cgoCXXFLAGS)
  2588		for _, file := range gxxfiles {
  2589			ofile := nextOfile()
  2590			if err := b.gxx(a, p, a.Objdir, ofile, cxxflags, file); err != nil {
  2591				return nil, nil, err
  2592			}
  2593			outObj = append(outObj, ofile)
  2594		}
  2595	
  2596		for _, file := range mfiles {
  2597			ofile := nextOfile()
  2598			if err := b.gcc(a, p, a.Objdir, ofile, cflags, file); err != nil {
  2599				return nil, nil, err
  2600			}
  2601			outObj = append(outObj, ofile)
  2602		}
  2603	
  2604		fflags := str.StringList(cgoCPPFLAGS, cgoFFLAGS)
  2605		for _, file := range ffiles {
  2606			ofile := nextOfile()
  2607			if err := b.gfortran(a, p, a.Objdir, ofile, fflags, file); err != nil {
  2608				return nil, nil, err
  2609			}
  2610			outObj = append(outObj, ofile)
  2611		}
  2612	
  2613		switch cfg.BuildToolchainName {
  2614		case "gc":
  2615			importGo := objdir + "_cgo_import.go"
  2616			if err := b.dynimport(a, p, objdir, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil {
  2617				return nil, nil, err
  2618			}
  2619			outGo = append(outGo, importGo)
  2620	
  2621		case "gccgo":
  2622			defunC := objdir + "_cgo_defun.c"
  2623			defunObj := objdir + "_cgo_defun.o"
  2624			if err := BuildToolchain.cc(b, a, defunObj, defunC); err != nil {
  2625				return nil, nil, err
  2626			}
  2627			outObj = append(outObj, defunObj)
  2628	
  2629		default:
  2630			noCompiler()
  2631		}
  2632	
  2633		return outGo, outObj, nil
  2634	}
  2635	
  2636	
  2637	
  2638	
  2639	func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error {
  2640		cfile := objdir + "_cgo_main.c"
  2641		ofile := objdir + "_cgo_main.o"
  2642		if err := b.gcc(a, p, objdir, ofile, cflags, cfile); err != nil {
  2643			return err
  2644		}
  2645	
  2646		linkobj := str.StringList(ofile, outObj, p.SysoFiles)
  2647		dynobj := objdir + "_cgo_.o"
  2648	
  2649		
  2650		ldflags := cgoLDFLAGS
  2651		if (cfg.Goarch == "arm" && cfg.Goos == "linux") || cfg.Goos == "android" {
  2652			
  2653			
  2654			n := make([]string, 0, len(ldflags))
  2655			for _, flag := range ldflags {
  2656				if flag != "-static" {
  2657					n = append(n, flag)
  2658				}
  2659			}
  2660			ldflags = append(n, "-pie")
  2661		}
  2662		if err := b.gccld(a, p, objdir, dynobj, ldflags, linkobj); err != nil {
  2663			return err
  2664		}
  2665	
  2666		
  2667		var cgoflags []string
  2668		if p.Standard && p.ImportPath == "runtime/cgo" {
  2669			cgoflags = []string{"-dynlinker"} 
  2670		}
  2671		return b.run(a, p.Dir, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
  2672	}
  2673	
  2674	
  2675	
  2676	
  2677	func (b *Builder) swig(a *Action, p *load.Package, objdir string, pcCFLAGS []string) (outGo, outC, outCXX []string, err error) {
  2678		if err := b.swigVersionCheck(); err != nil {
  2679			return nil, nil, nil, err
  2680		}
  2681	
  2682		intgosize, err := b.swigIntSize(objdir)
  2683		if err != nil {
  2684			return nil, nil, nil, err
  2685		}
  2686	
  2687		for _, f := range p.SwigFiles {
  2688			goFile, cFile, err := b.swigOne(a, p, f, objdir, pcCFLAGS, false, intgosize)
  2689			if err != nil {
  2690				return nil, nil, nil, err
  2691			}
  2692			if goFile != "" {
  2693				outGo = append(outGo, goFile)
  2694			}
  2695			if cFile != "" {
  2696				outC = append(outC, cFile)
  2697			}
  2698		}
  2699		for _, f := range p.SwigCXXFiles {
  2700			goFile, cxxFile, err := b.swigOne(a, p, f, objdir, pcCFLAGS, true, intgosize)
  2701			if err != nil {
  2702				return nil, nil, nil, err
  2703			}
  2704			if goFile != "" {
  2705				outGo = append(outGo, goFile)
  2706			}
  2707			if cxxFile != "" {
  2708				outCXX = append(outCXX, cxxFile)
  2709			}
  2710		}
  2711		return outGo, outC, outCXX, nil
  2712	}
  2713	
  2714	
  2715	var (
  2716		swigCheckOnce sync.Once
  2717		swigCheck     error
  2718	)
  2719	
  2720	func (b *Builder) swigDoVersionCheck() error {
  2721		out, err := b.runOut(nil, "", nil, "swig", "-version")
  2722		if err != nil {
  2723			return err
  2724		}
  2725		re := regexp.MustCompile(`[vV]ersion +([\d]+)([.][\d]+)?([.][\d]+)?`)
  2726		matches := re.FindSubmatch(out)
  2727		if matches == nil {
  2728			
  2729			return nil
  2730		}
  2731	
  2732		major, err := strconv.Atoi(string(matches[1]))
  2733		if err != nil {
  2734			
  2735			return nil
  2736		}
  2737		const errmsg = "must have SWIG version >= 3.0.6"
  2738		if major < 3 {
  2739			return errors.New(errmsg)
  2740		}
  2741		if major > 3 {
  2742			
  2743			return nil
  2744		}
  2745	
  2746		
  2747		if len(matches[2]) > 0 {
  2748			minor, err := strconv.Atoi(string(matches[2][1:]))
  2749			if err != nil {
  2750				return nil
  2751			}
  2752			if minor > 0 {
  2753				
  2754				return nil
  2755			}
  2756		}
  2757	
  2758		
  2759		if len(matches[3]) > 0 {
  2760			patch, err := strconv.Atoi(string(matches[3][1:]))
  2761			if err != nil {
  2762				return nil
  2763			}
  2764			if patch < 6 {
  2765				
  2766				return errors.New(errmsg)
  2767			}
  2768		}
  2769	
  2770		return nil
  2771	}
  2772	
  2773	func (b *Builder) swigVersionCheck() error {
  2774		swigCheckOnce.Do(func() {
  2775			swigCheck = b.swigDoVersionCheck()
  2776		})
  2777		return swigCheck
  2778	}
  2779	
  2780	
  2781	var (
  2782		swigIntSizeOnce  sync.Once
  2783		swigIntSize      string
  2784		swigIntSizeError error
  2785	)
  2786	
  2787	
  2788	const swigIntSizeCode = `
  2789	package main
  2790	const i int = 1 << 32
  2791	`
  2792	
  2793	
  2794	
  2795	func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
  2796		if cfg.BuildN {
  2797			return "$INTBITS", nil
  2798		}
  2799		src := filepath.Join(b.WorkDir, "swig_intsize.go")
  2800		if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil {
  2801			return
  2802		}
  2803		srcs := []string{src}
  2804	
  2805		p := load.GoFilesPackage(srcs)
  2806	
  2807		if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, "", false, srcs); e != nil {
  2808			return "32", nil
  2809		}
  2810		return "64", nil
  2811	}
  2812	
  2813	
  2814	
  2815	func (b *Builder) swigIntSize(objdir string) (intsize string, err error) {
  2816		swigIntSizeOnce.Do(func() {
  2817			swigIntSize, swigIntSizeError = b.swigDoIntSize(objdir)
  2818		})
  2819		return swigIntSize, swigIntSizeError
  2820	}
  2821	
  2822	
  2823	func (b *Builder) swigOne(a *Action, p *load.Package, file, objdir string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
  2824		cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _, err := b.CFlags(p)
  2825		if err != nil {
  2826			return "", "", err
  2827		}
  2828	
  2829		var cflags []string
  2830		if cxx {
  2831			cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
  2832		} else {
  2833			cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS)
  2834		}
  2835	
  2836		n := 5 
  2837		if cxx {
  2838			n = 8 
  2839		}
  2840		base := file[:len(file)-n]
  2841		goFile := base + ".go"
  2842		gccBase := base + "_wrap."
  2843		gccExt := "c"
  2844		if cxx {
  2845			gccExt = "cxx"
  2846		}
  2847	
  2848		gccgo := cfg.BuildToolchainName == "gccgo"
  2849	
  2850		
  2851		args := []string{
  2852			"-go",
  2853			"-cgo",
  2854			"-intgosize", intgosize,
  2855			"-module", base,
  2856			"-o", objdir + gccBase + gccExt,
  2857			"-outdir", objdir,
  2858		}
  2859	
  2860		for _, f := range cflags {
  2861			if len(f) > 3 && f[:2] == "-I" {
  2862				args = append(args, f)
  2863			}
  2864		}
  2865	
  2866		if gccgo {
  2867			args = append(args, "-gccgo")
  2868			if pkgpath := gccgoPkgpath(p); pkgpath != "" {
  2869				args = append(args, "-go-pkgpath", pkgpath)
  2870			}
  2871		}
  2872		if cxx {
  2873			args = append(args, "-c++")
  2874		}
  2875	
  2876		out, err := b.runOut(a, p.Dir, nil, "swig", args, file)
  2877		if err != nil {
  2878			if len(out) > 0 {
  2879				if bytes.Contains(out, []byte("-intgosize")) || bytes.Contains(out, []byte("-cgo")) {
  2880					return "", "", errors.New("must have SWIG version >= 3.0.6")
  2881				}
  2882				b.showOutput(a, p.Dir, p.Desc(), b.processOutput(out)) 
  2883				return "", "", errPrintedOutput
  2884			}
  2885			return "", "", err
  2886		}
  2887		if len(out) > 0 {
  2888			b.showOutput(a, p.Dir, p.Desc(), b.processOutput(out)) 
  2889		}
  2890	
  2891		
  2892		
  2893		
  2894		
  2895		
  2896		
  2897		
  2898		
  2899		goFile = objdir + goFile
  2900		newGoFile := objdir + "_" + base + "_swig.go"
  2901		if err := os.Rename(goFile, newGoFile); err != nil {
  2902			return "", "", err
  2903		}
  2904		return newGoFile, objdir + gccBase + gccExt, nil
  2905	}
  2906	
  2907	
  2908	
  2909	
  2910	
  2911	
  2912	
  2913	
  2914	
  2915	
  2916	
  2917	func (b *Builder) disableBuildID(ldflags []string) []string {
  2918		switch cfg.Goos {
  2919		case "android", "dragonfly", "linux", "netbsd":
  2920			ldflags = append(ldflags, "-Wl,--build-id=none")
  2921		}
  2922		return ldflags
  2923	}
  2924	
  2925	
  2926	
  2927	
  2928	func mkAbsFiles(dir string, files []string) []string {
  2929		abs := make([]string, len(files))
  2930		for i, f := range files {
  2931			if !filepath.IsAbs(f) {
  2932				f = filepath.Join(dir, f)
  2933			}
  2934			abs[i] = f
  2935		}
  2936		return abs
  2937	}
  2938	
  2939	
  2940	
  2941	
  2942	
  2943	
  2944	
  2945	
  2946	func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) {
  2947		cleanup = func() {} 
  2948	
  2949		var argLen int
  2950		for _, arg := range cmd.Args {
  2951			argLen += len(arg)
  2952		}
  2953	
  2954		
  2955		
  2956		if !useResponseFile(cmd.Path, argLen) {
  2957			return
  2958		}
  2959	
  2960		tf, err := ioutil.TempFile("", "args")
  2961		if err != nil {
  2962			log.Fatalf("error writing long arguments to response file: %v", err)
  2963		}
  2964		cleanup = func() { os.Remove(tf.Name()) }
  2965		var buf bytes.Buffer
  2966		for _, arg := range cmd.Args[1:] {
  2967			fmt.Fprintf(&buf, "%s\n", arg)
  2968		}
  2969		if _, err := tf.Write(buf.Bytes()); err != nil {
  2970			tf.Close()
  2971			cleanup()
  2972			log.Fatalf("error writing long arguments to response file: %v", err)
  2973		}
  2974		if err := tf.Close(); err != nil {
  2975			cleanup()
  2976			log.Fatalf("error writing long arguments to response file: %v", err)
  2977		}
  2978		cmd.Args = []string{cmd.Args[0], "@" + tf.Name()}
  2979		return cleanup
  2980	}
  2981	
  2982	func useResponseFile(path string, argLen int) bool {
  2983		
  2984		if runtime.GOOS != "windows" {
  2985			return false
  2986		}
  2987	
  2988		
  2989		
  2990		
  2991		prog := strings.TrimSuffix(filepath.Base(path), ".exe")
  2992		switch prog {
  2993		case "compile", "link":
  2994		default:
  2995			return false
  2996		}
  2997	
  2998		
  2999		
  3000		if argLen > (30 << 10) {
  3001			return true
  3002		}
  3003	
  3004		
  3005		
  3006		isBuilder := os.Getenv("GO_BUILDER_NAME") != ""
  3007		if isBuilder && rand.Intn(10) == 0 {
  3008			return true
  3009		}
  3010	
  3011		return false
  3012	}
  3013	
View as plain text