SOCI/soci

Static linking error on Windows

Tectu opened this issue · 9 comments

Tectu commented

I recently switched from linking SOCI dynamically to linking it statically.

On FreeBSD everything works like a charm. However, I just fired up the test builds on WIndows (under MSYS2) And I am getting the following link time error:

C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccMVg5XN.ltrans1.ltrans.o::(.text+0x472b): undefined reference to `soci::details::parse_std_tm(char const*, tm&)'

This is with:

  • SOCI commit 074722a (second last commit on master branch)
  • GCC 12.2.0
  • CMake 3.24.2
  • Compiling under MSYS2
  • My application uses C++20 (shouldn't be relevant but just for completion)

I'm linking to both Soci::core_static and Soci::sqlite3_static.
I'm observing the same problem no matter the values of SOCI_VISIBILITY and SOCI_LTO (the former shouldn't matter anyway).

Any ideas what I'm missing?

Tectu commented

I had another quick go at this but still couldn't find the underlying issue. Any ideas?

vadz commented

Do you define SOCI_DLL when building your project?

Tectu commented

Thank you for your response.

SOCI_DLL was not defined. For testing purposes I did define SOCI_DLL and performed a clean built. This results in way more linking errors.
It would also seem like SOCI_DLL would not be needed when building static libraries anyway. It only seems to have an effect regarding shared library import/exports.

Any other ideas or hints?

vadz commented

Ah, wait, could it be just the usual static linking library order problem? You need to put the core library after all the backend libraries when linking statically.

Tectu commented

That was spot on! After ensuring that the core gets linked after the backends everything works as expected :)
Why exactly is this a thing? What underlying mechanism is at play here?

Thanks for your help - once again!

vadz commented

This is just a property of classic Unix linkers, they resolve dependencies in left to right order, i.e. when you link with -lA -lB -lC, only symbols used by libA will be taken from libB, and anything used by libC won't be -- because by the time libB is processed they're not used yet and the linker never goes back to look for them later.

This is the way linking has worked on Unix since always and probably will remain working for as long as the concept of linking still exists...

Tectu commented

This part I get. What I am curious about is why these symptoms didn't show up under FreeBSD/Clang but do show up under Windows/MinGW :D

I should probably have worded my question different than "Why is this a thing?".

vadz commented

I don't know enough about FreeBSD to answer this, but normally you should have had the same problem there if the link order was the same. You definitely should have it under Linux.

Tectu commented

Yeah this is curious. I inspected the resulting FreeBSD binaries and SOCI was linked statically. moreover, the resulting binary ran fine on a foreign system where SOCI libs are definitely not present in any form.

If I happen to have some spare time I'll dive into this, it's really curious.

Of course, this is nothing related to SOCI anymore so I'll stop wasting your time now. Thanks again - much appreciated!