pgrx icon indicating copy to clipboard operation
pgrx copied to clipboard

PG_init fails to compile when we have bindings

Open latot opened this issue 1 month ago • 20 comments

Hi all! I has been working in this pg extension which also uses bindings from the original extension, the postgis one.

Actually I has been able to use bindings, and keep almost all working from the original project, all bindings works great with pgrx with only one exception, when we want to use _PG_init the compiler fails to link everything with rust-lld: error: undefined symbol: errstart a veery long list, the symbols are from the bindings.

I perform some tests with [no_mangle], extern "C-unwind" and other functions names, all compiles righ, the undefined symbol issue only shows when the function name is _PG_init using [no_mangle] or [pg_guard], I perform both tests just to check if there was a way to make it works.

From seems to be now, pgrx links external libraries all fine, except when it is for _PG_init, where it just does not link and fully ignore build.rs.

Thx!

latot avatar Nov 06 '25 21:11 latot

"bindings from the original extension"?

How are you adding in these other bindings?

workingjubilee avatar Nov 06 '25 21:11 workingjubilee

Hi! I used bindgen to make them autmatically in other crate, I have other crate that makes them safe for rust, but in this case the only function I'm calling that fails is in this way:

#[pg_guard]
pub extern "C-unwind" fn _PG_init() {
        unsafe {
                postgis_sys::bindings::pg_install_lwgeom_handlers();
        }
}

As a temporary workaround for me, I'm calling the function pg_install_lwgeom_handlers like this:

#[pg_extern]
pub fn init() {
        unsafe {
                postgis_sys::bindings::pg_install_lwgeom_handlers();
        }
}

Which works nice, I also call it from key functions to make this works because in some cases a extension can be initialized several times when some contexts changes.

You may want some extra logs, here they are:

