marcboeker / go-duckdb

go-duckdb provides a database/sql driver for the DuckDB database engine.
MIT License
679 stars 103 forks source link

How to cross-compile an application which uses DuckDB? #243

Closed goloroden closed 3 days ago

goloroden commented 3 months ago

I am writing an application, using macOS on Apple Silicon.

If I try to compile for this platform, it works:

$ CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build -o ./build/test-darwin-arm64 main.go

If I try to compile for macOS on AMD64, it works as well:

$ CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -o ./build/test-darwin-amd64 main.go

(In this case I have not yet tested whether it also actually runs, but at least it compiles without errors.)

Compiling for Linux

So, from the fact that this works I assume that cross-compiling my application with a statically linked DuckDB should be possible. Otherwise, it wouldn't work for AMD64, would it?

However, next I try to compile for Linux on AMD64, using this command:

$ CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o ./build/test-linux-amd64 main.go

Now I get an error message:

# runtime/cgo
linux_syscall.c:67:13: error: call to undeclared function 'setresgid'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
linux_syscall.c:67:13: note: did you mean 'setregid'?
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/unistd.h:593:6: note: 'setregid' declared here
linux_syscall.c:73:13: error: call to undeclared function 'setresuid'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
linux_syscall.c:73:13: note: did you mean 'setreuid'?
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/unistd.h:595:6: note: 'setreuid' declared here

The same is true for Linux on ARM64 (with the exact same error message):

Compiling for Windows

And I try to compile for Windows on AMD64, I get this error message:

# runtime/cgo
gcc_libinit_windows.c:6:10: fatal error: 'windows.h' file not found

What am I missing? Is cross-compiling my application even possible this way? If so, how?

PS

I'm using go-duckdb@1.7.0, and my application so far only initializes an in-memory database, creates a table, and saves a few records, nothing fancy.

marcboeker commented 3 months ago

You can use a cross compilation toolchain like https://github.com/messense/homebrew-macos-cross-toolchains Then you can specify the compiler you want to use based on your target OS and arch.

$ brew tap messense/macos-cross-toolchains
$ brew install x86_64-unknown-linux-gnu
$ CC="x86_64-linux-gnu-gcc" CXX="x86_64-linux-gnu-g++" CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build examples/simple.go 

$ file simple                                                                                                                                                                                                                                                     6s 23:28:07
simple: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.16, Go BuildID=i6RQPUhd0Xie_bKC0bEu/7m1ok2LyOSc_iqV_yit2/k6vBV4UuwG49abwOIE4s/luX5f5nVpyFsEeykOAZQ, with debug_info, not stripped

Does this work for you?

Windows is a chapter by itself. We're still struggling to get DuckDB cross-compile to Windows.

goloroden commented 3 months ago

Yes, this worked – thanks a lot for your help 🎉

I assume that compiling for Linux on ARM would work in a similar way (one needs to figure out what to install for this). And I assume that the same is basically possible the other way round – compiling for macOS, but on Linux.

Given that it's just a few lines, at least if you know what you're doing, wouldn't that be something that could be helpful to add to the documentation?

goloroden commented 3 days ago

I am closing this, since my initial question has been answered, and there is a follow-up issue at #279