Closed
Description
Being able to inclue a .syso file in a package is great. A Go program using that package works well when that program is linked using the internal linker. Link is however broken when the that program is linked using the external linker, for example, because the Go program also uses cgo.
What version of Go are you using (go version
)?
$ go version go version go1.12.7 linux/amd64
Does this issue reproduce with the latest release?
This affects all go versions, including tip (at the time of submission).
What operating system and processor architecture are you using (go env
)?
This affects all GOOS/GOARCH pairs. I have tried it on darwin/amd64 and linux/amd64.
go env
Output
$ go env GOARCH="amd64" GOBIN="" GOCACHE="/home/jpap/.cache/go-build" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOOS="linux" GOPATH="/home/jpap/go" GOPROXY="" GORACE="" GOROOT="/home/jpap/Local/go" GOTMPDIR="" GOTOOLDIR="/home/jpap/Local/go/pkg/tool/linux_amd64" GCCGO="gccgo" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build378647343=/tmp/go-build -gno-record-gcc-switches"
What did you do?
- Create a package that has a .syso file.
- Create a main package that uses the package above.
- Link the main package in external link mode to build an executable. (This could be explicit, using
-ldflags='-linkmode=external'
, or by using cgo in the main package, where the external linker is then required.)
Sample project follows...
Directory structure
$GOPATH/src/jpap.org/linktest
├── cmd
│ ├── external
│ │ └── main.go
│ └── internal
│ └── main.go
└── syso
├── asm
│ ├── Makefile
│ ├── test_darwin.s
│ └── test_linux.s
├── test.go
├── test.s
└── test.syso
To build the test.syso
file on Linux using gcc,
$ cd $GOPATH/src/jpap.org/linktest/syso/asm
$ make linux
gcc -c -o ../test.syso test_linux.s
$
syso/asm/Makefile
linux:
gcc -c -o ../test.syso test_linux.s
darwin:
gcc -c -o ../test.syso test_darwin.s
syso/asm/test_darwin.s
.globl _asmTest
_asmTest:
ret
syso/asm/test_linux.s
.globl asmTest
asmTest:
ret
syso/test.go
package syso
func Test()
syso/test.s
#include "textflag.h"
TEXT ·Test(SB), NOSPLIT, $0
JMP asmTest(SB)
cmd/internal/main.go
package main
import (
"jpap.org/linktest/syso"
)
func main() {
syso.Test()
}
cmd/external/main.go
/*
// Force use of external linker
#include <stdio.h>
*/
import "C"
import (
"jpap.org/linktest/syso"
)
func main() {
syso.Test()
}
What did you expect to see?
- Link successful, and executable built for both
cmd/internal/main.go
(using internal link) andcmd/external/main.go
(using external link).
What did you see instead?
- Internal link succeeds for
cmd/internal/main.go
. - External link fails for
cmd/external/main.go
with errorrelocation target XXX not defined
for each referenced global symbol in the imported package .syso, for example:
$ cd $GOPATH/src/jpap.org/cmd/external
$ go build .
# jpap.org/linktest/cmd/external
jpap.org/linktest/syso.Test: relocation target asmTest not defined
$