]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: pass in overlaid file paths to C compiler
authorMichael Matloob <matloob@golang.org>
Thu, 29 Oct 2020 23:05:56 +0000 (19:05 -0400)
committerMichael Matloob <matloob@golang.org>
Thu, 12 Nov 2020 21:21:18 +0000 (21:21 +0000)
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>
src/cmd/go/internal/work/action.go
src/cmd/go/internal/work/exec.go
src/cmd/go/testdata/script/build_overlay.txt

index 825e763c033d0be2c5e8079da005a71f7443f407..f461c5780f21abc3e1e8a9d5d859752040a499ee 100644 (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.
index eb76ad4e27c92a321b4e805fc7ce4390492bda09..2c40a4bf001e2a31ccbb8049c395aae5201e85b2 100644 (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
index f9487da9f19a54bee46a4feb7409d09f38b892d9..58c0de9a553d5672eb8c4bdf806fc507586f810a 100644 (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() {
             }
         }
     }
-}
\ No newline at end of file
+}