2
votes

Example source of a binary I want to run before each build, once per add_executable:

#include <stdio.h>

int main(int argc, char *argv[]) {
    for(int i=0; i<argc; ++i)
        printf("argv[%d] = %s\n", i, argv[i]);
    fclose(fopen("foo.hh", "a"));
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(foo_proj)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(SOURCE_FILES main.cpp)
# ---- this line changes ----
add_executable(foo_proj ${SOURCE_FILES})

Attempts:

add_custom_target(create_foo_hh COMMAND /tmp/bin/create_foo_hh)
add_dependencies(${SOURCE_FILES} create_foo_hh)

Error:Cannot add target-level dependencies to non-existent target "main.cpp". The add_dependencies works for top-level logical targets created by the add_executable, add_library, or add_custom_target commands. If you want to add file-level dependencies see the DEPENDS option of the add_custom_target and add_custom_command commands.

execute_process(COMMAND /tmp/bin/create_foo_hh main.cpp)

No error, but foo.hh isn't created.

How do I automate the running of this command?

2

2 Answers

5
votes

execute_process() is invoked at configuration time.

You can use add_custom_command():

add_custom_command(
  OUTPUT foo.hh
  COMMAND /tmp/bin/create_foo_h main.cpp
  DEPENDS ${SOURCE_FILES} /tmp/bin/create_foo_hh main.cpp
  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(foo_proj ${SOURCE_FILES} foo.hh)

That way, foo.hh is a dependency of foo_proj: and your command will be invoked when building foo_proj. It depends on ${SOURCE_FILES} and /tmp/bin/create_foo_hh main.cpp so that it is generated again if one of those files changes.

Regarding paths, add_custom_command() is configured to run in the current build directory to generate the file there, and include_directories() is used to add the build directory to the include dirs.

0
votes

You probably don't want the custom target to depend on your source files (because they aren't targets themselves and are therefore never "run"), but on the target you create with them:

target_add_dependencies(foo_proj create_foo_hh)