error: linking with `cc` failed: exit status: 1
  |
  = note:  "cc" "-m64" "/tmp/rustcPpnHow/symbols.o" "<98 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/home/pipe/Documentos/latot/postgis_rs/target/debug/deps/{libpostgis_rs,libpostgis_bindings,libpostgis_sys,libpgrx-61e1c924fc89b543,libheapless-870040b540f2dd61,libhash32-78642d69c51c1f01,libbyteorder-7b2246451a749927,libseahash-e829f66ff11187a9,libserde_cbor-7dcf6a83684fcb86,libhalf-64d3417cd4ec5649,libatomic_traits-44c7af4549456e80,libcfg_if-42dc2972d6f135a9,libserde_json-278917d1e2815135,libmemchr-c66d9520ba8e484d,libitoa-a586594d020aa48a,libryu-675674a647ff1eb1,libenum_map-1e18e0d64983def4,libpgrx_pg_sys-7f24ae81e8b430f4,libsptr-42ced466fee9379a,libserde-0f4616ce0eaa7a0b,libcee_scape-b7a4bf8c3661da89,liblibc-93773208c600b31b,libbitvec-760132ea21007c94,libwyz-ab1c9a7cf33403c2,libtap-db64676956143bc2,libradium-36782edbbaf60c9f,libfunty-d622d5d086347b83,libpgrx_sql_entity_graph-2b07608b5da1d14e,libunescape-2392be61bce9fe9f,libpetgraph-6e9bd1bcc7c6ac52,libindexmap-0184208684a9a187,libhashbrown-dfa2bad1bba96b23,libfoldhash-abf39bc0971f8ebd,libequivalent-3ff77df1ac69f53a,liballocator_api2-302c8aaff85fe901,libfixedbitset-eb9d888c851121be,libthiserror-02942ff8a4440e79,libconvert_case-52b304eef94699e7,libunicode_segmentation-745c28ea3c19c6e9,libeyre-b5ec78d54212ec71,libindenter-1d15fa30e45643d1,libsyn-04fe33bad33db3b1,libquote-92ac0de92fb5080b,libproc_macro2-9b63c256c2e5ae0c,libunicode_ident-00291e71c3df335a}.rlib" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libproc_macro-*,librustc_literal_escaper-*,librustc_std_workspace_std-*}.rlib" "/home/pipe/Documentos/latot/postgis_rs/target/debug/deps/{libonce_cell-6c5ecd365f058077,libbitflags-5b237602bafbe330}.rlib" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,libcfg_if-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,liblibc-*,librustc_std_workspace_core-*,liballoc-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lpgport" "-lgeos" "-lgeos_c" "-ljson-c" "-lpostgis-3" "-lproj" "-lpgport" "-lgeos" "-lgeos_c" "-ljson-c" "-lpostgis-3" "-lproj" "-lgeos" "-lgeos_c" "-ljson-c" "-lpostgis-3" "-lproj" "-lresolv" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-L" "/tmp/rustcPpnHow/raw-dylibs" "-B<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld" "-fuse-ld=lld" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/home/pipe/Documentos/latot/postgis_rs/target/debug/build/pgrx-pg-sys-923540d267e77d57/out" "-L" "/home/pipe/Documentos/latot/postgis_rs/target/debug/build/cee-scape-ad35d2a7c464cc04/out" "-L" "/home/pipe/.pgrx/16.9/pgrx-install/lib" "-L" "/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/liblwgeom/.libs" "-L" "/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon" "-L" "/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/postgis" "-L" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/pipe/Documentos/latot/postgis_rs/target/debug/deps/pgrx_embed_postgis_rs-a7f310b853259c5d" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs"
  = note: some arguments are omitted. use `--verbose` to show all linker arguments
  = note: rust-lld: error: undefined symbol: ErrorContext
          >>> referenced by panic.rs:402 (/home/pipe/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-pg-sys-0.14.3/src/submodules/panic.rs:402)
          >>>               postgis_rs.8nbi4f6r3a3wya2znlo3vyi8n.1nb9a81.rcgu.o:(pgrx_pg_sys::submodules::panic::pgrx_extern_c_guard::h11b9ca5a4eb8f197) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_rs.rlib
          >>> referenced by panic.rs:402 (/home/pipe/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-pg-sys-0.14.3/src/submodules/panic.rs:402)
          >>>               postgis_rs.8nbi4f6r3a3wya2znlo3vyi8n.1nb9a81.rcgu.o:(pgrx_pg_sys::submodules::panic::pgrx_extern_c_guard::h11b9ca5a4eb8f197) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_rs.rlib
          >>> referenced by panic.rs:546 (src/submodules/panic.rs:546)
          >>>               pgrx_pg_sys-7f24ae81e8b430f4.pgrx_pg_sys.e5959c7b50b83aa3-cgu.2.rcgu.o:(pgrx_pg_sys::submodules::panic::do_ereport::hd62a12418f4ef87d) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpgrx_pg_sys-7f24ae81e8b430f4.rlib
          >>> referenced 1 more times
          
          rust-lld: error: undefined symbol: CurrentMemoryContext
          >>> referenced by panic.rs:402 (/home/pipe/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-pg-sys-0.14.3/src/submodules/panic.rs:402)
          >>>               postgis_rs.8nbi4f6r3a3wya2znlo3vyi8n.1nb9a81.rcgu.o:(pgrx_pg_sys::submodules::panic::pgrx_extern_c_guard::h11b9ca5a4eb8f197) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_rs.rlib
          >>> referenced by panic.rs:402 (/home/pipe/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-pg-sys-0.14.3/src/submodules/panic.rs:402)
          >>>               postgis_rs.8nbi4f6r3a3wya2znlo3vyi8n.1nb9a81.rcgu.o:(pgrx_pg_sys::submodules::panic::pgrx_extern_c_guard::h11b9ca5a4eb8f197) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_rs.rlib
          >>> referenced by ffi.rs:169 (src/submodules/ffi.rs:169)
          >>>               pgrx_pg_sys-7f24ae81e8b430f4.pgrx_pg_sys.e5959c7b50b83aa3-cgu.0.rcgu.o:(pgrx_pg_sys::include::pg16::CopyErrorData::h0291a45bb9916453) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpgrx_pg_sys-7f24ae81e8b430f4.rlib
          >>> referenced 11 more times

This is only a fragment, they are very long with the list.

As I said, this only happens calling bindings from _PG_init.

latot avatar Nov 06 '25 21:11 latot

#[pg_guard] applies #[no_mangle] it seems

workingjubilee avatar Nov 06 '25 21:11 workingjubilee

But only to _PG_init!

workingjubilee avatar Nov 06 '25 21:11 workingjubilee

@latot When you run rust-bindgen over against postgis.h or whatever, you are making a request for rust-bindgen to create this for every function:

unsafe extern "C" {
    fn {fn_name}({fn_args}) -> {fn_ret};
}

For any function you create this for, you are creating a request to link against that function, which means it goes into the global namespace.

That is why you experience a symbol collision here.

I don't know if you should be using bindgen at all, really, but you need to use bindgen's ability to exclude symbols to exclude any symbols you need to produce for your own library.

workingjubilee avatar Nov 06 '25 21:11 workingjubilee

