Commit d06be395 authored by Andrew Wilkins's avatar Andrew Wilkins Committed by Rob Pike

cmd/cgo, cmd/go: remove #cgo directive parsing from cmd/cgo

This change removes processing of #cgo directives from cmd/cgo,
pushing the onus back on cmd/go to pass all necessary flags.

Fixes #5224. See comments for rationale.

R=golang-dev, iant, r
CC=golang-dev
https://golang.org/cl/8610044
parent 082a4a8a
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test that the #cgo CFLAGS directive works,
// with and without platform filters.
// See http://code.google.com/p/go/issues/detail?id=5224 for details.
package cgotest
/*
#cgo CFLAGS: -DCOMMON_VALUE=123
#cgo windows CFLAGS: -DIS_WINDOWS=1
#cgo !windows CFLAGS: -DIS_WINDOWS=0
int common = COMMON_VALUE;
int is_windows = IS_WINDOWS;
*/
import "C"
import (
"runtime"
"testing"
)
func testCflags(t *testing.T) {
is_windows := C.is_windows == 1
if is_windows != (runtime.GOOS == "windows") {
t.Errorf("is_windows: %v, runtime.GOOS: %s", is_windows, runtime.GOOS)
}
if C.common != 123 {
t.Errorf("common: %v (expected 123)", C.common)
}
}
...@@ -38,5 +38,6 @@ func Test3775(t *testing.T) { test3775(t) } ...@@ -38,5 +38,6 @@ func Test3775(t *testing.T) { test3775(t) }
func TestCthread(t *testing.T) { testCthread(t) } func TestCthread(t *testing.T) { testCthread(t) }
func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) } func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) }
func Test5227(t *testing.T) { test5227(t) } func Test5227(t *testing.T) { test5227(t) }
func TestCflags(t *testing.T) { testCflags(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
...@@ -66,71 +66,16 @@ func cname(s string) string { ...@@ -66,71 +66,16 @@ func cname(s string) string {
return s return s
} }
// ParseFlags extracts #cgo CFLAGS and LDFLAGS options from the file // DiscardCgoDirectives processes the import C preamble, and discards
// preamble. Multiple occurrences are concatenated with a separating space, // all #cgo CFLAGS and LDFLAGS directives, so they don't make their
// even across files. // way into _cgo_export.h.
func (p *Package) ParseFlags(f *File, srcfile string) { func (f *File) DiscardCgoDirectives() {
linesIn := strings.Split(f.Preamble, "\n") linesIn := strings.Split(f.Preamble, "\n")
linesOut := make([]string, 0, len(linesIn)) linesOut := make([]string, 0, len(linesIn))
NextLine:
for _, line := range linesIn { for _, line := range linesIn {
l := strings.TrimSpace(line) l := strings.TrimSpace(line)
if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) { if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
linesOut = append(linesOut, line) linesOut = append(linesOut, line)
continue
}
l = strings.TrimSpace(l[4:])
fields := strings.SplitN(l, ":", 2)
if len(fields) != 2 {
fatalf("%s: bad #cgo line: %s", srcfile, line)
}
var k string
kf := strings.Fields(fields[0])
switch len(kf) {
case 1:
k = kf[0]
case 2:
k = kf[1]
switch kf[0] {
case goos:
case goarch:
case goos + "/" + goarch:
default:
continue NextLine
}
default:
fatalf("%s: bad #cgo option: %s", srcfile, fields[0])
}
args, err := splitQuoted(fields[1])
if err != nil {
fatalf("%s: bad #cgo option %s: %s", srcfile, k, err)
}
for _, arg := range args {
if !safeName(arg) {
fatalf("%s: #cgo option %s is unsafe: %s", srcfile, k, arg)
}
}
switch k {
case "CFLAGS", "LDFLAGS":
p.addToFlag(k, args)
case "pkg-config":
cflags, ldflags, err := pkgConfig(args)
if err != nil {
fatalf("%s: bad #cgo option %s: %s", srcfile, k, err)
}
p.addToFlag("CFLAGS", cflags)
p.addToFlag("LDFLAGS", ldflags)
default:
fatalf("%s: unsupported #cgo option %s", srcfile, k)
} }
} }
f.Preamble = strings.Join(linesOut, "\n") f.Preamble = strings.Join(linesOut, "\n")
...@@ -146,36 +91,6 @@ func (p *Package) addToFlag(flag string, args []string) { ...@@ -146,36 +91,6 @@ func (p *Package) addToFlag(flag string, args []string) {
} }
} }
// pkgConfig runs pkg-config and extracts --libs and --cflags information
// for packages.
func pkgConfig(packages []string) (cflags, ldflags []string, err error) {
for _, name := range packages {
if len(name) == 0 || name[0] == '-' {
return nil, nil, errors.New(fmt.Sprintf("invalid name: %q", name))
}
}
args := append([]string{"pkg-config", "--cflags"}, packages...)
stdout, stderr, ok := run(nil, args)
if !ok {
os.Stderr.Write(stderr)
return nil, nil, errors.New("pkg-config failed")
}
cflags, err = splitQuoted(string(stdout))
if err != nil {
return
}
args = append([]string{"pkg-config", "--libs"}, packages...)
stdout, stderr, ok = run(nil, args)
if !ok {
os.Stderr.Write(stderr)
return nil, nil, errors.New("pkg-config failed")
}
ldflags, err = splitQuoted(string(stdout))
return
}
// splitQuoted splits the string s around each instance of one or more consecutive // splitQuoted splits the string s around each instance of one or more consecutive
// white space characters while taking into account quotes and escaping, and // white space characters while taking into account quotes and escaping, and
// returns an array of substrings of s or an empty list if s contains only white space. // returns an array of substrings of s or an empty list if s contains only white space.
......
...@@ -235,10 +235,9 @@ func main() { ...@@ -235,10 +235,9 @@ func main() {
fs := make([]*File, len(goFiles)) fs := make([]*File, len(goFiles))
for i, input := range goFiles { for i, input := range goFiles {
// Parse flags for all files before translating due to CFLAGS.
f := new(File) f := new(File)
f.ReadGo(input) f.ReadGo(input)
p.ParseFlags(f, input) f.DiscardCgoDirectives()
fs[i] = f fs[i] = f
} }
...@@ -291,11 +290,6 @@ func main() { ...@@ -291,11 +290,6 @@ func main() {
// newPackage returns a new Package that will invoke // newPackage returns a new Package that will invoke
// gcc with the additional arguments specified in args. // gcc with the additional arguments specified in args.
func newPackage(args []string) *Package { func newPackage(args []string) *Package {
// Copy the gcc options to a new slice so the list
// can grow without overwriting the slice that args is in.
gccOptions := make([]string, len(args))
copy(gccOptions, args)
goarch = runtime.GOARCH goarch = runtime.GOARCH
if s := os.Getenv("GOARCH"); s != "" { if s := os.Getenv("GOARCH"); s != "" {
goarch = s goarch = s
...@@ -318,12 +312,12 @@ func newPackage(args []string) *Package { ...@@ -318,12 +312,12 @@ func newPackage(args []string) *Package {
os.Setenv("LC_ALL", "C") os.Setenv("LC_ALL", "C")
p := &Package{ p := &Package{
PtrSize: ptrSize, PtrSize: ptrSize,
IntSize: intSize, IntSize: intSize,
GccOptions: gccOptions, CgoFlags: make(map[string][]string),
CgoFlags: make(map[string][]string), Written: make(map[string]bool),
Written: make(map[string]bool),
} }
p.addToFlag("CFLAGS", args)
return p return p
} }
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime" "runtime"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
...@@ -1200,8 +1201,8 @@ var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`) ...@@ -1200,8 +1201,8 @@ var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`)
// run runs the command given by cmdline in the directory dir. // run runs the command given by cmdline in the directory dir.
// If the command fails, run prints information about the failure // If the command fails, run prints information about the failure
// and returns a non-nil error. // and returns a non-nil error.
func (b *builder) run(dir string, desc string, cmdargs ...interface{}) error { func (b *builder) run(dir string, desc string, env []string, cmdargs ...interface{}) error {
out, err := b.runOut(dir, desc, cmdargs...) out, err := b.runOut(dir, desc, env, cmdargs...)
if len(out) > 0 { if len(out) > 0 {
if desc == "" { if desc == "" {
desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " ")) desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " "))
...@@ -1233,7 +1234,7 @@ func (b *builder) processOutput(out []byte) string { ...@@ -1233,7 +1234,7 @@ func (b *builder) processOutput(out []byte) string {
// runOut runs the command given by cmdline in the directory dir. // runOut runs the command given by cmdline in the directory dir.
// It returns the command output and any errors that occurred. // It returns the command output and any errors that occurred.
func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byte, error) { func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) {
cmdline := stringList(cmdargs...) cmdline := stringList(cmdargs...)
if buildN || buildX { if buildN || buildX {
b.showcmd(dir, "%s", strings.Join(cmdline, " ")) b.showcmd(dir, "%s", strings.Join(cmdline, " "))
...@@ -1249,7 +1250,7 @@ func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byt ...@@ -1249,7 +1250,7 @@ func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byt
cmd.Stdout = &buf cmd.Stdout = &buf
cmd.Stderr = &buf cmd.Stderr = &buf
cmd.Dir = dir cmd.Dir = dir
cmd.Env = envForDir(cmd.Dir) cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir))
err := cmd.Run() err := cmd.Run()
// cmd.Run will fail on Unix if some other process has the binary // cmd.Run will fail on Unix if some other process has the binary
...@@ -1450,13 +1451,13 @@ func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, g ...@@ -1450,13 +1451,13 @@ func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, g
args = append(args, mkAbs(p.Dir, f)) args = append(args, mkAbs(p.Dir, f))
} }
output, err = b.runOut(p.Dir, p.ImportPath, args) output, err = b.runOut(p.Dir, p.ImportPath, nil, args)
return ofile, output, err return ofile, output, err
} }
func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
sfile = mkAbs(p.Dir, sfile) sfile = mkAbs(p.Dir, sfile)
return b.run(p.Dir, p.ImportPath, tool(archChar+"a"), "-I", obj, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile) return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-I", obj, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile)
} }
func (gcToolchain) pkgpath(basedir string, p *Package) string { func (gcToolchain) pkgpath(basedir string, p *Package) string {
...@@ -1469,7 +1470,7 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s ...@@ -1469,7 +1470,7 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
for _, f := range ofiles { for _, f := range ofiles {
absOfiles = append(absOfiles, mkAbs(objDir, f)) absOfiles = append(absOfiles, mkAbs(objDir, f))
} }
return b.run(p.Dir, p.ImportPath, tool("pack"), "grcP", b.work, mkAbs(objDir, afile), absOfiles) return b.run(p.Dir, p.ImportPath, nil, tool("pack"), "grcP", b.work, mkAbs(objDir, afile), absOfiles)
} }
func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error { func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
...@@ -1488,14 +1489,14 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, ...@@ -1488,14 +1489,14 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action,
swigDirs[sd] = true swigDirs[sd] = true
} }
} }
return b.run(".", p.ImportPath, tool(archChar+"l"), "-o", out, importArgs, swigArg, buildLdflags, mainpkg) return b.run(".", p.ImportPath, nil, tool(archChar+"l"), "-o", out, importArgs, swigArg, buildLdflags, mainpkg)
} }
func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
cfile = mkAbs(p.Dir, cfile) cfile = mkAbs(p.Dir, cfile)
args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile) args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile)
return b.run(p.Dir, p.ImportPath, args) return b.run(p.Dir, p.ImportPath, nil, args)
} }
// The Gccgo toolchain. // The Gccgo toolchain.
...@@ -1527,7 +1528,7 @@ func (gccgoToolchain) gc(b *builder, p *Package, obj string, importArgs []string ...@@ -1527,7 +1528,7 @@ func (gccgoToolchain) gc(b *builder, p *Package, obj string, importArgs []string
args = append(args, mkAbs(p.Dir, f)) args = append(args, mkAbs(p.Dir, f))
} }
output, err = b.runOut(p.Dir, p.ImportPath, args) output, err = b.runOut(p.Dir, p.ImportPath, nil, args)
return ofile, output, err return ofile, output, err
} }
...@@ -1538,7 +1539,7 @@ func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) erro ...@@ -1538,7 +1539,7 @@ func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) erro
defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
} }
defs = append(defs, b.gccArchArgs()...) defs = append(defs, b.gccArchArgs()...)
return b.run(p.Dir, p.ImportPath, "gccgo", "-I", obj, "-o", ofile, defs, sfile) return b.run(p.Dir, p.ImportPath, nil, "gccgo", "-I", obj, "-o", ofile, defs, sfile)
} }
func (gccgoToolchain) pkgpath(basedir string, p *Package) string { func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
...@@ -1553,7 +1554,7 @@ func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles ...@@ -1553,7 +1554,7 @@ func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles
for _, f := range ofiles { for _, f := range ofiles {
absOfiles = append(absOfiles, mkAbs(objDir, f)) absOfiles = append(absOfiles, mkAbs(objDir, f))
} }
return b.run(p.Dir, p.ImportPath, "ar", "cru", mkAbs(objDir, afile), absOfiles) return b.run(p.Dir, p.ImportPath, nil, "ar", "cru", mkAbs(objDir, afile), absOfiles)
} }
func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error { func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
...@@ -1595,7 +1596,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] ...@@ -1595,7 +1596,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
if usesCgo && goos == "linux" { if usesCgo && goos == "linux" {
ldflags = append(ldflags, "-Wl,-E") ldflags = append(ldflags, "-Wl,-E")
} }
return b.run(".", p.ImportPath, "gccgo", "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags) return b.run(".", p.ImportPath, nil, "gccgo", "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags)
} }
func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
...@@ -1607,7 +1608,7 @@ func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) er ...@@ -1607,7 +1608,7 @@ func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) er
defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
} }
// TODO: Support using clang here (during gccgo build)? // TODO: Support using clang here (during gccgo build)?
return b.run(p.Dir, p.ImportPath, "gcc", "-Wall", "-g", return b.run(p.Dir, p.ImportPath, nil, "gcc", "-Wall", "-g",
"-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile)
} }
...@@ -1647,7 +1648,7 @@ func (b *builder) libgcc(p *Package) (string, error) { ...@@ -1647,7 +1648,7 @@ func (b *builder) libgcc(p *Package) (string, error) {
return fmt.Fprint(&buf, a...) return fmt.Fprint(&buf, a...)
} }
} }
f, err := b.runOut(p.Dir, p.ImportPath, gccCmd, "-print-libgcc-file-name") f, err := b.runOut(p.Dir, p.ImportPath, nil, gccCmd, "-print-libgcc-file-name")
if err != nil { if err != nil {
return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", err, f) return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", err, f)
} }
...@@ -1670,12 +1671,12 @@ func (b *builder) libgcc(p *Package) (string, error) { ...@@ -1670,12 +1671,12 @@ func (b *builder) libgcc(p *Package) (string, error) {
// gcc runs the gcc C compiler to create an object from a single C file. // gcc runs the gcc C compiler to create an object from a single C file.
func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error { func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error {
cfile = mkAbs(p.Dir, cfile) cfile = mkAbs(p.Dir, cfile)
return b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), flags, "-o", out, "-c", cfile) return b.run(p.Dir, p.ImportPath, nil, b.gccCmd(p.Dir), flags, "-o", out, "-c", cfile)
} }
// gccld runs the gcc linker to create an executable from a set of object files // gccld runs the gcc linker to create an executable from a set of object files
func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error { func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error {
return b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), "-o", out, obj, flags) return b.run(p.Dir, p.ImportPath, nil, b.gccCmd(p.Dir), "-o", out, obj, flags)
} }
// gccCmd returns a gcc command line prefix // gccCmd returns a gcc command line prefix
...@@ -1756,7 +1757,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, ...@@ -1756,7 +1757,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
cgoLDFLAGS := stringList(envList("CGO_LDFLAGS"), p.CgoLDFLAGS) cgoLDFLAGS := stringList(envList("CGO_LDFLAGS"), p.CgoLDFLAGS)
if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
out, err := b.runOut(p.Dir, p.ImportPath, "pkg-config", "--cflags", pkgs) out, err := b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs)
if err != nil { if err != nil {
b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out)) b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out))
b.print(err.Error() + "\n") b.print(err.Error() + "\n")
...@@ -1765,7 +1766,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, ...@@ -1765,7 +1766,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
if len(out) > 0 { if len(out) > 0 {
cgoCFLAGS = append(cgoCFLAGS, strings.Fields(string(out))...) cgoCFLAGS = append(cgoCFLAGS, strings.Fields(string(out))...)
} }
out, err = b.runOut(p.Dir, p.ImportPath, "pkg-config", "--libs", pkgs) out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs)
if err != nil { if err != nil {
b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out)) b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out))
b.print(err.Error() + "\n") b.print(err.Error() + "\n")
...@@ -1802,6 +1803,16 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, ...@@ -1802,6 +1803,16 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
cgoflags = append(cgoflags, "-import_syscall=false") cgoflags = append(cgoflags, "-import_syscall=false")
} }
// Update $CGO_LDFLAGS with p.CgoLDFLAGS.
var cgoenv []string
if len(cgoLDFLAGS) > 0 {
flags := make([]string, len(cgoLDFLAGS))
for i, f := range cgoLDFLAGS {
flags[i] = strconv.Quote(f)
}
cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
}
if _, ok := buildToolchain.(gccgoToolchain); ok { if _, ok := buildToolchain.(gccgoToolchain); ok {
cgoflags = append(cgoflags, "-gccgo") cgoflags = append(cgoflags, "-gccgo")
if pkgpath := gccgoPkgpath(p); pkgpath != "" { if pkgpath := gccgoPkgpath(p); pkgpath != "" {
...@@ -1809,7 +1820,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, ...@@ -1809,7 +1820,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
} }
objExt = "o" objExt = "o"
} }
if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, cgoflags, "--", cgoCFLAGS, p.CgoFiles); err != nil { if err := b.run(p.Dir, p.ImportPath, cgoenv, cgoExe, "-objdir", obj, cgoflags, "--", cgoCFLAGS, p.CgoFiles); err != nil {
return nil, nil, err return nil, nil, err
} }
outGo = append(outGo, gofiles...) outGo = append(outGo, gofiles...)
...@@ -1894,7 +1905,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, ...@@ -1894,7 +1905,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
if p.Standard && p.ImportPath == "runtime/cgo" { if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker
} }
if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil { if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil {
return nil, nil, err return nil, nil, err
} }
...@@ -2017,7 +2028,7 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri ...@@ -2017,7 +2028,7 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri
args = append(args, "-c++") args = append(args, "-c++")
} }
if out, err := b.runOut(p.Dir, p.ImportPath, "swig", args, file); err != nil { if out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file); err != nil {
if len(out) > 0 { if len(out) > 0 {
if bytes.Contains(out, []byte("Unrecognized option -intgosize")) { if bytes.Contains(out, []byte("Unrecognized option -intgosize")) {
return "", "", errors.New("must have SWIG version >= 2.0.9\n") return "", "", errors.New("must have SWIG version >= 2.0.9\n")
...@@ -2055,7 +2066,7 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri ...@@ -2055,7 +2066,7 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri
cxxlib = []string{"-lstdc++"} cxxlib = []string{"-lstdc++"}
} }
ldflags := stringList(osldflags[goos], cxxlib) ldflags := stringList(osldflags[goos], cxxlib)
b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), "-o", soname, gccObj, ldflags) b.run(p.Dir, p.ImportPath, nil, b.gccCmd(p.Dir), "-o", soname, gccObj, ldflags)
return obj + goFile, cObj, nil return obj + goFile, cObj, nil
} }
......
...@@ -393,16 +393,26 @@ func runOut(dir string, cmdargs ...interface{}) []byte { ...@@ -393,16 +393,26 @@ func runOut(dir string, cmdargs ...interface{}) []byte {
// child will be faster. // child will be faster.
func envForDir(dir string) []string { func envForDir(dir string) []string {
env := os.Environ() env := os.Environ()
for i, kv := range env {
if strings.HasPrefix(kv, "PWD=") {
env[i] = "PWD=" + dir
return env
}
}
// Internally we only use rooted paths, so dir is rooted. // Internally we only use rooted paths, so dir is rooted.
// Even if dir is not rooted, no harm done. // Even if dir is not rooted, no harm done.
env = append(env, "PWD="+dir) return mergeEnvLists([]string{"PWD=" + dir}, env)
return env }
// mergeEnvLists merges the two environment lists such that
// variables with the same name in "in" replace those in "out".
func mergeEnvLists(in, out []string) []string {
NextVar:
for _, inkv := range in {
k := strings.SplitAfterN(inkv, "=", 2)[0]
for i, outkv := range out {
if strings.HasPrefix(outkv, k) {
out[i] = inkv
continue NextVar
}
}
out = append(out, inkv)
}
return out
} }
// matchPattern(pattern)(name) reports whether // matchPattern(pattern)(name) reports whether
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment