11

I have the following CMakeLists.txt:

cmake_minimum_required( VERSION 3.0)
project(addProject)
include (ExternalProject)

set(ExternalProjectCMakeArgs
  -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
  -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/external/genLib
)

ExternalProject_Add(genLib
SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/genLib
BINARY_DIR ${PROJECT_BINARY_DIR}/external/genLib
INSTALL_COMMAND ""
INSTALL_DIR ${PROJECT_BINARY_DIR}/external
CMAKE_ARGS ${ExternalProjectCMakeArgs}
)
add_custom_command( OUTPUT "generated.cpp"
COMMAND ${PROJECT_BINARY_DIR}/external/genLib/genLib "generated.cpp"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

add_executable(add main.cpp ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp)
add_dependencies (add genLib)

first time build is always correct:

mkdir build; cd build; cmake -GNinja ../; ninja

giving the following output:

-- The C compiler identification is GNU 4.4.7
-- The CXX compiler identification is GNU 4.4.7
-- Check for working C compiler using: Ninja
-- Check for working C compiler using: Ninja -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler using: Ninja
-- Check for working CXX compiler using: Ninja -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Devel/scratc/testingExternalProject2/build
41% 5/12@2.7 0: Performing configure step for 'genLib'
-- The C compiler identification is GNU 4.4.7
-- The CXX compiler identification is GNU 4.4.7
-- Check for working C compiler using: Ninja
-- Check for working C compiler using: Ninja -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler using: Ninja
-- Check for working CXX compiler using: Ninja -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Devel/scratc/testingExternalProject2/build/external/genLib
50% 6/12@3.0 0: Performing build step for 'genLib'
50% 1/2@? 1: Building CXX object CMakeFiles/genLib.dir/genLib.cpp.o
100% 2/2@40.2 1: Linking CXX executable genLib
100% 12/12@5.6 0: Linking CXX executable add

Now if I modify a source file in external project: touch ../external/genLib/genLib.cpp

and recompile ninja nothing changes: ninja: no work to do.

I have tested it using make instead of Ninja with exactly same behavior. I also have tested to add DEPENDS clause in my custom_command, which is working for individual files but not the full project (and it seems very hacky to add all source files of the external project as DEPENDS clause...)

Does anyone have more experience using external project and can explain the behavior of cmake decision to rebuild or not dependencies ?

Jeremy Fouriaux
  • 151
  • 1
  • 7

1 Answers1

17

If you can use at least cmake version 3.1, try adding BUILD_ALWAYS 1 to your ExternalProject_Add command:

ExternalProject_Add(genLib
    SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/genLib
    BINARY_DIR ${PROJECT_BINARY_DIR}/external/genLib
    BUILD_ALWAYS 1
    INSTALL_COMMAND ""
    INSTALL_DIR ${PROJECT_BINARY_DIR}/external
    CMAKE_ARGS ${ExternalProjectCMakeArgs}
)

According to the documentation of the ExternalProject_Add command

Enabling this option forces the build step to always be run. This can be the easiest way to robustly ensure that the external project’s own build dependencies are evaluated rather than relying on the default success timestamp-based method. This option is not normally needed unless developers are expected to modify something the external project’s build depends on in a way that is not detectable via the step target dependencies (e.g. SOURCE_DIR is used without a download method and developers might modify the sources in SOURCE_DIR).

Ryan Feeley
  • 597
  • 6
  • 12
  • How can I trigger an external project to be rebuilt on a change of its parameters? Ex: enabling part of it which wasn't enabled the first time it was built. – taranaki Oct 15 '19 at 19:00