afiles = append(xfiles, afiles...)
for _, a := range allactions {
- cgoldflags = append(cgoldflags, a.p.CgoLDFLAGS...)
+ // Gather CgoLDFLAGS, but not from standard packages.
+ // The go tool can dig up runtime/cgo from GOROOT and
+ // think that it should use its CgoLDFLAGS, but gccgo
+ // doesn't use runtime/cgo.
+ if !a.p.Standard {
+ cgoldflags = append(cgoldflags, a.p.CgoLDFLAGS...)
+ }
if len(a.p.CgoFiles) > 0 {
usesCgo = true
}
objc = true
}
}
+
+ if ldBuildmode == "c-archive" {
+ ldflags = append(ldflags, "-Wl,--whole-archive")
+ }
+
ldflags = append(ldflags, afiles...)
+
+ if ldBuildmode == "c-archive" {
+ ldflags = append(ldflags, "-Wl,--no-whole-archive")
+ }
+
ldflags = append(ldflags, cgoldflags...)
ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
ldflags = append(ldflags, p.CgoLDFLAGS...)
- if usesCgo && goos == "linux" {
- ldflags = append(ldflags, "-Wl,-E")
+
+ ldflags = stringList("-Wl,-(", ldflags, "-Wl,-)")
+
+ var realOut string
+ switch ldBuildmode {
+ case "exe":
+ if usesCgo && goos == "linux" {
+ ldflags = append(ldflags, "-Wl,-E")
+ }
+ if cxx {
+ ldflags = append(ldflags, "-lstdc++")
+ }
+ if objc {
+ ldflags = append(ldflags, "-lobjc")
+ }
+
+ case "c-archive":
+ // Link the Go files into a single .o, and also link
+ // in -lgolibbegin.
+ //
+ // We need to use --whole-archive with -lgolibbegin
+ // because it doesn't define any symbols that will
+ // cause the contents to be pulled in; it's just
+ // initialization code.
+ //
+ // The user remains responsible for linking against
+ // -lgo -lpthread -lm in the final link. We can't use
+ // -r to pick them up because we can't combine
+ // split-stack and non-split-stack code in a single -r
+ // link, and libgo picks up non-split-stack code from
+ // libffi.
+ ldflags = append(ldflags, "-Wl,-r", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive")
+
+ // We are creating an object file, so we don't want a build ID.
+ ldflags = b.disableBuildID(ldflags)
+
+ realOut = out
+ out = out + ".o"
+
+ default:
+ fatalf("-buildmode=%s not supported for gccgo", ldBuildmode)
}
- if cxx {
- ldflags = append(ldflags, "-lstdc++")
+
+ if err := b.run(".", p.ImportPath, nil, tools.linker(), "-o", out, ofiles, ldflags, buildGccgoflags); err != nil {
+ return err
}
- if objc {
- ldflags = append(ldflags, "-lobjc")
+
+ switch ldBuildmode {
+ case "c-archive":
+ if err := b.run(".", p.ImportPath, nil, "ar", "rc", realOut, out); err != nil {
+ return err
+ }
}
- return b.run(".", p.ImportPath, nil, tools.linker(), "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags)
+
+ return nil
}
func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
}
+ switch goarch {
+ case "386", "amd64":
+ defs = append(defs, "-fsplit-stack")
+ }
return b.run(p.Dir, p.ImportPath, nil, envList("CC", defaultCC), "-Wall", "-g",
"-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile)
}
}
if _, ok := buildToolchain.(gccgoToolchain); ok {
+ switch goarch {
+ case "386", "amd64":
+ cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack")
+ }
cgoflags = append(cgoflags, "-gccgo")
if pkgpath := gccgoPkgpath(p); pkgpath != "" {
cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath)
}
ldflags := stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs)
- // Some systems, such as Ubuntu, always add --build-id to
- // every link, but we don't want a build ID since we are
- // producing an object file. On some of those system a plain
- // -r (not -Wl,-r) will turn off --build-id, but clang 3.0
- // doesn't support a plain -r. I don't know how to turn off
- // --build-id when using clang other than passing a trailing
- // --build-id=none. So that is what we do, but only on
- // systems likely to support it, which is to say, systems that
- // normally use gold or the GNU linker.
- switch goos {
- case "android", "dragonfly", "linux", "netbsd":
- ldflags = append(ldflags, "-Wl,--build-id=none")
- }
+ // We are creating an object file, so we don't want a build ID.
+ ldflags = b.disableBuildID(ldflags)
if err := b.gccld(p, ofile, ldflags, gccObjs); err != nil {
return nil, nil, err
return obj + goFile, obj + gccBase + gccExt, nil
}
+// disableBuildID adjusts a linker command line to avoid creating a
+// build ID when creating an object file rather than an executable or
+// shared library. Some systems, such as Ubuntu, always add
+// --build-id to every link, but we don't want a build ID when we are
+// producing an object file. On some of those system a plain -r (not
+// -Wl,-r) will turn off --build-id, but clang 3.0 doesn't support a
+// plain -r. I don't know how to turn off --build-id when using clang
+// other than passing a trailing --build-id=none. So that is what we
+// do, but only on systems likely to support it, which is to say,
+// systems that normally use gold or the GNU linker.
+func (b *builder) disableBuildID(ldflags []string) []string {
+ switch goos {
+ case "android", "dragonfly", "linux", "netbsd":
+ ldflags = append(ldflags, "-Wl,--build-id=none")
+ }
+ return ldflags
+}
+
// An actionQueue is a priority queue of actions.
type actionQueue []*action