]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go, go/build: support .m files
authorCarlos Castillo <cookieo9@gmail.com>
Thu, 13 Feb 2014 18:11:44 +0000 (10:11 -0800)
committerIan Lance Taylor <iant@golang.org>
Thu, 13 Feb 2014 18:11:44 +0000 (10:11 -0800)
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

doc/go1.3.txt
src/cmd/go/build.go
src/cmd/go/doc.go
src/cmd/go/list.go
src/cmd/go/pkg.go
src/pkg/go/build/build.go

index 3da88a5a2c804c26bcca19b502460655f626b5a4..d2ba78ddddf7682fd0da890d8a3e47a73c0f5454 100644 (file)
@@ -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)
index f3daa41cb26fcb4c251596576cfcc7232dbe9187..283e9c3aee85d7a3d1037c74b0d97eee5671fc83 100644 (file)
@@ -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
index 9a8a194fe755d2a424e346dbdb03a4d18402048e..3b79ee6fe37b7b3d96cdf4300c0eb52cb91a352b 100644 (file)
@@ -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.
 
index f56ebed38293a042594166940f15e8e57d3517aa..2cd8e5fa78b4b9b7f35e7eba59d56ced3b4b389a 100644 (file)
@@ -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
index 2f4f6cc558276ccb0026e6eb2cab43213a1df461..0190b6784f02f0df87b22173c1a8ec22c0ee7249 100644 (file)
@@ -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
index e4fc853b4a3c6b6a6a8ba70350ab234590167956..e2591883d9610f83d1ac8e274f6b519b686c8263 100644 (file)
@@ -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