Home > Software design >  How to configure cmake to recompile a target when a non .cpp source file is modified
How to configure cmake to recompile a target when a non .cpp source file is modified

Time:01-08

If we look at the minimal example below,

cmake_minimum_required(VERSION 3.20)

project(example)

add_executable(${PROJECT_NAME} main.cpp test.txt)

Once the executable target is built, it will only rebuild if main.cpp is modified. If test.txt is modified, it wouldn't rebuild because eventhough test.txt is included as a source for the executable target, it isn't used to compile the executable. Is there any way that we can configure cmake so that when test.txt is modified, it will trigger a rebuild?

The real use case for my application is I have a metal file that is associated with an executable target (e.g. add_executable(${PROJECT_NAME} main.cpp mylib.metal)) and I want to generate mylib.metallib along with the example executable when the target is build. I have something like

add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
                   COMMAND "the command to compile .metal into .metallib")

but this add_custom_command will only be invoked during the first compilation of the executable target, or whenever main.cpp is modified, I want this add_custom_command to be invoked also when mylib.metal is modified. How can this be done?

CodePudding user response:

I think you should try using the DEPENDS option for add_custom_command to specify that your custom command depends on your .metal file. For example, add DEPENDS foo.metal to your add_custom_command call.

There are also some other ways to specify dependencies for a custom command which are documented here:

https://cmake.org/cmake/help/latest/command/add_custom_command.html

CodePudding user response:

One way is to create a custom target and add a custom command to it that will generate your mylib.metallib

cmake_minimum_required(VERSION 3.20)
project(custom_file_target VERSION 1.0.0)

add_executable(main main.cpp) # main target

add_custom_target(
    custom
    DEPENDS ${CMAKE_BINARY_DIR}/mylib.metallib
)

add_custom_command(
    OUTPUT ${CMAKE_BINARY_DIR}/mylib.metallib
    COMMAND echo your command that will create mylib.metallib
    DEPENDS ${CMAKE_SOURCE_DIR}/mylib.metal
)

add_dependencies(main custom)

You can swap main and custom in the last line depending on what dependency ordering you want (main depends on custom or the other way round).

See also my other answer here: https://stackoverflow.com/a/70626372/8088550

If mylib.metallib is actually linkable you can also think about creating an imported library that depends on your custom target, i.e.

cmake_minimum_required(VERSION 3.20)
project(custom_file_target VERSION 1.0.0)

add_executable(main main.cpp) # main target

add_custom_target(
    custom
    DEPENDS ${CMAKE_BINARY_DIR}/mylib.metallib
)

add_custom_command(
    OUTPUT ${CMAKE_BINARY_DIR}/mylib.metallib
    COMMAND echo your command that will create mylib.metallib
    DEPENDS ${CMAKE_SOURCE_DIR}/mylib.metal
)

add_library(mylib STATIC IMPORTED)
set_property(
    TARGET mylib PROPERTY
    IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/mylib.metallib
)
add_dependencies(mylib custom)

target_link_libraries(main PRIVATE mylib)
  •  Tags:  
  • Related