in that case shouldn't this also fails?

#[pg_extern]
pub fn init() {
        unsafe {
                postgis_sys::bindings::pg_install_lwgeom_handlers();
        }
}

because it works.

latot avatar Nov 06 '25 21:11 latot

how do you know is a symbol collision and not a undefined one (failing to link)? (I has been learning about this from some time about bindings but I'm far from some who knows it very well)

latot avatar Nov 06 '25 22:11 latot

other note, I had in the project symbols that collide, I have excluded them, because the project just was not compiling but I other error, not like this one, still that does not exclude the possibility.

Maybe as you says, I should change how to generate the bindings and do the manual way instead of bindgen.

latot avatar Nov 06 '25 22:11 latot

in that case shouldn't this also fails?

#[pg_extern] pub fn init() { unsafe { postgis_sys::bindings::pg_install_lwgeom_handlers(); } }

because it works.

why would it not work?

workingjubilee avatar Nov 07 '25 06:11 workingjubilee

What you described as "fully ignore build.rs", does not happen. The contents of the build.rs are still affecting the build. Your code just doesn't have the effect you want. These are very different things.

workingjubilee avatar Nov 07 '25 06:11 workingjubilee

That can be completely by true, the reason I get confused is that:

#[pg_extern]
pub fn init() {
  unsafe {
   postgis_sys::bindings::pg_install_lwgeom_handlers();
  }
}

Right, that code works, the linker works, I can run that function from PG as extension, in that crate the only way to make do not works is using [no_mangle], if I change the build.rs I can see how it affects that code, if I miss linker a lib I can get the error of missing symbols, all that while [no_mangle] is not present.

So I really get confused why [no_mangle] does all this change, I would expect the code above to also fail, but it works.

If you are getting tired or want me to look at the in other place tell me pls, thx to your suggestions and some tweaks here isolating the bindings from pgrx, I was able to reproduce this without it.

Still is like magic to me why works and fails:

  • Create with pgrx:
    • with [pg_extern]: Works
    • with [pg_guard]/[no_mangle]: Don't works
  • In other normal crate without pgrx, just do not works

latot avatar Nov 07 '25 13:11 latot

@workingjubilee this could be interesting, look at this:

Rebuilding pgrx_embed, in debug mode, for SQL generation with features pg16
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
package:   /home/pipe/Documentos/latot/postgis_rs/postgis_rs/Cargo.toml
workspace: /home/pipe/Documentos/latot/postgis_rs/Cargo.toml
   Compiling postgis_rs v0.0.0 (/home/pipe/Documentos/latot/postgis_rs/postgis_rs)
error: linking with `cc` failed: exit status: 1
  |
  = note:  "cc" "-m64" "/tmp/rustcFptln4/symbols.o" "<99 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/home/pipe/Documentos/latot/postgis_rs/target/debug/deps/{libpostgis_rs,libpostgis_bindings-8b95fc9c16e7b2c8,libpostgis_sys-c7af46b01b4f93b1,libpgrx-8e9b675e26920cc6,libseahash-d93d6830cf4e65ab,libserde_cbor-59554119fbcd6e14,libhalf-eaecdf77f4725ab7,libserde_json-a2d0918e4d3254f4,libmemchr-5c5eadba8b986a50,libitoa-d481a5965213aa41,libryu-3685a3e93b399258,libenum_map-5d527a4d92e2a668,libpgrx_pg_sys-5dc97701d1502ee4,libserde-9c8b1a1b41214233,libserde_core-3043f393a082b2f9,libcee_scape-f87a3f964218548b,liblibc-6892b7c5032dc7cc,libbitvec-daf727bdfb5b5b25,libwyz-0b597af1c52a7cf5,libtap-3113989fbe284bbd,libradium-97a570c5c8d4f269,libfunty-a7872e34421125fb,libpgrx_sql_entity_graph-62f6f104a2a5c2fa,libunescape-0a6ff601ca75d0a2,libpetgraph-e292fa625cf02dd8,libhashbrown-974782671682ebf8,libfoldhash-c9990f85645ebf0c,libindexmap-419c381d5e58c976,libequivalent-cafadcc626c7a9d3,libhashbrown-3d924e4195c9e1f4,libfixedbitset-6f1dc0389b50863b,libthiserror-c92a35be179dcb35,libconvert_case-cd784c9350dece7b,libunicode_segmentation-a4f1a0e1cc49f990,libeyre-ec0e48d7ff373708,libindenter-1853c62ea32cd7bd,libonce_cell-bad884e249b7be55,libsyn-ebefa7cff4ce871a,libquote-8da49ace7c28f075,libproc_macro2-e4f3133f044ef951,libunicode_ident-dd81c2d1368ebc49}.rlib" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libproc_macro-*,librustc_literal_escaper-*,librustc_std_workspace_std-*}.rlib" "/home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libbitflags-0b8aec663ab57358.rlib" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,libcfg_if-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,liblibc-*,librustc_std_workspace_core-*,liballoc-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lpgport" "-lgeos" "-lgeos_c" "-ljson-c" "-lpostgis-3" "-lproj" "-lpgport" "-lgeos" "-lgeos_c" "-ljson-c" "-lpostgis-3" "-lproj" "-lgeos" "-lgeos_c" "-ljson-c" "-lpostgis-3" "-lproj" "-lresolv" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-L" "/tmp/rustcFptln4/raw-dylibs" "-B<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld" "-fuse-ld=lld" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/home/pipe/Documentos/latot/postgis_rs/target/debug/build/pgrx-pg-sys-301fc3c9fb63e83a/out" "-L" "/home/pipe/Documentos/latot/postgis_rs/target/debug/build/cee-scape-29d26d0f0d064d3f/out" "-L" "/home/pipe/.pgrx/16.9/pgrx-install/lib" "-L" "/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/liblwgeom/.libs" "-L" "/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon" "-L" "/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/postgis" "-L" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/pipe/Documentos/latot/postgis_rs/target/debug/deps/pgrx_embed_postgis_rs-79b1fad38aba1850" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs"
  = note: some arguments are omitted. use `--verbose` to show all linker arguments
  = note: rust-lld: error: undefined symbol: ErrorContext
          >>> referenced by panic.rs:402 (/home/pipe/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-pg-sys-0.16.1/src/submodules/panic.rs:402)
          >>>               postgis_rs.eewccsndo9sqet976qng2apyi.0dmuqo5.rcgu.o:(pgrx_pg_sys::submodules::panic::pgrx_extern_c_guard::h0943be00388f53ce) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_rs.rlib
          >>> referenced by panic.rs:402 (/home/pipe/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-pg-sys-0.16.1/src/submodules/panic.rs:402)
          >>>               postgis_rs.eewccsndo9sqet976qng2apyi.0dmuqo5.rcgu.o:(pgrx_pg_sys::submodules::panic::pgrx_extern_c_guard::h0943be00388f53ce) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_rs.rlib
          >>> referenced by panic.rs:546 (src/submodules/panic.rs:546)
          >>>               pgrx_pg_sys-5dc97701d1502ee4.pgrx_pg_sys.db7cb8be07625962-cgu.2.rcgu.o:(pgrx_pg_sys::submodules::panic::do_ereport::h7c660d6188a55b4d) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpgrx_pg_sys-5dc97701d1502ee4.rlib
          >>> referenced 1 more times
          
          rust-lld: error: undefined symbol: CurrentMemoryContext
          >>> referenced by panic.rs:402 (/home/pipe/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-pg-sys-0.16.1/src/submodules/panic.rs:402)
          >>>               postgis_rs.eewccsndo9sqet976qng2apyi.0dmuqo5.rcgu.o:(pgrx_pg_sys::submodules::panic::pgrx_extern_c_guard::h0943be00388f53ce) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_rs.rlib
          >>> referenced by panic.rs:402 (/home/pipe/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-pg-sys-0.16.1/src/submodules/panic.rs:402)
          >>>               postgis_rs.eewccsndo9sqet976qng2apyi.0dmuqo5.rcgu.o:(pgrx_pg_sys::submodules::panic::pgrx_extern_c_guard::h0943be00388f53ce) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_rs.rlib
          >>> referenced by ffi.rs:170 (src/submodules/ffi.rs:170)
          >>>               pgrx_pg_sys-5dc97701d1502ee4.pgrx_pg_sys.db7cb8be07625962-cgu.0.rcgu.o:(pgrx_pg_sys::include::pg16::CopyErrorData::h2bed71cb5f9bbe01) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpgrx_pg_sys-5dc97701d1502ee4.rlib
          >>> referenced 11 more times
          
          rust-lld: error: undefined symbol: pg_re_throw
          >>> referenced by panic.rs:403 (/home/pipe/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pgrx-pg-sys-0.16.1/src/submodules/panic.rs:403)
          >>>               postgis_rs.eewccsndo9sqet976qng2apyi.0dmuqo5.rcgu.o:(pgrx_pg_sys::submodules::panic::pgrx_extern_c_guard::h0943be00388f53ce) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_rs.rlib
          
          rust-lld: error: undefined symbol: errstart
          >>> referenced by lwgeom_pg.c:389 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:389)
          >>>               lwgeom_pg.o:(pg_notice) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced by lwgeom_pg.c:376 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:376)
          >>>               lwgeom_pg.o:(pg_warning) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced by lwgeom_pg.c:403 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:403)
          >>>               lwgeom_pg.o:(pg_debug) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced 3 more times
          
          rust-lld: error: undefined symbol: errmsg_internal
          >>> referenced by lwgeom_pg.c:389 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:389)
          >>>               lwgeom_pg.o:(pg_notice) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced by lwgeom_pg.c:363 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:363)
          >>>               lwgeom_pg.o:(pg_error) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced by lwgeom_pg.c:376 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:376)
          >>>               lwgeom_pg.o:(pg_warning) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced 9 more times
          
          rust-lld: error: undefined symbol: errfinish
          >>> referenced by lwgeom_pg.c:389 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:389)
          >>>               lwgeom_pg.o:(pg_notice) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced by lwgeom_pg.c:363 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:363)
          >>>               lwgeom_pg.o:(pg_error) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced by lwgeom_pg.c:376 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:376)
          >>>               lwgeom_pg.o:(pg_warning) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced 12 more times
          
          rust-lld: error: undefined symbol: errstart_cold
          >>> referenced by lwgeom_pg.c:363 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:363)
          >>>               lwgeom_pg.o:(pg_error) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced by lwgeom_pg.c:294 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:294)
          >>>               lwgeom_pg.o:(pg_parser_errhint) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced by lwgeom_pg.c:143 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:143)
          >>>               lwgeom_pg.o:(postgis_initialize_cache.cold) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced 6 more times
          
          rust-lld: error: undefined symbol: InterruptPending
          >>> referenced by lwgeom_pg.c:336 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:336)
          >>>               lwgeom_pg.o:(pg_realloc) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced by lwgeom_pg.c:320 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:320)
          >>>               lwgeom_pg.o:(pg_alloc) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: ProcessInterrupts
          >>> referenced by lwgeom_pg.c:336 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:336)
          >>>               lwgeom_pg.o:(pg_realloc) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          >>> referenced by lwgeom_pg.c:320 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:320)
          >>>               lwgeom_pg.o:(pg_alloc) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: get_extension_oid
          >>> referenced by lwgeom_pg.c:157 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:157)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: table_open
          >>> referenced by lwgeom_pg.c:76 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:76)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: ScanKeyInit
          >>> referenced by lwgeom_pg.c:77 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:77)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: systable_beginscan
          >>> referenced by lwgeom_pg.c:82 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:82)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: systable_getnext
          >>> referenced by lwgeom_pg.c:85 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:85)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: systable_endscan
          >>> referenced by lwgeom_pg.c:93 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:93)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: table_close
          >>> referenced by lwgeom_pg.c:95 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:95)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: CacheMemoryContext
          >>> referenced by lwgeom_pg.c:172 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:172)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: AllocSetContextCreateInternal
          >>> referenced by lwgeom_pg.c:172 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:172)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: MemoryContextAlloc
          >>> referenced by lwgeom_pg.c:178 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:178)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: undefined symbol: get_namespace_name
          >>> referenced by lwgeom_pg.c:181 (/home/pipe/Documentos/latot/postgis_rs/postgis_src/source/libpgcommon/lwgeom_pg.c:181)
          >>>               lwgeom_pg.o:(postgis_initialize_cache) in archive /home/pipe/Documentos/latot/postgis_rs/target/debug/deps/libpostgis_bindings-8b95fc9c16e7b2c8.rlib
          
          rust-lld: error: too many errors emitted, stopping now (use --error-limit=0 to see all errors)
          collect2: error: ld returned 1 exit status
          

