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>
This commit is contained in:
Michael Matloob 2020-10-29 19:05:56 -04:00
parent 062e0e5ce6
commit 60b1253293
3 changed files with 51 additions and 40 deletions

View file

@ -93,11 +93,12 @@ type Action struct {
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.

View file

@ -538,6 +538,34 @@ func (b *Builder) build(ctx context.Context, a *Action) (err error) {
}
}
// 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 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
}
}
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 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
cfiles = append(cfiles, f+".cgo2.c")
}
hfiles := append([]string{}, p.HFiles...)
// TODO: make cgo not depend on $GOARCH?
cgoflags := []string{}
@ -2703,35 +2733,6 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
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

View file

@ -106,6 +106,7 @@ the actual code is in the overlay
"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 @@ func main() {
// 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 @@ func main() {
}
-- 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 @@ func main() {
}
}
}
}
}