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,
ProjectBCMakeLists.txtlibb.cppProjectA(git submodule)CMakeLists.txtliba.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,
ProjectCCMakeLists.txtlibc.cppProjectA(git submodule)CMakeLists.txtliba.cpp
ProjectB(git submodule)CMakeLists.txtlibb.cppProjectA(git submodule of the submoduleProjectB)CMakeLists.txtliba.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.