marcboeker / go-duckdb

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

Question about static linking #116

Open eatonphil opened 1 year ago

eatonphil commented 1 year ago

Hey Marc! I am taking a look at this repo for the first time in a bit. Here's the sample code I'm trying.

package main

import (
        "database/sql"
        "fmt"

        _ "github.com/marcboeker/go-duckdb"
)

func main() {
        db, err := sql.Open("duckdb", "")
        if err != nil {
                panic(err)
        }

        _, err = db.Exec("CREATE TABLE x (name TEXT, age INT)")
        if err != nil {
                panic(err)
        }

        _, err = db.Exec("INSERT INTO x VALUES ('Terry', 12), ('Marge', 14)")
        if err != nil {
                panic(err)
        }

        rows, err := db.Query("SELECT name, age FROM x")
        for rows.Next() {
                var name string
                var age int
                err = rows.Scan(&name, &age)
                if err != nil {
                        panic(err)
                }

                fmt.Println(name, age)
        }

        if err := rows.Err(); err != nil {
                panic(err)
        }
}

While based on the file size, it seems like static linking worked, when I run ldd it seems to show dynamically linked libraries (though not necessarily duckdb).

$ go build
$ ldd duckdb-tests
        linux-vdso.so.1 (0x00007ffd273bf000)
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f70ebc00000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f70ebeb4000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f70ebb1f000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f70ebe90000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f70eb941000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f70ebed7000)
$ ls -lah duckdb-tests
-rwxr-xr-x 1 phil phil  31M Aug 20 14:23 duckdb-tests

Whereas when I build a basic Go program:

$ cat test.go
package main

import "fmt"

func main() {
        fmt.Println("hey")
}
$ go build
$ ldd test
        not a dynamic executable
$ ls -lah test
-rwxr-xr-x 1 phil phil 1.8M Aug 20 14:16 test

So is there a way to build with go-duckdb that actually produces a static binary? Thanks!

javierhonduco commented 1 year ago

On a Fedora box, your code above compiles to a static executable:

CGO_ENABLED=1 CGO_LDFLAGS="-L/usr/lib" go build --ldflags="-extldflags=-static" -tags osusergo,netgo .
$ ldd ./hello
    not a dynamic executable

That being said, there is a warning as dlopen seems to be used by duckdb:

# hello
/usr/bin/ld: /home/javierhonduco/go/pkg/mod/github.com/marcboeker/go-duckdb@v1.4.3/deps/linux_amd64/libduckdb.a(duckdb.o): in function `AdbcLoadDriver':
duckdb.cpp:(.text+0x35671): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/bin/ld: /home/javierhonduco/go/pkg/mod/github.com/marcboeker/go-duckdb@v1.4.3/deps/linux_amd64/libduckdb.a(duckdb.o): in function `int duckdb_httplib::detail::create_socket<duckdb_httplib::detail::create_client_socket(char const*, char const*, int, int, bool, std::function<void (int)>, long, long, long, long, long, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, duckdb_httplib::Error&)::{lambda(int, addrinfo&)#1}>(char const*, char const*, int, int, int, bool, std::function<void (int)>, duckdb_httplib::detail::create_client_socket(char const*, char const*, int, int, bool, std::function<void (int)>, long, long, long, long, long, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, duckdb_httplib::Error&)::{lambda(int, addrinfo&)#1})':
duckdb.cpp:(.text._ZN14duckdb_httplib6detail13create_socketIZNS0_20create_client_socketEPKcS3_iibSt8functionIFviEEllllllRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_5ErrorEEUliR8addrinfoE_EEiS3_S3_iiibS6_T_[_ZN14duckdb_httplib6detail13create_socketIZNS0_20create_client_socketEPKcS3_iibSt8functionIFviEEllllllRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERNS_5ErrorEEUliR8addrinfoE_EEiS3_S3_iiibS6_T_]+0xb3): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

Perhaps it would be useful to bring this up to the duckdb devs?

eatonphil commented 1 year ago

Thank you for the incantation! (Also, for Marc, assuming we get the DuckDB devs to help out with the dlopen warning, can we get this incantation to be the default build mode?)

I'll ping someone from DuckDB to see.

marcboeker commented 1 year ago

Yes, there is by default a glibc dependency from DuckDB. We also have another discussion around this going on in #54. If someone wants to discuss this with the DuckDB devs would be great, as I do not have much free time at the moment.