I'm working on a cross-compilation project with a top-level CMakeLists.txt
file generating Makefile
s. Some of the cross-compiled source code is generated by a host-based code generation tool; since that tool needs a different toolchain, the top-level CMakeLists.txt
uses ExternalProject_Add()
to invoke the code generator subdirectory's CMakeLists.txt
, with BUILD_ALWAYS
set to TRUE
. The code generation targets depend on the code generator target, so during the initial build the code generator is built, and then the code is generated, and then the whole shebang is compiled into the final result.
If I change the source of the code generator then the code generator executable will be properly rebuilt on the next make
. Problem: the dependent code generation targets will NOT be rebuilt. There seems to be no way with an ExternalProject_Add()
target to indicate when/if any dependencies of the target should be rebuilt.
For instance, if the code generator target were configured using Add_Custom_Command()
, then I'd use the OUTPUT
keyword to specify the resulting executable file, and any dependent targets could be configured to automatically rebuild when the code generator executable's timestamp was updated.
(Edit for clarity: after specifying an OUTPUT
file for Add_Custom_Command()
, I'd then create a convenience target using Add_Custom_Target()
whose DEPENDS
keyword referenced the Add_Custom_Command()
's OUTPUT
file. I'd then have the code generation targets depend on this convenience target. But, AFAIK, that won't work for me.)
Is there a way to configure an ExternalProject_Add()
-based target so that dependent targets will be automatically rebuilt when the main target's output changes?
I needed to IMPORT
a target based on the code generator executable. In my top-level CMakeLists.txt
:
# Run next-gen code generation
# Use ExternalProject_Add() because we are building this for the host
# We DO NOT want cross-compile toolchain applied here
set(CODEGEN_EXECUTABLE ${CMAKE_CURRENT_LIST_DIR}/codegen/_build/codegen)
ExternalProject_Add(codegenExecutable
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/codegen
# The two "--unset" options tell it to use the host defaults rather than the configured ones.
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env --unset=CC --unset=CXX ${CMAKE_COMMAND} -H. -B_build
INSTALL_COMMAND ""
BUILD_IN_SOURCE TRUE
EXCLUDE_FROM_ALL TRUE
BUILD_ALWAYS TRUE
)
# Imported target, so that any change in the code generator will result in rerunning the
# code generation.
add_executable(codegen IMPORTED)
set_property(
TARGET codegen
PROPERTY
IMPORTED_LOCATION "${CODEGEN_EXECUTABLE}"
)
add_dependencies(codegen codegenExecutable)
Any of the code generation targets are set to depend on codegen. The first time I build:
codegenExecutable
external project is built, creating the ${CODEGEN_EXECUTABLE}
executablecodegen
target's timestamp is set by the executable's timestampcodegen
are rebuiltWith no changes, subsequent builds do the following:
codegenExecutable
external project is built, but since none of its source has changed the executable isn't rebuilt and doesn't change its timestampcodegen
target's timestamp doesn't changecodegen
aren't rebuiltIf I touch any codegen
source and build, then:
codegenExecutable
external project is built, creating a new ${CODEGEN_EXECUTABLE}
executable with an updated timestampcodegen
target's timestamp is updated by the executable's timestampcodegen
are rebuiltI believe that if I set up an EXPORT
ed target from the codegen
's CMakeLists.txt
then I wouldn't have to hard-code the executable path. A task for the future...