Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute output of cmake target as dependency for another

Tags:

c++

cmake

I have the following directory structure:

.
├── CMakeLists.txt
├── generator
│   ├── CMakeLists.txt
│   └── main.cpp
├── include
└── src
    ├── CMakeLists.txt
    └── mylib.cpp

I would like to build generator, then use generator to generate a source file that will be used to build mylib. I tried this:

generator/CMakeLists.txt:

add_executable(gen main.cpp)

add_custom_command(
    OUTPUT
        ${CMAKE_BINARY_DIR}/generated.cpp
    DEPENDS
        gen
    COMMAND
        ${CMAKE_BINARY_DIR}/gen -d /tmp
    VERBATIM
)

src/CMakeLists.txt:

add_library(py-cppast
        ${CMAKE_BINARY_DIR}/generated.cpp
        mylib.cpp)

CMakeLists.txt:

cmake_minimum_required(VERSION 3.1.2)
project(my-project)

add_subdirectory(generator)    
add_subdirectory(src)

However, the command is not executed. Instead, I just get the error:

CMake Error at src/CMakeLists.txt:2 (add_library):
  Cannot find source file:

    /home/....(the cmake binary dir)..../generated.cpp

  Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
  .hxx .in .txx

How can I tell cmake to execute the program I'm building with it? Is this even possible in a single build?

like image 417
Tamás Szelei Avatar asked May 07 '17 21:05

Tamás Szelei


1 Answers

The problem comes from the fact that you are generating the file generated.cpp in one directory and then trying to add it to a target defined in a different directory. CMake only supports adding generated files to targets defined in the same directory scope. The add_custom_command() documentation explicitly mentions this restriction.

You probably want to move the generation of generated.cpp into the src directory. You should also use just the gen target name to refer to the executable to run, not ${CMAKE_BINARY_DIR}/gen which is not going to be correct with all CMake generator types. It would also be better style to use the current binary directory rather than the top level binary directory as the output dir. Your src/CMakeLists.txt should look something like this:

add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp
    DEPENDS gen
    COMMAND gen -d /tmp
    VERBATIM
)
add_library(py-cppast
    ${CMAKE_CURRENT_BINARY_DIR}/generated.cpp
    mylib.cpp
)

CMake will automatically substitute the location of the gen target for you, even though it was defined in a different directory. There are some further subtleties to be aware of when using generated sources, particularly relating to dependencies. You may find this article helpful to fill in some gaps.

like image 117
Craig Scott Avatar answered Nov 08 '22 05:11

Craig Scott