1

I have a project where I mix between static and shared libs. The shared libs are delivered. Each shared lib is built with its correspondence static lib. A shared lib can depend on other shared libs as well. For example, I have: sharedA, sharedB, sharedC, staticA, staticB and staticC. SharedA is built with staticA inside and similar for other shared. Let's say sharedC, besides its dependency on staticC, also depends on sharedB.

For the static libraries, if they need dependency on another static one, I link against the one's correspondence shared lib. For example:

staticB depends on staticA. Hence, I link staticB against sharedA. The reason for this is to avoid size increase if statically declare staticB's dependency on staticA.

This system has been working. However, problem arises when I build the static libs with hidden visibility. The linker links with no error. But more than one symbols of a specific class might end up in the final symbol map. Therefore, the program can pick up the undesired one, which causes weird behaviour.

I have been reading about cmake object library, and probably switching the static libs to object libs could help in this case. I change the static libs to object, and get undefined symbol errors. I define dependency of an object lib on other, but still could not get rid of all the errors. My questions are:

  1. I am using target_link_libraries(obj2 PUBLIC obj) to declare dependency between 2 object libs. Can this be the reason for undefined symbol error I get? Because according to cmake documentation:

Object Libraries may "link" to other object libraries to get usage requirements, but since they do not have a link step nothing is done with their object files.

  1. Maybe I should switch to target_link_libraries(obj2 $<TARGET_OBJECTS:obj>) so obj2 is built with object files from obj.c? Another thing with this is: obj needs to be a library (created with add_library). In the function where I define all the links, obj is a variable and could not be put after $<TARGET_OBJECTS:. I have been looking around but not able to find anything. Is there a way I can put variable name after $<TARGET_OBJECTS:, or I have to refractor somehow to make this possible?

  2. Any other suggestion on how to do this would be helpful to me

no_name
  • 45
  • 5
  • What I'm confused about: Static libraries don't link other static libraries. (Both libraries have to be linked into the executable instead.) This is unrelated to the fact that there might be a dependency which you have to express, of course, in CMake. – Scheff's Cat Nov 18 '21 at 10:30
  • Do you mean I should edit my wording? When I say staticB depends on staticA, I mean B needs to be built with symbols from A. Instead of embedding both staticA and staticB inside the binary of sharedB (which already has staticB inside), I link staticB with sharedA (which already contains staticA). By doing this, sharedB does not contain staticA. Do I answer your question? – no_name Nov 18 '21 at 11:19
  • I must admit it's a long time ago that I used static linking last time. There is an `option(BUILD_SHARED_LIBS "Build shared libraries" ON)` to build DLLs for any lib. project. (I'm on Windows.) _embedding both staticA and staticB inside the binary of sharedB_ ??? I'm used to build either a static or a dynamic library. If a static library (`staticA`) is linked to a DLL (`sharedB`) it's in fact "embedded". (DLLs are actually like EXEs on Windows. I don't know how this is in case of shared objects in Linux.) However, in CMake you provide dependencies, that's it. – Scheff's Cat Nov 18 '21 at 11:35
  • ... The rest is subject of the generated build scripts and the resp. tool chain. `target_link_libraries(obj2 PUBLIC obj)` sounds reasonable. (This is what we use always in any of our project.) – Scheff's Cat Nov 18 '21 at 11:42
  • Btw. on Windows, the outcome for `staticA` as static lib. would be `staticA.lib`. As shared lib. it would be `staticA.dll` and `staticA.lib`. In the latter case, the `staticA.lib` is not the static library but a (quite small) library, other applications can link against to get link symbols for the DLL. (That's actually everything what was exported from the DLL.) So, if you support static _and_ shared libraries, care of your library names so that the `.lib` files can be distinguished. – Scheff's Cat Nov 18 '21 at 11:43
  • I think we are not on the same page. What I mean is: `target_link_libraries(staticB PUBLIC sharedA)`. With this line, the symbols of staticA is linked with staticB, but staticA won't be in sharedB when I do `target_link_libraries(sharedB PUBLIC staticB)` – no_name Nov 18 '21 at 11:43
  • This is yet another thing, I'm confused about: I would link everything shared. In the past, we linked everything static. I could live with a shared lib. where dependencies are statically linked in (although I would prevent this when possible). But a static lib. with a dependency to a shared lib.? I couldn't imagine any case where I would do this (except the shared lib. is a system or 3rd party lib.) – Scheff's Cat Nov 18 '21 at 11:46
  • `target_link_libraries(sharedB PUBLIC staticB)` And this looks even more suspicious. (I tried to explain why this shouldn't be necessary. It seems I wasn't that lucky...) :-( – Scheff's Cat Nov 18 '21 at 11:48
  • Yes, I agree mixing them means asking for more trouble. That's the reason why I am investigating switching the static libs to object. But you suggest trying to change them to shared? – no_name Nov 18 '21 at 11:49
  • If you intend to deliver shared libs only, I would built up the CMake project straight forward, and not consider anything static. I believe as well that mixing static and shared is asking for trouble... – Scheff's Cat Nov 18 '21 at 11:52

0 Answers0