4

I have asked this question in the past but in a different context. I have a C++ application (App) which links to a static C++ library A (libA), which links to a static C library B (libB):

# App CMakeLists.txt
add_executable(App ${APP_HEADER_FILES} ${APP_SOURCE_FILES})
target_link_libraries(App PUBLIC LibA)

# LibA CMakeLists.txt
add_library(LibA STATIC ${LIBA_HEADER_FILES} ${LIBA_SOURCE_FILES})
target_link_libraries(LibA PUBLIC LibB)

The problem is that when I build App I get a linker error: "error: undefined reference to mpfit". mpfit is a function in libB. Here is the strange thing now:

  • If I make LibA shared (by replacing STATIC with SHARED in CMake) I get no linker error!

Someone told me that I will have to link all the shared libraries to App myself. I tried that and it actually worked. But here is my question now:

  • Isn't CMake supposed to automatically propagate all the link dependencies to my executable? Isn't this the purpose of the PUBLIC keyword in the target_link_libraries function?
  • Why I get no linker errors when LibA is a shared library?

EDIT1:

If that helps: If I do nm libA I get:

libA.cpp.o:
    // ... blah blah ...
    U mpfit
    // ... blah blah ...
AstrOne
  • 3,569
  • 7
  • 32
  • 54
  • do you have `error: undefined reference to` symbols from `libB`used by `libA` – UmNyobe Jun 23 '16 at 15:05
  • @UmNyobe yes, exactly – AstrOne Jun 23 '16 at 15:52
  • If we are talking about e.g. the GNU toolchain you could use [verbose output](http://stackoverflow.com/questions/37994484) to see what's actual called (e.g. on Windows platforms there are [weird workarounds](https://github.com/Kitware/CMake/blob/master/Modules/Platform/Windows-GNU.cmake#L133) in there). Generally speaking the difference between `STATIC` and `SHARED` here is, that a `SHARED` LibA does actually have LibB linked to it. – Florian Jun 23 '16 at 20:19
  • Possible duplicate of [CMake link not subfolder](http://stackoverflow.com/questions/33709241/cmake-link-not-subfolder) – Florian Jun 23 '16 at 20:31

1 Answers1

1

It's quite possible that the linker is dropping non referenced symbols when linking libB to libA. Which means that by the time you link to App, some symbols of libB are missing.

In that case you may want to specify linkers options to keep the whole libB during the first linkage. For instance, for gcc you have --whole-archive ld parameter

Community
  • 1
  • 1
UmNyobe
  • 22,539
  • 9
  • 61
  • 90