1
0
mirror of https://github.com/golang/go synced 2024-11-19 06:54:39 -07:00

go/build: add variable expansion to cgo lines

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>
This commit is contained in:
Carlos Castillo 2014-12-08 07:28:40 -08:00 committed by Ian Lance Taylor
parent 108dbd0dc7
commit 131758183f
3 changed files with 53 additions and 1 deletions

View 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 concatenated and sent to pkg-config simultaneously to add to each appropriate
set of command-line flags. 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 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 "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 them as part of the Go package. Any .c, .s, or .S files will be

View File

@ -1120,10 +1120,12 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
if err != nil { if err != nil {
return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig) 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) { if !safeCgoName(arg) {
return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg) return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg)
} }
args[i] = arg
} }
switch verb { switch verb {
@ -1144,6 +1146,14 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
return nil 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. // 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. // 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. // See golang.org/issue/6038.

View 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") 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)
}
}
}