1

In my CMake project I have the following targets:

  • LibA library that has a missing function void foo() that the user needs to implement when linking with LibA
  • LibB library which among other implements foo() and links to LibA
  • Proj executable which links to LibB

CMakeLists.txt looks something like this:

add_library(LibA STATIC libA_source.cpp)

add_library(LibB STATIC libB_source.cpp libA_retarget.cpp) #foo() is implemented in retarget
target_link_libraries(LibB LibA)

add_executable(Proj proj_source.cpp)
target_link_libraries(Proj LibB)

If I use VisualStudio as my generator my project builds fine. However if I use MinGW I get linker error that void foo() is not defined.

Is there something I did fundamentally wrong? In my understanding everything is fine and should work. I have no idea why linker in MinGW cannot find foo() from LibB.

rozina
  • 4,120
  • 27
  • 49
  • As `LibA` needs a function, defined in `LibB`, then `libA` should be linked with `libB`: `target_link_libraries(LibA LibB)`. It is not a problem for `libB` to be dependent from `libA` too, as *cyclic linkage* works perfectly in case of **static** libraries. – Tsyvarev Oct 10 '19 at 10:50
  • @Tsyvarev It doesnt make sense for `LibA` to link with `LibB`, because `LibA` has no idea `LibB` even exists. `LibB` however does know about `LibA`, because it uses it.Unless I should write `target_link_libraries(LibA LibB)` in LibB's CMakeLists.txt? – rozina Oct 10 '19 at 11:03
  • You have a dependency which cannot be resolved by other means. Every library should know the symbols it uses. Instead of designing `libA` library to use `foo` function directly, you may take this function as callback for one of your `libA` functions. Alternatively, instead of `libA` being library you may create a *module* (plugin), which is loaded by `libB` with `dlopen`. – Tsyvarev Oct 10 '19 at 11:26
  • @Tsyvarev I cannot agree. Retarget functions are pretty standard in embedded development. And there is no unresolved dependencies, which is why with Visual Studio generator the program builds fine. It is only MinGW that somehow has a problem and cannot find `foo()` even though it should be in the compiled object files. – rozina Oct 10 '19 at 12:38
  • Your case is clearly described in [that answer](https://stackoverflow.com/a/24675715/3440745) to the generic question about "undefined reference". Some compiler(linkers) don't depend from the libraries order, but others do. – Tsyvarev Oct 10 '19 at 13:13
  • As for "embedded development", instead of library `libA` you may use plain object file. Unlike to libraries, an order of the object files in the linker's command line doesn't matter. – Tsyvarev Oct 10 '19 at 13:18
  • @Tsyvarev Thanks for pointing me in the right direction. I was able to solve the problem by repeating `LibA` in `target_link_libraries` of `Proj`. `target_link_libraries(Proj LibA LibB)` – rozina Oct 11 '19 at 08:17
  • Note, that order of `LibA LibB` is important. And with the fixed order this call is efficiently the same as two calls: `target_link_libraries(Proj LibA)` plus `target_link_libraries(LibA LibB)`, which are more descriptive. – Tsyvarev Oct 11 '19 at 08:38
  • @Tsyvarev Unfortualtely I cannot add `target_link_libraries(LibA LibB)` because LibA and LibB are defined in different CMakeLists.txt. Also I don't think your example works, beucase LibB also depends on LibA. In the end `target_link_libraries(Proj LibA LibB LibA)` is really needed, which is what my shorter version effectively does. – rozina Oct 11 '19 at 08:47

0 Answers0