1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
31 var cmdBuild
= &Command
{
32 UsageLine
: "build [-o output] [-i] [build flags] [packages]",
33 Short
: "compile packages and dependencies",
35 Build compiles the packages named by the import paths,
36 along with their dependencies, but it does not install the results.
38 If the arguments to build are a list of .go files, build treats
39 them as a list of source files specifying a single package.
41 When compiling a single main package, build writes
42 the resulting executable to an output file named after
43 the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
44 or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe').
45 The '.exe' suffix is added when writing a Windows executable.
47 When compiling multiple packages or a single non-main package,
48 build compiles the packages but discards the resulting object,
49 serving only as a check that the packages can be built.
51 When compiling packages, build ignores files that end in '_test.go'.
53 The -o flag, only allowed when compiling a single package,
54 forces build to write the resulting executable or object
55 to the named output file, instead of the default behavior described
56 in the last two paragraphs.
58 The -i flag installs the packages that are dependencies of the target.
60 The build flags are shared by the build, clean, get, install, list, run,
64 force rebuilding of packages that are already up-to-date.
66 print the commands but do not run them.
68 the number of programs, such as build commands or
69 test binaries, that can be run in parallel.
70 The default is the number of CPUs available.
72 enable data race detection.
73 Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
75 enable interoperation with memory sanitizer.
76 Supported only on linux/amd64,
77 and only with Clang/LLVM as the host C compiler.
79 print the names of packages as they are compiled.
81 print the name of the temporary work directory and
82 do not delete it when exiting.
87 arguments to pass on each go tool asm invocation.
89 build mode to use. See 'go help buildmode' for more.
91 name of compiler to use, as in runtime.Compiler (gccgo or gc).
92 -gccgoflags 'arg list'
93 arguments to pass on each gccgo compiler/linker invocation.
95 arguments to pass on each go tool compile invocation.
97 a suffix to use in the name of the package installation directory,
98 in order to keep output separate from default builds.
99 If using the -race flag, the install suffix is automatically set to race
100 or, if set explicitly, has _race appended to it. Likewise for the -msan
101 flag. Using a -buildmode option that requires non-default compile flags
102 has a similar effect.
104 arguments to pass on each go tool link invocation.
106 link against shared libraries previously created with
109 install and load all packages from dir instead of the usual locations.
110 For example, when building with a non-standard configuration,
111 use -pkgdir to keep generated packages in a separate location.
113 a list of build tags to consider satisfied during the build.
114 For more information about build tags, see the description of
115 build constraints in the documentation for the go/build package.
117 a program to use to invoke toolchain programs like vet and asm.
118 For example, instead of running asm, the go command will run
119 'cmd args /path/to/asm <arguments for asm>'.
121 The list flags accept a space-separated list of strings. To embed spaces
122 in an element in the list, surround it with either single or double quotes.
124 For more about specifying packages, see 'go help packages'.
125 For more about where packages and binaries are installed,
126 run 'go help gopath'.
127 For more about calling between Go and C/C++, run 'go help c'.
129 Note: Build adheres to certain conventions such as those described
130 by 'go help gopath'. Not all projects can follow these conventions,
131 however. Installations that have their own conventions or that use
132 a separate software build system may choose to use lower-level
133 invocations such as 'go tool compile' and 'go tool link' to avoid
134 some of the overheads and design decisions of the build tool.
136 See also: go install, go get, go clean.
142 cmdBuild
.Run
= runBuild
143 cmdInstall
.Run
= runInstall
145 cmdBuild
.Flag
.BoolVar(&buildI
, "i", false, "")
147 addBuildFlags(cmdBuild
)
148 addBuildFlags(cmdInstall
)
151 // Flags set by multiple commands.
152 var buildA
bool // -a flag
153 var buildN
bool // -n flag
154 var buildP
= runtime
.NumCPU() // -p flag
155 var buildV
bool // -v flag
156 var buildX
bool // -x flag
157 var buildI
bool // -i flag
158 var buildO
= cmdBuild
.Flag
.String("o", "", "output file")
159 var buildWork
bool // -work flag
160 var buildAsmflags
[]string // -asmflags flag
161 var buildGcflags
[]string // -gcflags flag
162 var buildLdflags
[]string // -ldflags flag
163 var buildGccgoflags
[]string // -gccgoflags flag
164 var buildRace
bool // -race flag
165 var buildMSan
bool // -msan flag
166 var buildToolExec
[]string // -toolexec flag
167 var buildBuildmode
string // -buildmode flag
168 var buildLinkshared
bool // -linkshared flag
169 var buildPkgdir
string // -pkgdir flag
171 // Require the source for go std packages
172 var reqStdPkgSrc
bool
173 var buildContext
= build
.Default
174 var buildToolchain toolchain
= noToolchain
{}
175 var ldBuildmode
string
177 // buildCompiler implements flag.Var.
178 // It implements Set by updating both
179 // buildToolchain and buildContext.Compiler.
180 type buildCompiler
struct{}
182 func (c buildCompiler
) Set(value
string) error
{
185 buildToolchain
= gcToolchain
{}
187 buildToolchain
= gccgoToolchain
{}
189 return fmt
.Errorf("unknown compiler %q", value
)
191 buildContext
.Compiler
= value
195 func (c buildCompiler
) String() string {
196 return buildContext
.Compiler
200 switch build
.Default
.Compiler
{
202 buildToolchain
= gcToolchain
{}
204 buildToolchain
= gccgoToolchain
{}
208 // addBuildFlags adds the flags common to the build, clean, get,
209 // install, list, run, and test commands.
210 func addBuildFlags(cmd
*Command
) {
211 cmd
.Flag
.BoolVar(&buildA
, "a", false, "")
212 cmd
.Flag
.BoolVar(&buildN
, "n", false, "")
213 cmd
.Flag
.IntVar(&buildP
, "p", buildP
, "")
214 cmd
.Flag
.BoolVar(&buildV
, "v", false, "")
215 cmd
.Flag
.BoolVar(&buildX
, "x", false, "")
217 cmd
.Flag
.Var((*stringsFlag
)(&buildAsmflags
), "asmflags", "")
218 cmd
.Flag
.Var(buildCompiler
{}, "compiler", "")
219 cmd
.Flag
.StringVar(&buildBuildmode
, "buildmode", "default", "")
220 cmd
.Flag
.Var((*stringsFlag
)(&buildGcflags
), "gcflags", "")
221 cmd
.Flag
.Var((*stringsFlag
)(&buildGccgoflags
), "gccgoflags", "")
222 cmd
.Flag
.StringVar(&buildContext
.InstallSuffix
, "installsuffix", "", "")
223 cmd
.Flag
.Var((*stringsFlag
)(&buildLdflags
), "ldflags", "")
224 cmd
.Flag
.BoolVar(&buildLinkshared
, "linkshared", false, "")
225 cmd
.Flag
.StringVar(&buildPkgdir
, "pkgdir", "", "")
226 cmd
.Flag
.BoolVar(&buildRace
, "race", false, "")
227 cmd
.Flag
.BoolVar(&buildMSan
, "msan", false, "")
228 cmd
.Flag
.Var((*stringsFlag
)(&buildContext
.BuildTags
), "tags", "")
229 cmd
.Flag
.Var((*stringsFlag
)(&buildToolExec
), "toolexec", "")
230 cmd
.Flag
.BoolVar(&buildWork
, "work", false, "")
231 switch build
.Default
.Compiler
{
239 func addBuildFlagsNX(cmd
*Command
) {
240 cmd
.Flag
.BoolVar(&buildN
, "n", false, "")
241 cmd
.Flag
.BoolVar(&buildX
, "x", false, "")
244 func isSpaceByte(c
byte) bool {
245 return c
== ' ' || c
== '\t' || c
== '\n' || c
== '\r'
248 // fileExtSplit expects a filename and returns the name
249 // and ext (without the dot). If the file has no
250 // extension, ext will be empty.
251 func fileExtSplit(file
string) (name
, ext
string) {
252 dotExt
:= filepath
.Ext(file
)
253 name
= file
[:len(file
)-len(dotExt
)]
260 type stringsFlag
[]string
262 func (v
*stringsFlag
) Set(s
string) error
{
264 *v
, err
= splitQuotedFields(s
)
271 func splitQuotedFields(s
string) ([]string, error
) {
272 // Split fields allowing '' or "" around elements.
273 // Quotes further inside the string do not count.
276 for len(s
) > 0 && isSpaceByte(s
[0]) {
282 // Accepted quoted string. No unescaping inside.
283 if s
[0] == '"' || s
[0] == '\'' {
287 for i
< len(s
) && s
[i
] != quote
{
291 return nil, fmt
.Errorf("unterminated %c string", quote
)
298 for i
< len(s
) && !isSpaceByte(s
[i
]) {
307 func (v
*stringsFlag
) String() string {
308 return "<stringsFlag>"
311 func pkgsMain(pkgs
[]*Package
) (res
[]*Package
) {
312 for _
, p
:= range pkgs
{
313 if p
.Name
== "main" {
320 func pkgsNotMain(pkgs
[]*Package
) (res
[]*Package
) {
321 for _
, p
:= range pkgs
{
322 if p
.Name
!= "main" {
329 var pkgsFilter
= func(pkgs
[]*Package
) []*Package
{ return pkgs
}
331 func buildModeInit() {
332 _
, gccgo
:= buildToolchain
.(gccgoToolchain
)
333 var codegenArg
string
334 platform
:= goos
+ "/" + goarch
335 switch buildBuildmode
{
337 pkgsFilter
= pkgsNotMain
339 pkgsFilter
= func(p
[]*Package
) []*Package
{
340 if len(p
) != 1 || p
[0].Name
!= "main" {
341 fatalf("-buildmode=c-archive requires exactly one main package")
349 case "darwin/arm", "darwin/arm64":
350 codegenArg
= "-shared"
353 case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
354 // Use -shared so that the result is
355 // suitable for inclusion in a PIE or
357 codegenArg
= "-shared"
362 ldBuildmode
= "c-archive"
364 pkgsFilter
= pkgsMain
369 case "linux/amd64", "linux/arm", "linux/arm64", "linux/386",
370 "android/amd64", "android/arm", "android/arm64", "android/386":
371 codegenArg
= "-shared"
372 case "darwin/amd64", "darwin/386":
374 fatalf("-buildmode=c-shared not supported on %s\n", platform
)
377 ldBuildmode
= "c-shared"
380 case "android/arm", "android/arm64", "android/amd64", "android/386":
382 codegenArg
= "-shared"
385 case "darwin/arm", "darwin/arm64":
387 codegenArg
= "-shared"
394 pkgsFilter
= pkgsMain
401 case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
402 "android/amd64", "android/arm", "android/arm64", "android/386":
403 codegenArg
= "-shared"
405 fatalf("-buildmode=pie not supported on %s\n", platform
)
410 pkgsFilter
= pkgsNotMain
415 case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
417 fatalf("-buildmode=shared not supported on %s\n", platform
)
419 codegenArg
= "-dynlink"
422 fatalf("-buildmode=shared and -o not supported together")
424 ldBuildmode
= "shared"
426 pkgsFilter
= pkgsMain
431 case "linux/amd64", "linux/arm", "linux/arm64", "linux/386",
432 "android/amd64", "android/arm", "android/arm64", "android/386":
434 fatalf("-buildmode=plugin not supported on %s\n", platform
)
436 codegenArg
= "-dynlink"
439 ldBuildmode
= "plugin"
441 fatalf("buildmode=%s not supported", buildBuildmode
)
448 case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
449 buildAsmflags
= append(buildAsmflags
, "-D=GOBUILDMODE_shared=1")
451 fatalf("-linkshared not supported on %s\n", platform
)
453 codegenArg
= "-dynlink"
454 // TODO(mwhudson): remove -w when that gets fixed in linker.
455 buildLdflags
= append(buildLdflags
, "-linkshared", "-w")
458 if codegenArg
!= "" {
460 buildGccgoflags
= append(buildGccgoflags
, codegenArg
)
462 buildAsmflags
= append(buildAsmflags
, codegenArg
)
463 buildGcflags
= append(buildGcflags
, codegenArg
)
465 // Don't alter InstallSuffix when modifying default codegen args.
466 if buildBuildmode
!= "default" || buildLinkshared
{
467 if buildContext
.InstallSuffix
!= "" {
468 buildContext
.InstallSuffix
+= "_"
470 buildContext
.InstallSuffix
+= codegenArg
[1:]
475 func runBuild(cmd
*Command
, args
[]string) {
481 pkgs
:= packagesForBuild(args
)
483 if len(pkgs
) == 1 && pkgs
[0].Name
== "main" && *buildO
== "" {
484 _
, *buildO
= path
.Split(pkgs
[0].ImportPath
)
488 // Special case -o /dev/null by not writing at all.
489 if *buildO
== os
.DevNull
{
493 // sanity check some often mis-used options
494 switch buildContext
.Compiler
{
496 if len(buildGcflags
) != 0 {
497 fmt
.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
499 if len(buildLdflags
) != 0 {
500 fmt
.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
503 if len(buildGccgoflags
) != 0 {
504 fmt
.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags")
510 depMode
= modeInstall
515 fatalf("go build: cannot use -o with multiple packages")
516 } else if len(pkgs
) == 0 {
517 fatalf("no packages to build")
521 p
.Stale
= true // must build - not up to date
522 p
.StaleReason
= "build -o flag in use"
523 a
:= b
.action(modeInstall
, depMode
, p
)
529 if buildBuildmode
== "shared" {
530 pkgs
:= pkgsFilter(packages(args
))
531 if libName
, err
:= libname(args
, pkgs
); err
!= nil {
532 fatalf("%s", err
.Error())
534 a
= b
.libaction(libName
, pkgs
, modeBuild
, depMode
)
538 for _
, p
:= range pkgsFilter(packages(args
)) {
539 a
.deps
= append(a
.deps
, b
.action(modeBuild
, depMode
, p
))
545 var cmdInstall
= &Command
{
546 UsageLine
: "install [build flags] [packages]",
547 Short
: "compile and install packages and dependencies",
549 Install compiles and installs the packages named by the import paths,
550 along with their dependencies.
552 For more about the build flags, see 'go help build'.
553 For more about specifying packages, see 'go help packages'.
555 See also: go build, go get, go clean.
559 // isMetaPackage checks if name is a reserved package name that expands to multiple packages
560 func isMetaPackage(name
string) bool {
561 return name
== "std" || name
== "cmd" || name
== "all"
564 // libname returns the filename to use for the shared library when using
565 // -buildmode=shared. The rules we use are:
566 // Use arguments for special 'meta' packages:
568 // std cmd --> libstd,cmd.so
569 // A single non-meta argument with trailing "/..." is special cased:
570 // foo/... --> libfoo.so
571 // (A relative path like "./..." expands the "." first)
572 // Use import paths for other cases, changing '/' to '-':
573 // somelib --> libsubdir-somelib.so
574 // ./ or ../ --> libsubdir-somelib.so
575 // gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
576 // a/... b/... ---> liba/c,b/d.so - all matching import paths
577 // Name parts are joined with ','.
578 func libname(args
[]string, pkgs
[]*Package
) (string, error
) {
580 appendName
:= func(arg
string) {
588 for _
, arg
:= range args
{
589 if isMetaPackage(arg
) {
595 if len(libname
) == 0 { // non-meta packages only. use import paths
596 if len(args
) == 1 && strings
.HasSuffix(args
[0], "/...") {
597 // Special case of "foo/..." as mentioned above.
598 arg
:= strings
.TrimSuffix(args
[0], "/...")
599 if build
.IsLocalImport(arg
) {
601 bp
, _
:= buildContext
.ImportDir(filepath
.Join(cwd
, arg
), build
.FindOnly
)
602 if bp
.ImportPath
!= "" && bp
.ImportPath
!= "." {
606 appendName(strings
.Replace(arg
, "/", "-", -1))
608 for _
, pkg
:= range pkgs
{
609 appendName(strings
.Replace(pkg
.ImportPath
, "/", "-", -1))
612 } else if haveNonMeta
{ // have both meta package and a non-meta one
613 return "", errors
.New("mixing of meta and non-meta packages is not allowed")
615 // TODO(mwhudson): Needs to change for platforms that use different naming
617 return "lib" + libname
+ ".so", nil
620 func runInstall(cmd
*Command
, args
[]string) {
621 installPackages(args
, false)
624 func installPackages(args
[]string, forGet
bool) {
625 if gobin
!= "" && !filepath
.IsAbs(gobin
) {
626 fatalf("cannot install, GOBIN must be an absolute path")
631 pkgs
:= pkgsFilter(packagesForBuild(args
))
633 for _
, p
:= range pkgs
{
634 if p
.Target
== "" && (!p
.Standard || p
.ImportPath
!= "unsafe") {
637 errorf("go install: cannot install cross-compiled binaries when GOBIN is set")
639 errorf("go install: no install location for .go files listed on command line (GOBIN not set)")
640 case p
.ConflictDir
!= "":
641 errorf("go install: no install location for %s: hidden by %s", p
.Dir
, p
.ConflictDir
)
643 errorf("go install: no install location for directory %s outside GOPATH\n"+
644 "\tFor more details see: 'go help gopath'", p
.Dir
)
652 // Set the behavior for `go get` to not error on packages with test files only.
653 b
.testFilesOnlyOK
= forGet
655 if buildBuildmode
== "shared" {
656 if libName
, err
:= libname(args
, pkgs
); err
!= nil {
657 fatalf("%s", err
.Error())
659 a
= b
.libaction(libName
, pkgs
, modeInstall
, modeInstall
)
664 for _
, p
:= range pkgs
{
665 // If p is a tool, delay the installation until the end of the build.
666 // This avoids installing assemblers/compilers that are being executed
667 // by other steps in the build.
668 // cmd/cgo is handled specially in b.action, so that we can
669 // both build and use it in the same 'go install'.
670 action
:= b
.action(modeInstall
, modeInstall
, p
)
671 if goTools
[p
.ImportPath
] == toTool
&& p
.ImportPath
!= "cmd/cgo" {
672 a
.deps
= append(a
.deps
, action
.deps
...)
673 action
.deps
= append(action
.deps
, a
)
674 tools
= append(tools
, action
)
677 a
.deps
= append(a
.deps
, action
)
688 // Success. If this command is 'go install' with no arguments
689 // and the current directory (the implicit argument) is a command,
690 // remove any leftover command binary from a previous 'go build'.
691 // The binary is installed; it's not needed here anymore.
692 // And worse it might be a stale copy, which you don't want to find
693 // instead of the installed one if $PATH contains dot.
694 // One way to view this behavior is that it is as if 'go install' first
695 // runs 'go build' and the moves the generated file to the install dir.
697 if len(args
) == 0 && len(pkgs
) == 1 && pkgs
[0].Name
== "main" {
698 // Compute file 'go build' would have created.
699 // If it exists and is an executable file, remove it.
700 _
, targ
:= filepath
.Split(pkgs
[0].ImportPath
)
702 if filepath
.Join(pkgs
[0].Dir
, targ
) != pkgs
[0].Target
{ // maybe $GOBIN is the current directory
703 fi
, err
:= os
.Stat(targ
)
707 if m
&0111 != 0 || goos
== "windows" { // windows never sets executable bit
716 // Global build parameters (used during package load)
725 goarch
= buildContext
.GOARCH
726 goos
= buildContext
.GOOS
728 if goos
== "windows" {
731 gopath
= filepath
.SplitList(buildContext
.GOPATH
)
734 // A builder holds global state about a build.
735 // It does not hold per-package state, because we
736 // build packages in parallel, and the builder is shared.
737 type builder
struct {
738 work
string // the temporary work directory (ends in filepath.Separator)
739 actionCache
map[cacheKey
]*action
// a cache of already-constructed actions
740 mkdirCache
map[string]bool // a cache of created directories
741 flagCache
map[string]bool // a cache of supported compiler flags
742 print func(args
...interface{}) (int, error
)
744 testFilesOnlyOK
bool // do not error if the packages only have test files
747 scriptDir
string // current directory in printed script
754 // An action represents a single action in the action graph.
756 p
*Package
// the package this action works on
757 deps
[]*action
// actions that must happen before this one
758 triggers
[]*action
// inverse of deps
759 cgo
*action
// action for cgo binary if needed
760 args
[]string // additional args for runProgram
761 testOutput
*bytes
.Buffer
// test output buffer
763 f
func(*builder
, *action
) error
// the action itself (nil = no-op)
764 ignoreFail
bool // whether to run f even if dependencies fail
766 // Generated files, directories.
767 link
bool // target is executable, not just package
768 pkgdir
string // the -I or -L argument to use when importing this package
769 objdir
string // directory for intermediate objects
770 objpkg
string // the intermediate package .a file created during the action
771 target
string // goal of the action: the created package or executable
774 pending
int // number of deps yet to complete
775 priority
int // relative execution priority
776 failed
bool // whether the action failed
779 // cacheKey is the key for the action cache.
780 type cacheKey
struct {
786 // buildMode specifies the build mode:
787 // are we just building things or also installing the results?
791 modeBuild buildMode
= iota
796 goroot
= filepath
.Clean(runtime
.GOROOT())
797 gobin
= os
.Getenv("GOBIN")
798 gorootBin
= filepath
.Join(goroot
, "bin")
799 gorootPkg
= filepath
.Join(goroot
, "pkg")
800 gorootSrc
= filepath
.Join(goroot
, "src")
803 func (b
*builder
) init() {
805 b
.print = func(a
...interface{}) (int, error
) {
806 return fmt
.Fprint(os
.Stderr
, a
...)
808 b
.actionCache
= make(map[cacheKey
]*action
)
809 b
.mkdirCache
= make(map[string]bool)
814 b
.work
, err
= ioutil
.TempDir("", "go-build")
818 if buildX || buildWork
{
819 fmt
.Fprintf(os
.Stderr
, "WORK=%s\n", b
.work
)
823 atexit(func() { os
.RemoveAll(workdir
) })
828 // goFilesPackage creates a package for building a collection of Go files
829 // (typically named on the command line). The target is named p.a for
830 // package p or named after the first Go file for package main.
831 func goFilesPackage(gofiles
[]string) *Package
{
832 // TODO: Remove this restriction.
833 for _
, f
:= range gofiles
{
834 if !strings
.HasSuffix(f
, ".go") {
835 fatalf("named files must be .go files")
841 ctxt
.UseAllFiles
= true
843 // Synthesize fake "directory" that only shows the named files,
844 // to make it look like this is a standard package or
845 // command directory. So that local imports resolve
846 // consistently, the files must all be in the same directory.
847 var dirent
[]os
.FileInfo
849 for _
, file
:= range gofiles
{
850 fi
, err
:= os
.Stat(file
)
855 fatalf("%s is a directory, should be a Go file", file
)
857 dir1
, _
:= filepath
.Split(file
)
863 } else if dir
!= dir1
{
864 fatalf("named files must all be in one directory; have %s and %s", dir
, dir1
)
866 dirent
= append(dirent
, fi
)
868 ctxt
.ReadDir
= func(string) ([]os
.FileInfo
, error
) { return dirent
, nil }
874 dir
, err
= filepath
.Abs(dir
)
879 bp
, err
:= ctxt
.ImportDir(dir
, 0)
884 pkg
.load(&stk
, bp
, err
)
886 pkg
.localPrefix
= dirToImportPath(dir
)
887 pkg
.ImportPath
= "command-line-arguments"
890 if pkg
.Name
== "main" {
891 _
, elem
:= filepath
.Split(gofiles
[0])
892 exe
:= elem
[:len(elem
)-len(".go")] + exeSuffix
897 pkg
.target
= filepath
.Join(gobin
, exe
)
901 pkg
.Target
= pkg
.target
903 pkg
.StaleReason
= "files named on command line"
909 // readpkglist returns the list of packages that were built into the shared library
910 // at shlibpath. For the native toolchain this list is stored, newline separated, in
911 // an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the
912 // .go_export section.
913 func readpkglist(shlibpath
string) (pkgs
[]*Package
) {
915 if _
, gccgo
:= buildToolchain
.(gccgoToolchain
); gccgo
{
916 f
, _
:= elf
.Open(shlibpath
)
917 sect
:= f
.Section(".go_export")
918 data
, _
:= sect
.Data()
919 scanner
:= bufio
.NewScanner(bytes
.NewBuffer(data
))
922 if strings
.HasPrefix(t
, "pkgpath ") {
923 t
= strings
.TrimPrefix(t
, "pkgpath ")
924 t
= strings
.TrimSuffix(t
, ";")
925 pkgs
= append(pkgs
, loadPackage(t
, &stk
))
929 pkglistbytes
, err
:= readELFNote(shlibpath
, "Go\x00\x00", 1)
931 fatalf("readELFNote failed: %v", err
)
933 scanner
:= bufio
.NewScanner(bytes
.NewBuffer(pkglistbytes
))
936 pkgs
= append(pkgs
, loadPackage(t
, &stk
))
942 // action returns the action for applying the given operation (mode) to the package.
943 // depMode is the action to use when building dependencies.
944 // action never looks for p in a shared library, but may find p's dependencies in a
945 // shared library if buildLinkshared is true.
946 func (b
*builder
) action(mode buildMode
, depMode buildMode
, p
*Package
) *action
{
947 return b
.action1(mode
, depMode
, p
, false, "")
950 // action1 returns the action for applying the given operation (mode) to the package.
951 // depMode is the action to use when building dependencies.
952 // action1 will look for p in a shared library if lookshared is true.
953 // forShlib is the shared library that p will become part of, if any.
954 func (b
*builder
) action1(mode buildMode
, depMode buildMode
, p
*Package
, lookshared
bool, forShlib
string) *action
{
959 key
:= cacheKey
{mode
, p
, shlib
}
961 a
:= b
.actionCache
[key
]
966 key2
:= cacheKey
{modeInstall
, nil, shlib
}
967 a
= b
.actionCache
[key2
]
969 b
.actionCache
[key
] = a
972 pkgs
:= readpkglist(shlib
)
973 a
= b
.libaction(filepath
.Base(shlib
), pkgs
, modeInstall
, depMode
)
974 b
.actionCache
[key2
] = a
975 b
.actionCache
[key
] = a
979 a
= &action
{p
: p
, pkgdir
: p
.build
.PkgRoot
}
980 if p
.pkgdir
!= "" { // overrides p.t
983 b
.actionCache
[key
] = a
985 for _
, p1
:= range p
.imports
{
987 // p is part of a shared library.
988 if p1
.Shlib
!= "" && p1
.Shlib
!= forShlib
{
989 // p1 is explicitly part of a different shared library.
990 // Put the action for that shared library into a.deps.
991 a
.deps
= append(a
.deps
, b
.action1(depMode
, depMode
, p1
, true, p1
.Shlib
))
993 // p1 is (implicitly or not) part of this shared library.
994 // Put the action for p1 into a.deps.
995 a
.deps
= append(a
.deps
, b
.action1(depMode
, depMode
, p1
, false, forShlib
))
998 // p is not part of a shared library.
999 // If p1 is in a shared library, put the action for that into
1000 // a.deps, otherwise put the action for p1 into a.deps.
1001 a
.deps
= append(a
.deps
, b
.action1(depMode
, depMode
, p1
, buildLinkshared
, p1
.Shlib
))
1005 // If we are not doing a cross-build, then record the binary we'll
1006 // generate for cgo as a dependency of the build of any package
1007 // using cgo, to make sure we do not overwrite the binary while
1008 // a package is using it. If this is a cross-build, then the cgo we
1009 // are writing is not the cgo we need to use.
1010 if goos
== runtime
.GOOS
&& goarch
== runtime
.GOARCH
&& !buildRace
&& !buildMSan
&& reqStdPkgSrc
{
1011 if (len(p
.CgoFiles
) > 0 || p
.Standard
&& p
.ImportPath
== "runtime/cgo") && !buildLinkshared
&& buildBuildmode
!= "shared" {
1013 p1
:= loadPackage("cmd/cgo", &stk
)
1014 if p1
.Error
!= nil {
1015 fatalf("load cmd/cgo: %v", p1
.Error
)
1017 a
.cgo
= b
.action(depMode
, depMode
, p1
)
1018 a
.deps
= append(a
.deps
, a
.cgo
)
1023 switch p
.ImportPath
{
1024 case "builtin", "unsafe":
1025 // Fake packages - nothing to build.
1028 // gccgo standard library is "fake" too.
1029 if _
, ok
:= buildToolchain
.(gccgoToolchain
); ok
{
1030 // the target name is needed for cgo.
1036 if !p
.Stale
&& p
.target
!= "" {
1037 // p.Stale==false implies that p.target is up-to-date.
1038 // Record target name for use by actions depending on this one.
1043 if p
.local
&& p
.target
== "" {
1044 // Imported via local path. No permanent target.
1051 a
.objdir
= filepath
.Join(work
, a
.p
.ImportPath
, "_obj") + string(filepath
.Separator
)
1052 a
.objpkg
= buildToolchain
.pkgpath(work
, a
.p
)
1053 a
.link
= p
.Name
== "main"
1057 a
.f
= (*builder
).install
1058 a
.deps
= []*action
{b
.action1(modeBuild
, depMode
, p
, lookshared
, forShlib
)}
1059 a
.target
= a
.p
.target
1061 // Install header for cgo in c-archive and c-shared modes.
1062 if p
.usesCgo() && (buildBuildmode
== "c-archive" || buildBuildmode
== "c-shared") {
1063 hdrTarget
:= a
.target
[:len(a
.target
)-len(filepath
.Ext(a
.target
))] + ".h"
1064 if buildContext
.Compiler
== "gccgo" && *buildO
== "" {
1065 // For the header file, remove the "lib"
1066 // added by go/build, so we generate pkg.h
1067 // rather than libpkg.h.
1068 dir
, file
:= filepath
.Split(hdrTarget
)
1069 file
= strings
.TrimPrefix(file
, "lib")
1070 hdrTarget
= filepath
.Join(dir
, file
)
1074 deps
: []*action
{a
.deps
[0]},
1075 f
: (*builder
).installHeader
,
1080 a
.deps
= append(a
.deps
, ah
)
1084 a
.f
= (*builder
).build
1087 // An executable file. (This is the name of a temporary file.)
1088 // Because we run the temporary file in 'go run' and 'go test',
1089 // the name will show up in ps listings. If the caller has specified
1090 // a name, use that instead of a.out. The binary is generated
1091 // in an otherwise empty subdirectory named exe to avoid
1092 // naming conflicts. The only possible conflict is if we were
1093 // to create a top-level package named exe.
1095 if p
.exeName
!= "" {
1097 } else if goos
== "darwin" && buildBuildmode
== "c-shared" && p
.target
!= "" {
1098 // On OS X, the linker output name gets recorded in the
1099 // shared library's LC_ID_DYLIB load command.
1100 // The code invoking the linker knows to pass only the final
1101 // path element. Arrange that the path element matches what
1102 // we'll install it as; otherwise the library is only loadable as "a.out".
1103 _
, name
= filepath
.Split(p
.target
)
1105 a
.target
= a
.objdir
+ filepath
.Join("exe", name
) + exeSuffix
1112 func (b
*builder
) libaction(libname
string, pkgs
[]*Package
, mode
, depMode buildMode
) *action
{
1116 fatalf("unrecognized mode %v", mode
)
1119 a
.f
= (*builder
).linkShared
1120 a
.target
= filepath
.Join(b
.work
, libname
)
1121 for _
, p
:= range pkgs
{
1125 a
.deps
= append(a
.deps
, b
.action(depMode
, depMode
, p
))
1129 // Currently build mode shared forces external linking mode, and
1130 // external linking mode forces an import of runtime/cgo (and
1131 // math on arm). So if it was not passed on the command line and
1132 // it is not present in another shared library, add it here.
1133 _
, gccgo
:= buildToolchain
.(gccgoToolchain
)
1136 for _
, p
:= range pkgs
{
1137 seencgo
= seencgo ||
(p
.Standard
&& p
.ImportPath
== "runtime/cgo")
1141 p
:= loadPackage("runtime/cgo", &stk
)
1143 fatalf("load runtime/cgo: %v", p
.Error
)
1146 // If runtime/cgo is in another shared library, then that's
1147 // also the shared library that contains runtime, so
1148 // something will depend on it and so runtime/cgo's staleness
1149 // will be checked when processing that library.
1150 if p
.Shlib
== "" || p
.Shlib
== libname
{
1151 pkgs
= append([]*Package
{}, pkgs
...)
1152 pkgs
= append(pkgs
, p
)
1155 if goarch
== "arm" {
1157 for _
, p
:= range pkgs
{
1158 seenmath
= seenmath ||
(p
.Standard
&& p
.ImportPath
== "math")
1162 p
:= loadPackage("math", &stk
)
1164 fatalf("load math: %v", p
.Error
)
1167 // If math is in another shared library, then that's
1168 // also the shared library that contains runtime, so
1169 // something will depend on it and so math's staleness
1170 // will be checked when processing that library.
1171 if p
.Shlib
== "" || p
.Shlib
== libname
{
1172 pkgs
= append([]*Package
{}, pkgs
...)
1173 pkgs
= append(pkgs
, p
)
1179 // Figure out where the library will go.
1181 for _
, p
:= range pkgs
{
1182 plibdir
:= p
.build
.PkgTargetRoot
1184 plibdir
= filepath
.Join(plibdir
, "shlibs")
1188 } else if libdir
!= plibdir
{
1189 fatalf("multiple roots %s & %s", libdir
, plibdir
)
1192 a
.target
= filepath
.Join(libdir
, libname
)
1194 // Now we can check whether we need to rebuild it.
1197 if fi
, err
:= os
.Stat(a
.target
); err
== nil {
1198 built
= fi
.ModTime()
1200 for _
, p
:= range pkgs
{
1204 stale
= stale || p
.Stale
1205 lstat
, err
:= os
.Stat(p
.target
)
1206 if err
!= nil || lstat
.ModTime().After(built
) {
1209 a
.deps
= append(a
.deps
, b
.action1(depMode
, depMode
, p
, false, a
.target
))
1213 a
.f
= (*builder
).install
1214 buildAction
:= b
.libaction(libname
, pkgs
, modeBuild
, depMode
)
1215 a
.deps
= []*action
{buildAction
}
1216 for _
, p
:= range pkgs
{
1220 shlibnameaction
:= &action
{}
1221 shlibnameaction
.f
= (*builder
).installShlibname
1222 shlibnameaction
.target
= p
.target
[:len(p
.target
)-2] + ".shlibname"
1223 a
.deps
= append(a
.deps
, shlibnameaction
)
1224 shlibnameaction
.deps
= append(shlibnameaction
.deps
, buildAction
)
1231 // actionList returns the list of actions in the dag rooted at root
1232 // as visited in a depth-first post-order traversal.
1233 func actionList(root
*action
) []*action
{
1234 seen
:= map[*action
]bool{}
1236 var walk
func(*action
)
1237 walk
= func(a
*action
) {
1242 for _
, a1
:= range a
.deps
{
1245 all
= append(all
, a
)
1251 // allArchiveActions returns a list of the archive dependencies of root.
1252 // This is needed because if package p depends on package q that is in libr.so, the
1253 // action graph looks like p->libr.so->q and so just scanning through p's
1254 // dependencies does not find the import dir for q.
1255 func allArchiveActions(root
*action
) []*action
{
1256 seen
:= map[*action
]bool{}
1258 var walk
func(*action
)
1259 walk
= func(a
*action
) {
1264 if strings
.HasSuffix(a
.target
, ".so") || a
== root
{
1265 for _
, a1
:= range a
.deps
{
1268 } else if strings
.HasSuffix(a
.target
, ".a") {
1276 // do runs the action graph rooted at root.
1277 func (b
*builder
) do(root
*action
) {
1278 /* Commented out for gccgo, which does not have osArchSupportsCgo.
1280 if _, ok := osArchSupportsCgo[goos+"/"+goarch]; !ok && buildContext.Compiler == "gc" {
1281 fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", goos, goarch)
1286 // Build list of all actions, assigning depth-first post-order priority.
1287 // The original implementation here was a true queue
1288 // (using a channel) but it had the effect of getting
1289 // distracted by low-level leaf actions to the detriment
1290 // of completing higher-level actions. The order of
1291 // work does not matter much to overall execution time,
1292 // but when running "go test std" it is nice to see each test
1293 // results as soon as possible. The priorities assigned
1294 // ensure that, all else being equal, the execution prefers
1295 // to do what it would have done first in a simple depth-first
1296 // dependency order traversal.
1297 all
:= actionList(root
)
1298 for i
, a
:= range all
{
1302 b
.readySema
= make(chan bool, len(all
))
1304 // Initialize per-action execution state.
1305 for _
, a
:= range all
{
1306 for _
, a1
:= range a
.deps
{
1307 a1
.triggers
= append(a1
.triggers
, a
)
1309 a
.pending
= len(a
.deps
)
1316 // Handle runs a single action and takes care of triggering
1317 // any actions that are runnable as a result.
1318 handle
:= func(a
*action
) {
1320 if a
.f
!= nil && (!a
.failed || a
.ignoreFail
) {
1324 // The actions run in parallel but all the updates to the
1325 // shared work state are serialized through b.exec.
1327 defer b
.exec
.Unlock()
1330 if err
== errPrintedOutput
{
1332 } else if _
, ok
:= err
.(*build
.NoGoError
); ok
&& len(a
.p
.TestGoFiles
) > 0 && b
.testFilesOnlyOK
{
1333 // Ignore the "no buildable Go source files" error for a package with only test files.
1340 for _
, a0
:= range a
.triggers
{
1344 if a0
.pending
--; a0
.pending
== 0 {
1355 var wg sync
.WaitGroup
1357 // Kick off goroutines according to parallelism.
1358 // If we are using the -n flag (just printing commands)
1359 // drop the parallelism to 1, both to make the output
1360 // deterministic and because there is no real work anyway.
1365 for i
:= 0; i
< par
; i
++ {
1371 case _
, ok
:= <-b
.readySema
:
1375 // Receiving a value from b.readySema entitles
1376 // us to take from the ready queue.
1392 // build is the action for building a single package or command.
1393 func (b
*builder
) build(a
*action
) (err error
) {
1394 // Return an error for binary-only package.
1395 // We only reach this if isStale believes the binary form is
1396 // either not present or not usable.
1398 return fmt
.Errorf("missing or invalid package binary for binary-only package %s", a
.p
.ImportPath
)
1401 // Return an error if the package has CXX files but it's not using
1402 // cgo nor SWIG, since the CXX files can only be processed by cgo
1404 if len(a
.p
.CXXFiles
) > 0 && !a
.p
.usesCgo() && !a
.p
.usesSwig() {
1405 return fmt
.Errorf("can't build package %s because it contains C++ files (%s) but it's not using cgo nor SWIG",
1406 a
.p
.ImportPath
, strings
.Join(a
.p
.CXXFiles
, ","))
1408 // Same as above for Objective-C files
1409 if len(a
.p
.MFiles
) > 0 && !a
.p
.usesCgo() && !a
.p
.usesSwig() {
1410 return fmt
.Errorf("can't build package %s because it contains Objective-C files (%s) but it's not using cgo nor SWIG",
1411 a
.p
.ImportPath
, strings
.Join(a
.p
.MFiles
, ","))
1413 // Same as above for Fortran files
1414 if len(a
.p
.FFiles
) > 0 && !a
.p
.usesCgo() && !a
.p
.usesSwig() {
1415 return fmt
.Errorf("can't build package %s because it contains Fortran files (%s) but it's not using cgo nor SWIG",
1416 a
.p
.ImportPath
, strings
.Join(a
.p
.FFiles
, ","))
1420 if _
, ok
:= err
.(*build
.NoGoError
); err
!= nil && err
!= errPrintedOutput
&& !(ok
&& b
.testFilesOnlyOK
&& len(a
.p
.TestGoFiles
) > 0) {
1421 err
= fmt
.Errorf("go build %s: %v", a
.p
.ImportPath
, err
)
1425 // In -n mode, print a banner between packages.
1426 // The banner is five lines so that when changes to
1427 // different sections of the bootstrap script have to
1428 // be merged, the banners give patch something
1429 // to use to find its context.
1430 b
.print("\n#\n# " + a
.p
.ImportPath
+ "\n#\n\n")
1434 b
.print(a
.p
.ImportPath
+ "\n")
1437 // Make build directory.
1439 if err
:= b
.mkdir(obj
); err
!= nil {
1443 // make target directory
1444 dir
, _
:= filepath
.Split(a
.target
)
1446 if err
:= b
.mkdir(dir
); err
!= nil {
1451 var gofiles
, cgofiles
, objdirCgofiles
, cfiles
, sfiles
, cxxfiles
, objects
, cgoObjects
, pcCFLAGS
, pcLDFLAGS
[]string
1453 gofiles
= append(gofiles
, a
.p
.GoFiles
...)
1454 cgofiles
= append(cgofiles
, a
.p
.CgoFiles
...)
1455 cfiles
= append(cfiles
, a
.p
.CFiles
...)
1456 sfiles
= append(sfiles
, a
.p
.SFiles
...)
1457 cxxfiles
= append(cxxfiles
, a
.p
.CXXFiles
...)
1459 if a
.p
.usesCgo() || a
.p
.usesSwig() {
1460 if pcCFLAGS
, pcLDFLAGS
, err
= b
.getPkgConfigFlags(a
.p
); err
!= nil {
1465 // Run SWIG on each .swig and .swigcxx file.
1466 // Each run will generate two files, a .go file and a .c or .cxx file.
1467 // The .go file will use import "C" and is to be processed by cgo.
1469 outGo
, outC
, outCXX
, err
:= b
.swig(a
.p
, obj
, pcCFLAGS
)
1473 objdirCgofiles
= append(objdirCgofiles
, outGo
...)
1474 cfiles
= append(cfiles
, outC
...)
1475 cxxfiles
= append(cxxfiles
, outCXX
...)
1479 if a
.p
.usesCgo() || a
.p
.usesSwig() {
1480 // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
1481 // There is one exception: runtime/cgo's job is to bridge the
1482 // cgo and non-cgo worlds, so it necessarily has files in both.
1483 // In that case gcc only gets the gcc_* files.
1484 var gccfiles
[]string
1485 gccfiles
= append(gccfiles
, cfiles
...)
1487 if a
.p
.Standard
&& a
.p
.ImportPath
== "runtime/cgo" {
1488 filter
:= func(files
, nongcc
, gcc
[]string) ([]string, []string) {
1489 for _
, f
:= range files
{
1490 if strings
.HasPrefix(f
, "gcc_") {
1491 gcc
= append(gcc
, f
)
1493 nongcc
= append(nongcc
, f
)
1498 sfiles
, gccfiles
= filter(sfiles
, sfiles
[:0], gccfiles
)
1500 gccfiles
= append(gccfiles
, sfiles
...)
1504 cgoExe
:= tool("cgo")
1505 if a
.cgo
!= nil && a
.cgo
.target
!= "" {
1506 cgoExe
= a
.cgo
.target
1508 outGo
, outObj
, err
:= b
.cgo(a
, cgoExe
, obj
, pcCFLAGS
, pcLDFLAGS
, cgofiles
, objdirCgofiles
, gccfiles
, cxxfiles
, a
.p
.MFiles
, a
.p
.FFiles
)
1512 if _
, ok
:= buildToolchain
.(gccgoToolchain
); ok
{
1513 cgoObjects
= append(cgoObjects
, filepath
.Join(a
.objdir
, "_cgo_flags"))
1515 cgoObjects
= append(cgoObjects
, outObj
...)
1516 gofiles
= append(gofiles
, outGo
...)
1519 if len(gofiles
) == 0 {
1520 return &build
.NoGoError
{Dir
: a
.p
.Dir
}
1523 // If we're doing coverage, preprocess the .go files and put them in the work directory
1524 if a
.p
.coverMode
!= "" {
1525 for i
, file
:= range gofiles
{
1526 var sourceFile
string
1527 var coverFile
string
1529 if strings
.HasSuffix(file
, ".cgo1.go") {
1530 // cgo files have absolute paths
1531 base
:= filepath
.Base(file
)
1533 coverFile
= filepath
.Join(obj
, base
)
1534 key
= strings
.TrimSuffix(base
, ".cgo1.go") + ".go"
1536 sourceFile
= filepath
.Join(a
.p
.Dir
, file
)
1537 coverFile
= filepath
.Join(obj
, file
)
1540 cover
:= a
.p
.coverVars
[key
]
1541 if cover
== nil ||
isTestFile(file
) {
1542 // Not covering this file.
1545 if err
:= b
.cover(a
, coverFile
, sourceFile
, 0666, cover
.Var
); err
!= nil {
1548 gofiles
[i
] = coverFile
1552 // Prepare Go import path list.
1553 inc
:= b
.includeArgs("-I", allArchiveActions(a
))
1556 ofile
, out
, err
:= buildToolchain
.gc(b
, a
.p
, a
.objpkg
, obj
, len(sfiles
) > 0, inc
, gofiles
)
1558 b
.showOutput(a
.p
.Dir
, a
.p
.ImportPath
, b
.processOutput(out
))
1560 return errPrintedOutput
1566 if ofile
!= a
.objpkg
{
1567 objects
= append(objects
, ofile
)
1570 // Copy .h files named for goos or goarch or goos_goarch
1571 // to names using GOOS and GOARCH.
1572 // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
1573 _goos_goarch
:= "_" + goos
+ "_" + goarch
1575 _goarch
:= "_" + goarch
1576 for _
, file
:= range a
.p
.HFiles
{
1577 name
, ext
:= fileExtSplit(file
)
1579 case strings
.HasSuffix(name
, _goos_goarch
):
1580 targ
:= file
[:len(name
)-len(_goos_goarch
)] + "_GOOS_GOARCH." + ext
1581 if err
:= b
.copyFile(a
, obj
+targ
, filepath
.Join(a
.p
.Dir
, file
), 0666, true); err
!= nil {
1584 case strings
.HasSuffix(name
, _goarch
):
1585 targ
:= file
[:len(name
)-len(_goarch
)] + "_GOARCH." + ext
1586 if err
:= b
.copyFile(a
, obj
+targ
, filepath
.Join(a
.p
.Dir
, file
), 0666, true); err
!= nil {
1589 case strings
.HasSuffix(name
, _goos
):
1590 targ
:= file
[:len(name
)-len(_goos
)] + "_GOOS." + ext
1591 if err
:= b
.copyFile(a
, obj
+targ
, filepath
.Join(a
.p
.Dir
, file
), 0666, true); err
!= nil {
1597 for _
, file
:= range cfiles
{
1598 out
:= file
[:len(file
)-len(".c")] + ".o"
1599 if err
:= buildToolchain
.cc(b
, a
.p
, obj
, obj
+out
, file
); err
!= nil {
1602 objects
= append(objects
, out
)
1605 // Assemble .s files.
1606 if len(sfiles
) > 0 {
1607 ofiles
, err
:= buildToolchain
.asm(b
, a
.p
, obj
, sfiles
)
1611 objects
= append(objects
, ofiles
...)
1614 // NOTE(rsc): On Windows, it is critically important that the
1615 // gcc-compiled objects (cgoObjects) be listed after the ordinary
1616 // objects in the archive. I do not know why this is.
1617 // https://golang.org/issue/2601
1618 objects
= append(objects
, cgoObjects
...)
1620 // Add system object files.
1621 for _
, syso
:= range a
.p
.SysoFiles
{
1622 objects
= append(objects
, filepath
.Join(a
.p
.Dir
, syso
))
1625 // Pack into archive in obj directory.
1626 // If the Go compiler wrote an archive, we only need to add the
1627 // object files for non-Go sources to the archive.
1628 // If the Go compiler wrote an archive and the package is entirely
1629 // Go sources, there is no pack to execute at all.
1630 if len(objects
) > 0 {
1631 if err
:= buildToolchain
.pack(b
, a
.p
, obj
, a
.objpkg
, objects
); err
!= nil {
1638 // The compiler only cares about direct imports, but the
1639 // linker needs the whole dependency tree.
1640 all
:= actionList(a
)
1641 all
= all
[:len(all
)-1] // drop a
1642 if err
:= buildToolchain
.ld(b
, a
, a
.target
, all
, a
.objpkg
, objects
); err
!= nil {
1650 // pkgconfigCmd returns a pkg-config binary name
1651 // defaultPkgConfig is defined in zdefaultcc.go, written by cmd/dist.
1652 func (b
*builder
) pkgconfigCmd() string {
1653 return envList("PKG_CONFIG", defaultPkgConfig
)[0]
1656 // splitPkgConfigOutput parses the pkg-config output into a slice of
1657 // flags. pkg-config always uses \ to escape special characters.
1658 func splitPkgConfigOutput(out
[]byte) []string {
1663 flag
:= make([]byte, len(out
))
1667 case ' ', '\t', '\r', '\n':
1669 flags
= append(flags
, string(flag
[:w
]))
1684 flags
= append(flags
, string(flag
[:w
]))
1689 // Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
1690 func (b
*builder
) getPkgConfigFlags(p
*Package
) (cflags
, ldflags
[]string, err error
) {
1691 if pkgs
:= p
.CgoPkgConfig
; len(pkgs
) > 0 {
1693 out
, err
= b
.runOut(p
.Dir
, p
.ImportPath
, nil, b
.pkgconfigCmd(), "--cflags", pkgs
)
1695 b
.showOutput(p
.Dir
, b
.pkgconfigCmd()+" --cflags "+strings
.Join(pkgs
, " "), string(out
))
1696 b
.print(err
.Error() + "\n")
1697 err
= errPrintedOutput
1701 cflags
= splitPkgConfigOutput(out
)
1703 out
, err
= b
.runOut(p
.Dir
, p
.ImportPath
, nil, b
.pkgconfigCmd(), "--libs", pkgs
)
1705 b
.showOutput(p
.Dir
, b
.pkgconfigCmd()+" --libs "+strings
.Join(pkgs
, " "), string(out
))
1706 b
.print(err
.Error() + "\n")
1707 err
= errPrintedOutput
1711 ldflags
= strings
.Fields(string(out
))
1717 func (b
*builder
) installShlibname(a
*action
) error
{
1719 err
:= ioutil
.WriteFile(a
.target
, []byte(filepath
.Base(a1
.target
)+"\n"), 0666)
1724 b
.showcmd("", "echo '%s' > %s # internal", filepath
.Base(a1
.target
), a
.target
)
1729 func (b
*builder
) linkShared(a
*action
) (err error
) {
1730 allactions
:= actionList(a
)
1731 allactions
= allactions
[:len(allactions
)-1]
1732 return buildToolchain
.ldShared(b
, a
.deps
, a
.target
, allactions
)
1735 // install is the action for installing a single package or executable.
1736 func (b
*builder
) install(a
*action
) (err error
) {
1738 if err
!= nil && err
!= errPrintedOutput
{
1739 err
= fmt
.Errorf("go install %s: %v", a
.p
.ImportPath
, err
)
1743 perm
:= os
.FileMode(0666)
1745 switch buildBuildmode
{
1746 case "c-archive", "c-shared", "plugin":
1752 // make target directory
1753 dir
, _
:= filepath
.Split(a
.target
)
1755 if err
:= b
.mkdir(dir
); err
!= nil {
1760 // remove object dir to keep the amount of
1761 // garbage down in a large build. On an operating system
1762 // with aggressive buffering, cleaning incrementally like
1763 // this keeps the intermediate objects from hitting the disk.
1765 defer os
.RemoveAll(a1
.objdir
)
1766 defer os
.Remove(a1
.target
)
1769 return b
.moveOrCopyFile(a
, a
.target
, a1
.target
, perm
, false)
1772 // includeArgs returns the -I or -L directory list for access
1773 // to the results of the list of actions.
1774 func (b
*builder
) includeArgs(flag
string, all
[]*action
) []string {
1776 incMap
:= map[string]bool{
1777 b
.work
: true, // handled later
1779 "": true, // ignore empty strings
1782 // Look in the temporary space for results of test-specific actions.
1783 // This is the $WORK/my/package/_test directory for the
1784 // package being built, so there are few of these.
1785 for _
, a1
:= range all
{
1789 if dir
:= a1
.pkgdir
; dir
!= a1
.p
.build
.PkgRoot
&& !incMap
[dir
] {
1791 inc
= append(inc
, flag
, dir
)
1795 // Also look in $WORK for any non-test packages that have
1796 // been built but not installed.
1797 inc
= append(inc
, flag
, b
.work
)
1799 // Finally, look in the installed package directories for each action.
1800 // First add the package dirs corresponding to GOPATH entries
1801 // in the original GOPATH order.
1802 need
:= map[string]*build
.Package
{}
1803 for _
, a1
:= range all
{
1804 if a1
.p
!= nil && a1
.pkgdir
== a1
.p
.build
.PkgRoot
{
1805 need
[a1
.p
.build
.Root
] = a1
.p
.build
1808 for _
, root
:= range gopath
{
1809 if p
:= need
[root
]; p
!= nil && !incMap
[p
.PkgRoot
] {
1810 incMap
[p
.PkgRoot
] = true
1811 inc
= append(inc
, flag
, p
.PkgTargetRoot
)
1815 // Then add anything that's left.
1816 for _
, a1
:= range all
{
1820 if dir
:= a1
.pkgdir
; dir
== a1
.p
.build
.PkgRoot
&& !incMap
[dir
] {
1822 inc
= append(inc
, flag
, a1
.p
.build
.PkgTargetRoot
)
1829 // moveOrCopyFile is like 'mv src dst' or 'cp src dst'.
1830 func (b
*builder
) moveOrCopyFile(a
*action
, dst
, src
string, perm os
.FileMode
, force
bool) error
{
1832 b
.showcmd("", "mv %s %s", src
, dst
)
1836 // If we can update the mode and rename to the dst, do it.
1837 // Otherwise fall back to standard copy.
1839 // The perm argument is meant to be adjusted according to umask,
1840 // but we don't know what the umask is.
1841 // Create a dummy file to find out.
1842 // This avoids build tags and works even on systems like Plan 9
1843 // where the file mask computation incorporates other information.
1845 f
, err
:= os
.OpenFile(filepath
.Clean(dst
)+"-go-tmp-umask", os
.O_WRONLY|os
.O_CREATE|os
.O_EXCL
, perm
)
1849 mode
= fi
.Mode() & 0777
1856 if err
:= os
.Chmod(src
, mode
); err
== nil {
1857 if err
:= os
.Rename(src
, dst
); err
== nil {
1859 b
.showcmd("", "mv %s %s", src
, dst
)
1865 return b
.copyFile(a
, dst
, src
, perm
, force
)
1868 // copyFile is like 'cp src dst'.
1869 func (b
*builder
) copyFile(a
*action
, dst
, src
string, perm os
.FileMode
, force
bool) error
{
1870 if buildN || buildX
{
1871 b
.showcmd("", "cp %s %s", src
, dst
)
1877 sf
, err
:= os
.Open(src
)
1883 // Be careful about removing/overwriting dst.
1884 // Do not remove/overwrite if dst exists and is a directory
1885 // or a non-object file.
1886 if fi
, err
:= os
.Stat(dst
); err
== nil {
1888 return fmt
.Errorf("build output %q already exists and is a directory", dst
)
1890 if !force
&& fi
.Mode().IsRegular() && !isObject(dst
) {
1891 return fmt
.Errorf("build output %q already exists and is not an object file", dst
)
1895 // On Windows, remove lingering ~ file from last attempt.
1897 if _
, err
:= os
.Stat(dst
+ "~"); err
== nil {
1898 os
.Remove(dst
+ "~")
1902 mayberemovefile(dst
)
1903 df
, err
:= os
.OpenFile(dst
, os
.O_WRONLY|os
.O_CREATE|os
.O_TRUNC
, perm
)
1904 if err
!= nil && toolIsWindows
{
1905 // Windows does not allow deletion of a binary file
1906 // while it is executing. Try to move it out of the way.
1907 // If the move fails, which is likely, we'll try again the
1908 // next time we do an install of this binary.
1909 if err
:= os
.Rename(dst
, dst
+"~"); err
== nil {
1910 os
.Remove(dst
+ "~")
1912 df
, err
= os
.OpenFile(dst
, os
.O_WRONLY|os
.O_CREATE|os
.O_TRUNC
, perm
)
1918 _
, err
= io
.Copy(df
, sf
)
1921 mayberemovefile(dst
)
1922 return fmt
.Errorf("copying %s to %s: %v", src
, dst
, err
)
1927 // Install the cgo export header file, if there is one.
1928 func (b
*builder
) installHeader(a
*action
) error
{
1929 src
:= a
.objdir
+ "_cgo_install.h"
1930 if _
, err
:= os
.Stat(src
); os
.IsNotExist(err
) {
1931 // If the file does not exist, there are no exported
1932 // functions, and we do not install anything.
1936 dir
, _
:= filepath
.Split(a
.target
)
1938 if err
:= b
.mkdir(dir
); err
!= nil {
1943 return b
.moveOrCopyFile(a
, a
.target
, src
, 0666, true)
1946 // cover runs, in effect,
1947 // go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go
1948 func (b
*builder
) cover(a
*action
, dst
, src
string, perm os
.FileMode
, varName
string) error
{
1949 return b
.run(a
.objdir
, "cover "+a
.p
.ImportPath
, nil,
1952 "-mode", a
.p
.coverMode
,
1958 var objectMagic
= [][]byte{
1959 {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}, // Package archive
1960 {'\x7F', 'E', 'L', 'F'}, // ELF
1961 {0xFE, 0xED, 0xFA, 0xCE}, // Mach-O big-endian 32-bit
1962 {0xFE, 0xED, 0xFA, 0xCF}, // Mach-O big-endian 64-bit
1963 {0xCE, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 32-bit
1964 {0xCF, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 64-bit
1965 {0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00}, // PE (Windows) as generated by 6l/8l and gcc
1966 {0x00, 0x00, 0x01, 0xEB}, // Plan 9 i386
1967 {0x00, 0x00, 0x8a, 0x97}, // Plan 9 amd64
1968 {0x00, 0x00, 0x06, 0x47}, // Plan 9 arm
1971 func isObject(s
string) bool {
1972 f
, err
:= os
.Open(s
)
1977 buf
:= make([]byte, 64)
1979 for _
, magic
:= range objectMagic
{
1980 if bytes
.HasPrefix(buf
, magic
) {
1987 // mayberemovefile removes a file only if it is a regular file
1988 // When running as a user with sufficient privileges, we may delete
1989 // even device files, for example, which is not intended.
1990 func mayberemovefile(s
string) {
1991 if fi
, err
:= os
.Lstat(s
); err
== nil && !fi
.Mode().IsRegular() {
1997 // fmtcmd formats a command in the manner of fmt.Sprintf but also:
1999 // If dir is non-empty and the script is not in dir right now,
2000 // fmtcmd inserts "cd dir\n" before the command.
2002 // fmtcmd replaces the value of b.work with $WORK.
2003 // fmtcmd replaces the value of goroot with $GOROOT.
2004 // fmtcmd replaces the value of b.gobin with $GOBIN.
2006 // fmtcmd replaces the name of the current directory with dot (.)
2007 // but only when it is at the beginning of a space-separated token.
2009 func (b
*builder
) fmtcmd(dir
string, format
string, args
...interface{}) string {
2010 cmd
:= fmt
.Sprintf(format
, args
...)
2011 if dir
!= "" && dir
!= "/" {
2012 cmd
= strings
.Replace(" "+cmd
, " "+dir
, " .", -1)[1:]
2013 if b
.scriptDir
!= dir
{
2015 cmd
= "cd " + dir
+ "\n" + cmd
2019 cmd
= strings
.Replace(cmd
, b
.work
, "$WORK", -1)
2024 // showcmd prints the given command to standard output
2025 // for the implementation of -n or -x.
2026 func (b
*builder
) showcmd(dir
string, format
string, args
...interface{}) {
2028 defer b
.output
.Unlock()
2029 b
.print(b
.fmtcmd(dir
, format
, args
...) + "\n")
2032 // showOutput prints "# desc" followed by the given output.
2033 // The output is expected to contain references to 'dir', usually
2034 // the source directory for the package that has failed to build.
2035 // showOutput rewrites mentions of dir with a relative path to dir
2036 // when the relative path is shorter. This is usually more pleasant.
2037 // For example, if fmt doesn't compile and we are in src/html,
2042 // ../fmt/print.go:1090: undefined: asdf
2049 // /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf
2052 // showOutput also replaces references to the work directory with $WORK.
2054 func (b
*builder
) showOutput(dir
, desc
, out
string) {
2055 prefix
:= "# " + desc
2056 suffix
:= "\n" + out
2057 if reldir
:= shortPath(dir
); reldir
!= dir
{
2058 suffix
= strings
.Replace(suffix
, " "+dir
, " "+reldir
, -1)
2059 suffix
= strings
.Replace(suffix
, "\n"+dir
, "\n"+reldir
, -1)
2061 suffix
= strings
.Replace(suffix
, " "+b
.work
, " $WORK", -1)
2064 defer b
.output
.Unlock()
2065 b
.print(prefix
, suffix
)
2068 // shortPath returns an absolute or relative name for path, whatever is shorter.
2069 func shortPath(path
string) string {
2070 if rel
, err
:= filepath
.Rel(cwd
, path
); err
== nil && len(rel
) < len(path
) {
2076 // relPaths returns a copy of paths with absolute paths
2077 // made relative to the current directory if they would be shorter.
2078 func relPaths(paths
[]string) []string {
2080 pwd
, _
:= os
.Getwd()
2081 for _
, p
:= range paths
{
2082 rel
, err
:= filepath
.Rel(pwd
, p
)
2083 if err
== nil && len(rel
) < len(p
) {
2086 out
= append(out
, p
)
2091 // errPrintedOutput is a special error indicating that a command failed
2092 // but that it generated output as well, and that output has already
2093 // been printed, so there's no point showing 'exit status 1' or whatever
2094 // the wait status was. The main executor, builder.do, knows not to
2095 // print this error.
2096 var errPrintedOutput
= errors
.New("already printed output - no need to show error")
2098 var cgoLine
= regexp
.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`)
2099 var cgoTypeSigRe
= regexp
.MustCompile(`\b_Ctype_\B`)
2101 // run runs the command given by cmdline in the directory dir.
2102 // If the command fails, run prints information about the failure
2103 // and returns a non-nil error.
2104 func (b
*builder
) run(dir
string, desc
string, env
[]string, cmdargs
...interface{}) error
{
2105 out
, err
:= b
.runOut(dir
, desc
, env
, cmdargs
...)
2108 desc
= b
.fmtcmd(dir
, "%s", strings
.Join(stringList(cmdargs
...), " "))
2110 b
.showOutput(dir
, desc
, b
.processOutput(out
))
2112 err
= errPrintedOutput
2118 // processOutput prepares the output of runOut to be output to the console.
2119 func (b
*builder
) processOutput(out
[]byte) string {
2120 if out
[len(out
)-1] != '\n' {
2121 out
= append(out
, '\n')
2123 messages
:= string(out
)
2124 // Fix up output referring to cgo-generated code to be more readable.
2125 // Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19.
2126 // Replace *[100]_Ctype_foo with *[100]C.foo.
2127 // If we're using -x, assume we're debugging and want the full dump, so disable the rewrite.
2128 if !buildX
&& cgoLine
.MatchString(messages
) {
2129 messages
= cgoLine
.ReplaceAllString(messages
, "")
2130 messages
= cgoTypeSigRe
.ReplaceAllString(messages
, "C.")
2135 // runOut runs the command given by cmdline in the directory dir.
2136 // It returns the command output and any errors that occurred.
2137 func (b
*builder
) runOut(dir
string, desc
string, env
[]string, cmdargs
...interface{}) ([]byte, error
) {
2138 cmdline
:= stringList(cmdargs
...)
2139 if buildN || buildX
{
2140 var envcmdline
string
2141 for i
:= range env
{
2142 envcmdline
+= env
[i
]
2145 envcmdline
+= joinUnambiguously(cmdline
)
2146 b
.showcmd(dir
, "%s", envcmdline
)
2154 var buf bytes
.Buffer
2155 cmd
:= exec
.Command(cmdline
[0], cmdline
[1:]...)
2159 cmd
.Env
= mergeEnvLists(env
, envForDir(cmd
.Dir
, os
.Environ()))
2162 // cmd.Run will fail on Unix if some other process has the binary
2163 // we want to run open for writing. This can happen here because
2164 // we build and install the cgo command and then run it.
2165 // If another command was kicked off while we were writing the
2166 // cgo binary, the child process for that command may be holding
2167 // a reference to the fd, keeping us from running exec.
2169 // But, you might reasonably wonder, how can this happen?
2170 // The cgo fd, like all our fds, is close-on-exec, so that we need
2171 // not worry about other processes inheriting the fd accidentally.
2172 // The answer is that running a command is fork and exec.
2173 // A child forked while the cgo fd is open inherits that fd.
2174 // Until the child has called exec, it holds the fd open and the
2175 // kernel will not let us run cgo. Even if the child were to close
2176 // the fd explicitly, it would still be open from the time of the fork
2177 // until the time of the explicit close, and the race would remain.
2179 // On Unix systems, this results in ETXTBSY, which formats
2180 // as "text file busy". Rather than hard-code specific error cases,
2181 // we just look for that string. If this happens, sleep a little
2182 // and try again. We let this happen three times, with increasing
2183 // sleep lengths: 100+200+400 ms = 0.7 seconds.
2185 // An alternate solution might be to split the cmd.Run into
2186 // separate cmd.Start and cmd.Wait, and then use an RWLock
2187 // to make sure that copyFile only executes when no cmd.Start
2188 // call is in progress. However, cmd.Start (really syscall.forkExec)
2189 // only guarantees that when it returns, the exec is committed to
2190 // happen and succeed. It uses a close-on-exec file descriptor
2191 // itself to determine this, so we know that when cmd.Start returns,
2192 // at least one close-on-exec file descriptor has been closed.
2193 // However, we cannot be sure that all of them have been closed,
2194 // so the program might still encounter ETXTBSY even with such
2195 // an RWLock. The race window would be smaller, perhaps, but not
2196 // guaranteed to be gone.
2198 // Sleeping when we observe the race seems to be the most reliable
2201 // https://golang.org/issue/3001
2203 if err
!= nil && nbusy
< 3 && strings
.Contains(err
.Error(), "text file busy") {
2204 time
.Sleep(100 * time
.Millisecond
<< uint(nbusy
))
2209 // err can be something like 'exit status 1'.
2210 // Add information about what program was running.
2211 // Note that if buf.Bytes() is non-empty, the caller usually
2212 // shows buf.Bytes() and does not print err at all, so the
2213 // prefix here does not make most output any more verbose.
2215 err
= errors
.New(cmdline
[0] + ": " + err
.Error())
2217 return buf
.Bytes(), err
2221 // joinUnambiguously prints the slice, quoting where necessary to make the
2222 // output unambiguous.
2223 // TODO: See issue 5279. The printing of commands needs a complete redo.
2224 func joinUnambiguously(a
[]string) string {
2225 var buf bytes
.Buffer
2226 for i
, s
:= range a
{
2230 q
:= strconv
.Quote(s
)
2231 if s
== "" || strings
.Contains(s
, " ") ||
len(q
) > len(s
)+2 {
2240 // mkdir makes the named directory.
2241 func (b
*builder
) mkdir(dir
string) error
{
2243 defer b
.exec
.Unlock()
2244 // We can be a little aggressive about being
2245 // sure directories exist. Skip repeated calls.
2246 if b
.mkdirCache
[dir
] {
2249 b
.mkdirCache
[dir
] = true
2251 if buildN || buildX
{
2252 b
.showcmd("", "mkdir -p %s", dir
)
2258 if err
:= os
.MkdirAll(dir
, 0777); err
!= nil {
2264 // mkAbs returns an absolute path corresponding to
2265 // evaluating f in the directory dir.
2266 // We always pass absolute paths of source files so that
2267 // the error messages will include the full path to a file
2268 // in need of attention.
2269 func mkAbs(dir
, f
string) string {
2270 // Leave absolute paths alone.
2271 // Also, during -n mode we use the pseudo-directory $WORK
2272 // instead of creating an actual work directory that won't be used.
2273 // Leave paths beginning with $WORK alone too.
2274 if filepath
.IsAbs(f
) || strings
.HasPrefix(f
, "$WORK") {
2277 return filepath
.Join(dir
, f
)
2280 type toolchain
interface {
2281 // gc runs the compiler in a specific directory on a set of files
2282 // and returns the name of the generated output file.
2283 gc(b
*builder
, p
*Package
, archive
, obj
string, asmhdr
bool, importArgs
[]string, gofiles
[]string) (ofile
string, out
[]byte, err error
)
2284 // cc runs the toolchain's C compiler in a directory on a C file
2285 // to produce an output file.
2286 cc(b
*builder
, p
*Package
, objdir
, ofile
, cfile
string) error
2287 // asm runs the assembler in a specific directory on specific files
2288 // and returns a list of named output files.
2289 asm(b
*builder
, p
*Package
, obj
string, sfiles
[]string) ([]string, error
)
2290 // pkgpath builds an appropriate path for a temporary package file.
2291 pkgpath(basedir
string, p
*Package
) string
2292 // pack runs the archive packer in a specific directory to create
2293 // an archive from a set of object files.
2294 // typically it is run in the object directory.
2295 pack(b
*builder
, p
*Package
, objDir
, afile
string, ofiles
[]string) error
2296 // ld runs the linker to create an executable starting at mainpkg.
2297 ld(b
*builder
, root
*action
, out
string, allactions
[]*action
, mainpkg
string, ofiles
[]string) error
2298 // ldShared runs the linker to create a shared library containing the pkgs built by toplevelactions
2299 ldShared(b
*builder
, toplevelactions
[]*action
, out
string, allactions
[]*action
) error
2305 type noToolchain
struct{}
2307 func noCompiler() error
{
2308 log
.Fatalf("unknown compiler %q", buildContext
.Compiler
)
2312 func (noToolchain
) compiler() string {
2317 func (noToolchain
) linker() string {
2322 func (noToolchain
) gc(b
*builder
, p
*Package
, archive
, obj
string, asmhdr
bool, importArgs
[]string, gofiles
[]string) (ofile
string, out
[]byte, err error
) {
2323 return "", nil, noCompiler()
2326 func (noToolchain
) asm(b
*builder
, p
*Package
, obj
string, sfiles
[]string) ([]string, error
) {
2327 return nil, noCompiler()
2330 func (noToolchain
) pkgpath(basedir
string, p
*Package
) string {
2335 func (noToolchain
) pack(b
*builder
, p
*Package
, objDir
, afile
string, ofiles
[]string) error
{
2339 func (noToolchain
) ld(b
*builder
, root
*action
, out
string, allactions
[]*action
, mainpkg
string, ofiles
[]string) error
{
2343 func (noToolchain
) ldShared(b
*builder
, toplevelactions
[]*action
, out
string, allactions
[]*action
) error
{
2347 func (noToolchain
) cc(b
*builder
, p
*Package
, objdir
, ofile
, cfile
string) error
{
2351 // The Go toolchain.
2352 type gcToolchain
struct{}
2354 func (gcToolchain
) compiler() string {
2355 return tool("compile")
2358 func (gcToolchain
) linker() string {
2362 func (gcToolchain
) gc(b
*builder
, p
*Package
, archive
, obj
string, asmhdr
bool, importArgs
[]string, gofiles
[]string) (ofile
string, output
[]byte, err error
) {
2370 gcargs
:= []string{"-p", p
.ImportPath
}
2371 if p
.Name
== "main" {
2374 if p
.Standard
&& (p
.ImportPath
== "runtime" || strings
.HasPrefix(p
.ImportPath
, "runtime/internal")) {
2375 // runtime compiles with a special gc flag to emit
2376 // additional reflect type data.
2377 gcargs
= append(gcargs
, "-+")
2380 // If we're giving the compiler the entire package (no C etc files), tell it that,
2381 // so that it can give good error messages about forward declarations.
2382 // Exceptions: a few standard packages have forward declarations for
2383 // pieces supplied behind-the-scenes by package runtime.
2384 extFiles
:= len(p
.CgoFiles
) + len(p
.CFiles
) + len(p
.CXXFiles
) + len(p
.MFiles
) + len(p
.FFiles
) + len(p
.SFiles
) + len(p
.SysoFiles
) + len(p
.SwigFiles
) + len(p
.SwigCXXFiles
)
2386 switch p
.ImportPath
{
2387 case "bytes", "net", "os", "runtime/pprof", "sync", "time":
2392 gcargs
= append(gcargs
, "-complete")
2394 if buildContext
.InstallSuffix
!= "" {
2395 gcargs
= append(gcargs
, "-installsuffix", buildContext
.InstallSuffix
)
2397 if p
.buildID
!= "" {
2398 gcargs
= append(gcargs
, "-buildid", p
.buildID
)
2401 for _
, path
:= range p
.Imports
{
2402 if i
:= strings
.LastIndex(path
, "/vendor/"); i
>= 0 {
2403 gcargs
= append(gcargs
, "-importmap", path
[i
+len("/vendor/"):]+"="+path
)
2404 } else if strings
.HasPrefix(path
, "vendor/") {
2405 gcargs
= append(gcargs
, "-importmap", path
[len("vendor/"):]+"="+path
)
2409 args
:= []interface{}{buildToolExec
, tool("compile"), "-o", ofile
, "-trimpath", b
.work
, buildGcflags
, gcargs
, "-D", p
.localPrefix
, importArgs
}
2410 if ofile
== archive
{
2411 args
= append(args
, "-pack")
2414 args
= append(args
, "-asmhdr", obj
+"go_asm.h")
2416 for _
, f
:= range gofiles
{
2417 args
= append(args
, mkAbs(p
.Dir
, f
))
2420 output
, err
= b
.runOut(p
.Dir
, p
.ImportPath
, nil, args
...)
2421 return ofile
, output
, err
2424 func (gcToolchain
) asm(b
*builder
, p
*Package
, obj
string, sfiles
[]string) ([]string, error
) {
2425 // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
2426 inc
:= filepath
.Join(goroot
, "pkg", "include")
2427 args
:= []interface{}{buildToolExec
, tool("asm"), "-trimpath", b
.work
, "-I", obj
, "-I", inc
, "-D", "GOOS_" + goos
, "-D", "GOARCH_" + goarch
, buildAsmflags
}
2428 if p
.ImportPath
== "runtime" && goarch
== "386" {
2429 for _
, arg
:= range buildAsmflags
{
2430 if arg
== "-dynlink" {
2431 args
= append(args
, "-D=GOBUILDMODE_shared=1")
2436 for _
, sfile
:= range sfiles
{
2437 ofile
:= obj
+ sfile
[:len(sfile
)-len(".s")] + ".o"
2438 ofiles
= append(ofiles
, ofile
)
2439 a
:= append(args
, "-o", ofile
, mkAbs(p
.Dir
, sfile
))
2440 if err
:= b
.run(p
.Dir
, p
.ImportPath
, nil, a
...); err
!= nil {
2447 // toolVerify checks that the command line args writes the same output file
2448 // if run using newTool instead.
2449 // Unused now but kept around for future use.
2450 func toolVerify(b
*builder
, p
*Package
, newTool
string, ofile
string, args
[]interface{}) error
{
2451 newArgs
:= make([]interface{}, len(args
))
2453 newArgs
[1] = tool(newTool
)
2454 newArgs
[3] = ofile
+ ".new" // x.6 becomes x.6.new
2455 if err
:= b
.run(p
.Dir
, p
.ImportPath
, nil, newArgs
...); err
!= nil {
2458 data1
, err
:= ioutil
.ReadFile(ofile
)
2462 data2
, err
:= ioutil
.ReadFile(ofile
+ ".new")
2466 if !bytes
.Equal(data1
, data2
) {
2467 return fmt
.Errorf("%s and %s produced different output files:\n%s\n%s", filepath
.Base(args
[1].(string)), newTool
, strings
.Join(stringList(args
...), " "), strings
.Join(stringList(newArgs
...), " "))
2469 os
.Remove(ofile
+ ".new")
2473 func (gcToolchain
) pkgpath(basedir
string, p
*Package
) string {
2474 end
:= filepath
.FromSlash(p
.ImportPath
+ ".a")
2475 return filepath
.Join(basedir
, end
)
2478 func (gcToolchain
) pack(b
*builder
, p
*Package
, objDir
, afile
string, ofiles
[]string) error
{
2479 var absOfiles
[]string
2480 for _
, f
:= range ofiles
{
2481 absOfiles
= append(absOfiles
, mkAbs(objDir
, f
))
2483 absAfile
:= mkAbs(objDir
, afile
)
2485 // The archive file should have been created by the compiler.
2486 // Since it used to not work that way, verify.
2488 if _
, err
:= os
.Stat(absAfile
); err
!= nil {
2489 fatalf("os.Stat of archive file failed: %v", err
)
2493 if buildN || buildX
{
2494 cmdline
:= stringList("pack", "r", absAfile
, absOfiles
)
2495 b
.showcmd(p
.Dir
, "%s # internal", joinUnambiguously(cmdline
))
2500 if err
:= packInternal(b
, absAfile
, absOfiles
); err
!= nil {
2501 b
.showOutput(p
.Dir
, p
.ImportPath
, err
.Error()+"\n")
2502 return errPrintedOutput
2507 func packInternal(b
*builder
, afile
string, ofiles
[]string) error
{
2508 dst
, err
:= os
.OpenFile(afile
, os
.O_WRONLY|os
.O_APPEND
, 0)
2512 defer dst
.Close() // only for error returns or panics
2513 w
:= bufio
.NewWriter(dst
)
2515 for _
, ofile
:= range ofiles
{
2516 src
, err
:= os
.Open(ofile
)
2520 fi
, err
:= src
.Stat()
2525 // Note: Not using %-16.16s format because we care
2526 // about bytes, not runes.
2531 name
+= strings
.Repeat(" ", 16-len(name
))
2534 fmt
.Fprintf(w
, "%s%-12d%-6d%-6d%-8o%-10d`\n",
2535 name
, 0, 0, 0, 0644, size
)
2536 n
, err
:= io
.Copy(w
, src
)
2538 if err
== nil && n
< size
{
2539 err
= io
.ErrUnexpectedEOF
2540 } else if err
== nil && n
> size
{
2541 err
= fmt
.Errorf("file larger than size reported by stat")
2544 return fmt
.Errorf("copying %s to %s: %v", ofile
, afile
, err
)
2551 if err
:= w
.Flush(); err
!= nil {
2557 // setextld sets the appropriate linker flags for the specified compiler.
2558 func setextld(ldflags
[]string, compiler
[]string) []string {
2559 for _
, f
:= range ldflags
{
2560 if f
== "-extld" || strings
.HasPrefix(f
, "-extld=") {
2561 // don't override -extld if supplied
2565 ldflags
= append(ldflags
, "-extld="+compiler
[0])
2566 if len(compiler
) > 1 {
2568 add
:= strings
.Join(compiler
[1:], " ")
2569 for i
, f
:= range ldflags
{
2570 if f
== "-extldflags" && i
+1 < len(ldflags
) {
2571 ldflags
[i
+1] = add
+ " " + ldflags
[i
+1]
2574 } else if strings
.HasPrefix(f
, "-extldflags=") {
2575 ldflags
[i
] = "-extldflags=" + add
+ " " + ldflags
[i
][len("-extldflags="):]
2581 ldflags
= append(ldflags
, "-extldflags="+add
)
2587 func (gcToolchain
) ld(b
*builder
, root
*action
, out
string, allactions
[]*action
, mainpkg
string, ofiles
[]string) error
{
2588 importArgs
:= b
.includeArgs("-L", allactions
)
2589 cxx
:= len(root
.p
.CXXFiles
) > 0 ||
len(root
.p
.SwigCXXFiles
) > 0
2590 for _
, a
:= range allactions
{
2591 if a
.p
!= nil && (len(a
.p
.CXXFiles
) > 0 ||
len(a
.p
.SwigCXXFiles
) > 0) {
2595 var ldflags
[]string
2596 if buildContext
.InstallSuffix
!= "" {
2597 ldflags
= append(ldflags
, "-installsuffix", buildContext
.InstallSuffix
)
2599 if root
.p
.omitDWARF
{
2600 ldflags
= append(ldflags
, "-w")
2602 if buildBuildmode
== "plugin" {
2603 pluginpath
:= root
.p
.ImportPath
2604 if pluginpath
== "command-line-arguments" {
2605 pluginpath
= "plugin/unnamed-" + root
.p
.buildID
2607 ldflags
= append(ldflags
, "-pluginpath", pluginpath
)
2610 // If the user has not specified the -extld option, then specify the
2611 // appropriate linker. In case of C++ code, use the compiler named
2612 // by the CXX environment variable or defaultCXX if CXX is not set.
2613 // Else, use the CC environment variable and defaultCC as fallback.
2614 var compiler
[]string
2616 compiler
= envList("CXX", defaultCXX
)
2618 compiler
= envList("CC", defaultCC
)
2620 ldflags
= setextld(ldflags
, compiler
)
2621 ldflags
= append(ldflags
, "-buildmode="+ldBuildmode
)
2622 if root
.p
.buildID
!= "" {
2623 ldflags
= append(ldflags
, "-buildid="+root
.p
.buildID
)
2625 ldflags
= append(ldflags
, buildLdflags
...)
2627 // On OS X when using external linking to build a shared library,
2628 // the argument passed here to -o ends up recorded in the final
2629 // shared library in the LC_ID_DYLIB load command.
2630 // To avoid putting the temporary output directory name there
2631 // (and making the resulting shared library useless),
2632 // run the link in the output directory so that -o can name
2633 // just the final path element.
2635 if goos
== "darwin" && buildBuildmode
== "c-shared" {
2636 dir
, out
= filepath
.Split(out
)
2639 return b
.run(dir
, root
.p
.ImportPath
, nil, buildToolExec
, tool("link"), "-o", out
, importArgs
, ldflags
, mainpkg
)
2642 func (gcToolchain
) ldShared(b
*builder
, toplevelactions
[]*action
, out
string, allactions
[]*action
) error
{
2643 importArgs
:= b
.includeArgs("-L", allactions
)
2644 ldflags
:= []string{"-installsuffix", buildContext
.InstallSuffix
}
2645 ldflags
= append(ldflags
, "-buildmode=shared")
2646 ldflags
= append(ldflags
, buildLdflags
...)
2648 for _
, a
:= range allactions
{
2649 if a
.p
!= nil && (len(a
.p
.CXXFiles
) > 0 ||
len(a
.p
.SwigCXXFiles
) > 0) {
2653 // If the user has not specified the -extld option, then specify the
2654 // appropriate linker. In case of C++ code, use the compiler named
2655 // by the CXX environment variable or defaultCXX if CXX is not set.
2656 // Else, use the CC environment variable and defaultCC as fallback.
2657 var compiler
[]string
2659 compiler
= envList("CXX", defaultCXX
)
2661 compiler
= envList("CC", defaultCC
)
2663 ldflags
= setextld(ldflags
, compiler
)
2664 for _
, d
:= range toplevelactions
{
2665 if !strings
.HasSuffix(d
.target
, ".a") { // omit unsafe etc and actions for other shared libraries
2668 ldflags
= append(ldflags
, d
.p
.ImportPath
+"="+d
.target
)
2670 return b
.run(".", out
, nil, buildToolExec
, tool("link"), "-o", out
, importArgs
, ldflags
)
2673 func (gcToolchain
) cc(b
*builder
, p
*Package
, objdir
, ofile
, cfile
string) error
{
2674 return fmt
.Errorf("%s: C source files not supported without cgo", mkAbs(p
.Dir
, cfile
))
2677 // The Gccgo toolchain.
2678 type gccgoToolchain
struct{}
2680 var gccgoName
, gccgoBin
string
2683 gccgoName
= os
.Getenv("GCCGO")
2684 if gccgoName
== "" {
2685 gccgoName
= defaultGCCGO
2687 gccgoBin
, _
= exec
.LookPath(gccgoName
)
2690 func (gccgoToolchain
) compiler() string {
2694 func (gccgoToolchain
) linker() string {
2698 func (tools gccgoToolchain
) gc(b
*builder
, p
*Package
, archive
, obj
string, asmhdr
bool, importArgs
[]string, gofiles
[]string) (ofile
string, output
[]byte, err error
) {
2701 gcargs
:= []string{"-g"}
2702 gcargs
= append(gcargs
, b
.gccArchArgs()...)
2703 gcargs
= append(gcargs
, "-fdebug-prefix-map="+b
.work
+"=/tmp/go-build")
2704 gcargs
= append(gcargs
, "-gno-record-gcc-switches")
2705 if pkgpath
:= gccgoPkgpath(p
); pkgpath
!= "" {
2706 gcargs
= append(gcargs
, "-fgo-pkgpath="+pkgpath
)
2708 if p
.localPrefix
!= "" {
2709 gcargs
= append(gcargs
, "-fgo-relative-import-path="+p
.localPrefix
)
2711 savedirs
:= []string{}
2712 for _
, incdir
:= range importArgs
{
2714 savedirs
= append(savedirs
, incdir
)
2718 for _
, path
:= range p
.Imports
{
2719 // If this is a new vendor path, add it to the list of importArgs
2720 if i
:= strings
.LastIndex(path
, "/vendor/"); i
>= 0 {
2721 for _
, dir
:= range savedirs
{
2722 // Check if the vendor path is already included in dir
2723 if strings
.HasSuffix(dir
, path
[:i
+len("/vendor/")]) {
2726 // Make sure this vendor path is not already in the list for importArgs
2727 vendorPath
:= dir
+ "/" + path
[:i
+len("/vendor/")]
2728 for _
, imp
:= range importArgs
{
2732 // This vendorPath is already in the list
2733 if imp
== vendorPath
{
2737 // New vendorPath not yet in the importArgs list, so add it
2738 importArgs
= append(importArgs
, "-I", vendorPath
)
2741 } else if strings
.HasPrefix(path
, "vendor/") {
2742 for _
, dir
:= range savedirs
{
2743 // Make sure this vendor path is not already in the list for importArgs
2744 vendorPath
:= dir
+ "/" + path
[len("/vendor"):]
2745 for _
, imp
:= range importArgs
{
2749 if imp
== vendorPath
{
2753 // This vendor path is needed and not already in the list, so add it
2754 importArgs
= append(importArgs
, "-I", vendorPath
)
2760 args
:= stringList(tools
.compiler(), importArgs
, "-c", gcargs
, "-o", ofile
, buildGccgoflags
)
2761 for _
, f
:= range gofiles
{
2762 args
= append(args
, mkAbs(p
.Dir
, f
))
2765 output
, err
= b
.runOut(p
.Dir
, p
.ImportPath
, nil, args
)
2766 return ofile
, output
, err
2769 func (tools gccgoToolchain
) asm(b
*builder
, p
*Package
, obj
string, sfiles
[]string) ([]string, error
) {
2771 for _
, sfile
:= range sfiles
{
2772 ofile
:= obj
+ sfile
[:len(sfile
)-len(".s")] + ".o"
2773 ofiles
= append(ofiles
, ofile
)
2774 sfile
= mkAbs(p
.Dir
, sfile
)
2775 defs
:= []string{"-D", "GOOS_" + goos
, "-D", "GOARCH_" + goarch
}
2776 if pkgpath
:= gccgoCleanPkgpath(p
); pkgpath
!= "" {
2777 defs
= append(defs
, `-D`, `GOPKGPATH=`+pkgpath
)
2779 defs
= tools
.maybePIC(defs
)
2780 defs
= append(defs
, b
.gccArchArgs()...)
2781 err
:= b
.run(p
.Dir
, p
.ImportPath
, nil, tools
.compiler(), "-xassembler-with-cpp", "-I", obj
, "-c", "-o", ofile
, defs
, sfile
)
2789 func (gccgoToolchain
) pkgpath(basedir
string, p
*Package
) string {
2790 end
:= filepath
.FromSlash(p
.ImportPath
+ ".a")
2791 afile
:= filepath
.Join(basedir
, end
)
2792 // add "lib" to the final element
2793 return filepath
.Join(filepath
.Dir(afile
), "lib"+filepath
.Base(afile
))
2796 func (gccgoToolchain
) pack(b
*builder
, p
*Package
, objDir
, afile
string, ofiles
[]string) error
{
2797 var absOfiles
[]string
2798 for _
, f
:= range ofiles
{
2799 absOfiles
= append(absOfiles
, mkAbs(objDir
, f
))
2801 absAfile
:= mkAbs(objDir
, afile
)
2802 // Try with D modifier first, then without if that fails.
2803 if b
.run(p
.Dir
, p
.ImportPath
, nil, "ar", "rcD", absAfile
, absOfiles
) != nil {
2804 return b
.run(p
.Dir
, p
.ImportPath
, nil, "ar", "rc", absAfile
, absOfiles
)
2809 func (tools gccgoToolchain
) link(b
*builder
, root
*action
, out
string, allactions
[]*action
, mainpkg
string, ofiles
[]string, buildmode
, desc
string) error
{
2810 // gccgo needs explicit linking with all package dependencies,
2811 // and all LDFLAGS from cgo dependencies.
2812 apackagePathsSeen
:= make(map[string]bool)
2813 afiles
:= []string{}
2814 shlibs
:= []string{}
2815 ldflags
:= b
.gccArchArgs()
2816 cgoldflags
:= []string{}
2822 cxx
= len(root
.p
.CXXFiles
) > 0 ||
len(root
.p
.SwigCXXFiles
) > 0
2823 objc
= len(root
.p
.MFiles
) > 0
2824 fortran
= len(root
.p
.FFiles
) > 0
2827 readCgoFlags
:= func(flagsFile
string) error
{
2828 flags
, err
:= ioutil
.ReadFile(flagsFile
)
2832 const ldflagsPrefix
= "_CGO_LDFLAGS="
2833 for _
, line
:= range strings
.Split(string(flags
), "\n") {
2834 if strings
.HasPrefix(line
, ldflagsPrefix
) {
2835 newFlags
:= strings
.Fields(line
[len(ldflagsPrefix
):])
2836 for _
, flag
:= range newFlags
{
2837 // Every _cgo_flags file has -g and -O2 in _CGO_LDFLAGS
2838 // but they don't mean anything to the linker so filter
2840 if flag
!= "-g" && !strings
.HasPrefix(flag
, "-O") {
2841 cgoldflags
= append(cgoldflags
, flag
)
2849 readAndRemoveCgoFlags
:= func(archive
string) (string, error
) {
2850 newa
, err
:= ioutil
.TempFile(b
.work
, filepath
.Base(archive
))
2854 olda
, err
:= os
.Open(archive
)
2858 _
, err
= io
.Copy(newa
, olda
)
2871 newarchive
:= newa
.Name()
2872 err
= b
.run(b
.work
, desc
, nil, "ar", "x", newarchive
, "_cgo_flags")
2876 err
= b
.run(".", desc
, nil, "ar", "d", newarchive
, "_cgo_flags")
2880 err
= readCgoFlags(filepath
.Join(b
.work
, "_cgo_flags"))
2884 return newarchive
, nil
2887 actionsSeen
:= make(map[*action
]bool)
2888 // Make a pre-order depth-first traversal of the action graph, taking note of
2889 // whether a shared library action has been seen on the way to an action (the
2890 // construction of the graph means that if any path to a node passes through
2891 // a shared library action, they all do).
2892 var walk
func(a
*action
, seenShlib
bool)
2894 walk
= func(a
*action
, seenShlib
bool) {
2898 actionsSeen
[a
] = true
2899 if a
.p
!= nil && !seenShlib
{
2903 // We record the target of the first time we see a .a file
2904 // for a package to make sure that we prefer the 'install'
2905 // rather than the 'build' location (which may not exist any
2906 // more). We still need to traverse the dependencies of the
2907 // build action though so saying
2908 // if apackagePathsSeen[a.p.ImportPath] { return }
2910 if !apackagePathsSeen
[a
.p
.ImportPath
] {
2911 apackagePathsSeen
[a
.p
.ImportPath
] = true
2913 if len(a
.p
.CgoFiles
) > 0 || a
.p
.usesSwig() {
2914 target
, err
= readAndRemoveCgoFlags(target
)
2919 afiles
= append(afiles
, target
)
2922 if strings
.HasSuffix(a
.target
, ".so") {
2923 shlibs
= append(shlibs
, a
.target
)
2926 for _
, a1
:= range a
.deps
{
2933 for _
, a1
:= range root
.deps
{
2940 for _
, a
:= range allactions
{
2941 // Gather CgoLDFLAGS, but not from standard packages.
2942 // The go tool can dig up runtime/cgo from GOROOT and
2943 // think that it should use its CgoLDFLAGS, but gccgo
2944 // doesn't use runtime/cgo.
2949 cgoldflags
= append(cgoldflags
, a
.p
.CgoLDFLAGS
...)
2951 if len(a
.p
.CgoFiles
) > 0 {
2957 if len(a
.p
.CXXFiles
) > 0 ||
len(a
.p
.SwigCXXFiles
) > 0 {
2960 if len(a
.p
.MFiles
) > 0 {
2963 if len(a
.p
.FFiles
) > 0 {
2968 for i
, o
:= range ofiles
{
2969 if filepath
.Base(o
) == "_cgo_flags" {
2971 ofiles
= append(ofiles
[:i
], ofiles
[i
+1:]...)
2976 ldflags
= append(ldflags
, "-Wl,--whole-archive")
2977 ldflags
= append(ldflags
, afiles
...)
2978 ldflags
= append(ldflags
, "-Wl,--no-whole-archive")
2980 ldflags
= append(ldflags
, cgoldflags
...)
2981 ldflags
= append(ldflags
, envList("CGO_LDFLAGS", "")...)
2983 ldflags
= append(ldflags
, root
.p
.CgoLDFLAGS
...)
2986 ldflags
= stringList("-Wl,-(", ldflags
, "-Wl,-)")
2988 for _
, shlib
:= range shlibs
{
2991 "-L"+filepath
.Dir(shlib
),
2992 "-Wl,-rpath="+filepath
.Dir(shlib
),
2993 "-l"+strings
.TrimSuffix(
2994 strings
.TrimPrefix(filepath
.Base(shlib
), "lib"),
3001 if usesCgo
&& goos
== "linux" {
3002 ldflags
= append(ldflags
, "-Wl,-E")
3006 // Link the Go files into a single .o, and also link
3009 // We need to use --whole-archive with -lgolibbegin
3010 // because it doesn't define any symbols that will
3011 // cause the contents to be pulled in; it's just
3012 // initialization code.
3014 // The user remains responsible for linking against
3015 // -lgo -lpthread -lm in the final link. We can't use
3016 // -r to pick them up because we can't combine
3017 // split-stack and non-split-stack code in a single -r
3018 // link, and libgo picks up non-split-stack code from
3020 ldflags
= append(ldflags
, "-Wl,-r", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive")
3022 if b
.gccSupportsNoPie() {
3023 ldflags
= append(ldflags
, "-no-pie")
3026 // We are creating an object file, so we don't want a build ID.
3027 ldflags
= b
.disableBuildID(ldflags
)
3033 ldflags
= append(ldflags
, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc", "-lc", "-lgcc")
3035 ldflags
= append(ldflags
, "-zdefs", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc")
3037 ldflags
= append(ldflags
, "-pie")
3040 fatalf("-buildmode=%s not supported for gccgo", buildmode
)
3044 case "exe", "c-shared":
3046 ldflags
= append(ldflags
, "-lstdc++")
3049 ldflags
= append(ldflags
, "-lobjc")
3052 fc
:= os
.Getenv("FC")
3056 // support gfortran out of the box and let others pass the correct link options
3058 if strings
.Contains(fc
, "gfortran") {
3059 ldflags
= append(ldflags
, "-lgfortran")
3064 if err
:= b
.run(".", desc
, nil, tools
.linker(), "-o", out
, ofiles
, ldflags
, buildGccgoflags
); err
!= nil {
3070 if err
:= b
.run(".", desc
, nil, "ar", "rc", realOut
, out
); err
!= nil {
3077 func (tools gccgoToolchain
) ld(b
*builder
, root
*action
, out
string, allactions
[]*action
, mainpkg
string, ofiles
[]string) error
{
3078 return tools
.link(b
, root
, out
, allactions
, mainpkg
, ofiles
, ldBuildmode
, root
.p
.ImportPath
)
3081 func (tools gccgoToolchain
) ldShared(b
*builder
, toplevelactions
[]*action
, out
string, allactions
[]*action
) error
{
3082 fakeRoot
:= &action
{}
3083 fakeRoot
.deps
= toplevelactions
3084 return tools
.link(b
, fakeRoot
, out
, allactions
, "", nil, "shared", out
)
3087 func (tools gccgoToolchain
) cc(b
*builder
, p
*Package
, objdir
, ofile
, cfile
string) error
{
3088 inc
:= filepath
.Join(goroot
, "pkg", "include")
3089 cfile
= mkAbs(p
.Dir
, cfile
)
3090 defs
:= []string{"-D", "GOOS_" + goos
, "-D", "GOARCH_" + goarch
}
3091 defs
= append(defs
, b
.gccArchArgs()...)
3092 if pkgpath
:= gccgoCleanPkgpath(p
); pkgpath
!= "" {
3093 defs
= append(defs
, `-D`, `GOPKGPATH="`+pkgpath
+`"`)
3095 if b
.gccSupportsFlag("-fsplit-stack") {
3096 defs
= append(defs
, "-fsplit-stack")
3098 defs
= tools
.maybePIC(defs
)
3099 if b
.gccSupportsFlag("-fdebug-prefix-map=a=b") {
3100 defs
= append(defs
, "-fdebug-prefix-map="+b
.work
+"=/tmp/go-build")
3102 if b
.gccSupportsFlag("-gno-record-gcc-switches") {
3103 defs
= append(defs
, "-gno-record-gcc-switches")
3105 return b
.run(p
.Dir
, p
.ImportPath
, nil, envList("CC", defaultCC
), "-Wall", "-g",
3106 "-I", objdir
, "-I", inc
, "-o", ofile
, defs
, "-c", cfile
)
3109 // maybePIC adds -fPIC to the list of arguments if needed.
3110 func (tools gccgoToolchain
) maybePIC(args
[]string) []string {
3111 switch buildBuildmode
{
3112 case "c-archive", "c-shared", "shared", "plugin":
3113 args
= append(args
, "-fPIC")
3118 func gccgoPkgpath(p
*Package
) string {
3119 if p
.build
.IsCommand() && !p
.forceLibrary
{
3125 func gccgoCleanPkgpath(p
*Package
) string {
3126 clean
:= func(r rune
) rune
{
3128 case 'A' <= r
&& r
<= 'Z', 'a' <= r
&& r
<= 'z',
3129 '0' <= r
&& r
<= '9':
3134 return strings
.Map(clean
, gccgoPkgpath(p
))
3137 // gcc runs the gcc C compiler to create an object from a single C file.
3138 func (b
*builder
) gcc(p
*Package
, out
string, flags
[]string, cfile
string) error
{
3139 return b
.ccompile(p
, out
, flags
, cfile
, b
.gccCmd(p
.Dir
))
3142 // gxx runs the g++ C++ compiler to create an object from a single C++ file.
3143 func (b
*builder
) gxx(p
*Package
, out
string, flags
[]string, cxxfile
string) error
{
3144 return b
.ccompile(p
, out
, flags
, cxxfile
, b
.gxxCmd(p
.Dir
))
3147 // gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file.
3148 func (b
*builder
) gfortran(p
*Package
, out
string, flags
[]string, ffile
string) error
{
3149 return b
.ccompile(p
, out
, flags
, ffile
, b
.gfortranCmd(p
.Dir
))
3152 // ccompile runs the given C or C++ compiler and creates an object from a single source file.
3153 func (b
*builder
) ccompile(p
*Package
, outfile
string, flags
[]string, file
string, compiler
[]string) error
{
3154 file
= mkAbs(p
.Dir
, file
)
3155 desc
:= p
.ImportPath
3156 output
, err
:= b
.runOut(p
.Dir
, desc
, nil, compiler
, flags
, "-o", outfile
, "-c", file
)
3157 if len(output
) > 0 {
3158 // On FreeBSD 11, when we pass -g to clang 3.8 it
3159 // invokes its internal assembler with -dwarf-version=2.
3160 // When it sees .section .note.GNU-stack, it warns
3161 // "DWARF2 only supports one section per compilation unit".
3162 // This warning makes no sense, since the section is empty,
3163 // but it confuses people.
3164 // We work around the problem by detecting the warning
3165 // and dropping -g and trying again.
3166 if bytes
.Contains(output
, []byte("DWARF2 only supports one section per compilation unit")) {
3167 newFlags
:= make([]string, 0, len(flags
))
3168 for _
, f
:= range flags
{
3169 if !strings
.HasPrefix(f
, "-g") {
3170 newFlags
= append(newFlags
, f
)
3173 if len(newFlags
) < len(flags
) {
3174 return b
.ccompile(p
, outfile
, newFlags
, file
, compiler
)
3178 b
.showOutput(p
.Dir
, desc
, b
.processOutput(output
))
3180 err
= errPrintedOutput
3181 } else if os
.Getenv("GO_BUILDER_NAME") != "" {
3182 return errors
.New("C compiler warning promoted to error on Go builders")
3188 // gccld runs the gcc linker to create an executable from a set of object files.
3189 func (b
*builder
) gccld(p
*Package
, out
string, flags
[]string, obj
[]string) error
{
3191 if len(p
.CXXFiles
) > 0 ||
len(p
.SwigCXXFiles
) > 0 {
3192 cmd
= b
.gxxCmd(p
.Dir
)
3194 cmd
= b
.gccCmd(p
.Dir
)
3196 return b
.run(p
.Dir
, p
.ImportPath
, nil, cmd
, "-o", out
, obj
, flags
)
3199 // gccCmd returns a gcc command line prefix
3200 // defaultCC is defined in zdefaultcc.go, written by cmd/dist.
3201 func (b
*builder
) gccCmd(objdir
string) []string {
3202 return b
.ccompilerCmd("CC", defaultCC
, objdir
)
3205 // gxxCmd returns a g++ command line prefix
3206 // defaultCXX is defined in zdefaultcc.go, written by cmd/dist.
3207 func (b
*builder
) gxxCmd(objdir
string) []string {
3208 return b
.ccompilerCmd("CXX", defaultCXX
, objdir
)
3211 // gfortranCmd returns a gfortran command line prefix.
3212 func (b
*builder
) gfortranCmd(objdir
string) []string {
3213 return b
.ccompilerCmd("FC", "gfortran", objdir
)
3216 // ccompilerCmd returns a command line prefix for the given environment
3217 // variable and using the default command when the variable is empty.
3218 func (b
*builder
) ccompilerCmd(envvar
, defcmd
, objdir
string) []string {
3219 // NOTE: env.go's mkEnv knows that the first three
3220 // strings returned are "gcc", "-I", objdir (and cuts them off).
3222 compiler
:= envList(envvar
, defcmd
)
3223 a
:= []string{compiler
[0], "-I", objdir
}
3224 a
= append(a
, compiler
[1:]...)
3226 // Definitely want -fPIC but on Windows gcc complains
3227 // "-fPIC ignored for target (all code is position independent)"
3228 if goos
!= "windows" {
3229 a
= append(a
, "-fPIC")
3231 a
= append(a
, b
.gccArchArgs()...)
3232 // gcc-4.5 and beyond require explicit "-pthread" flag
3233 // for multithreading with pthread library.
3234 if buildContext
.CgoEnabled
{
3237 a
= append(a
, "-mthreads")
3239 a
= append(a
, "-pthread")
3243 if strings
.Contains(a
[0], "clang") {
3244 // disable ASCII art in clang errors, if possible
3245 a
= append(a
, "-fno-caret-diagnostics")
3246 // clang is too smart about command-line arguments
3247 a
= append(a
, "-Qunused-arguments")
3250 // disable word wrapping in error messages
3251 a
= append(a
, "-fmessage-length=0")
3253 // Tell gcc not to include the work directory in object files.
3254 if b
.gccSupportsFlag("-fdebug-prefix-map=a=b") {
3255 a
= append(a
, "-fdebug-prefix-map="+b
.work
+"=/tmp/go-build")
3258 // Tell gcc not to include flags in object files, which defeats the
3259 // point of -fdebug-prefix-map above.
3260 if b
.gccSupportsFlag("-gno-record-gcc-switches") {
3261 a
= append(a
, "-gno-record-gcc-switches")
3264 // On OS X, some of the compilers behave as if -fno-common
3265 // is always set, and the Mach-O linker in 6l/8l assumes this.
3266 // See https://golang.org/issue/3253.
3267 if goos
== "darwin" {
3268 a
= append(a
, "-fno-common")
3271 // gccgo uses the language-independent exception mechanism to
3272 // handle panics, so it always needs unwind tables.
3273 if _
, ok
:= buildToolchain
.(gccgoToolchain
); ok
{
3274 a
= append(a
, "-funwind-tables")
3280 // On systems with PIE (position independent executables) enabled by default,
3281 // -no-pie must be passed when doing a partial link with -Wl,-r. But -no-pie is
3282 // not supported by all compilers.
3283 func (b
*builder
) gccSupportsNoPie() bool {
3284 return b
.gccSupportsFlag("-no-pie")
3287 // gccSupportsFlag checks to see if the compiler supports a flag.
3288 func (b
*builder
) gccSupportsFlag(flag
string) bool {
3290 defer b
.exec
.Unlock()
3291 if b
, ok
:= b
.flagCache
[flag
]; ok
{
3294 if b
.flagCache
== nil {
3295 src
:= filepath
.Join(b
.work
, "trivial.c")
3296 if err
:= ioutil
.WriteFile(src
, []byte{}, 0666); err
!= nil {
3299 b
.flagCache
= make(map[string]bool)
3301 cmdArgs
:= append(envList("CC", defaultCC
), flag
, "-c", "trivial.c")
3302 if buildN || buildX
{
3303 b
.showcmd(b
.work
, "%s", joinUnambiguously(cmdArgs
))
3308 cmd
:= exec
.Command(cmdArgs
[0], cmdArgs
[1:]...)
3310 cmd
.Env
= mergeEnvLists([]string{"LC_ALL=C"}, envForDir(cmd
.Dir
, os
.Environ()))
3311 out
, err
:= cmd
.CombinedOutput()
3312 supported
:= err
== nil && !bytes
.Contains(out
, []byte("unrecognized"))
3313 b
.flagCache
[flag
] = supported
3317 // gccArchArgs returns arguments to pass to gcc based on the architecture.
3318 func (b
*builder
) gccArchArgs() []string {
3321 return []string{"-m32"}
3322 case "amd64", "amd64p32":
3323 return []string{"-m64"}
3325 return []string{"-marm"} // not thumb
3327 return []string{"-m64", "-march=z196"}
3328 case "mips64", "mips64le":
3329 return []string{"-mabi=64"}
3330 case "mips", "mipsle":
3331 return []string{"-mabi=32", "-march=mips32"}
3336 // envList returns the value of the given environment variable broken
3337 // into fields, using the default value when the variable is empty.
3338 func envList(key
, def
string) []string {
3343 return strings
.Fields(v
)
3346 // Return the flags to use when invoking the C, C++ or Fortran compilers, or cgo.
3347 func (b
*builder
) cflags(p
*Package
) (cppflags
, cflags
, cxxflags
, fflags
, ldflags
[]string) {
3348 defaults
:= "-g -O2"
3350 cppflags
= stringList(envList("CGO_CPPFLAGS", ""), p
.CgoCPPFLAGS
)
3351 cflags
= stringList(envList("CGO_CFLAGS", defaults
), p
.CgoCFLAGS
)
3352 cxxflags
= stringList(envList("CGO_CXXFLAGS", defaults
), p
.CgoCXXFLAGS
)
3353 fflags
= stringList(envList("CGO_FFLAGS", defaults
), p
.CgoFFLAGS
)
3354 ldflags
= stringList(envList("CGO_LDFLAGS", defaults
), p
.CgoLDFLAGS
)
3358 var cgoRe
= regexp
.MustCompile(`[/\\:]`)
3360 func (b
*builder
) cgo(a
*action
, cgoExe
, obj
string, pcCFLAGS
, pcLDFLAGS
, cgofiles
, objdirCgofiles
, gccfiles
, gxxfiles
, mfiles
, ffiles
[]string) (outGo
, outObj
[]string, err error
) {
3362 cgoCPPFLAGS
, cgoCFLAGS
, cgoCXXFLAGS
, cgoFFLAGS
, cgoLDFLAGS
:= b
.cflags(p
)
3363 cgoCPPFLAGS
= append(cgoCPPFLAGS
, pcCFLAGS
...)
3364 cgoLDFLAGS
= append(cgoLDFLAGS
, pcLDFLAGS
...)
3365 // If we are compiling Objective-C code, then we need to link against libobjc
3366 if len(mfiles
) > 0 {
3367 cgoLDFLAGS
= append(cgoLDFLAGS
, "-lobjc")
3370 // Likewise for Fortran, except there are many Fortran compilers.
3371 // Support gfortran out of the box and let others pass the correct link options
3373 if len(ffiles
) > 0 {
3374 fc
:= os
.Getenv("FC")
3378 if strings
.Contains(fc
, "gfortran") {
3379 cgoLDFLAGS
= append(cgoLDFLAGS
, "-lgfortran")
3384 cgoCFLAGS
= append([]string{"-fsanitize=memory"}, cgoCFLAGS
...)
3385 cgoLDFLAGS
= append([]string{"-fsanitize=memory"}, cgoLDFLAGS
...)
3388 // Allows including _cgo_export.h from .[ch] files in the package.
3389 cgoCPPFLAGS
= append(cgoCPPFLAGS
, "-I", obj
)
3391 // If we have cgo files in the object directory, then copy any
3392 // other cgo files into the object directory, and pass a
3393 // -srcdir option to cgo.
3394 var srcdirarg
[]string
3395 if len(objdirCgofiles
) > 0 {
3396 for _
, fn
:= range cgofiles
{
3397 if err
:= b
.copyFile(a
, obj
+filepath
.Base(fn
), filepath
.Join(p
.Dir
, fn
), 0666, false); err
!= nil {
3398 return nil, nil, err
3401 cgofiles
= append(cgofiles
, objdirCgofiles
...)
3402 srcdirarg
= []string{"-srcdir", obj
}
3407 gofiles
:= []string{obj
+ "_cgo_gotypes.go"}
3408 cfiles
:= []string{"_cgo_export.c"}
3409 for _
, fn
:= range cgofiles
{
3410 f
:= cgoRe
.ReplaceAllString(fn
[:len(fn
)-2], "_")
3411 gofiles
= append(gofiles
, obj
+f
+"cgo1.go")
3412 cfiles
= append(cfiles
, f
+"cgo2.c")
3415 // TODO: make cgo not depend on $GOARCH?
3417 cgoflags
:= []string{}
3418 if p
.Standard
&& p
.ImportPath
== "runtime/cgo" {
3419 cgoflags
= append(cgoflags
, "-import_runtime_cgo=false")
3421 if p
.Standard
&& (p
.ImportPath
== "runtime/race" || p
.ImportPath
== "runtime/msan" || p
.ImportPath
== "runtime/cgo") {
3422 cgoflags
= append(cgoflags
, "-import_syscall=false")
3425 // Update $CGO_LDFLAGS with p.CgoLDFLAGS.
3427 if len(cgoLDFLAGS
) > 0 {
3428 flags
:= make([]string, len(cgoLDFLAGS
))
3429 for i
, f
:= range cgoLDFLAGS
{
3430 flags
[i
] = strconv
.Quote(f
)
3432 cgoenv
= []string{"CGO_LDFLAGS=" + strings
.Join(flags
, " ")}
3435 if _
, ok
:= buildToolchain
.(gccgoToolchain
); ok
{
3436 if b
.gccSupportsFlag("-fsplit-stack") {
3437 cgoCFLAGS
= append(cgoCFLAGS
, "-fsplit-stack")
3439 cgoflags
= append(cgoflags
, "-gccgo")
3440 if pkgpath
:= gccgoPkgpath(p
); pkgpath
!= "" {
3441 cgoflags
= append(cgoflags
, "-gccgopkgpath="+pkgpath
)
3445 switch buildBuildmode
{
3446 case "c-archive", "c-shared":
3447 // Tell cgo that if there are any exported functions
3448 // it should generate a header file that C code can
3450 cgoflags
= append(cgoflags
, "-exportheader="+obj
+"_cgo_install.h")
3453 if err
:= b
.run(p
.Dir
, p
.ImportPath
, cgoenv
, buildToolExec
, cgoExe
, srcdirarg
, "-objdir", obj
, "-importpath", p
.ImportPath
, cgoflags
, "--", cgoCPPFLAGS
, cgoCFLAGS
, cgofiles
); err
!= nil {
3454 return nil, nil, err
3456 outGo
= append(outGo
, gofiles
...)
3459 cflags
:= stringList(cgoCPPFLAGS
, cgoCFLAGS
)
3460 for _
, cfile
:= range cfiles
{
3461 ofile
:= obj
+ cfile
[:len(cfile
)-1] + "o"
3462 if err
:= b
.gcc(p
, ofile
, cflags
, obj
+cfile
); err
!= nil {
3463 return nil, nil, err
3465 outObj
= append(outObj
, ofile
)
3468 for _
, file
:= range gccfiles
{
3469 base
:= filepath
.Base(file
)
3470 ofile
:= obj
+ cgoRe
.ReplaceAllString(base
[:len(base
)-1], "_") + "o"
3471 if err
:= b
.gcc(p
, ofile
, cflags
, file
); err
!= nil {
3472 return nil, nil, err
3474 outObj
= append(outObj
, ofile
)
3477 cxxflags
:= stringList(cgoCPPFLAGS
, cgoCXXFLAGS
)
3478 for _
, file
:= range gxxfiles
{
3479 // Append .o to the file, just in case the pkg has file.c and file.cpp
3480 ofile
:= obj
+ cgoRe
.ReplaceAllString(filepath
.Base(file
), "_") + ".o"
3481 if err
:= b
.gxx(p
, ofile
, cxxflags
, file
); err
!= nil {
3482 return nil, nil, err
3484 outObj
= append(outObj
, ofile
)
3487 for _
, file
:= range mfiles
{
3488 // Append .o to the file, just in case the pkg has file.c and file.m
3489 ofile
:= obj
+ cgoRe
.ReplaceAllString(filepath
.Base(file
), "_") + ".o"
3490 if err
:= b
.gcc(p
, ofile
, cflags
, file
); err
!= nil {
3491 return nil, nil, err
3493 outObj
= append(outObj
, ofile
)
3496 fflags
:= stringList(cgoCPPFLAGS
, cgoFFLAGS
)
3497 for _
, file
:= range ffiles
{
3498 // Append .o to the file, just in case the pkg has file.c and file.f
3499 ofile
:= obj
+ cgoRe
.ReplaceAllString(filepath
.Base(file
), "_") + ".o"
3500 if err
:= b
.gfortran(p
, ofile
, fflags
, file
); err
!= nil {
3501 return nil, nil, err
3503 outObj
= append(outObj
, ofile
)
3506 switch buildToolchain
.(type) {
3508 importGo
:= obj
+ "_cgo_import.go"
3509 if err
:= b
.dynimport(p
, obj
, importGo
, cgoExe
, cflags
, cgoLDFLAGS
, outObj
); err
!= nil {
3510 return nil, nil, err
3512 outGo
= append(outGo
, importGo
)
3514 ofile
:= obj
+ "_all.o"
3515 if err
:= b
.collect(p
, obj
, ofile
, cgoLDFLAGS
, outObj
); err
!= nil {
3516 return nil, nil, err
3518 outObj
= []string{ofile
}
3520 case gccgoToolchain
:
3521 defunC
:= obj
+ "_cgo_defun.c"
3522 defunObj
:= obj
+ "_cgo_defun.o"
3523 if err
:= buildToolchain
.cc(b
, p
, obj
, defunObj
, defunC
); err
!= nil {
3524 return nil, nil, err
3526 outObj
= append(outObj
, defunObj
)
3532 return outGo
, outObj
, nil
3535 // dynimport creates a Go source file named importGo containing
3536 // //go:cgo_import_dynamic directives for each symbol or library
3537 // dynamically imported by the object files outObj.
3538 func (b
*builder
) dynimport(p
*Package
, obj
, importGo
, cgoExe
string, cflags
, cgoLDFLAGS
, outObj
[]string) error
{
3539 cfile
:= obj
+ "_cgo_main.c"
3540 ofile
:= obj
+ "_cgo_main.o"
3541 if err
:= b
.gcc(p
, ofile
, cflags
, cfile
); err
!= nil {
3545 linkobj
:= stringList(ofile
, outObj
, p
.SysoFiles
)
3546 dynobj
:= obj
+ "_cgo_.o"
3548 // we need to use -pie for Linux/ARM to get accurate imported sym
3549 ldflags
:= cgoLDFLAGS
3550 if (goarch
== "arm" && goos
== "linux") || goos
== "android" {
3551 ldflags
= append(ldflags
, "-pie")
3553 if err
:= b
.gccld(p
, dynobj
, ldflags
, linkobj
); err
!= nil {
3558 var cgoflags
[]string
3559 if p
.Standard
&& p
.ImportPath
== "runtime/cgo" {
3560 cgoflags
= []string{"-dynlinker"} // record path to dynamic linker
3562 return b
.run(p
.Dir
, p
.ImportPath
, nil, buildToolExec
, cgoExe
, "-dynpackage", p
.Name
, "-dynimport", dynobj
, "-dynout", importGo
, cgoflags
)
3565 // collect partially links the object files outObj into a single
3566 // relocatable object file named ofile.
3567 func (b
*builder
) collect(p
*Package
, obj
, ofile
string, cgoLDFLAGS
, outObj
[]string) error
{
3568 // When linking relocatable objects, various flags need to be
3569 // filtered out as they are inapplicable and can cause some linkers
3571 var ldflags
[]string
3572 for i
:= 0; i
< len(cgoLDFLAGS
); i
++ {
3575 // skip "-lc" or "-l somelib"
3576 case strings
.HasPrefix(f
, "-l"):
3580 // skip "-framework X" on Darwin
3581 case goos
== "darwin" && f
== "-framework":
3583 // skip "*.{dylib,so,dll,o,a}"
3584 case strings
.HasSuffix(f
, ".dylib"),
3585 strings
.HasSuffix(f
, ".so"),
3586 strings
.HasSuffix(f
, ".dll"),
3587 strings
.HasSuffix(f
, ".o"),
3588 strings
.HasSuffix(f
, ".a"):
3589 // Remove any -fsanitize=foo flags.
3590 // Otherwise the compiler driver thinks that we are doing final link
3591 // and links sanitizer runtime into the object file. But we are not doing
3592 // the final link, we will link the resulting object file again. And
3593 // so the program ends up with two copies of sanitizer runtime.
3594 // See issue 8788 for details.
3595 case strings
.HasPrefix(f
, "-fsanitize="):
3597 // runpath flags not applicable unless building a shared
3598 // object or executable; see issue 12115 for details. This
3599 // is necessary as Go currently does not offer a way to
3600 // specify the set of LDFLAGS that only apply to shared
3602 case strings
.HasPrefix(f
, "-Wl,-rpath"):
3603 if f
== "-Wl,-rpath" || f
== "-Wl,-rpath-link" {
3604 // Skip following argument to -rpath* too.
3608 ldflags
= append(ldflags
, f
)
3612 ldflags
= append(ldflags
, "-Wl,-r", "-nostdlib")
3614 if b
.gccSupportsNoPie() {
3615 ldflags
= append(ldflags
, "-no-pie")
3618 // We are creating an object file, so we don't want a build ID.
3619 ldflags
= b
.disableBuildID(ldflags
)
3621 return b
.gccld(p
, ofile
, ldflags
, outObj
)
3624 // Run SWIG on all SWIG input files.
3625 // TODO: Don't build a shared library, once SWIG emits the necessary
3626 // pragmas for external linking.
3627 func (b
*builder
) swig(p
*Package
, obj
string, pcCFLAGS
[]string) (outGo
, outC
, outCXX
[]string, err error
) {
3628 if err
:= b
.swigVersionCheck(); err
!= nil {
3629 return nil, nil, nil, err
3632 intgosize
, err
:= b
.swigIntSize(obj
)
3634 return nil, nil, nil, err
3637 for _
, f
:= range p
.SwigFiles
{
3638 goFile
, cFile
, err
:= b
.swigOne(p
, f
, obj
, pcCFLAGS
, false, intgosize
)
3640 return nil, nil, nil, err
3643 outGo
= append(outGo
, goFile
)
3646 outC
= append(outC
, cFile
)
3649 for _
, f
:= range p
.SwigCXXFiles
{
3650 goFile
, cxxFile
, err
:= b
.swigOne(p
, f
, obj
, pcCFLAGS
, true, intgosize
)
3652 return nil, nil, nil, err
3655 outGo
= append(outGo
, goFile
)
3658 outCXX
= append(outCXX
, cxxFile
)
3661 return outGo
, outC
, outCXX
, nil
3664 // Make sure SWIG is new enough.
3666 swigCheckOnce sync
.Once
3670 func (b
*builder
) swigDoVersionCheck() error
{
3671 out
, err
:= b
.runOut("", "", nil, "swig", "-version")
3675 re
:= regexp
.MustCompile(`[vV]ersion +([\d]+)([.][\d]+)?([.][\d]+)?`)
3676 matches
:= re
.FindSubmatch(out
)
3678 // Can't find version number; hope for the best.
3682 major
, err
:= strconv
.Atoi(string(matches
[1]))
3684 // Can't find version number; hope for the best.
3687 const errmsg
= "must have SWIG version >= 3.0.6"
3689 return errors
.New(errmsg
)
3696 // We have SWIG version 3.x.
3697 if len(matches
[2]) > 0 {
3698 minor
, err
:= strconv
.Atoi(string(matches
[2][1:]))
3708 // We have SWIG version 3.0.x.
3709 if len(matches
[3]) > 0 {
3710 patch
, err
:= strconv
.Atoi(string(matches
[3][1:]))
3716 return errors
.New(errmsg
)
3723 func (b
*builder
) swigVersionCheck() error
{
3724 swigCheckOnce
.Do(func() {
3725 swigCheck
= b
.swigDoVersionCheck()
3730 // Find the value to pass for the -intgosize option to swig.
3732 swigIntSizeOnce sync
.Once
3734 swigIntSizeError error
3737 // This code fails to build if sizeof(int) <= 32
3738 const swigIntSizeCode
= `
3740 const i int = 1 << 32
3743 // Determine the size of int on the target system for the -intgosize option
3744 // of swig >= 2.0.9. Run only once.
3745 func (b
*builder
) swigDoIntSize(obj
string) (intsize
string, err error
) {
3747 return "$INTBITS", nil
3749 src
:= filepath
.Join(b
.work
, "swig_intsize.go")
3750 if err
= ioutil
.WriteFile(src
, []byte(swigIntSizeCode
), 0666); err
!= nil {
3753 srcs
:= []string{src
}
3755 p
:= goFilesPackage(srcs
)
3757 if _
, _
, e
:= buildToolchain
.gc(b
, p
, "", obj
, false, nil, srcs
); e
!= nil {
3763 // Determine the size of int on the target system for the -intgosize option
3764 // of swig >= 2.0.9.
3765 func (b
*builder
) swigIntSize(obj
string) (intsize
string, err error
) {
3766 swigIntSizeOnce
.Do(func() {
3767 swigIntSize
, swigIntSizeError
= b
.swigDoIntSize(obj
)
3769 return swigIntSize
, swigIntSizeError
3772 // Run SWIG on one SWIG input file.
3773 func (b
*builder
) swigOne(p
*Package
, file
, obj
string, pcCFLAGS
[]string, cxx
bool, intgosize
string) (outGo
, outC
string, err error
) {
3774 cgoCPPFLAGS
, cgoCFLAGS
, cgoCXXFLAGS
, _
, _
:= b
.cflags(p
)
3777 cflags
= stringList(cgoCPPFLAGS
, pcCFLAGS
, cgoCXXFLAGS
)
3779 cflags
= stringList(cgoCPPFLAGS
, pcCFLAGS
, cgoCFLAGS
)
3782 n
:= 5 // length of ".swig"
3784 n
= 8 // length of ".swigcxx"
3786 base
:= file
[:len(file
)-n
]
3787 goFile
:= base
+ ".go"
3788 gccBase
:= base
+ "_wrap."
3794 _
, gccgo
:= buildToolchain
.(gccgoToolchain
)
3800 "-intgosize", intgosize
,
3802 "-o", obj
+ gccBase
+ gccExt
,
3806 for _
, f
:= range cflags
{
3807 if len(f
) > 3 && f
[:2] == "-I" {
3808 args
= append(args
, f
)
3813 args
= append(args
, "-gccgo")
3814 if pkgpath
:= gccgoPkgpath(p
); pkgpath
!= "" {
3815 args
= append(args
, "-go-pkgpath", pkgpath
)
3819 args
= append(args
, "-c++")
3822 out
, err
:= b
.runOut(p
.Dir
, p
.ImportPath
, nil, "swig", args
, file
)
3825 if bytes
.Contains(out
, []byte("-intgosize")) || bytes
.Contains(out
, []byte("-cgo")) {
3826 return "", "", errors
.New("must have SWIG version >= 3.0.6")
3828 b
.showOutput(p
.Dir
, p
.ImportPath
, b
.processOutput(out
)) // swig error
3829 return "", "", errPrintedOutput
3834 b
.showOutput(p
.Dir
, p
.ImportPath
, b
.processOutput(out
)) // swig warning
3837 return goFile
, obj
+ gccBase
+ gccExt
, nil
3840 // disableBuildID adjusts a linker command line to avoid creating a
3841 // build ID when creating an object file rather than an executable or
3842 // shared library. Some systems, such as Ubuntu, always add
3843 // --build-id to every link, but we don't want a build ID when we are
3844 // producing an object file. On some of those system a plain -r (not
3845 // -Wl,-r) will turn off --build-id, but clang 3.0 doesn't support a
3846 // plain -r. I don't know how to turn off --build-id when using clang
3847 // other than passing a trailing --build-id=none. So that is what we
3848 // do, but only on systems likely to support it, which is to say,
3849 // systems that normally use gold or the GNU linker.
3850 func (b
*builder
) disableBuildID(ldflags
[]string) []string {
3852 case "android", "dragonfly", "linux", "netbsd":
3853 ldflags
= append(ldflags
, "-Wl,--build-id=none")
3858 // An actionQueue is a priority queue of actions.
3859 type actionQueue
[]*action
3861 // Implement heap.Interface
3862 func (q
*actionQueue
) Len() int { return len(*q
) }
3863 func (q
*actionQueue
) Swap(i
, j
int) { (*q
)[i
], (*q
)[j
] = (*q
)[j
], (*q
)[i
] }
3864 func (q
*actionQueue
) Less(i
, j
int) bool { return (*q
)[i
].priority
< (*q
)[j
].priority
}
3865 func (q
*actionQueue
) Push(x
interface{}) { *q
= append(*q
, x
.(*action
)) }
3866 func (q
*actionQueue
) Pop() interface{} {
3873 func (q
*actionQueue
) push(a
*action
) {
3877 func (q
*actionQueue
) pop() *action
{
3878 return heap
.Pop(q
).(*action
)
3881 func instrumentInit() {
3882 if !buildRace
&& !buildMSan
{
3885 if buildRace
&& buildMSan
{
3886 fmt
.Fprintf(os
.Stderr
, "go %s: may not use -race and -msan simultaneously\n", flag
.Args()[0])
3889 if buildMSan
&& (goos
!= "linux" || goarch
!= "amd64") {
3890 fmt
.Fprintf(os
.Stderr
, "-msan is not supported on %s/%s\n", goos
, goarch
)
3893 if goarch
!= "amd64" || goos
!= "linux" && goos
!= "freebsd" && goos
!= "darwin" && goos
!= "windows" {
3894 fmt
.Fprintf(os
.Stderr
, "go %s: -race and -msan are only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag
.Args()[0])
3897 if !buildContext
.CgoEnabled
{
3898 fmt
.Fprintf(os
.Stderr
, "go %s: -race requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag
.Args()[0])
3902 buildGcflags
= append(buildGcflags
, "-race")
3903 buildLdflags
= append(buildLdflags
, "-race")
3905 buildGcflags
= append(buildGcflags
, "-msan")
3906 buildLdflags
= append(buildLdflags
, "-msan")
3908 if buildContext
.InstallSuffix
!= "" {
3909 buildContext
.InstallSuffix
+= "_"
3913 buildContext
.InstallSuffix
+= "race"
3914 buildContext
.BuildTags
= append(buildContext
.BuildTags
, "race")
3916 buildContext
.InstallSuffix
+= "msan"
3917 buildContext
.BuildTags
= append(buildContext
.BuildTags
, "msan")