error: could not compile `postgis_rs` (bin "pgrx_embed_postgis_rs") due to 1 previous error

First the error is compiling pgrx_embed_postgis_rs, second all errors all symbols from PG, maybe PGRX do something and links this without us know it! maybe in the first place all this error should happen becase I'm not manually linking to PG.

latot avatar Nov 07 '25 19:11 latot

I firmly believe it's because of a symbol clash during linkage. like I am telling you. A Rust symbol is naturally mangled to be unambiguous even if the same symbol is present in another crate.

The way linkers behave can be very nonintuitive and they usually provide limited or just bad diagnostics. It seems very possible to confuse them in multiple different ways, getting different errors for similar problems. There's some other things unspecified about your setup, so I honestly can't explain exactly what's going on with full certainty. I am fully willing to say "I am wrong" if you provide more information.

Though right now I'm mostly interested in knowing if you have tried Builder::blocklist_function("_PG_init") while generating the PostGIS bindings.

workingjubilee avatar Nov 07 '25 20:11 workingjubilee

Hi! yes, actually I tried that a few mins ago, give the same problem.

Rn from my limitated knowlodge, seems the linker is trying to solve the symbols that should be loaded by pg, the symbols from the error should not be resolved in that moment.

latot avatar Nov 07 '25 20:11 latot

