Let’s say there’s the following directory structure:
projects
|
+--lib1
| |
| +-CMakeFiles.txt
|
+--lib2
| |
| +-CMakeFiles.txt
|
+--test
|
+-CMakeFiles.txt
lib1/CMakeFiles.txt:
cmake_minimum_required(VERSION 2.0)
add_library(lib1 STATIC lib1.cpp)
lib2/CMakeFiles.txt:
cmake_minimum_required(VERSION 2.0)
add_subdirectory(../lib1 ${CMAKE_CURRENT_BINARY_DIR}/lib1)
add_library(lib2 STATIC lib2.cpp)
target_link_libraries(lib2 lib1)
test/CMakeFiles.txt:
cmake_minimum_required(VERSION 2.0)
project(test)
add_subdirectory(../lib1 ${CMAKE_CURRENT_BINARY_DIR}/lib1)
add_subdirectory(../lib2 ${CMAKE_CURRENT_BINARY_DIR}/lib2)
add_executable(test main.cpp)
target_link_libraries(test lib1 lib2)
I.e. lib2 depends on lib1 and test depends on both of them. (I know that technically static libraries don’t “link”, but that’s just an example.)
The problem is that with the current setup, lib1 compiles twice – the first time it is within the “test” build directory, and a second time it is within “test/build_directory/lib2/build_directory”. I’d like to avoid that.
I want to be able to add a dependency on lib1, lib2 or both of them (using add_subdirectory) to any project that’s located elsewhere. So moving CMakeFiles isn’t an option. I also want to avoid compiling any library several times.
How can I do that?
Platform: CMake v. 2.8.4 and Windows XP SP3
A top-level CMakeLists.txt file isn’t an option, because I want to keep a clean top-level directory and be able to include libraries in other projects that can be located elsewhere. Because it is Windows, I can’t “install package system-wide” – I don’t want to lose ability to switch compiler on the fly. Utility libraries built with different compilers will use different C runtime libraries/ABI, and as a result will be incompatible.
With CMake, library dependencies are transitive, so you shouldn’t call
add_subdirectorytwice intest/CMakeFiles.txt(nor do you need to listlib1as a dependency oftestsince it is already a dependency oflib2‘s).So you could modify
test‘s CMakeFiles.txt to:Also, you should probably remove the
cmake_minimum_requiredcalls from your non-project CMakeFiles.txt files (the lib ones). For further info, run:This setup will still cause all libs to be recompiled if you add a similar test2 subdirectory and project which depends on
lib1andlib2. If you really don’t want to have a top-level CMakeFiles.txt inprojects/, then you’re stuck with what you’re doing, or you could use either theexportorinstallcommand.exportwould create a file which could beincluded by other projects and which imports the targets into the project which callsinclude.installcould install the libraries to another common subdirectory ofprojects/. Depending on your source directory structure, this could have the benefit of only making the intended library API headers available to dependent projects.However, both of these options require the dependent library projects to be rebuilt (and installed) if they are modified, whereas your current setup includes all the dependent targets in your project, so any change to a source file in a dependent library will cause your
testtarget to go out of date.For further details about
exportandinstall, run: