Skip to content

Commit d8efa0e

Browse files
committed
cmd/go: add gccgo support for recent work
Implement importcfg on behalf of gccgo by writing out a tree of symbolic links. In addition to keeping gccgo working with the latest changes, this also fixes a precedence bug in gccgo's cmd/go vendor support (the vendor equivalent of #14271). Change-Id: I0e5645116e1c84c957936baf22e3126ba6b0d46e Reviewed-on: https://go-review.googlesource.com/61731 Run-TryBot: Russ Cox <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: David Crawshaw <[email protected]>
1 parent 0be2d52 commit d8efa0e

File tree

11 files changed

+159
-22
lines changed

11 files changed

+159
-22
lines changed

src/cmd/go/go_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,19 @@ func (tg *testgoData) failSSH() {
723723
tg.setenv("PATH", fmt.Sprintf("%v%c%v", fail, filepath.ListSeparator, os.Getenv("PATH")))
724724
}
725725

726+
func TestBuildComplex(t *testing.T) {
727+
// Simple smoke test for build configuration.
728+
tg := testgo(t)
729+
defer tg.cleanup()
730+
tg.parallel()
731+
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
732+
tg.run("build", "-o", os.DevNull, "complex")
733+
734+
if _, err := exec.LookPath("gccgo"); err == nil {
735+
tg.run("build", "-o", os.DevNull, "-compiler=gccgo", "complex")
736+
}
737+
}
738+
726739
func TestFileLineInErrorMessages(t *testing.T) {
727740
tg := testgo(t)
728741
defer tg.cleanup()

src/cmd/go/internal/work/build.go

+94-22
Original file line numberDiff line numberDiff line change
@@ -1397,18 +1397,19 @@ func (b *Builder) build(a *Action) (err error) {
13971397
if p1.ImportPath == "unsafe" {
13981398
continue
13991399
}
1400+
if p1.Internal.Pkgfile == "" {
1401+
// This happens for gccgo-internal packages like runtime.
1402+
continue
1403+
}
14001404
// TODO(rsc): runtime/internal/sys appears twice sometimes,
14011405
// because of the blind append in ../load/pkg.go that
14021406
// claims to fix issue 13655. That's probably not the right fix.
14031407
// Look into that.
14041408
fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, p1.Internal.Pkgfile)
14051409
}
1406-
if err := b.writeFile(objdir+"importcfg", icfg.Bytes()); err != nil {
1407-
return err
1408-
}
14091410

