Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling header files dependencies with cmake

I am using CMake on a small C++ project and so far it works great... with one twist :x

When I change a header file, it typically requires recompiling a number of sources files (those which include it, directly or indirectly), however it seems that cmake only detects some of the source files to be recompiled, leading to a corrupted state. I can work around this by wiping out the project and rebuilding from scratch, but this circumvents the goal of using a make utility: only recompiling what is needed.

Therefore, I suppose I am doing something wrong.

My project is very simply organized:

  • a top directory where all resources sit, the main CMakeLists.txt sits there
  • a "include" directory where all public headers lies (in various subdirectories)
  • a "src" directory where all the subdirectories for sources files are, the src CMakeLists.txt sits there
  • a CMakeLists.txt per subdirectory in the "src" directory

The main directory has:

cmake_minimum_required(VERSION 2.8)  project(FOO)  set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)  # Compiler Options set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++0x -Wall -Wextra -Werror")  include_directories($(FOO_SOURCE_DIR)/include)  add_subdirectory(src) 

The "src" directory:

add_subdirectory(sub1) add_subdirectory(sub2) add_subdirectory(sub3) add_subdirectory(sub4)  add_executable(foo main.cpp)  target_link_libraries(foo sub1 sub2 sub3 sub4) 

Where sub4 depends on sub3 which depends on sub2 which depends on sub1

And an example of a subdirectory (sub3):

set(SUB3_SRCS     File1.cpp     File2.cpp     File3.cpp     File4.cpp     File5.cpp     File6.cpp     )  add_library(sub3 ${SUB3_SRCS})  target_link_libraries(sub3 sub1 sub2) 

I'd be glad if anyone could point my mistake to me, searching here or on CMake didn't yield anything so I guess it's very easy or should work out of the box...

(for reference, I am using cmake version 2.8.2 on MSYS)

EDIT:

Thanks to Bill's suggestion I have checked the depend.make file generated by CMake, and it is indeed lacking (severely). Here is an example:

src/sub3/CMakeFiles/sub3.dir/File1.cpp.obj: ../src/sub3/File1.cpp 

Yep, that's all, none of the includes were referenced at all :x

like image 775
Matthieu M. Avatar asked Sep 18 '11 10:09

Matthieu M.


People also ask

Do you include header files in CMake?

With CMake, adding header include directories to your C++ project is as easy as using your head in football! Heading those C++ include directories is easy with CMake. As you are probably aware, you can include other source files in C++ with the #include pre-processor directive.

What does Add_subdirectory do in CMake?

Add a subdirectory to the build. Adds a subdirectory to the build. The source_dir specifies the directory in which the source CMakeLists.

What are CMake dependencies?

CMake files provided with a software package contain instructions for finding each build dependency. Some build dependencies are optional in that the build may succeed with a different feature set if the dependency is missing, and some dependencies are required.

How do I include a path in CMake?

First, you use include_directories() to tell CMake to add the directory as -I to the compilation command line. Second, you list the headers in your add_executable() or add_library() call.


2 Answers

You should look at the depend.make files in your binary tree. It will be in CMakeFiles/target.dir/depend.make. Try to find one of those that is missing a .h file that you think it should have. Then create a bug report for cmake or email the cmake mailing list.

like image 85
Bill Hoffman Avatar answered Oct 06 '22 12:10

Bill Hoffman


I just hit the same issue. After changing paths in include_directories() from absolute to relative it added appropriate dependencies.

Looks like CMake tries to guess which headers are system and which are project related. I suspect that directories that starts with / passed as -isystem /some/path and thus are not presented in generated dependencies.

If you can't replace ${FOO_SOURCE_DIR} with relative path you can try to calculate relative path using appropriate CMake functions. I.e.:

file(RELATIVE_PATH FOO_SOURCE_REL_DIR      ${CMAKE_CURRENT_SOURCE_DIR}      ${FOO_SOURCE_DIR}/.) include_directories(${FOO_SOURCE_REL_DIR}/include) 
like image 39
ony Avatar answered Oct 06 '22 10:10

ony