From: Carlos Castillo Date: Thu, 13 Feb 2014 18:11:44 +0000 (-0800) Subject: cmd/go, go/build: support .m files X-Git-Tag: go1.3beta1~725 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=7861cd6082993becfedeaab75567eaba0c9a03f8;p=gostls13.git 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 --- diff --git a/doc/go1.3.txt b/doc/go1.3.txt index 3da88a5a2c..d2ba78dddd 100644 --- a/doc/go1.3.txt +++ b/doc/go1.3.txt @@ -5,3 +5,4 @@ runtime: output how long goroutines are blocked (CL 50420043) syscall: add NewCallbackCDecl to use for windows callbacks (CL 36180044) testing: diagnose buggy tests that panic(nil) (CL 55780043) misc/benchcmp has been replaced by go tool benchcmp (CL 47980043) +cmd/go, go/build: support .m files (CL 60590044) diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index f3daa41cb2..283e9c3aee 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -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", 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() { if err != nil && err != errPrintedOutput { err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err) @@ -857,7 +862,7 @@ func (b *builder) build(a *action) (err error) { if a.cgo != nil && 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 { return err } @@ -872,7 +877,7 @@ func (b *builder) build(a *action) (err error) { gccfiles := append(cfiles, sfiles...) cfiles = 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 { return err } @@ -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. // Exceptions: a few standard packages have forward declarations for // 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 { switch p.ImportPath { case "os", "runtime/pprof", "sync", "time": @@ -1824,6 +1829,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] cgoldflags := []string{} usesCgo := false cxx := false + objc := false for _, a := range allactions { if a.p != nil { if !a.p.Standard { @@ -1850,6 +1856,9 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] if len(a.p.CXXFiles) > 0 { cxx = true } + if len(a.p.MFiles) > 0 { + objc = true + } } } ldflags = append(ldflags, afiles...) @@ -1861,6 +1870,9 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] if cxx { ldflags = append(ldflags, "-lstdc++") } + if objc { + ldflags = append(ldflags, "-lobjc") + } return b.run(".", p.ImportPath, nil, "gccgo", "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags) } @@ -2054,7 +2066,7 @@ var ( 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 { 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 cgoCXXFLAGS := stringList(envList("CGO_CXXFLAGS"), p.CgoCXXFLAGS) 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 { out, err := b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs) if err != nil { @@ -2215,6 +2232,16 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfile 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...) dynobj := obj + "_cgo_.o" 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 // Run SWIG on all SWIG input files. // TODO: Don't build a shared library, once SWIG emits the necessary // 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 for _, file := range gccfiles { @@ -2292,6 +2319,15 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles []string) (out 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) if err != nil { return nil, nil, err diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go index 9a8a194fe7..3b79ee6fe3 100644 --- a/src/cmd/go/doc.go +++ b/src/cmd/go/doc.go @@ -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 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 -files to the C compiler, and any .cc, .cpp, .cxx files to the C++ +When either cgo or SWIG is used, go build will pass any .c, .m, .s, +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 the C or C++ compiler, respectively, to use. diff --git a/src/cmd/go/list.go b/src/cmd/go/list.go index f56ebed382..2cd8e5fa78 100644 --- a/src/cmd/go/list.go +++ b/src/cmd/go/list.go @@ -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 CFiles []string // .c source files CXXFiles []string // .cc, .cxx and .cpp source files + MFiles []string // .m source files HFiles []string // .h, .hh, .hpp and .hxx source files SFiles []string // .s source files SwigFiles []string // .swig files diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go index 2f4f6cc558..0190b6784f 100644 --- a/src/cmd/go/pkg.go +++ b/src/cmd/go/pkg.go @@ -42,6 +42,7 @@ type Package struct { IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints CFiles []string `json:",omitempty"` // .c 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 SFiles []string `json:",omitempty"` // .s source files SwigFiles []string `json:",omitempty"` // .swig files @@ -113,6 +114,7 @@ func (p *Package) copyBuild(pp *build.Package) { p.IgnoredGoFiles = pp.IgnoredGoFiles p.CFiles = pp.CFiles p.CXXFiles = pp.CXXFiles + p.MFiles = pp.MFiles p.HFiles = pp.HFiles p.SFiles = pp.SFiles p.SwigFiles = pp.SwigFiles @@ -458,6 +460,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package p.IgnoredGoFiles, p.CFiles, p.CXXFiles, + p.MFiles, p.HFiles, p.SFiles, p.SysoFiles, @@ -685,7 +688,7 @@ func isStale(p *Package, topRoot map[string]bool) bool { 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 { if olderThan(filepath.Join(p.Dir, src)) { return true diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go index e4fc853b4a..e2591883d9 100644 --- a/src/pkg/go/build/build.go +++ b/src/pkg/go/build/build.go @@ -357,6 +357,7 @@ type Package struct { IgnoredGoFiles []string // .go source files ignored for this build CFiles []string // .c 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 SFiles []string // .s source files SwigFiles []string // .swig files @@ -621,6 +622,9 @@ Found: case ".cc", ".cpp", ".cxx": p.CXXFiles = append(p.CXXFiles, name) continue + case ".m": + p.MFiles = append(p.MFiles, name) + continue case ".h", ".hh", ".hpp", ".hxx": p.HFiles = append(p.HFiles, name) continue @@ -788,7 +792,7 @@ func (ctxt *Context) matchFile(dir, name string, returnImports bool, allTags map } 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 case ".syso": // binary, no reading