Commit 7861cd60 authored by Carlos Castillo's avatar Carlos Castillo Committed by Ian Lance Taylor

cmd/go, go/build: support .m files

go/build is changed to list the .m files in a package, and match them for build constraints, adding them to a new field: Package.MFiles.

The go tool is changed to support building .m files and linking in the results during CGO and SWIG builds. This means packages that create a C interface to calls Objective-C code from go are now go-gettable without producing and distributing .syso files. This change is analogous to the one in Go 1.2 made to support C++ built code.

This change doesn't support .mm files (Objective C++).

Also added support for these MFiles to go list's -json mode.

Fixes #6536.

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/60590044
parent fc8e77ca
...@@ -5,3 +5,4 @@ runtime: output how long goroutines are blocked (CL 50420043) ...@@ -5,3 +5,4 @@ runtime: output how long goroutines are blocked (CL 50420043)
syscall: add NewCallbackCDecl to use for windows callbacks (CL 36180044) syscall: add NewCallbackCDecl to use for windows callbacks (CL 36180044)
testing: diagnose buggy tests that panic(nil) (CL 55780043) testing: diagnose buggy tests that panic(nil) (CL 55780043)
misc/benchcmp has been replaced by go tool benchcmp (CL 47980043) misc/benchcmp has been replaced by go tool benchcmp (CL 47980043)
cmd/go, go/build: support .m files (CL 60590044)
...@@ -766,6 +766,11 @@ func (b *builder) build(a *action) (err error) { ...@@ -766,6 +766,11 @@ func (b *builder) build(a *action) (err error) {
return fmt.Errorf("can't build package %s because it contains C++ files (%s) but it's not using cgo nor SWIG", 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, ",")) a.p.ImportPath, strings.Join(a.p.CXXFiles, ","))
} }
// Same as above for Objective-C files
if len(a.p.MFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
return fmt.Errorf("can't build package %s because it contains Objective-C files (%s) but it's not using cgo nor SWIG",
a.p.ImportPath, strings.Join(a.p.MFiles, ","))
}
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)
...@@ -857,7 +862,7 @@ func (b *builder) build(a *action) (err error) { ...@@ -857,7 +862,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, a.p.CXXFiles) outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles, a.p.CXXFiles, a.p.MFiles)
if err != nil { if err != nil {
return err return err
} }
...@@ -872,7 +877,7 @@ func (b *builder) build(a *action) (err error) { ...@@ -872,7 +877,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
outGo, outObj, err := b.swig(a.p, obj, gccfiles, a.p.CXXFiles) outGo, outObj, err := b.swig(a.p, obj, gccfiles, a.p.CXXFiles, a.p.MFiles)
if err != nil { if err != nil {
return err return err
} }
...@@ -1559,7 +1564,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs [] ...@@ -1559,7 +1564,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []
// 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.CXXFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles) extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + 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":
...@@ -1824,6 +1829,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] ...@@ -1824,6 +1829,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
cgoldflags := []string{} cgoldflags := []string{}
usesCgo := false usesCgo := false
cxx := false cxx := false
objc := false
for _, a := range allactions { for _, a := range allactions {
if a.p != nil { if a.p != nil {
if !a.p.Standard { if !a.p.Standard {
...@@ -1850,6 +1856,9 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] ...@@ -1850,6 +1856,9 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
if len(a.p.CXXFiles) > 0 { if len(a.p.CXXFiles) > 0 {
cxx = true cxx = true
} }
if len(a.p.MFiles) > 0 {
objc = true
}
} }
} }
ldflags = append(ldflags, afiles...) ldflags = append(ldflags, afiles...)
...@@ -1861,6 +1870,9 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] ...@@ -1861,6 +1870,9 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
if cxx { if cxx {
ldflags = append(ldflags, "-lstdc++") ldflags = append(ldflags, "-lstdc++")
} }
if objc {
ldflags = append(ldflags, "-lobjc")
}
return b.run(".", p.ImportPath, nil, "gccgo", "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags) return b.run(".", p.ImportPath, nil, "gccgo", "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags)
} }
...@@ -2054,7 +2066,7 @@ var ( ...@@ -2054,7 +2066,7 @@ var (
cgoLibGccFileOnce sync.Once cgoLibGccFileOnce sync.Once
) )
func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfiles []string) (outGo, outObj []string, err error) { func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles []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")
} }
...@@ -2064,6 +2076,11 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfile ...@@ -2064,6 +2076,11 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfile
cgoCXXFLAGS := stringList(envList("CGO_CXXFLAGS"), p.CgoCXXFLAGS) cgoCXXFLAGS := stringList(envList("CGO_CXXFLAGS"), p.CgoCXXFLAGS)
cgoLDFLAGS := stringList(envList("CGO_LDFLAGS"), p.CgoLDFLAGS) cgoLDFLAGS := stringList(envList("CGO_LDFLAGS"), p.CgoLDFLAGS)
// If we are compiling Objective-C code, then we need to link against libobjc
if len(mfiles) > 0 {
cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc")
}
if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
out, err := b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs) out, err := b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs)
if err != nil { if err != nil {
...@@ -2215,6 +2232,16 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfile ...@@ -2215,6 +2232,16 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfile
outObj = append(outObj, ofile) outObj = append(outObj, ofile)
} }
for _, file := range mfiles {
// Append .o to the file, just in case the pkg has file.c and file.m
ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
if err := b.gcc(p, ofile, cflags, 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
...@@ -2272,7 +2299,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfile ...@@ -2272,7 +2299,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfile
// Run SWIG on all SWIG input files. // Run SWIG on all SWIG input files.
// TODO: Don't build a shared library, once SWIG emits the necessary // TODO: Don't build a shared library, once SWIG emits the necessary
// pragmas for external linking. // pragmas for external linking.
func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles []string) (outGo, outObj []string, err error) { func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
var extraObj []string var extraObj []string
for _, file := range gccfiles { for _, file := range gccfiles {
...@@ -2292,6 +2319,15 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles []string) (out ...@@ -2292,6 +2319,15 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles []string) (out
extraObj = append(extraObj, ofile) extraObj = append(extraObj, ofile)
} }
for _, file := range mfiles {
// 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.gcc(p, ofile, nil, file); err != nil {
return nil, nil, err
}
extraObj = append(extraObj, ofile)
}
intgosize, err := b.swigIntSize(obj) intgosize, err := b.swigIntSize(obj)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
......
...@@ -478,8 +478,8 @@ http://swig.org/. When running go build, any file with a .swig ...@@ -478,8 +478,8 @@ http://swig.org/. When running go build, any file with a .swig
extension will be passed to SWIG. Any file with a .swigcxx extension extension will be passed to SWIG. Any file with a .swigcxx extension
will be passed to SWIG with the -c++ option. will be passed to SWIG with the -c++ option.
When either cgo or SWIG is used, go build will pass any .c, .s, or .S When either cgo or SWIG is used, go build will pass any .c, .m, .s,
files to the C compiler, and any .cc, .cpp, .cxx files to the C++ or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++
compiler. The CC or CXX environment variables may be set to determine compiler. The CC or CXX environment variables may be set to determine
the C or C++ compiler, respectively, to use. the C or C++ compiler, respectively, to use.
......
...@@ -47,6 +47,7 @@ which calls strings.Join. The struct being passed to the template is: ...@@ -47,6 +47,7 @@ which calls strings.Join. The struct being passed to the template is:
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
CXXFiles []string // .cc, .cxx and .cpp source files CXXFiles []string // .cc, .cxx and .cpp source files
MFiles []string // .m source files
HFiles []string // .h, .hh, .hpp and .hxx source files HFiles []string // .h, .hh, .hpp and .hxx source files
SFiles []string // .s source files SFiles []string // .s source files
SwigFiles []string // .swig files SwigFiles []string // .swig files
......
...@@ -42,6 +42,7 @@ type Package struct { ...@@ -42,6 +42,7 @@ type Package struct {
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
CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files
MFiles []string `json:",omitempty"` // .m source files
HFiles []string `json:",omitempty"` // .h, .hh, .hpp and .hxx 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
SwigFiles []string `json:",omitempty"` // .swig files SwigFiles []string `json:",omitempty"` // .swig files
...@@ -113,6 +114,7 @@ func (p *Package) copyBuild(pp *build.Package) { ...@@ -113,6 +114,7 @@ func (p *Package) copyBuild(pp *build.Package) {
p.IgnoredGoFiles = pp.IgnoredGoFiles p.IgnoredGoFiles = pp.IgnoredGoFiles
p.CFiles = pp.CFiles p.CFiles = pp.CFiles
p.CXXFiles = pp.CXXFiles p.CXXFiles = pp.CXXFiles
p.MFiles = pp.MFiles
p.HFiles = pp.HFiles p.HFiles = pp.HFiles
p.SFiles = pp.SFiles p.SFiles = pp.SFiles
p.SwigFiles = pp.SwigFiles p.SwigFiles = pp.SwigFiles
...@@ -458,6 +460,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package ...@@ -458,6 +460,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
p.IgnoredGoFiles, p.IgnoredGoFiles,
p.CFiles, p.CFiles,
p.CXXFiles, p.CXXFiles,
p.MFiles,
p.HFiles, p.HFiles,
p.SFiles, p.SFiles,
p.SysoFiles, p.SysoFiles,
...@@ -685,7 +688,7 @@ func isStale(p *Package, topRoot map[string]bool) bool { ...@@ -685,7 +688,7 @@ func isStale(p *Package, topRoot map[string]bool) bool {
return false return false
} }
srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.HFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles) srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles)
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
......
...@@ -357,6 +357,7 @@ type Package struct { ...@@ -357,6 +357,7 @@ type Package struct {
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
CXXFiles []string // .cc, .cpp and .cxx source files CXXFiles []string // .cc, .cpp and .cxx source files
MFiles []string // .m (Objective-C) source files
HFiles []string // .h, .hh, .hpp and .hxx source files HFiles []string // .h, .hh, .hpp and .hxx source files
SFiles []string // .s source files SFiles []string // .s source files
SwigFiles []string // .swig files SwigFiles []string // .swig files
...@@ -621,6 +622,9 @@ Found: ...@@ -621,6 +622,9 @@ Found:
case ".cc", ".cpp", ".cxx": case ".cc", ".cpp", ".cxx":
p.CXXFiles = append(p.CXXFiles, name) p.CXXFiles = append(p.CXXFiles, name)
continue continue
case ".m":
p.MFiles = append(p.MFiles, name)
continue
case ".h", ".hh", ".hpp", ".hxx": case ".h", ".hh", ".hpp", ".hxx":
p.HFiles = append(p.HFiles, name) p.HFiles = append(p.HFiles, name)
continue continue
...@@ -788,7 +792,7 @@ func (ctxt *Context) matchFile(dir, name string, returnImports bool, allTags map ...@@ -788,7 +792,7 @@ func (ctxt *Context) matchFile(dir, name string, returnImports bool, allTags map
} }
switch ext { switch ext {
case ".go", ".c", ".cc", ".cxx", ".cpp", ".s", ".h", ".hh", ".hpp", ".hxx", ".S", ".swig", ".swigcxx": case ".go", ".c", ".cc", ".cxx", ".cpp", ".m", ".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, no reading // binary, no reading
......
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