]> Cypherpunks repositories - gostls13.git/commitdiff
go/build: add variable expansion to cgo lines
authorCarlos Castillo <cookieo9@gmail.com>
Mon, 8 Dec 2014 15:28:40 +0000 (07:28 -0800)
committerIan Lance Taylor <iant@golang.org>
Tue, 23 Dec 2014 20:35:49 +0000 (20:35 +0000)
When go parses #cgo lines, expand ${SRCDIR} into the path to the
source directory. This allows options to be passed to the
compiler and linker that involve file paths relative to the
source code directory. Without the expansion the paths would be
invalid when the current working directory changes.

Fixes #7891
Fixes #5428

Change-Id: I343a145a9771a5ccbaa958e4a1ecd1716fcae52d
Reviewed-on: https://go-review.googlesource.com/1756
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/cgo/doc.go
src/go/build/build.go
src/go/build/build_test.go

index 6179c7afd19eb1d587c5bedce46d5b375c64834b..06d5be675b4f27b8fcd8b68a44b6aac6f743a38f 100644 (file)
@@ -60,6 +60,18 @@ concatenated and used at link time.  All the pkg-config directives are
 concatenated and sent to pkg-config simultaneously to add to each appropriate
 set of command-line flags.
 
+When the cgo directives are parsed, any occurrence of the string ${SRCDIR}
+will be replaced by the absolute path to the directory containing the source
+file. This allows pre-compiled static libraries to be included in the package
+directory and linked properly.
+For example if package foo is in the directory /go/src/foo:
+
+       // #cgo LDFLAGS: -L${SRCDIR}/libs -lfoo
+
+Will be expanded to:
+
+       // #cgo LDFLAGS: -L/go/src/foo/libs -lfoo
+
 When the Go tool sees that one or more Go files use the special import
 "C", it will look for other non-Go files in the directory and compile
 them as part of the Go package.  Any .c, .s, or .S files will be
index 9fb4b52e1446503c7dffed3a35f7d99812b517cc..7cf2f1f774bd7265953067b253e171c49d8e8465 100644 (file)
@@ -1120,10 +1120,12 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
                if err != nil {
                        return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
                }
-               for _, arg := range args {
+               for i, arg := range args {
+                       arg = expandSrcDir(arg, di.Dir)
                        if !safeCgoName(arg) {
                                return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg)
                        }
+                       args[i] = arg
                }
 
                switch verb {
@@ -1144,6 +1146,14 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
        return nil
 }
 
+func expandSrcDir(str string, srcdir string) string {
+       // "\" delimited paths cause safeCgoName to fail
+       // so convert native paths with a different delimeter
+       // to "/" before starting (eg: on windows)
+       srcdir = filepath.ToSlash(srcdir)
+       return strings.Replace(str, "${SRCDIR}", srcdir, -1)
+}
+
 // NOTE: $ is not safe for the shell, but it is allowed here because of linker options like -Wl,$ORIGIN.
 // We never pass these arguments to a shell (just to programs we construct argv for), so this should be okay.
 // See golang.org/issue/6038.
index bdd4c05675b1c6d30468ed6d705c5e33cb82ebb8..3985638189db2353286005d845d7ecdf6160b977 100644 (file)
@@ -231,3 +231,33 @@ func TestImportCmd(t *testing.T) {
                t.Fatalf("Import cmd/internal/objfile returned Dir=%q, want %q", filepath.ToSlash(p.Dir), ".../src/cmd/internal/objfile")
        }
 }
+
+var (
+       expandSrcDirPath = filepath.Join(string(filepath.Separator)+"projects", "src", "add")
+)
+
+var expandSrcDirTests = []struct {
+       input, expected string
+}{
+       {"-L ${SRCDIR}/libs -ladd", "-L /projects/src/add/libs -ladd"},
+       {"${SRCDIR}/add_linux_386.a -pthread -lstdc++", "/projects/src/add/add_linux_386.a -pthread -lstdc++"},
+       {"Nothing to expand here!", "Nothing to expand here!"},
+       {"$", "$"},
+       {"$$", "$$"},
+       {"${", "${"},
+       {"$}", "$}"},
+       {"$FOO ${BAR}", "$FOO ${BAR}"},
+       {"Find me the $SRCDIRECTORY.", "Find me the $SRCDIRECTORY."},
+       {"$SRCDIR is missing braces", "$SRCDIR is missing braces"},
+}
+
+func TestExpandSrcDir(t *testing.T) {
+       for _, test := range expandSrcDirTests {
+               output := expandSrcDir(test.input, expandSrcDirPath)
+               if output != test.expected {
+                       t.Errorf("%q expands to %q with SRCDIR=%q when %q is expected", test.input, output, expandSrcDirPath, test.expected)
+               } else {
+                       t.Logf("%q expands to %q with SRCDIR=%q", test.input, output, expandSrcDirPath)
+               }
+       }
+}