1
0
mirror of https://github.com/golang/go synced 2024-11-22 04:34:39 -07:00

cmd/go: new cgo build procedure

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
This commit is contained in:
Shenghou Ma 2012-08-17 03:42:34 +08:00
parent 1ac397f4b9
commit 551d8b9ff5
5 changed files with 87 additions and 2 deletions

View File

@ -27,5 +27,6 @@ func Test1328(t *testing.T) { test1328(t) }
func TestParallelSleep(t *testing.T) { testParallelSleep(t) } func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
func TestSetEnv(t *testing.T) { testSetEnv(t) } func TestSetEnv(t *testing.T) { testSetEnv(t) }
func TestHelpers(t *testing.T) { testHelpers(t) } func TestHelpers(t *testing.T) { testHelpers(t) }
func TestLibgcc(t *testing.T) { testLibgcc(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }

View File

@ -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
}
}
}

View File

@ -5,6 +5,10 @@
package cgotest 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> #include <windows.h>
unsigned int sleep(unsigned int seconds) { unsigned int sleep(unsigned int seconds) {

View File

@ -1558,6 +1558,24 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
// gcc // gcc
var linkobj []string 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 { 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, 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 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 // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows
// must be processed before the gcc-generated objects. // must be processed before the gcc-generated objects.
// Put it first. http://golang.org/issue/2601 // Put it first. http://golang.org/issue/2601
outObj = append([]string{importObj}, outObj...) outObj = stringList(importObj, nonGccObjs, ofile)
return outGo, outObj, nil return outGo, outObj, nil
} }

View File

@ -64,12 +64,18 @@ echo.
::echo. ::echo.
:: cgo tests :: cgo tests
:: TODO: Other cgo tests
if x%CGO_ENABLED% == x0 goto nocgo if x%CGO_ENABLED% == x0 goto nocgo
echo # ..\misc\cgo\life echo # ..\misc\cgo\life
go run %GOROOT%\test\run.go - ..\misc\cgo\life go run %GOROOT%\test\run.go - ..\misc\cgo\life
if errorlevel 1 goto fail if errorlevel 1 goto fail
echo. echo.
:: TODO ..\misc\cgo\stdio
echo # ..\misc\cgo\test
go test ..\misc\cgo\test
if errorlevel 1 goto fail
echo.
:nocgo :nocgo
:: TODO: The other tests in run.bash. :: TODO: The other tests in run.bash.