1

I've search the internet all over, but there is no simple answer for the issue. I've read this: CMake: Attempted to add link library to target which is not built in this directory

But i don't want to put the target_link_libraries into the same cmake list, instead i want to leave the linkage commands inside each respective list because a library cmake list has to know which one library dependency it must be linked with.

Mine project's structure is this:

   <main_exe>     :   /main
       |          :    |
   <main_lib>     :    +- /_3dparty
    /      \      :    |   |
<lib_A>  <lib_B>  :    |   +- /lib_A/CMakeLists.txt
    \      /      :    |   +- /lib_B/CMakeLists.txt
    <lib_X>       :    |   +- /lib_X/CMakeLists.txt
                  :    |
                  :    +- /CMakeLists.txt

All 3 libraries are standalone and static, and i don't want to make them as a subdirectory to each other.

But when i tried to add_subdirectory with external binary directory from lib_A and lib_B respectively:

if (NOT TARGET lib_X)
    add_subdirectory(${lib_X_ROOT} ${CMAKE_BUILD_ROOT}/_3dparty/lib_X)
endif()

add_dependencies(${PROJECT_NAME} lib_X)

target_link_libraries(${PROJECT_NAME}
    PUBLIC
      lib_X
)

, then the cmake throw an error:

Attempt to add link library "lib_X" to target "lib_B" which is not built in
this directory

Is there a way to put it to work w/o excessive ExternalProject_Add usage?

EDIT:

I reproduced the issue on the minimal example.

The library libB actually had slightly different structure:

/main
 |
 +- /_3dparty
 |   |
 |   +- /lib_A/CMakeLists.txt
 |   +- /lib_B
 |   |   |
 |   |   +- /libsubdir/CMakeLists.txt
 |   |   +- /CMakeLists.txt
 |   |
 |   +- /lib_X/CMakeLists.txt
 |
 +- /CMakeLists.txt

That was the cause of the issue.

/CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

project(main_project)

set(CMAKE_BUILD_ROOT ${CMAKE_CURRENT_LIST_DIR}/_build)
set(CMAKE_LIBS_ROOT ${CMAKE_CURRENT_LIST_DIR}/_3dparty)

add_library(mainlib ${CMAKE_CURRENT_LIST_DIR}/main.cpp)

add_subdirectory(${CMAKE_LIBS_ROOT}/libA ${CMAKE_BUILD_ROOT}/_3party/libA)
add_subdirectory(${CMAKE_LIBS_ROOT}/libB ${CMAKE_BUILD_ROOT}/_3party/libB)

target_link_libraries(mainlib
  PUBLIC
    libA
    libB
)

/_3dparty/libA/CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

project(libA_project)

add_library(libA STATIC ${CMAKE_CURRENT_LIST_DIR}/main.cpp)

add_subdirectory(${CMAKE_LIBS_ROOT}/libX ${CMAKE_BUILD_ROOT}/_3party/libX)

target_link_libraries(libA
  PUBLIC
    libX
)

/_3dparty/libB/CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

project(libB_project)

#add_library(libB STATIC ${CMAKE_CURRENT_LIST_DIR}/libsubdir/main.cpp)

add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/libsubdir) # the root cause of the issue

#add_subdirectory(${CMAKE_LIBS_ROOT}/libX ${CMAKE_BUILD_ROOT}/_3party/libX) # would be an error if add this twice

target_link_libraries(libB # <- the issue error is here
  PUBLIC
    libX
)

/_3dparty/libB/libsubdir/CMakeLists.txt

add_library(libB STATIC main.cpp)

/_3dparty/libX/CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

project(libX_project)

add_library(libX STATIC ${CMAKE_CURRENT_LIST_DIR}/main.cpp)

Output:

x:\_cmake_test\_out>cmake .. -G "Visual Studio 14 2015"
CMake Error at _3dparty/libB/CMakeLists.txt:11 (target_link_libraries):
  Attempt to add link library "libX" to target "libB" which is not built in
  this directory.


-- Configuring incomplete, errors occurred!
See also "X:/_cmake_test/_out/CMakeFiles/CMakeOutput.log".

If uncomment the add_library(libB ... and comment add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/libsubdir) then the issue disappears.

Any suggestions how to fix that w/o edit a 3dparty library?

Andry
  • 2,273
  • 29
  • 28
  • Do you add this code into `lib_B/CMakeLists.txt`? But where `lib_B` is built (with `add_library`)? Also, `add_dependency` is redundant when you already have `target_link_libraries`. – Tsyvarev Jul 10 '18 at 19:33
  • @Tsyvarev Both, from `lib_A` and `lib_B`, which are in turn called through the `add_subdirectory` from the `main_lib`. – Andry Jul 10 '18 at 20:22
  • note about the error you're getting: https://stackoverflow.com/q/26838367/11107541 (you probably won't get it if you have CMake 3.13+) – starball Jul 08 '23 at 07:44

1 Answers1

0

Do not do add_subdirectory() in cmake-projects which are likely to be used as sub-directories itself.

Instead create a super-project which does all the add_subdirectory() at the same level (in the same CMakeLists.txt). The order is not important, CMake resolves the target-dependency (done via target_link_libraries()) once all CMakeLists.txt have been processed.

This is an approach I ended up using in all my projects. It has some disadvantages, for example unit-testing of each library might be difficult, but this is solvable with conditioning the tests with a variable.

Patrick B.
  • 11,773
  • 8
  • 58
  • 101
  • I know that i can do it. I want to known how to do it most correctly respective to a 3dparty dependencies. I don't want to know what dependencies having a 3dparty project as long as it is a standalone project. – Andry Jul 11 '18 at 11:54
  • Use ExternalProject() then and import the resulting libraries via an `INTERFACE`-library and by using BYPRODUCTS of ExternalProject. Even or especially if your third-party is a cmake-project. – Patrick B. Jul 11 '18 at 11:57
  • With the `ExternalProject_Add` I have to rewrite everything on the way to the `lib_X`. It raises another set of configuration errors that leads might be to the same complications on the way and even harder to support. – Andry Jul 11 '18 at 12:02
  • Third-parties will always be configured differently between each other and your code, so configuration-problems will always exist. The goal should be to centralise and isolate. ExternalProject_Add is the right solution. – Patrick B. Jul 11 '18 at 12:05
  • This IS the problem. I DO NOT want to configure them differently. Third-parties are the same projects as all others, why i have to configure them differently? I DO want a common way to configure everything in the cmake including 3dparties. – Andry Jul 11 '18 at 12:08
  • Do you control how the CMakeLists.txt of your third-party-code is written? – Patrick B. Jul 11 '18 at 12:17
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/174803/discussion-between-andry-and-patrick-b). – Andry Jul 11 '18 at 12:17