How CMake automatically detects header dependencies
When I run cmake . -B build
it creates the following make target in ./build/CMakeFiles/main.dir/build.make
CMakeFiles/main.dir/main.cpp.o: CMakeFiles/main.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/nikolay/Cpp/Train/Cppref/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object CMakeFiles/main.dir/main.cpp.o"
/usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /home/nikolay/Cpp/Train/Cppref/main.cpp
Pay attention to the -MD compiler option, as
it is used to dump dependencies visible to the preprocessor.
So after the first build it will create ./build/CMakeFiles/main.dir/main.cpp.o.d
with the following content
CMakeFiles/main.dir/main.cpp.o: /home/nikolay/Cpp/Train/Cppref/main.cpp \
/home/nikolay/Cpp/Train/Cppref/header.h
So whenever you change header.h
, the target main.o
will be rebuilt.
CMake get dependent header files like gcc -M
Check the build folder for your CMake project. For each target, CMake should generate a file called C.includecache
. This file contains the include dependency information.
If, for example, you have a main.c
file which is including the stdio.h
and math.h
headers. The C.includecache
file will contain an entry like:
/path/to/main.c
stdio.h
-
math.h
-
CMake - dependencies (headers) between apps/libraries in same project
Here's one possible solution:
Root CMakeLists.txt:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(${PROJECT_NAME})
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)
lib1/CMakeLists.txt:
project(Lib1)
add_library(lib1 lib1.cpp lib1.h)
lib2/CMakeLists.txt:
project(Lib2)
add_library(lib2 lib2.cpp lib2.h)
# Add /lib1 to #include search path
include_directories(${Lib1_SOURCE_DIR})
# Specify lib2's dependency on lib1
target_link_libraries(lib2 lib1)
app/CMakeLists.txt:
project(App)
add_executable(app main.cpp some_header.h)
# Add /lib1 and /lib2 to #include search path
include_directories(${Lib1_SOURCE_DIR} ${Lib2_SOURCE_DIR})
# Specify app's dependency on lib2.
# lib2's dependency on lib1 is automatically added.
target_link_libraries(app lib2)
There are plenty of different ways to achieve the same end result here. For a relatively small project, I'd probably just use a single CMakeLists.txt:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(Test)
add_library(lib1 lib1/lib1.cpp lib1/lib1.h)
add_library(lib2 lib2/lib2.cpp lib2/lib2.h)
add_executable(app app/main.cpp app/some_header.h)
include_directories(${CMAKE_SOURCE_DIR}/lib1 ${CMAKE_SOURCE_DIR}/lib2)
target_link_libraries(lib2 lib1)
target_link_libraries(app lib2)
For further info on the relevant commands and their rationale, run:
cmake --help-command add_subdirectory
cmake --help-command include_directories
cmake --help-command target_link_libraries
CMake cannot figure out header dependencies if build is out-of-source?
If your build directory is a subdirectory of the source directory, then it's not really out-of-source, but a sort of hybrid. The recommended CMake approach is to do proper out-of-source builds where the source and binary directory are totally unrelated. This means they can be siblings or further removed, but neither is a descendant of the other.
CMAKE auto header file dependency
As mentioned in my comment, I have tried out your example and things were working fine: if main.h
was modified then main.c
would be recompiled.
My installation of CMake (version 2.8.0) told me to add
cmake_minimum_required(VERSION 2.8)
to the CMakeLists.txt
file, but that is all of the adjustments I needed.
CMake and issues with header files in subfolders
As the name implies, target_include_directories
only affects one target. So when you set target_include_directories(${PROJECT_NAME} PUBLIC Lib/headers/)
, this adds to the include path for the executable target named ${PROJECT_NAME}
but not to the include path for the library name_of_lib
.
To fix this, you can add the include path for your library in the lower level CMakeLists.txt
:
target_include_directories(name_of_lib PUBLIC headers)
As a bonus, because it's PUBLIC
, this path is also automatically added to any target that depends on name_of_lib
. So in the top-level CMakeLists.txt
, you can remove this line:
target_include_directories(${PROJECT_NAME} PUBLIC Lib/headers/)
Aside, this line looks useless and can probably be removed as well:
target_link_directories(${PROJECT_NAME} PRIVATE Lib/headers/)
Link libraries are not usually placed in headers directories.
Importing header files and linking .a file in CMake
In your primary CMakeLists.txt file you would simply add the following:
target_link_libraries(project skia)
If CMake cannot find the library, you can either do:
target_link_libraries(project /full/path/to/libskia.a)
or:
link_directories(/path/to/libraries)
target_link_libraries(project skia)
Related Topics
How Does Switch Compile in Visual C++ and How Optimized and Fast Is It
Are "Seekp" & "Seekg" Interchangeable
Why Does A%B Produce Sigfpe When B Is Zero
Are There Stackless or Heapless Implementation of C++
C++ - Repeatedly Using Istringstream
A Fast Method to Round a Double to a 32-Bit Int Explained
What Does "Memory Allocated at Compile Time" Really Mean
Differencebetween Packaged_Task and Async
Boost::Flat_Map and Its Performance Compared to Map and Unordered_Map
Difference in Behavior While Using Dynamic_Cast with Reference and Pointers
Is the Ranged Based for Loop Beneficial to Performance
How to Estimate Memory Usage of Std::Map
Should a Move Constructor Take a Const or Non-Const Rvalue Reference
Operator= and Functions That Are Not Inherited in C++
Reduce Flicker with Gdi+ and C++