Commit 84485361 authored by Alberto García Hierro's avatar Alberto García Hierro Committed by Ian Lance Taylor

cmd/go: Add support for including C++ files in packages

* Add a CXXFiles field to Package, which includes .cc, .cpp and .cxx  files.
* CXXFiles are compiled using g++, which can be overridden using the CXX environment variable.
* Include .hh, .hpp and .hxx files in HFiles.
* Add support for CPPFLAGS (used for both C and C++) and CXXFLAGS (used only for C++) in cgo directive.
* Changed pkg-config cgo directive to modify CPPFLAGS rather than CFLAGS, so both C and C++ files get any flag returned by pkg-config --cflags.

Fixes #1476.

R=iant, r
CC=bradfitz, gobot, golang-dev, iant, minux.ma, remyoudompheng, seb.binet
https://golang.org/cl/8248043
parent ab5c762a
...@@ -24,7 +24,7 @@ the C parts of the package. For example: ...@@ -24,7 +24,7 @@ the C parts of the package. For example:
// #include <errno.h> // #include <errno.h>
import "C" import "C"
CFLAGS and LDFLAGS may be defined with pseudo #cgo directives CPPFLAGS, CFLAGS, CXXFLAGS and LDFLAGS may be defined with pseudo #cgo directives
within these comments to tweak the behavior of gcc. Values defined within these comments to tweak the behavior of gcc. Values defined
in multiple directives are concatenated together. Options prefixed in multiple directives are concatenated together. Options prefixed
by $GOOS, $GOARCH, or $GOOS/$GOARCH are only defined in matching by $GOOS, $GOARCH, or $GOOS/$GOARCH are only defined in matching
...@@ -36,7 +36,7 @@ systems. For example: ...@@ -36,7 +36,7 @@ systems. For example:
// #include <png.h> // #include <png.h>
import "C" import "C"
Alternatively, CFLAGS and LDFLAGS may be obtained via the pkg-config Alternatively, CPPFLAGS and LDFLAGS may be obtained via the pkg-config
tool using a '#cgo pkg-config:' directive followed by the package names. tool using a '#cgo pkg-config:' directive followed by the package names.
For example: For example:
...@@ -44,7 +44,7 @@ For example: ...@@ -44,7 +44,7 @@ For example:
// #include <png.h> // #include <png.h>
import "C" import "C"
The CGO_CFLAGS and CGO_LDFLAGS environment variables are added The CGO_CPPFLAGS, CGO_CFLAGS, CGO_CXXFLAGS and CGO_LDFLAGS environment variables are added
to the flags derived from these directives. Package-specific flags should to the flags derived from these directives. Package-specific flags should
be set using the directives, not the environment variables, so that builds be set using the directives, not the environment variables, so that builds
work in unmodified environments. work in unmodified environments.
......
...@@ -185,6 +185,18 @@ func isSpaceByte(c byte) bool { ...@@ -185,6 +185,18 @@ func isSpaceByte(c byte) bool {
return c == ' ' || c == '\t' || c == '\n' || c == '\r' return c == ' ' || c == '\t' || c == '\n' || c == '\r'
} }
// fileExtSplit expects a filename and returns the name
// and ext (without the dot). If the file has no
// extension, ext will be empty.
func fileExtSplit(file string) (name, ext string) {
dotExt := filepath.Ext(file)
name = file[:len(file)-len(dotExt)]
if dotExt != "" {
ext = dotExt[1:]
}
return
}
type stringsFlag []string type stringsFlag []string
func (v *stringsFlag) Set(s string) error { func (v *stringsFlag) Set(s string) error {
...@@ -727,6 +739,15 @@ func hasString(strings []string, s string) bool { ...@@ -727,6 +739,15 @@ func hasString(strings []string, s string) bool {
// build is the action for building a single package or command. // build is the action for building a single package or command.
func (b *builder) build(a *action) (err error) { func (b *builder) build(a *action) (err error) {
// Return an error if the package has CXX files but it's not using
// cgo nor SWIG, since the CXX files can only be processed by cgo
// and SWIG (it's possible to have packages with C files without
// using cgo, they will get compiled with the plan9 C compiler and
// linked with the rest of the package).
if len(a.p.CXXFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
return fmt.Errorf("can't build package %s because it contains C++ files (%s) but it's not using cgo nor SWIG",
a.p.ImportPath, strings.Join(a.p.CXXFiles, ","))
}
defer func() { defer func() {
if err != nil && err != errPrintedOutput { if err != nil && err != errPrintedOutput {
err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err) err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err)
...@@ -770,8 +791,8 @@ func (b *builder) build(a *action) (err error) { ...@@ -770,8 +791,8 @@ func (b *builder) build(a *action) (err error) {
sfiles = append(sfiles, a.p.SFiles...) sfiles = append(sfiles, a.p.SFiles...)
// Run cgo. // Run cgo.
if len(a.p.CgoFiles) > 0 { if a.p.usesCgo() {
// In a package using cgo, cgo compiles the C and assembly files with gcc. // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
// There is one exception: runtime/cgo's job is to bridge the // There is one exception: runtime/cgo's job is to bridge the
// cgo and non-cgo worlds, so it necessarily has files in both. // cgo and non-cgo worlds, so it necessarily has files in both.
// In that case gcc only gets the gcc_* files. // In that case gcc only gets the gcc_* files.
...@@ -799,7 +820,7 @@ func (b *builder) build(a *action) (err error) { ...@@ -799,7 +820,7 @@ func (b *builder) build(a *action) (err error) {
if a.cgo != nil && a.cgo.target != "" { if a.cgo != nil && a.cgo.target != "" {
cgoExe = a.cgo.target cgoExe = a.cgo.target
} }
outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles) outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles, a.p.CXXFiles)
if err != nil { if err != nil {
return err return err
} }
...@@ -814,6 +835,7 @@ func (b *builder) build(a *action) (err error) { ...@@ -814,6 +835,7 @@ func (b *builder) build(a *action) (err error) {
gccfiles := append(cfiles, sfiles...) gccfiles := append(cfiles, sfiles...)
cfiles = nil cfiles = nil
sfiles = nil sfiles = nil
// TODO(hierro): Handle C++ files with SWIG
outGo, outObj, err := b.swig(a.p, obj, gccfiles) outGo, outObj, err := b.swig(a.p, obj, gccfiles)
if err != nil { if err != nil {
return err return err
...@@ -843,23 +865,24 @@ func (b *builder) build(a *action) (err error) { ...@@ -843,23 +865,24 @@ func (b *builder) build(a *action) (err error) {
// Copy .h files named for goos or goarch or goos_goarch // Copy .h files named for goos or goarch or goos_goarch
// to names using GOOS and GOARCH. // to names using GOOS and GOARCH.
// For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h. // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
_goos_goarch := "_" + goos + "_" + goarch + ".h" _goos_goarch := "_" + goos + "_" + goarch
_goos := "_" + goos + ".h" _goos := "_" + goos
_goarch := "_" + goarch + ".h" _goarch := "_" + goarch
for _, file := range a.p.HFiles { for _, file := range a.p.HFiles {
name, ext := fileExtSplit(file)
switch { switch {
case strings.HasSuffix(file, _goos_goarch): case strings.HasSuffix(name, _goos_goarch):
targ := file[:len(file)-len(_goos_goarch)] + "_GOOS_GOARCH.h" targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext
if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil { if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
return err return err
} }
case strings.HasSuffix(file, _goarch): case strings.HasSuffix(name, _goarch):
targ := file[:len(file)-len(_goarch)] + "_GOARCH.h" targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext
if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil { if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
return err return err
} }
case strings.HasSuffix(file, _goos): case strings.HasSuffix(name, _goos):
targ := file[:len(file)-len(_goos)] + "_GOOS.h" targ := file[:len(name)-len(_goos)] + "_GOOS." + ext
if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil { if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
return err return err
} }
...@@ -1454,7 +1477,7 @@ func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, g ...@@ -1454,7 +1477,7 @@ func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, g
// so that it can give good error messages about forward declarations. // so that it can give good error messages about forward declarations.
// Exceptions: a few standard packages have forward declarations for // Exceptions: a few standard packages have forward declarations for
// pieces supplied behind-the-scenes by package runtime. // pieces supplied behind-the-scenes by package runtime.
extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles) extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles)
if p.Standard { if p.Standard {
switch p.ImportPath { switch p.ImportPath {
case "os", "runtime/pprof", "sync", "time": case "os", "runtime/pprof", "sync", "time":
...@@ -1689,26 +1712,53 @@ func (b *builder) libgcc(p *Package) (string, error) { ...@@ -1689,26 +1712,53 @@ 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) return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir))
return b.run(p.Dir, p.ImportPath, nil, b.gccCmd(p.Dir), flags, "-o", out, "-c", cfile) }
// gxx runs the g++ C++ compiler to create an object from a single C++ file.
func (b *builder) gxx(p *Package, out string, flags []string, cxxfile string) error {
return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir))
}
// ccompile runs the given C or C++ compiler and creates an object from a single source file.
func (b *builder) ccompile(p *Package, out string, flags []string, file string, compiler []string) error {
file = mkAbs(p.Dir, file)
return b.run(p.Dir, p.ImportPath, nil, compiler, flags, "-o", out, "-c", file)
} }
// 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, nil, b.gccCmd(p.Dir), "-o", out, obj, flags) var cmd []string
if len(p.CXXFiles) > 0 {
cmd = b.gxxCmd(p.Dir)
} else {
cmd = b.gccCmd(p.Dir)
}
return b.run(p.Dir, p.ImportPath, nil, cmd, "-o", out, obj, flags)
} }
// gccCmd returns a gcc command line prefix // gccCmd returns a gcc command line prefix
func (b *builder) gccCmd(objdir string) []string { func (b *builder) gccCmd(objdir string) []string {
return b.ccompilerCmd("CC", "gcc", objdir)
}
// gxxCmd returns a g++ command line prefix
func (b *builder) gxxCmd(objdir string) []string {
return b.ccompilerCmd("CXX", "g++", objdir)
}
// ccompilerCmd returns a command line prefix for the given environment
// variable and using the default command when the variable is empty
func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
// NOTE: env.go's mkEnv knows that the first three // NOTE: env.go's mkEnv knows that the first three
// strings returned are "gcc", "-I", objdir (and cuts them off). // strings returned are "gcc", "-I", objdir (and cuts them off).
gcc := strings.Fields(os.Getenv("CC")) compiler := strings.Fields(os.Getenv(envvar))
if len(gcc) == 0 { if len(compiler) == 0 {
gcc = append(gcc, "gcc") compiler = append(compiler, defcmd)
} }
a := []string{gcc[0], "-I", objdir, "-g", "-O2"} a := []string{compiler[0], "-I", objdir, "-g", "-O2"}
a = append(a, gcc[1:]...) a = append(a, compiler[1:]...)
// Definitely want -fPIC but on Windows gcc complains // Definitely want -fPIC but on Windows gcc complains
// "-fPIC ignored for target (all code is position independent)" // "-fPIC ignored for target (all code is position independent)"
...@@ -1767,12 +1817,14 @@ var ( ...@@ -1767,12 +1817,14 @@ var (
cgoLibGccFileOnce sync.Once cgoLibGccFileOnce sync.Once
) )
func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, outObj []string, err error) { func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfiles []string) (outGo, outObj []string, err error) {
if goos != toolGOOS { if goos != toolGOOS {
return nil, nil, errors.New("cannot use cgo when compiling for a different operating system") return nil, nil, errors.New("cannot use cgo when compiling for a different operating system")
} }
cgoCPPFLAGS := stringList(envList("CGO_CPPFLAGS"), p.CgoCPPFLAGS)
cgoCFLAGS := stringList(envList("CGO_CFLAGS"), p.CgoCFLAGS) cgoCFLAGS := stringList(envList("CGO_CFLAGS"), p.CgoCFLAGS)
cgoCXXFLAGS := stringList(envList("CGO_CXXFLAGS"), p.CgoCXXFLAGS)
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 {
...@@ -1783,7 +1835,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, ...@@ -1783,7 +1835,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
return nil, nil, errPrintedOutput return nil, nil, errPrintedOutput
} }
if len(out) > 0 { if len(out) > 0 {
cgoCFLAGS = append(cgoCFLAGS, strings.Fields(string(out))...) cgoCPPFLAGS = append(cgoCPPFLAGS, strings.Fields(string(out))...)
} }
out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs) out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs)
if err != nil { if err != nil {
...@@ -1797,7 +1849,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, ...@@ -1797,7 +1849,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
} }
// Allows including _cgo_export.h from .[ch] files in the package. // Allows including _cgo_export.h from .[ch] files in the package.
cgoCFLAGS = append(cgoCFLAGS, "-I", obj) cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj)
// cgo // cgo
// TODO: CGOPKGPATH, CGO_FLAGS? // TODO: CGOPKGPATH, CGO_FLAGS?
...@@ -1839,7 +1891,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, ...@@ -1839,7 +1891,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, cgoenv, cgoExe, "-objdir", obj, cgoflags, "--", cgoCFLAGS, p.CgoFiles); err != nil { if err := b.run(p.Dir, p.ImportPath, cgoenv, cgoExe, "-objdir", obj, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, p.CgoFiles); err != nil {
return nil, nil, err return nil, nil, err
} }
outGo = append(outGo, gofiles...) outGo = append(outGo, gofiles...)
...@@ -1893,9 +1945,10 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, ...@@ -1893,9 +1945,10 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
staticLibs = append(staticLibs, cgoLibGccFile) staticLibs = append(staticLibs, cgoLibGccFile)
} }
cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
for _, cfile := range cfiles { for _, cfile := range cfiles {
ofile := obj + cfile[:len(cfile)-1] + "o" ofile := obj + cfile[:len(cfile)-1] + "o"
if err := b.gcc(p, ofile, cgoCFLAGS, obj+cfile); err != nil { if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil {
return nil, nil, err return nil, nil, err
} }
linkobj = append(linkobj, ofile) linkobj = append(linkobj, ofile)
...@@ -1903,14 +1956,27 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, ...@@ -1903,14 +1956,27 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
outObj = append(outObj, ofile) outObj = append(outObj, ofile)
} }
} }
for _, file := range gccfiles { for _, file := range gccfiles {
ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o" ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
if err := b.gcc(p, ofile, cgoCFLAGS, file); err != nil { if err := b.gcc(p, ofile, cflags, file); err != nil {
return nil, nil, err return nil, nil, err
} }
linkobj = append(linkobj, ofile) linkobj = append(linkobj, ofile)
outObj = append(outObj, ofile) outObj = append(outObj, ofile)
} }
cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS)
for _, file := range gxxfiles {
// Append .o to the file, just in case the pkg has file.c and file.cpp
ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
if err := b.gxx(p, ofile, cxxflags, file); err != nil {
return nil, nil, err
}
linkobj = append(linkobj, ofile)
outObj = append(outObj, ofile)
}
linkobj = append(linkobj, p.SysoFiles...) linkobj = append(linkobj, p.SysoFiles...)
dynobj := obj + "_cgo_.o" dynobj := obj + "_cgo_.o"
if goarch == "arm" && goos == "linux" { // we need to use -pie for Linux/ARM to get accurate imported sym if goarch == "arm" && goos == "linux" { // we need to use -pie for Linux/ARM to get accurate imported sym
......
...@@ -318,14 +318,17 @@ which calls strings.Join. The struct being passed to the template is: ...@@ -318,14 +318,17 @@ which calls strings.Join. The struct being passed to the template is:
CgoFiles []string // .go sources files that import "C" CgoFiles []string // .go sources files that import "C"
IgnoredGoFiles []string // .go sources ignored due to build constraints IgnoredGoFiles []string // .go sources ignored due to build constraints
CFiles []string // .c source files CFiles []string // .c source files
HFiles []string // .h source files CXXFiles []string // .cc, .cxx and .cpp source files
HFiles []string // .h, .hh, .hpp and .hxx source files
SFiles []string // .s source files SFiles []string // .s source files
SysoFiles []string // .syso object files to add to archive SysoFiles []string // .syso object files to add to archive
SwigFiles []string // .swig files SwigFiles []string // .swig files
SwigCXXFiles []string // .swigcxx files SwigCXXFiles []string // .swigcxx files
// Cgo directives // Cgo directives
CgoCPPFLAGS []string // cgo: flags for C preprocessor
CgoCFLAGS []string // cgo: flags for C compiler CgoCFLAGS []string // cgo: flags for C compiler
CgoCXXFLAGS []string // cgo: flags for C++ compiler
CgoLDFLAGS []string // cgo: flags for linker CgoLDFLAGS []string // cgo: flags for linker
CgoPkgConfig []string // cgo: pkg-config names CgoPkgConfig []string // cgo: pkg-config names
......
...@@ -46,14 +46,17 @@ which calls strings.Join. The struct being passed to the template is: ...@@ -46,14 +46,17 @@ which calls strings.Join. The struct being passed to the template is:
CgoFiles []string // .go sources files that import "C" CgoFiles []string // .go sources files that import "C"
IgnoredGoFiles []string // .go sources ignored due to build constraints IgnoredGoFiles []string // .go sources ignored due to build constraints
CFiles []string // .c source files CFiles []string // .c source files
HFiles []string // .h source files CXXFiles []string // .cc, .cxx and .cpp source files
HFiles []string // .h, .hh, .hpp and .hxx source files
SFiles []string // .s source files SFiles []string // .s source files
SysoFiles []string // .syso object files to add to archive SysoFiles []string // .syso object files to add to archive
SwigFiles []string // .swig files SwigFiles []string // .swig files
SwigCXXFiles []string // .swigcxx files SwigCXXFiles []string // .swigcxx files
// Cgo directives // Cgo directives
CgoCPPFLAGS []string // cgo: flags for C preprocessor
CgoCFLAGS []string // cgo: flags for C compiler CgoCFLAGS []string // cgo: flags for C compiler
CgoCXXFLAGS []string // cgo: flags for C++ compiler
CgoLDFLAGS []string // cgo: flags for linker CgoLDFLAGS []string // cgo: flags for linker
CgoPkgConfig []string // cgo: pkg-config names CgoPkgConfig []string // cgo: pkg-config names
......
...@@ -40,14 +40,17 @@ type Package struct { ...@@ -40,14 +40,17 @@ type Package struct {
CgoFiles []string `json:",omitempty"` // .go sources files that import "C" CgoFiles []string `json:",omitempty"` // .go sources files that import "C"
IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints
CFiles []string `json:",omitempty"` // .c source files CFiles []string `json:",omitempty"` // .c source files
HFiles []string `json:",omitempty"` // .h source files CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files
HFiles []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files
SFiles []string `json:",omitempty"` // .s source files SFiles []string `json:",omitempty"` // .s source files
SysoFiles []string `json:",omitempty"` // .syso system object files added to package SysoFiles []string `json:",omitempty"` // .syso system object files added to package
SwigFiles []string `json:",omitempty"` // .swig files SwigFiles []string `json:",omitempty"` // .swig files
SwigCXXFiles []string `json:",omitempty"` // .swigcxx files SwigCXXFiles []string `json:",omitempty"` // .swigcxx files
// Cgo directives // Cgo directives
CgoCPPFLAGS []string `json:",omitempty"` // cgo: flags for C preprocessor
CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler
CgoCXXFLAGS []string `json:",omitempty"` // cgo: flags for C++ compiler
CgoLDFLAGS []string `json:",omitempty"` // cgo: flags for linker CgoLDFLAGS []string `json:",omitempty"` // cgo: flags for linker
CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names
...@@ -98,12 +101,15 @@ func (p *Package) copyBuild(pp *build.Package) { ...@@ -98,12 +101,15 @@ func (p *Package) copyBuild(pp *build.Package) {
p.CgoFiles = pp.CgoFiles p.CgoFiles = pp.CgoFiles
p.IgnoredGoFiles = pp.IgnoredGoFiles p.IgnoredGoFiles = pp.IgnoredGoFiles
p.CFiles = pp.CFiles p.CFiles = pp.CFiles
p.CXXFiles = pp.CXXFiles
p.HFiles = pp.HFiles p.HFiles = pp.HFiles
p.SFiles = pp.SFiles p.SFiles = pp.SFiles
p.SysoFiles = pp.SysoFiles p.SysoFiles = pp.SysoFiles
p.SwigFiles = pp.SwigFiles p.SwigFiles = pp.SwigFiles
p.SwigCXXFiles = pp.SwigCXXFiles p.SwigCXXFiles = pp.SwigCXXFiles
p.CgoCPPFLAGS = pp.CgoCPPFLAGS
p.CgoCFLAGS = pp.CgoCFLAGS p.CgoCFLAGS = pp.CgoCFLAGS
p.CgoCXXFLAGS = pp.CgoCXXFLAGS
p.CgoLDFLAGS = pp.CgoLDFLAGS p.CgoLDFLAGS = pp.CgoLDFLAGS
p.CgoPkgConfig = pp.CgoPkgConfig p.CgoPkgConfig = pp.CgoPkgConfig
p.Imports = pp.Imports p.Imports = pp.Imports
...@@ -389,6 +395,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package ...@@ -389,6 +395,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
p.CgoFiles, p.CgoFiles,
p.IgnoredGoFiles, p.IgnoredGoFiles,
p.CFiles, p.CFiles,
p.CXXFiles,
p.HFiles, p.HFiles,
p.SFiles, p.SFiles,
p.SysoFiles, p.SysoFiles,
...@@ -481,6 +488,11 @@ func (p *Package) usesSwig() bool { ...@@ -481,6 +488,11 @@ func (p *Package) usesSwig() bool {
return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0 return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0
} }
// usesCgo returns whether the package needs to run cgo
func (p *Package) usesCgo() bool {
return len(p.CgoFiles) > 0
}
// swigSoname returns the name of the shared library we create for a // swigSoname returns the name of the shared library we create for a
// SWIG input file. // SWIG input file.
func (p *Package) swigSoname(file string) string { func (p *Package) swigSoname(file string) string {
...@@ -611,7 +623,7 @@ func isStale(p *Package, topRoot map[string]bool) bool { ...@@ -611,7 +623,7 @@ func isStale(p *Package, topRoot map[string]bool) bool {
return false return false
} }
srcs := stringList(p.GoFiles, p.CFiles, p.HFiles, p.SFiles, p.CgoFiles, p.SysoFiles) srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.HFiles, p.SFiles, p.CgoFiles, p.SysoFiles)
for _, src := range srcs { for _, src := range srcs {
if olderThan(filepath.Join(p.Dir, src)) { if olderThan(filepath.Join(p.Dir, src)) {
return true return true
......
...@@ -657,10 +657,16 @@ func (x *Indexer) addFile(filename string, goFile bool) (file *token.File, ast * ...@@ -657,10 +657,16 @@ func (x *Indexer) addFile(filename string, goFile bool) (file *token.File, ast *
var whitelisted = map[string]bool{ var whitelisted = map[string]bool{
".bash": true, ".bash": true,
".c": true, ".c": true,
".cc": true,
".cpp": true,
".cxx": true,
".css": true, ".css": true,
".go": true, ".go": true,
".goc": true, ".goc": true,
".h": true, ".h": true,
".hh": true,
".hpp": true,
".hxx": true,
".html": true, ".html": true,
".js": true, ".js": true,
".out": true, ".out": true,
......
...@@ -353,16 +353,19 @@ type Package struct { ...@@ -353,16 +353,19 @@ type Package struct {
CgoFiles []string // .go source files that import "C" CgoFiles []string // .go source files that import "C"
IgnoredGoFiles []string // .go source files ignored for this build IgnoredGoFiles []string // .go source files ignored for this build
CFiles []string // .c source files CFiles []string // .c source files
HFiles []string // .h source files CXXFiles []string // .cc, .cpp and .cxx source files
HFiles []string // .h, .hh, .hpp and .hxx source files
SFiles []string // .s source files SFiles []string // .s source files
SysoFiles []string // .syso system object files to add to archive SysoFiles []string // .syso system object files to add to archive
SwigFiles []string // .swig files SwigFiles []string // .swig files
SwigCXXFiles []string // .swigcxx files SwigCXXFiles []string // .swigcxx files
// Cgo directives // Cgo directives
CgoPkgConfig []string // Cgo pkg-config directives CgoCPPFLAGS []string // Cgo CPPFLAGS directives
CgoCFLAGS []string // Cgo CFLAGS directives CgoCFLAGS []string // Cgo CFLAGS directives
CgoCXXFLAGS []string // Cgo CXXFLAGS directives
CgoLDFLAGS []string // Cgo LDFLAGS directives CgoLDFLAGS []string // Cgo LDFLAGS directives
CgoPkgConfig []string // Cgo pkg-config directives
// Dependency information // Dependency information
Imports []string // imports from GoFiles, CgoFiles Imports []string // imports from GoFiles, CgoFiles
...@@ -600,7 +603,7 @@ Found: ...@@ -600,7 +603,7 @@ Found:
} }
switch ext { switch ext {
case ".go", ".c", ".s", ".h", ".S", ".swig", ".swigcxx": case ".go", ".c", ".cc", ".cxx", ".cpp", ".s", ".h", ".hh", ".hpp", ".hxx", ".S", ".swig", ".swigcxx":
// tentatively okay - read to make sure // tentatively okay - read to make sure
case ".syso": case ".syso":
// binary objects to add to package archive // binary objects to add to package archive
...@@ -643,7 +646,10 @@ Found: ...@@ -643,7 +646,10 @@ Found:
case ".c": case ".c":
p.CFiles = append(p.CFiles, name) p.CFiles = append(p.CFiles, name)
continue continue
case ".h": case ".cc", ".cpp", ".cxx":
p.CXXFiles = append(p.CXXFiles, name)
continue
case ".h", ".hh", ".hpp", ".hxx":
p.HFiles = append(p.HFiles, name) p.HFiles = append(p.HFiles, name)
continue continue
case ".s": case ".s":
...@@ -851,8 +857,8 @@ func (ctxt *Context) shouldBuild(content []byte) bool { ...@@ -851,8 +857,8 @@ func (ctxt *Context) shouldBuild(content []byte) bool {
} }
// saveCgo saves the information from the #cgo lines in the import "C" comment. // saveCgo saves the information from the #cgo lines in the import "C" comment.
// These lines set CFLAGS and LDFLAGS and pkg-config directives that affect // These lines set CPPCFLAGS, CFLAGS, CXXFLAGS and LDFLAGS and pkg-config directives
// the way cgo's C code is built. // that affect the way cgo's C code is built.
// //
// TODO(rsc): This duplicates code in cgo. // TODO(rsc): This duplicates code in cgo.
// Once the dust settles, remove this code from cgo. // Once the dust settles, remove this code from cgo.
...@@ -910,6 +916,10 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) ...@@ -910,6 +916,10 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
switch verb { switch verb {
case "CFLAGS": case "CFLAGS":
di.CgoCFLAGS = append(di.CgoCFLAGS, args...) di.CgoCFLAGS = append(di.CgoCFLAGS, args...)
case "CPPFLAGS":
di.CgoCPPFLAGS = append(di.CgoCPPFLAGS, args...)
case "CXXFLAGS":
di.CgoCXXFLAGS = append(di.CgoCXXFLAGS, args...)
case "LDFLAGS": case "LDFLAGS":
di.CgoLDFLAGS = append(di.CgoLDFLAGS, args...) di.CgoLDFLAGS = append(di.CgoLDFLAGS, args...)
case "pkg-config": case "pkg-config":
......
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