I can doc some thing and show you the project if want to see it, I have the feeling you know about postgis, I has been able to run and mix rust + postgis.

latot avatar Nov 07 '25 20:11 latot

Odd. Then it may be how you are linking things into the combined binary, yes.

workingjubilee avatar Nov 07 '25 20:11 workingjubilee

I can avoid to think pgrx has something to do, in last tests I found this, the only way to get the error is using the combination of the function name _PG_init + [no_mangle] which seems to cause something like to force to solve all the symbols.

I know it works with:

  • Any other function name
  • Using [pg_extern]

Could also be other type of symbol collision, I'm thinking, pgrx has its own pg symbols that must keep, but postgis bindings has the same symbols, maybe that ones are in conflict? (which should point to the same symbols)

latot avatar Nov 07 '25 21:11 latot

@workingjubilee I has been able to get a good point/clue of this happens, seems to be a collision between the bindings and pgrx:

#[pg_extern]
fn some_call_to_pg_internal() {
        unsafe {
                // Some function with bindings that calls PG internal things!
                postgis_sys::bindings::pg_install_lwgeom_handlers();
        }
}

#[pg_guard]
pub unsafe extern "C-unwind" fn _PG_init() {}

The trick is the next one, some_call_to_pg_internal will call functions that uses PG internal symbols, while [pg_guard] at https://github.com/pgcentralfoundation/pgrx/blob/15ce9eaf6de49133ceebeb8c67f908b7ed40264b/pgrx-pg-sys/src/submodules/panic.rs#L402 will insert a new pg symbol, in this case as a example from there CurrentMemoryContext, which enters in conflict with the bindings symbols.

