add_custom_command — update dependency list over rebuilds

不羁的心 提交于 2019-12-04 13:03:46
Antonio

Can you show how you initialize the variable codegenInputFiles? You can probably use a file(GLOB ... ) or file(GLOB_RECURSE ... ) command there. See documentation.

Note, though, that you will have to rerun cmake to have your command being generated. Are you working with git? Then you can have a hook that forces a cmake call every time you pull (so that if somebody modified the codegenInputFiles your auto generated files will be updated).


After clarification of the problem, you should be able to find a workaround by using IMPLICIT_DEPENDS instead of DEPENDS. Limitations:

  1. It can only work if your input file is C/C++ (check the syntax, as you must specify the language for each file specified)
  2. You might need to check your cmake version supports that command, even though it looks that it has been around for a while
  3. It's only supported for Makefile generator, which sounds pretty bad...

EDIT

After some iterations, I finally got what is your problem. I propose the following solution: separate the file generation in a separate cmake subproject. When you will build your main project (by calling make), you will trigger both cmake and make for your subproject. Calling cmake is necessary for keeping updated the dependencies, while calling make to actually build your auto-generated sources.

Here I show an example of a project and a subproject, with the project invoking cmake and make for the subproject.

Structure:

.
├── CMakeLists.txt
├── a.cpp
├── build
└── subProject
    └── CMakeLists.txt

File content

./CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)

add_custom_target(subProjectTarget ALL)
add_custom_command(TARGET subProjectTarget PRE_BUILD COMMAND mkdir -p ${CMAKE_BINARY_DIR}/subProject && cd ${CMAKE_BINARY_DIR}/subProject && ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/subProject && make)

include_directories(${CMAKE_BINARY_DIR}/subProject)
add_executable (dummy a.cpp)
add_dependencies (dummy subProjectTarget)

./a.cpp (Note that b.h doesn't exist yet)

#include "b.h"

int main () {
}

./SubProject/CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
file(WRITE ${CMAKE_BINARY_DIR}/b.h "//I am a dummy file\n")

Building the project (using default make)

me@here:~/example/build$ cmake ..
-- The C compiler identification is GNU 4.8.2
-- The CXX compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/example/build

me@here:~/example/build$ make
Scanning dependencies of target subProjectTarget
-- The C compiler identification is GNU 4.8.2
-- The CXX compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/example/build/subProject
[  0%] Built target subProjectTarget
Scanning dependencies of target dummy
[100%] Building CXX object CMakeFiles/dummy.dir/a.cpp.o
Linking CXX executable dummy
[100%] Built target dummy

Note that the second time the cmake calls is on the subproject.

At the next call everything is even faster:

me@here:~/example/build$ make
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/example/build/subProject
[  0%] Built target subProjectTarget
Scanning dependencies of target dummy
[100%] Building CXX object CMakeFiles/dummy.dir/a.cpp.o
Linking CXX executable dummy
[100%] Built target dummy

(Although here the file b.h is written every time causing a.cpp to be recompiled)

This stub can be very much improved by using cmake commands to generate the output directories (and not mkdir) and cascading the generator chosen for the main project (here I am assuming everything is using make)

Let me know if you need any further clarification.

I think that ${codegenInputFiles} should contain a list of hardcoded source files and include files required by the custom command. Documentation of file(GLOB ...) states:

We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.

The hard work (for which we are paid) is to keep the ${codegenInputFiles} up to date (causing the full project rebuild). Anyway, you would have similar problem if someone created a new source file and hadn't added it to the ${codegenInputFiles}, right? So I believe the additional dependency on include file should be treated the same.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!