1

From my own search, I'm not exactly sure what the "normal" behaviour is: Does CMake normally rebuild .obj-files when a header included in the associated source file changes? Because it doesn't do that in my project at all. Here's my top-level CMakeLists.txt:

cmake_minimum_required(VERSION 3.15 FATAL_ERROR)

enable_language(CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# project and binary name
project("myProjectName")


# compiler specific warnings
# and warnings are treated as errors
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
    "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    set(warnings "-Wall -Wextra -Werror")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
    set(warnings "/W4 /WX /EHsc")
endif()
if (NOT CONFIGURED_ONCE)
    set(CMAKE_CXX_FLAGS "${warnings}"
        CACHE STRING "Flags used by the compiler during all build types." FORCE)
    set(CMAKE_C_FLAGS   "${warnings}"
        CACHE STRING "Flags used by the compiler during all build types." FORCE)
endif()

# default build-type is Debug:

if (NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Debug")
endif()


# =============================
# libraries
# =============================

# external
# eigen numerics library
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
set( EIGEN Eigen3::Eigen )

# some internal libraries here
set( LIB_NAME_1 lib1 )
set( LIB_NAME_2 lib2 )


# =============================
# directory configuration
# =============================

# for finding libraries and such in the project's subdirectories
# all paths are prepended with the project's root directory
set(CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR})

# specifiying output directories 
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# the last one is disabled to allow for tests in a different directory

# include paths
include_directories(
    ${CMAKE_SOURCE_DIR}/include
    ${CMAKE_SOURCE_DIR}/lib # I put header-only libraries there
    ${CMAKE_SOURCE_DIR}/src # for template definitions
)


# =============================
# unit test configuration
# =============================
# enable_testing() sets the internal flag "CMAKE_TESTING_ENABLED" to 1
# add_test() commands are only run when enable_testing() has executed.
# here, it is only executed in debug mode
if(CMAKE_BUILD_TYPE MATCHES Debug)
    enable_testing()
endif()


# the unit test framework used here is "Catch2" (single header file "catch.hpp")
# (https://github.com/catchorg/Catch2)

if ( ${CMAKE_TESTING_ENABLED} )
    message( "-- Tests are enabled" )
    set( UNIT_TEST_LIB catch2 )
endif()


# =============================
# subdir calls
# =============================
# the second parameter specifies the output path for binaries.
# however, the respective CMAKE_XYZ_OUTPUT_DIRECTORY takes precedence
add_subdirectory(lib)
add_subdirectory(src bin)

if ( ${CMAKE_TESTING_ENABLED} )
    add_subdirectory(tests tests)
endif()

and then I have another CMakeLists.txt in lib, src and tests. These contain only addLibrary, addExecutable and targetLinkLibraries commands using the appropriate source files. Except in "tests", where there's also addTest and addCustomCommand to make the unit test executable run after building.

Here's the question: Did I miss something and it should be rebuilding when a header changes (1)? Or is this the normal behaviour (2)?

Possibly related questions:

Rebuilding object files when a header changes

Make doesn't rebuild headers when changed

GCC included header (using -include) changes not detected by CMake

RL-S
  • 734
  • 6
  • 21
  • Only if the headers are added to that target along with the source files. In your case in the subdirs `lib/src/tests`. – super Oct 05 '19 at 09:53

1 Answers1

1

CMake does rebuild object files when headers change, however CMake 3.15 had a bug where it didn't work properly for make targets. I encountered that issue too, and found that it was already reported: https://gitlab.kitware.com/cmake/cmake/issues/19507

It's fixed in 3.15.1, so the solution is to upgrade (and maybe change the cmake_minimum_required to 3.15.1).

mort
  • 704
  • 2
  • 9
  • 21