14101411
// Compile Go.
1411-
ofile, out, err := BuildToolchain.gc(b, a.Package, a.Objpkg, objdir, objdir+"importcfg", len(sfiles) > 0, gofiles)
1412+
ofile, out, err := BuildToolchain.gc(b, a.Package, a.Objpkg, objdir, icfg.Bytes(), len(sfiles) > 0, gofiles)
14121413
if len(out) > 0 {
14131414
b.showOutput(a.Package.Dir, a.Package.ImportPath, b.processOutput(out))
14141415
if err != nil {
@@ -2174,7 +2175,7 @@ func mkAbs(dir, f string) string {
21742175
type toolchain interface {
21752176
// gc runs the compiler in a specific directory on a set of files
21762177
// and returns the name of the generated output file.
2177-
gc(b *Builder, p *load.Package, archive, objdir, importcfg string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error)
2178+
gc(b *Builder, p *load.Package, archive, objdir string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, out []byte, err error)
21782179
// cc runs the toolchain's C compiler in a directory on a C file
21792180
// to produce an output file.
21802181
cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error
@@ -2213,7 +2214,7 @@ func (noToolchain) linker() string {
22132214
return ""
22142215
}
22152216

2216-
func (noToolchain) gc(b *Builder, p *load.Package, archive, objdir, importcfg string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) {
2217+
func (noToolchain) gc(b *Builder, p *load.Package, archive, objdir string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) {
22172218
return "", nil, noCompiler()
22182219
}
22192220

@@ -2253,7 +2254,7 @@ func (gcToolchain) linker() string {
22532254
return base.Tool("link")
22542255
}
22552256

2256-
func (gcToolchain) gc(b *Builder, p *load.Package, archive, objdir, importcfg string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
2257+
func (gcToolchain) gc(b *Builder, p *load.Package, archive, objdir string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
22572258
if archive != "" {
22582259
ofile = archive
22592260
} else {
@@ -2303,14 +2304,6 @@ func (gcToolchain) gc(b *Builder, p *load.Package, archive, objdir, importcfg st
23032304
gcargs = append(gcargs, "-dwarf=false")
23042305
}
23052306

2306-
for _, path := range p.Imports {
2307-
if i := strings.LastIndex(path, "/vendor/"); i >= 0 {
2308-
gcargs = append(gcargs, "-importmap", path[i+len("/vendor/"):]+"="+path)
2309-
} else if strings.HasPrefix(path, "vendor/") {
2310-
gcargs = append(gcargs, "-importmap", path[len("vendor/"):]+"="+path)
2311-
}
2312-
}
2313-
23142307
gcflags := buildGcflags
23152308
if compilingRuntime {
23162309
// Remove -N, if present.
@@ -2327,8 +2320,11 @@ func (gcToolchain) gc(b *Builder, p *load.Package, archive, objdir, importcfg st
23272320
}
23282321
}
23292322
args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", b.WorkDir, gcflags, gcargs, "-D", p.Internal.LocalPrefix}
2330-
if importcfg != "" {
2331-
args = append(args, "-importcfg", importcfg)
2323+
if importcfg != nil {
2324+
if err := b.writeFile(objdir+"importcfg", importcfg); err != nil {
2325+
return "", nil, err
2326+
}
2327+
args = append(args, "-importcfg", objdir+"importcfg")
23322328
}
23332329
if ofile == archive {
23342330
args = append(args, "-pack")
@@ -2703,7 +2699,7 @@ func checkGccgoBin() {
27032699
os.Exit(2)
27042700
}
27052701

2706-
func (tools gccgoToolchain) gc(b *Builder, p *load.Package, archive, objdir, importcfg string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
2702+
func (tools gccgoToolchain) gc(b *Builder, p *load.Package, archive, objdir string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
27072703
out := "_go_.o"
27082704
ofile = objdir + out
27092705
gcargs := []string{"-g"}
@@ -2716,8 +2712,19 @@ func (tools gccgoToolchain) gc(b *Builder, p *load.Package, archive, objdir, imp
27162712
}
27172713

27182714
args := str.StringList(tools.compiler(), "-c", gcargs, "-o", ofile)
2719-
if importcfg != "" {
2720-
args = append(args, "-importcfg", importcfg)
2715+
if importcfg != nil {
2716+
if b.gccSupportsFlag(args[:1], "-fgo-importcfg=/dev/null") {
2717+
if err := b.writeFile(objdir+"importcfg", importcfg); err != nil {
2718+
return "", nil, err
2719+
}
2720+
args = append(args, "-fgo-importcfg="+objdir+"importcfg")
2721+
} else {
2722+
root := objdir + "_importcfgroot_"
2723+
if err := buildImportcfgSymlinks(b, root, importcfg); err != nil {
2724+
return "", nil, err
2725+
}
2726+
args = append(args, "-I", root)
2727+
}
27212728
}
27222729
args = append(args, buildGccgoflags...)
27232730
for _, f := range gofiles {
@@ -2728,6 +2735,67 @@ func (tools gccgoToolchain) gc(b *Builder, p *load.Package, archive, objdir, imp
27282735
return ofile, output, err
27292736
}
27302737

2738+
// buildImportcfgSymlinks builds in root a tree of symlinks
2739+
// implementing the directives from importcfg.
2740+
// This serves as a temporary transition mechanism until
2741+
// we can depend on gccgo reading an importcfg directly.
2742+
// (The Go 1.9 and later gc compilers already do.)
2743+
func buildImportcfgSymlinks(b *Builder, root string, importcfg []byte) error {
2744+
for lineNum, line := range strings.Split(string(importcfg), "\n") {
2745+
lineNum++ // 1-based
2746+
line = strings.TrimSpace(line)
2747+
if line == "" {
2748+
continue
2749+
}
2750+
if line == "" || strings.HasPrefix(line, "#") {
2751+
continue
2752+
}
2753+
var verb, args string
2754+
if i := strings.Index(line, " "); i < 0 {
2755+
verb = line
2756+
} else {
2757+
verb, args = line[:i], strings.TrimSpace(line[i+1:])
2758+
}
2759+
var before, after string
2760+
if i := strings.Index(args, "="); i >= 0 {
2761+
before, after = args[:i], args[i+1:]
2762+
}
2763+
switch verb {
2764+
default:
2765+
base.Fatalf("importcfg:%d: unknown directive %q", lineNum, verb)
2766+
case "packagefile":
2767+
if before == "" || after == "" {
2768+
return fmt.Errorf(`importcfg:%d: invalid packagefile: syntax is "packagefile path=filename": %s`, lineNum, line)
2769+
}
2770+
archive := gccgoArchive(root, before)
2771+
if err := b.Mkdir(filepath.Dir(archive)); err != nil {
2772+
return err
2773+
}
2774+
if err := os.Symlink(after, archive); err != nil {
2775+
return err
2776+
}
2777+
case "importmap":
2778+
if before == "" || after == "" {
2779+
return fmt.Errorf(`importcfg:%d: invalid importmap: syntax is "importmap old=new": %s`, lineNum, line)
2780+
}
2781+
beforeA := gccgoArchive(root, before)
2782+
afterA := gccgoArchive(root, after)
2783+
if err := b.Mkdir(filepath.Dir(beforeA)); err != nil {
2784+
return err
2785+
}
2786+
if err := b.Mkdir(filepath.Dir(afterA)); err != nil {
2787+
return err
2788+
}
2789+
if err := os.Symlink(afterA, beforeA); err != nil {
2790+
return err
2791+
}
2792+
case "packageshlib":
2793+
return fmt.Errorf("gccgo -importcfg does not support shared libraries")
2794+
}
2795+
}
2796+
return nil
2797+
}
2798+
27312799
func (tools gccgoToolchain) asm(b *Builder, p *load.Package, objdir string, sfiles []string) ([]string, error) {
27322800
var ofiles []string
27332801
for _, sfile := range sfiles {
@@ -2749,7 +2817,11 @@ func (tools gccgoToolchain) asm(b *Builder, p *load.Package, objdir string, sfil
27492817
}
27502818

27512819
func (gccgoToolchain) Pkgpath(basedir string, p *load.Package) string {
2752-
end := filepath.FromSlash(p.ImportPath + ".a")
2820+
return gccgoArchive(basedir, p.ImportPath)
2821+
}
2822+
2823+
func gccgoArchive(basedir, imp string) string {
2824+
end := filepath.FromSlash(imp + ".a")
27532825
afile := filepath.Join(basedir, end)
27542826
// add "lib" to the final element
27552827
return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile))
@@ -3653,7 +3725,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
36533725

36543726
p := load.GoFilesPackage(srcs)
36553727

3656-
if _, _, e := BuildToolchain.gc(b, p, "", objdir, "", false, srcs); e != nil {
3728+
if _, _, e := BuildToolchain.gc(b, p, "", objdir, nil, false, srcs); e != nil {
36573729
return "32", nil
36583730
}
36593731
return "64", nil
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package main
2+
3+
import (
4+
_ "complex/nest/sub/test12"
5+
_ "complex/nest/sub/test23"
6+
"complex/w"
7+
"v"
8+
)
9+
10+
func main() {
11+
println(v.Hello + " " + w.World)
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package test12
2+
3+
// Check that vendor/v1 is used but vendor/v2 is NOT used (sub/vendor/v2 wins).
4+
5+
import (
6+
"v1"
7+
"v2"
8+
)
9+
10+
const x = v1.ComplexNestVendorV1
11+
const y = v2.ComplexNestSubVendorV2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package test23
2+
3+
// Check that vendor/v3 is used but vendor/v2 is NOT used (sub/vendor/v2 wins).
4+
5+
import (
6+
"v2"
7+
"v3"
8+
)
9+
10+
const x = v3.ComplexNestVendorV3
11+
const y = v2.ComplexNestSubVendorV2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package v2
2+
3+
const ComplexNestSubVendorV2 = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package v1
2+
3+
const ComplexNestVendorV1 = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package v2
2+
3+
const ComplexNestVendorV2 = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package v3
2+
3+
const ComplexNestVendorV3 = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package v
2+
3+
const Hello = "hello"
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package w
2+
3+
const World = "world"

0 commit comments

Comments
 (0)