2

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?

A T
  • 11,788
  • 17
  • 89
  • 150
  • Related: http://stackoverflow.com/questions/25687890/running-a-bash-command-via-cmake – A T Jun 16 '16 at 14:27

2 Answers2

5

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.

piwi
  • 4,928
  • 2
  • 21
  • 45
  • Error:Cannot add target-level dependencies to non-existent target "foo_proj". 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. – A T Jun 16 '16 at 14:34
  • @AT My bad, edited my answer; `foo.hh` has to be specified as a source file when declaring the executable. – piwi Jun 16 '16 at 14:36
  • @AT Could you elaborate? – piwi Jun 16 '16 at 14:52
  • Sorry, that wasn't meant to post, was getting this ready: https://gist.github.com/AlecTaylor/e416efbea8793da599513bf28e7d92d7 - 13 line CMakeLists.txt and 7 line main.cpp. It can't find the symbol `bar`. – A T Jun 16 '16 at 14:55
  • @AT I cannot try to compile your sample, but I guess it is that you have to setup your project to include the generated file; I edited my answer regarding that; also, I'm not sure your echo command properly runs as-is. – piwi Jun 16 '16 at 15:21
1

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)
starturtle
  • 641
  • 7
  • 24