2

I want to get a windows-DLL, but I want to compile it under Ubuntu-Linux.

Building an Executable was simple: env GOOS=windows GOARCH=386 go build wrapper.go generates a wrapper.exe, that behaves as expected.

but building a DLL with env GOOS=windows GOARCH=386 go build -buildmode=c-shared wrapper.go results in error:

running gcc failed: exit status 1
gcc: error: unrecognized command line option ‘-mconsole’; did you mean ‘--compile’?

I would prefer not to install and run go under windows, because my complete tool chain is running under Ubuntu

go version go1.15.6 linux/amd64

4
  • This seems very compiler implementation specific,so what's your go version and go env? Commented Jan 22, 2021 at 10:33
  • Also what gcc libraries did you install for compiling to windows? Commented Jan 22, 2021 at 10:36
  • I'm currently not using it to build c-shared libraries (and it could use a Go version update), but I did successfully build c-shared libraries with it in the past: github.com/tehsphinx/golang_cgo_windows/blob/master/Dockerfile. If you want to quickly test it, its also on docker hub: hub.docker.com/r/tehsphinx/golang_cgo_windows/… Commented Jan 22, 2021 at 10:42
  • what makes me wonder is, that building a .exe is working, but not building a .dll Commented Jan 22, 2021 at 10:42

1 Answer 1

6

If you would pass -x to the call to go build -buildmode=c-shared ..., you'd notice that in that mode the linker from the Go toolchain calls out to the external C linker; for instance, here on GNU/Linux with Go 1.15.x, I have:

mkdir -p $WORK/b001/exe/
cd $WORK/b001/exe/
/home/username/devel/golang-1.15.6/pkg/tool/linux_amd64/link -o cshared.dll -importcfg $WORK/b001/importcfg.link -buildmode=c-shared -buildid=OJVN3iT0GI_DEAMVbLDu/o9eT_YGfUiRe07beNQAA/-xRRfDcM8nVc03rltdqz/OJVN3iT0GI_DEAMVbLDu -extld=gcc $WORK/b001/_pkg_.a
# command-line-arguments
loadinternal: cannot find runtime/cgo
/home/username/devel/golang-1.15.6/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
gcc: error: unrecognized command line option ‘-mconsole’; did you mean ‘--compile’?

Note that pkg/tool/linux_amd64/link is called with -extld=gcc, and from go doc cmd/link, we gather that

-extld linker
Set the external linker (default "clang" or "gcc").

My guess is that in order to produce a C-compatible dynamic library, the Go toolchain relies on an external C linker, and that is carried out by cgo machinery — at which there's actually a hint in the documentation of -buildmode=c-shared:

-buildmode=c-shared
Build the listed main package, plus all packages it imports,
into a C shared library. The only callable symbols will
be those functions exported using a cgo //export comment.
Requires exactly one main package to be listed.

Hence my guess is that in order to do what you want you have to:

  • Install a cross-compiler supporting Windows/i386 — you can start with this.
  • Set up the environment before calling go build as explained in the cgo docs so that the Go toolchain calls the Windows-specific linker.
  • Verify it works by running go build with the -x command-line option.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.