]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/go: new cgo build procedure
authorShenghou Ma <minux.ma@gmail.com>
Thu, 16 Aug 2012 19:42:34 +0000 (03:42 +0800)
committerShenghou Ma <minux.ma@gmail.com>
Thu, 16 Aug 2012 19:42:34 +0000 (03:42 +0800)
   This CL adds a step to the build procedure for cgo programs. It uses 'ld -r'
to combine all gcc compiled object file and generate a relocatable object file
for our ld. Additionally, this linking step will combine some static linking
gcc library into the relocatable object file, so that we can use libgcc,
libmingwex and libmingw32 without problem.

   Fixes #3261.
   Fixes #1741.
   Added a testcase for linking in libgcc.

TODO:
1. still need to fix the INDIRECT_SYMBOL_LOCAL problem on Darwin/386.
2. still need to enable the libgcc test on Linux/ARM, because 5l can't deal
with thumb libgcc.

Tested on Darwin/amd64, Darwin/386, FreeBSD/amd64, FreeBSD/386, Linux/amd64,
Linux/386, Linux/ARM, Windows/amd64, Windows/386

R=iant, rsc, bradfitz, coldredlemur
CC=golang-dev
https://golang.org/cl/5822049

misc/cgo/test/cgo_test.go
misc/cgo/test/issue3261.go [new file with mode: 0644]
misc/cgo/test/sleep_windows_386.go [moved from misc/cgo/test/sleep_windows.go with 61% similarity]
src/cmd/go/build.go
src/run.bat

index 34beee69d194d4d387ca738acd6cf041c852fa03..9c3c1163453ceeaea80c80ed27c680f1d15e3dfa 100644 (file)
@@ -27,5 +27,6 @@ func Test1328(t *testing.T)                { test1328(t) }
 func TestParallelSleep(t *testing.T)       { testParallelSleep(t) }
 func TestSetEnv(t *testing.T)              { testSetEnv(t) }
 func TestHelpers(t *testing.T)             { testHelpers(t) }
+func TestLibgcc(t *testing.T)              { testLibgcc(t) }
 
 func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/misc/cgo/test/issue3261.go b/misc/cgo/test/issue3261.go
new file mode 100644 (file)
index 0000000..0411be8
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2012 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.
+
+package cgotest
+
+/*
+// libgcc on ARM might be compiled as thumb code, but our 5l
+// can't handle that, so we have to disable this test on arm.
+#ifdef __ARMEL__
+#include <stdio.h>
+int vabs(int x) {
+       puts("testLibgcc is disabled on ARM because 5l cannot handle thumb library.");
+       return (x < 0) ? -x : x;
+}
+#else
+int __absvsi2(int); // dummy prototype for libgcc function
+// we shouldn't name the function abs, as gcc might use
+// the builtin one.
+int vabs(int x) { return __absvsi2(x); }
+#endif
+*/
+import "C"
+
+import "testing"
+
+func testLibgcc(t *testing.T) {
+       var table = []struct {
+               in, out C.int
+       }{
+               {0, 0},
+               {1, 1},
+               {-42, 42},
+               {1000300, 1000300},
+               {1 - 1<<31, 1<<31 - 1},
+       }
+       for _, v := range table {
+               if o := C.vabs(v.in); o != v.out {
+                       t.Fatalf("abs(%d) got %d, should be %d", v.in, o, v.out)
+                       return
+               }
+       }
+}
similarity index 61%
rename from misc/cgo/test/sleep_windows.go
rename to misc/cgo/test/sleep_windows_386.go
index 007a1bb4c8002c09cbb3aa98bbc37f1b20f95875..75687d7831aa41107b9842ef2c622de7cc841bf8 100644 (file)
@@ -5,6 +5,10 @@
 package cgotest
 
 /*
+// mingw32 on windows/386 provides usleep() but not sleep(),
+// as we don't want to require all other OSes to provide usleep,
+// we emulate sleep(int s) using win32 API Sleep(int ms).
+
 #include <windows.h>
 
 unsigned int sleep(unsigned int seconds) {
index ff5e0b9c3f3748fea4604b5c984f2620dd15e435..e12698f9f01623c65d271e4685646660af261519 100644 (file)
@@ -1558,6 +1558,24 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
 
        // gcc
        var linkobj []string
+
+       var bareLDFLAGS []string
+       // filter out -lsomelib, and -framework X if on Darwin
+       for i := 0; i < len(cgoLDFLAGS); i++ {
+               f := cgoLDFLAGS[i]
+               if !strings.HasPrefix(f, "-l") {
+                       if goos == "darwin" && f == "-framework" { // skip the -framework X
+                               i += 1
+                               continue
+                       }
+                       bareLDFLAGS = append(bareLDFLAGS, f)
+               }
+       }
+       staticLibs := []string{"-lgcc"}
+       if goos == "windows" {
+               staticLibs = append(staticLibs, "-lmingwex", "-lmingw32")
+       }
+
        for _, cfile := range cfiles {
                ofile := obj + cfile[:len(cfile)-1] + "o"
                if err := b.gcc(p, ofile, cgoCFLAGS, obj+cfile); err != nil {
@@ -1605,10 +1623,23 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
                return nil, nil, err
        }
 
+       ofile := obj + "_all.o"
+       var gccObjs, nonGccObjs []string
+       for _, f := range outObj {
+               if strings.HasSuffix(f, ".o") {
+                       gccObjs = append(gccObjs, f)
+               } else {
+                       nonGccObjs = append(nonGccObjs, f)
+               }
+       }
+       if err := b.gccld(p, ofile, stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs), gccObjs); err != nil {
+               return nil, nil, err
+       }
+
        // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows
        // must be processed before the gcc-generated objects.
        // Put it first.  http://golang.org/issue/2601
-       outObj = append([]string{importObj}, outObj...)
+       outObj = stringList(importObj, nonGccObjs, ofile)
 
        return outGo, outObj, nil
 }
index 496cbe3d577e9564d7847fe19669ef99aaf91eca..36d24984e9a8e9c079b5386a3c16371001617279 100644 (file)
@@ -64,12 +64,18 @@ echo.
 ::echo.
 
 :: cgo tests
-:: TODO: Other cgo tests
 if x%CGO_ENABLED% == x0 goto nocgo
 echo # ..\misc\cgo\life
 go run %GOROOT%\test\run.go - ..\misc\cgo\life
 if errorlevel 1 goto fail
 echo.
+
+:: TODO ..\misc\cgo\stdio
+
+echo # ..\misc\cgo\test
+go test ..\misc\cgo\test
+if errorlevel 1 goto fail
+echo.
 :nocgo
 
 :: TODO: The other tests in run.bash.