cmd/go: pass in overlaid file paths to C compiler
This change moves the code in work.(*Builder).cgo that, when there is
an overlay, copies non-Go files to objdir into work.(*Builder).Build,
and creates an overlay structure mapping from the nominal file paths
into the copies in objdir. That's propagated through to
work.(*Builder).ccompile, which will use it to pass in the path to the
overlaid contents in objdir when calling the compiler.
This allows for overlays of C/C++/Fortran files.
For #39958
Change-Id: I9a2e3d3ba6afdf7ce19be1dbf4eee34805cdc05f
Reviewed-on: https://go-review.googlesource.com/c/go/+/266376
Trust: Michael Matloob <matloob@golang.org>
Run-TryBot: Michael Matloob <matloob@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
diff --git a/src/cmd/go/internal/work/action.go b/src/cmd/go/internal/work/action.go
index 825e763..f461c57 100644
--- a/src/cmd/go/internal/work/action.go
+++ b/src/cmd/go/internal/work/action.go
@@ -93,11 +93,12 @@
output []byte // output redirect buffer (nil means use b.Print)
// Execution state.
- pending int // number of deps yet to complete
- priority int // relative execution priority
- Failed bool // whether the action failed
- json *actionJSON // action graph information
- traceSpan *trace.Span
+ pending int // number of deps yet to complete
+ priority int // relative execution priority
+ Failed bool // whether the action failed
+ json *actionJSON // action graph information
+ nonGoOverlay map[string]string // map from non-.go source files to copied files in objdir. Nil if no overlay is used.
+ traceSpan *trace.Span
}
// BuildActionID returns the action ID section of a's build ID.
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index eb76ad4..2c40a4b 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -538,6 +538,34 @@
}
}
+ // Compute overlays for .c/.cc/.h/etc. and if there are any overlays
+ // put correct contents of all those files in the objdir, to ensure
+ // the correct headers are included. nonGoOverlay is the overlay that
+ // points from nongo files to the copied files in objdir.
+ nonGoFileLists := [][]string{a.Package.CFiles, a.Package.SFiles, a.Package.CXXFiles, a.Package.HFiles, a.Package.FFiles}
+OverlayLoop:
+ for _, fs := range nonGoFileLists {
+ for _, f := range fs {
+ if _, ok := fsys.OverlayPath(mkAbs(p.Dir, f)); ok {
+ a.nonGoOverlay = make(map[string]string)
+ break OverlayLoop
+ }
+ }
+ }
+ if a.nonGoOverlay != nil {
+ for _, fs := range nonGoFileLists {
+ for i := range fs {
+ from := mkAbs(p.Dir, fs[i])
+ opath, _ := fsys.OverlayPath(from)
+ dst := objdir + filepath.Base(fs[i])
+ if err := b.copyFile(dst, opath, 0666, false); err != nil {
+ return err
+ }
+ a.nonGoOverlay[from] = dst
+ }
+ }
+ }
+
// Run SWIG on each .swig and .swigcxx file.
// Each run will generate two files, a .go file and a .c or .cxx file.
// The .go file will use import "C" and is to be processed by cgo.
@@ -2269,7 +2297,11 @@
}
}
- output, err := b.runOut(a, filepath.Dir(file), b.cCompilerEnv(), compiler, flags, "-o", outfile, "-c", filepath.Base(file))
+ overlayPath := file
+ if p, ok := a.nonGoOverlay[overlayPath]; ok {
+ overlayPath = p
+ }
+ output, err := b.runOut(a, filepath.Dir(overlayPath), b.cCompilerEnv(), compiler, flags, "-o", outfile, "-c", filepath.Base(overlayPath))
if len(output) > 0 {
// On FreeBSD 11, when we pass -g to clang 3.8 it
// invokes its internal assembler with -dwarf-version=2.
@@ -2655,8 +2687,6 @@
cfiles = append(cfiles, f+".cgo2.c")
}
- hfiles := append([]string{}, p.HFiles...)
-
// TODO: make cgo not depend on $GOARCH?
cgoflags := []string{}
@@ -2703,35 +2733,6 @@
execdir := p.Dir
- // If any of the Cgo, C, or H files are overlaid, copy them all to
- // objdir to ensure that they refer to the right header files.
- // TODO(#39958): Ideally, we'd always do this, but this could
- // subtly break some cgo files that include .h files across directory
- // boundaries, even though they shouldn't.
- hasOverlay := false
- cgoFileLists := [][]string{gccfiles, gxxfiles, mfiles, ffiles, hfiles}
-OverlayLoop:
- for _, fs := range cgoFileLists {
- for _, f := range fs {
- if _, ok := fsys.OverlayPath(mkAbs(p.Dir, f)); ok {
- hasOverlay = true
- break OverlayLoop
- }
- }
- }
- if hasOverlay {
- execdir = objdir
- for _, fs := range cgoFileLists {
- for i := range fs {
- opath, _ := fsys.OverlayPath(mkAbs(p.Dir, fs[i]))
- fs[i] = objdir + filepath.Base(fs[i])
- if err := b.copyFile(fs[i], opath, 0666, false); err != nil {
- return nil, nil, err
- }
- }
- }
- }
-
// Rewrite overlaid paths in cgo files.
// cgo adds //line and #line pragmas in generated files with these paths.
var trimpath []string
diff --git a/src/cmd/go/testdata/script/build_overlay.txt b/src/cmd/go/testdata/script/build_overlay.txt
index f9487da..58c0de9 100644
--- a/src/cmd/go/testdata/script/build_overlay.txt
+++ b/src/cmd/go/testdata/script/build_overlay.txt
@@ -106,6 +106,7 @@
"printpath/main.go": "overlay/printpath.go",
"printpath/other.go": "overlay2/printpath2.go",
"cgo_hello_replace/cgo_header.h": "overlay/cgo_head.h",
+ "cgo_hello_replace/hello.c": "overlay/hello.c",
"cgo_hello_quote/cgo_hello.go": "overlay/cgo_hello_quote.go",
"cgo_hello_quote/cgo_header.h": "overlay/cgo_head.h",
"cgo_hello_angle/cgo_hello.go": "overlay/cgo_hello_angle.go",
@@ -125,10 +126,10 @@
// Test that this header is replaced with one that has the proper declaration.
void say_goodbye();
--- m/cgo_hello_replace/goodbye.c --
+-- m/cgo_hello_replace/hello.c --
#include <stdio.h>
-void say_hello() { puts("hello cgo\n"); fflush(stdout); }
+void say_goodbye() { puts("goodbye cgo\n"); fflush(stdout); }
-- m/overlay/f.go --
package main
@@ -204,6 +205,14 @@
}
-- m/overlay/cgo_head.h --
void say_hello();
+-- m/overlay/hello.c --
+#include <stdio.h>
+
+void say_hello() { puts("hello cgo\n"); fflush(stdout); }
+-- m/overlay/asm_file.s --
+TEXT ·foo(SB),0,$0
+ RET
+
-- m/cgo_hello_quote/hello.c --
#include <stdio.h>
@@ -242,4 +251,4 @@
}
}
}
-}
\ No newline at end of file
+}