How to build an object file for a specific GOOS and GOARCH with external linker?

138 views
Skip to first unread message

rotusm...@gmail.com

unread,
Aug 14, 2020, 11:29:32 AM8/14/20
to golang-nuts
i'm trying to create an object file by using "go build" for GOOS=linux GOARCH=386.
My current go environment has GOOS=linux GOARCH=amd64.

i know that go build directly builds and links the files, but i want to link files using an external linker file, so i need only the object file to be created.

i have tried to look up ways to do so, but i could not find any solution to this.

The files i'm trying to compile can be .go files that have a main function or just a non-main-package.

Ian Lance Taylor

unread,
Aug 14, 2020, 3:19:04 PM8/14/20
to rotusm...@gmail.com, golang-nuts
There is no way to do this for a non-main package. I'm not sure how
that makes sense. There wouldn't be any way for you to use such an
object.

For a main package, one trick to get you started is to use to use go
build -ldflags="-linkmode=external -extld=/bin/echo". That will show
you how the external linker is invoked, including the objects that are
passed to it. If you also use the go build -work option, it will save
the temporary directory, and you can grab the objects. Then in
principle you can copy those objects to the target system and run the
linker command there.

Ian

rotusm...@gmail.com

unread,
Aug 16, 2020, 3:52:48 AM8/16/20
to golang-nuts
i took your suggestions, tried the '-work' option it showed me the temporary directory where the build files are stored, but they didn't contain the object file. After exploring that a little, i found out out that the 'go build' command also makes a temporary link directory with the build directory but the link directory gets deleted even with the '-work' option.

i watched a video of gopher-os and looked through it's github repository for ways to extract the object files needed and tried his command as follows, but i'm getting these errors which i can't resolve:

GOARCH=386 GOOS=linux go build -n 2>&1 | sed -e "1s|^|set -e\n|" -e "1s|^|export GOOS=linux\n|" -e "1s|^|export GOARCH=386\n|" -e "1s|^|export CGO_ENABLED=0\n|" -e "1s|^|WORK='./build'\n|" -e "1s|^|alias pack='go tool pack'\n|" -e "/^mv/d" -e "s|-extld|-tmpdir='./build' -linkmode=external -extldflags='-nostdlib' -extld|g" | sh 2>&1 | sed -e "s/^/ | /g"

Errors/Warnings:

 | loadinternal: cannot find runtime/cgo
 | /usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000008049000

The above command is able to produce an object file in the ./build directory i specified, i can link it without any errors, but when i try to run the executable it doesn't work.

i know there is nothing wrong with the linker script because i have created object files using the gccgo cross-compiler, and they work.
i wish to use the extra set of features the 'go build' cross-compiler is able to provide that gccgo cross-compiler cannot.

Ian Lance Taylor

unread,
Aug 18, 2020, 12:54:38 AM8/18/20
to rotusm...@gmail.com, golang-nuts
On Sun, Aug 16, 2020 at 12:53 AM rotusm...@gmail.com
<rotusm...@gmail.com> wrote:
>
> i took your suggestions, tried the '-work' option it showed me the temporary directory where the build files are stored, but they didn't contain the object file. After exploring that a little, i found out out that the 'go build' command also makes a temporary link directory with the build directory but the link directory gets deleted even with the '-work' option.

Sorry, I forgot about that. I guess you don't need the -work flag.
Instead, add another flag to -ldflags: "-tmpdir=/my/tmp/dir". The
go.o file will be put into that directory. I see you figured that
out. Sorry for the confusion.


> i watched a video of gopher-os and looked through it's github repository for ways to extract the object files needed and tried his command as follows, but i'm getting these errors which i can't resolve:
>
> GOARCH=386 GOOS=linux go build -n 2>&1 | sed -e "1s|^|set -e\n|" -e "1s|^|export GOOS=linux\n|" -e "1s|^|export GOARCH=386\n|" -e "1s|^|export CGO_ENABLED=0\n|" -e "1s|^|WORK='./build'\n|" -e "1s|^|alias pack='go tool pack'\n|" -e "/^mv/d" -e "s|-extld|-tmpdir='./build' -linkmode=external -extldflags='-nostdlib' -extld|g" | sh 2>&1 | sed -e "s/^/ | /g"
>
> Errors/Warnings:
>
> | loadinternal: cannot find runtime/cgo
> | /usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000008049000
>
> The above command is able to produce an object file in the ./build directory i specified, i can link it without any errors, but when i try to run the executable it doesn't work.
>
> i know there is nothing wrong with the linker script because i have created object files using the gccgo cross-compiler, and they work.
> i wish to use the extra set of features the 'go build' cross-compiler is able to provide that gccgo cross-compiler cannot.

I'm not sure what's going on here. There are many possibilities. In
particular note that Go makes direct system calls; it does not use
libc. So your system has to provide a compatible system call
interface.

Ian
Reply all
Reply to author
Forward
0 new messages