6

I have:

  • a shared library X, which is independent
  • a shared library Y, using X
  • an executable Z, which uses both X and Y

All of them have their own CMakeLists.txt, and can be configured and built independently.

However, I cannot make the CMakeLists.txt for the executable (Z) to work.

My approach has been this:

foreach(clib ${OWN_LIBS})
   set(LIBS "${LIBS} ${clib}")
   set(CLIB_DIR "${PROJECT_SOURCE_DIR}/../lib${clib}")
   set(CLIB_BUILD_DIR "${CLIB_DIR}/build")

   add_subdirectory("${CLIB_DIR}" "${CLIB_BUILD_DIR}")
   include_directories("${CLIB_DIR}/incl")
   link_directories("${CLIB_BUILD_DIR}")
endforeach(clib)

With OWN_LIBS being just "X" in project Y, and being "X Y" in project Z.

This works for project Y, but in project Z, I get:

CMake Error at ... (add_subdirectory): The binary directory

.../libX/build

is already used to build a source directory. It cannot be used to build source directory

.../libX

Specify a unique binary directory name.

I also tried trying to create a local build directory, so for e.g. there would be libY/build/deps-libX/ containing the configured and built library X (when used from Y), and Z having this for both X and Y. Unfortunately, next I ran into:

add_library cannot create target "X" because another target with the same name already exists. The existing target is a shared library created in source directory "libX". See documentation for policy CMP0002 for more details.

Using ExternalProject is not an option.

ShdNx
  • 3,172
  • 5
  • 40
  • 47
  • I eventually ended up using the solution detailed at http://stackoverflow.com/a/11217008/128240. – ShdNx Jul 22 '14 at 16:32
  • possible duplicate of [CMake - dependencies (headers) between apps/libraries in same project](http://stackoverflow.com/questions/11216408/cmake-dependencies-headers-between-apps-libraries-in-same-project) – ShdNx Jul 22 '14 at 16:32

3 Answers3

8

An additional answer for others:

I got this error because of a merge "error". In a larger project, after merging, a CMakeLists.txt called "add_subdirectory" twice on the same subdirectory. It causes the same error message.

Gombat
  • 1,994
  • 16
  • 21
2

X's CMakeLists.txt is processed 2 times (add_subdirectory(X) is called from both Z and Y). That makes the target X defined multiple times, which violates the policy CMP0002 (X is not globally unique)

For this link situation

Z-->Y--->X
 --------^

you do not need to call add_subdirectory(X) from Z's CmakeLists.txt

Z/CmakeLists.txt
   add_subdirectory(Y ...)

Y/CmakeLists.txt
   add_subdirectory(X ...)
Peter Petrik
  • 9,701
  • 5
  • 41
  • 65
  • 5
    Right, but ideally I would not want to Z have to know that Y depends on X. Z's only concern should be that he uses both X and Y. Is there any robust way of doing this? – ShdNx Jul 15 '14 at 10:44
  • `X` and `Y` could be in a [package](http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries) – Peter Petrik Jul 15 '14 at 11:17
1

This is a very old question, but I'm going to dig into this graveyard as I recently ran into this, again. My problem space was much like OPs: I have two executables which I'd like to compile separately or as part of a larger compile which both link to the same library, which is also compiled through cmake. As this is simply not possible without altering the CMakeList.txt of each of the executables, the following answer proved extremely helpful:

https://stackoverflow.com/a/13290084

If the project is compiled using the "master" CmakeList.txt the linked library is not added in each of the executables. If an individual executable is compiled, the library is built and linked. Note that this produces the following within each CMakeLists.txt:

Master:

add_subdirectory( common )
add_subdirectory( exec1  )
add_subdirectory( exec2  )

exec1 and exec2:

set( COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../common )

if ( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR )
    add_subdirectory( ${COMMON_DIR} ${COMMON_DIR})
endif()
Alex Baum
  • 166
  • 9