This will works:

#[pg_extern]
fn some_call_to_pg_internal() {
        unsafe {
                // Some function with bindings that calls PG internal things!
                postgis_sys::bindings::pg_install_lwgeom_handlers();
        }
}

#[no_mangle]
pub unsafe extern "C-unwind" fn _PG_init() {}

Because [no_mangle] will not add the extra symbols, so with the current pgrx state, we can't use bindings, here a case with [no_mangle] that does not works, which simulates a little the pg_guard effect:

fn some_call_to_pg_internal() {
        unsafe {
                // Some function with bindings that calls PG internal things!
                postgis_sys::bindings::pg_install_lwgeom_handlers();
        }
}

#[no_mangle]
pub fn _PG_init() {
        let a = pgrx::memcxt::PgMemoryContexts::CurrentMemoryContext;
}

So, for now we can confirm that this happens when we mix bindings + pgrx own pg functions, I can for now summarize to reprex this is the next rules:

  • You must call a binding function that calls a PG server function out of _PG_init
  • You must use at least #[no_mangle] on _PG_init
  • You must use a PG server function (not a binding) in _PG_init
  • You must link to the pg original extension println!("cargo:rustc-link-lib=dylib=postgis-3"), which is the one who has the pg server symbols

I still do not know why is _PG_init related to this, I can confirm that symbol is being excluded from the bindings, so the only _PG_init that exists rn is from pgrx.

latot avatar Nov 07 '25 22:11 latot

Hmm. Why, exactly, are you linking against PostGIS internal functions, and why can't you rely on the fact that they will be made-available by the dlopen of PostGIS using RTLD_GLOBAL?

workingjubilee avatar Nov 08 '25 00:11 workingjubilee

I'm playing/testing move postgis functions to rust, so I made them available to I can start moving one by one.

I need access to a lot of internal functions, and replace from the top ones to down, each level will request different ones.

Take some time, but I has been able to replace geometry_in which a key one.

Also I have sys bindings, and other crate which implements safe usage of the original C code to rust, obvs this second one is done only to some functions, the ones I has been using for this.

latot avatar Nov 08 '25 01:11 latot