Search code examples
cmakedependencies

CMake: creating object and executable inplace


I have the following setup:

data/
  Makefile
src/
  main.cpp
CMakeLists.txt

The data/Makefile creates a file data/file via the all target.

The src/main.cpp needs to read data/file, e.g.

// src/main.cpp
...
      auto is = std::ifstream{"data/file"};
...

How can I specify that the executable target for src/main.cpp should depend on the output of data/Makefile?


Solution

  • The CMake documentation for add_custom_target states

    Adds a target with the given name that executes the given commands. The target has no output file and is always considered out of date even if the commands try to create a file with the name of the target. Use the add_custom_command() command to generate a file with dependencies. By default nothing depends on the custom target. Use the add_dependencies() command to add dependencies to or from other targets.

    Using that hint I found the following way to work:

    The top-level CMakeLists.txt

    # CMakeLists.txt
    add_subdirectory(data)
    add_executable(my_exec src/main.cpp)
    add_dependencies(my_exec data_files)
    

    The CMakeLists.txt in data/

    # data/CMakeLists.txt
    add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/file
                       COMMAND make all
                       DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Makefile 
                       WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
                       )
    add_custom_target(data_files
                      DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/file)