Consider the following three projects.
ProjectA
does not have any dependencies and its CMakeLists.txt
at top level is like the following,
cmake_minimum_required(VERSION 2.8.4)
project(A CXX)
add_library(a ${PROJECT_SOURCE_DIR}/liba.cpp)
ProjectB
depend on ProjectA
, and I add ProjectA
as a git-submodule, so its structure will be like below,
ProjectB
CMakeLists.txt
libb.cpp
ProjectA
(git submodule)
CMakeLists.txt
liba.cpp
and ProjectB
's CMakeLists.txt
look like the following
cmake_minimum_required(VERSION 2.8.4)
project(B CXX)
add_subdirectory(ProjectA)
add_library(b ${PROJECT_SOURCE_DIR}/libb.cpp)
target_link_libraries(b a)
So far it is alright.
Now let's say it comes a ProjectC
. It depends on both ProjectA
and ProjectB
. And let's assume that I am not aware that ProjectB
depends on ProjectA
already (e.g., I did not create the two before. Or think that ProjectC
actually have many dependencies and I shall not be forced to figure out an exact dependency tree among them).
Anyway, I add both ProjectA
and ProjectB
as git submodules in ProjectC
. So it has the following structure,
ProjectC
CMakeLists.txt
libc.cpp
ProjectA
(git submodule)
CMakeLists.txt
liba.cpp
ProjectB
(git submodule)
CMakeLists.txt
libb.cpp
ProjectA
(git submodule of the submodule ProjectB
)
CMakeLists.txt
liba.cpp
And it has the following CMakeLists.txt
.
cmake_minimum_required(VERSION 2.8.4)
project(C CXX)
add_subdirectory(ProjectA)
add_subdirectory(ProjectB)
add_library(c ${PROJECT_SOURCE_DIR}/libc.cpp)
target_link_libraries(c a b)
Now if I try to run cmake
for ProjectC
, I get the following error.
add_library cannot create target "a" because another target with the same
name already exists....
I understand the reason of this error. It is because ProjectA
is added as a subdirectory twice and all targets created by add_library
is Global. For this particular case, I can fix it by remove add_subdirectory(ProjectA)
in the ProjectC/CMakeLists.txt
. However, consider a situation that ProjectC
has many dependencies, and there might or might not be dependencies among them. From point of view of the developer of ProjectC
, he should not need to care about the inter-dependencies among its own dependencies.
In this situation, what is the best way to have ProjectC
include its dependencies? Having ProjectA
and ProjectB
as a git-submodule in source form is a must. I am aware that I can simply install ProjectA
and ProjectB
somewhere, and ProjectC
only need to find the installed files somewhere. However, if possible, I would like to avoid that kind of solution (for example, if the installation was built with a different ABI than the one used by ProjectC
, incompatibility issues arise). I would like all three projects to be built inside the build tree of ProjectC
.
You can check whether the target a
already exists before calling add_subdirectory
:
if (NOT TARGET a)
add_subdirectory(ProjectA)
endif ()
so that it only adds the subdirectory once for your whole CMake project.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With