Linking against static C++ lib that links against static C++ lib

I made a C++ cmake lib:

target_link_libraries(seal_tests seal stdc++)

which links statically with this lib:

and then I link it in my rust code:

println!("cargo:rustc-link-lib=static=seal_tests");

but I get undefined reference errors to SEAL objects:

      /workspaces/my-rust-project/seal_cpp/SEAL/native/src/seal/modulus.h:45: undefined reference to `seal::Modulus::set_value(unsigned long)'
      /usr/bin/ld: /workspaces/my-rust-project/target/debug/build/my-rust-project-8b92ea2f54bf11a3/out/build/libseal_tests.a(test1.o): in function `seal::EncryptionParameters::EncryptionParameters(seal::scheme_type)':

however, the SEAL library is static and linked statically to my seal_tests library, so I shouldn't get these

That's philosophical question whether that should happen or not.

That's just the fact: if you link static library libA and said library refers to functions from libB then you have to specify both -lA and then -lB (in that order, which is important, too!).

Now, lots of people find that strange and annoying thus many build systems (like libtool) try to hide that requirement from you and try to automagically supply -lB when you specify -lA.

Honestly, I'm not sure whether this magic was broken in your particular case or that combo is not even supposed to work like that.

wasn't static library linking supposed to be "glued" to the current lib being built? So I shouldn't worry about it at all. Since it's static, it should be built together with my lib in the same .a file, shouldn't it?

No, that's not how static libraries work at all.

When you build static libraries they don't even, really, know anything about each other.

The whole scheme was designed for C, remember? There each library may export some symbols and request some other symbols.

And any resolution happens only during final linking step. Till that point don't know about each other.

As you may guess that approach don't work all that well for more high-level languages like Rust or C++.

Thus build systems try to hide the fact that static libraries are independent from you. Some put "pseudolibraries" (these are .la files libtool creates), some track that in the config files.

But as you can see that doesn't always work.

And deep, deep, down below static libraries are independent from each other (while shared libraries are not independent, they can keep dependency information inside).

but if my lib uses other stuff from other lib, then when my lib is being compiled, everything should be resolved. Or by final linking step, do you mean when generating an executable?

Theoretically my static lib already knows everything it uses, so it could glue the static seal library with just the needed functions

It doesn't. There is no way for static libraries to contain any linker flags or library dependency names. It only contains unlinked object files.

It k “knows everything it uses”, but it doesn't knows what it doesn't use!

Suppose there are two functions: foo and bar in your static library. And they call foo_seal and bar_seal. And don't call baz_seal.

Sure, in theory it should be possible to keep just foo+foo_seal and baz+baz_seal and then, when you build the executable, decide if we need foo+foo_seal or baz+baz_seal (or both).

But this just complicates everything for very little gain: what if both foo and baz need baz_seal? Should we include everything once or twice? And if twice then how can we dedupe things later?

Thus nothing like that is done.

Instead linker starts with main. Then it would see if foo and/or bar are needed. Then it would decide if foo_sealed/bar_sealed/baz_sealed. And then all the functions which are not needed are discarded.

But for that to happen linker have to see all static libraries. Simultaneously. And in right order.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.