Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to link libduckdb statically #618

Merged
merged 4 commits into from
Feb 21, 2025
Merged

Conversation

tristan957
Copy link
Contributor

pg_duckdb is not the only Postgres extension using DuckDB these days. If two extensions both dynamically link to libduckdb.so and install that library into the Postgres libdir, then it is a race to see which extension installs their libduckdb last. This can lead to undefined symbols in any of the DuckDB Postgres extensions.

@tristan957
Copy link
Contributor Author

Should we make one of the CI jobs use DUCKDB_STATIC?

@tristan957
Copy link
Contributor Author

Static:

$ ldd pg_duckdb.so
        linux-vdso.so.1 (0x00007f0c8c6d4000)
        libpq.so.private16-5 => /lib64/libpq.so.private16-5 (0x00007f0c8c65d000)
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f0c8a800000)
        liblz4.so.1 => /lib64/liblz4.so.1 (0x00007f0c8c638000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f0c8c609000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f0c8a60d000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0c8c6d6000)
        libssl.so.3 => /lib64/libssl.so.3 (0x00007f0c8ab28000)
        libcrypto.so.3 => /lib64/libcrypto.so.3 (0x00007f0c8a000000)
        libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007f0c8c5b2000)
        libldap.so.2 => /lib64/libldap.so.2 (0x00007f0c8aac3000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f0c8a527000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f0c8aa9f000)
        libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007f0c89f36000)
        libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f0c8c599000)
        libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007f0c8aa98000)
        libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007f0c8aa88000)
        libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f0c8aa81000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f0c8aa6c000)
        liblber.so.2 => /lib64/liblber.so.2 (0x00007f0c8a515000)
        libevent-2.1.so.7 => /lib64/libevent-2.1.so.7 (0x00007f0c8a4be000)
        libsasl2.so.3 => /lib64/libsasl2.so.3 (0x00007f0c89f17000)
        libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f0c89ee8000)
        libcrypt.so.2 => /lib64/libcrypt.so.2 (0x00007f0c89eb2000)
        libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007f0c89e12000)

Shared:

$ ldd pg_duckdb.so
        linux-vdso.so.1 (0x00007fbb0db6a000)
        libpq.so.private16-5 => /lib64/libpq.so.private16-5 (0x00007fbb0da68000)
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fbb0d800000)
        liblz4.so.1 => /lib64/liblz4.so.1 (0x00007fbb0d7db000)
        libduckdb.so => not found
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fbb0d7ac000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fbb0d5b9000)
        libssl.so.3 => /lib64/libssl.so.3 (0x00007fbb0d4e1000)
        libcrypto.so.3 => /lib64/libcrypto.so.3 (0x00007fbb0d000000)
        libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007fbb0cfab000)
        libldap.so.2 => /lib64/libldap.so.2 (0x00007fbb0cf46000)
        libm.so.6 => /lib64/libm.so.6 (0x00007fbb0ce60000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fbb0db6c000)
        libz.so.1 => /lib64/libz.so.1 (0x00007fbb0d4bd000)
        libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007fbb0cd96000)
        libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007fbb0cd7f000)
        libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007fbb0d4b6000)
        libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007fbb0cd6f000)
        libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007fbb0cd68000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fbb0cd55000)
        liblber.so.2 => /lib64/liblber.so.2 (0x00007fbb0cd43000)
        libevent-2.1.so.7 => /lib64/libevent-2.1.so.7 (0x00007fbb0ccec000)
        libsasl2.so.3 => /lib64/libsasl2.so.3 (0x00007fbb0cccd000)
        libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fbb0cc9e000)
        libcrypt.so.2 => /lib64/libcrypt.so.2 (0x00007fbb0cc68000)
        libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007fbb0cbc8000)

pg_duckdb is not the only Postgres extension using DuckDB these days. If
two extensions both dynamically link to libduckdb.so and install that
library into the Postgres libdir, then it is a race to see which
extension installs their libduckdb last. This can lead to undefined
symbols in any of the DuckDB Postgres extensions.

Signed-off-by: Tristan Partin <[email protected]>
Copy link
Collaborator

@JelteF JelteF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work on this. Some notes:

  1. I get the following error when using this locally, so something is not fully working it seems. I assume you don't get this error?
2025-02-21 13:44:45.002 CET [184341] FATAL:  could not load library "/home/jelte/.pgenv/pgsql-17beta9/lib/pg_duckdb.so": /home/jelte/.pgenv/pgsql-17beta9/lib/pg_duckdb.so: undefined symbol: _ZTVN6duckdb21CachedHttpfsExtensionE
  1. The install-duckdb make target (which is called by install too) should not install the .a file to the postgres directory.
  2. Regarding CI: yeah I think it would be good if one of the jobs used static linking.

@JelteF
Copy link
Collaborator

JelteF commented Feb 21, 2025

Okay I pushed a few changes to make the resulting pg_duckdb.so actually work (at least on my machine, and on CI).

@JelteF
Copy link
Collaborator

JelteF commented Feb 21, 2025

The make bundle-library target was introduced in DuckDB by this PR: duckdb/duckdb#10507

@JelteF JelteF requested a review from Y-- February 21, 2025 13:59
Comment on lines +115 to +116
if [ '${{ matrix.version }}' = REL_17_STABLE ]; then
ERROR_ON_WARNING=1 make -j8 install DUCKDB_BUILD=Static
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems error-prone to only build one version that way no?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not too worried about the static library build of DuckDB working for one PG version, but not for another. I mainly added this CI coverage to make sure we don't accidentally break the static build logic in our makefile completely. So I think running it for just one version is fine. I'll add a code comment explaining that though.

Makefile Outdated
Comment on lines 31 to 34
else ifeq ($(DUCKDB_BUILD), Static)
DUCKDB_BUILD_CXX_FLAGS =
DUCKDB_BUILD_TYPE = release
DUCKDB_MAKE_TARGET = bundle-library
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static vs dynamic and debug vs release are orthogonal concepts.
Can we have ReleaseStatic instead? (and we'll add DebugStatic if/when need be.
(I don't think it's worth it to rename Release/Debug into ReleaseDynamic/DebugDynamic)

Copy link
Collaborator

@JelteF JelteF Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally agree, but DuckDB its make targets don't. There's no way to build a "debug" static library version currently, because the bundle-library hardcodes the release path. I'll rename it to ReleaseStatic though, because I agree that's clearer.

Copy link
Collaborator

@Y-- Y-- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@JelteF JelteF merged commit b1c7ba1 into duckdb:main Feb 21, 2025
5 checks passed
JelteF pushed a commit that referenced this pull request Feb 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants