9

I have following libraries lib_A, lib_B, lib_C, lib_D. I am doing something like this in my CMake files (order is important):

  1. ADD_LIBRARY(lib_A)
  2. ADD_LIBRARY(lib_B)
  3. ADD_LIBRARY(lib_C)
  4. ADD_LIBRARY(lib_D)
  5. TARGET_LINK_LIBRARIES(lib_B lib_C)
  6. TARGET_LINK_LIBRARIES(lib_A lib_B)
  7. ADD_EXECUTABLE(Exec)
  8. TARGET_LINK_LIBRARIES(exec lib_A)
  9. TARGET_LINK_LIBRARIES(exec lib_D)

This results in following linker command.

linker -llib_A -llib_D -llib_B -llib_C

Q1. Why are lib_B and lib_C after lib_D?

Q2. When I change CMake a little bit and do something like this:

  1. TARGET_LINK_LIBRARIES(lib_A lib_D)
  2. TARGET_LINK_LIBRARIES(exec lib_A)

then linking order is like this:

linker -llib_A -llib_B -llib_C -llib_D

Here, lib_B and lib_C are before lib_D. It means that target_link_libraries works differently for executable targets and library targets. Am I right?

The problem here is that lib_B and lib_C also depend on lib_D, but I don't want to make target_link_libraries(lib_B lib_D) and target_link_libraries(lib_C lib_D), because I have more of such cases, and I would have to do it manually for each library. Of course doing like in Q2 solves the problem but:

Q3 - Is this order guaranteed somehow by CMake or it is just a fortuity?

Thank you

5
  • Not sure about the difference in order between exes and libs, but if B and C both depend on D, you should really specify that.
    – Fraser
    Commented Jul 17, 2013 at 22:56
  • Problem is that B and C are logically part of platform indpendent A and A whole depends on platform lib D. I know I should do this but I have plenty of them and doing it manually will make a lot of efforts to maintain it and providing some automatic solution will increase complexity of my cmake based build system. Another issue is that when I will explicitly set this D dependency to each platform independent lib, it will result that D will be listed on linker list a lot of times. Commented Jul 17, 2013 at 23:13
  • I have the same issue with external library - boost for example. I would like to avoid setting dependency to boost in each library. Commented Jul 17, 2013 at 23:16
  • @user2301299 The only thing I can suggest is to create a list of external libraries that you link to all of your targets, in order to compact your target_link_libraries for each library. BTW, if you link to a dynamic library that is not necessary, the linker will understand that and remove the dependency: not really clean, but you can decide if you want to leave with that
    – Antonio
    Commented Jul 18, 2013 at 6:15
  • @user2301299 "This results in following linker command." -- Is there a way to generate the linker command or you just know that that's how it should be? Thanks in advance!
    – Milan
    Commented Aug 29, 2022 at 5:36

1 Answer 1

4

Just link lib_B and lib_C to lib_D, it's worth the effort (I can tell by experience), otherwise you will have big troubles, for example if you try to install your program. lib_C and lib_D should have all their symbols solved when you are finished creating their library files, before linking them to any other library.

By the way, you can compact your target_link_libraries in one line per target, like:

TARGET_LINK_LIBRARIES(exec lib_A lib_D)

And, if exec doesn't depend directly on lib_D, you can avoid linking it if you have correctly linked lib_A to lib_D.

Anyway, regarding Q1: even if the order is guaranteed by CMake, it is not guaranteed the way your linker will treat it, you are going to suffer pain if you rely on that

1
  • Thank you for answers. I have decided that I will add the dependency automatically to each library. It will solve another issue. Some of those libraries are shared across a number of executables. Keeping dependencies at the level of each library, i don't have to worry about unresolved symbols at the time of linking those executables. Commented Jul 18, 2013 at 12:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.