使用未知输出文件CMake ADD_CUSTOM_COMMAND

ACB*_*ACB 10 c++ cmake

我有一个工具来生成一些cpp和头文件,并希望使用ADD_CUSTOM_COMMAND添加它以在构建期间自动执行它并将文件添加到项目中.问题是预先不知道(大多数)输出文件的名称.我如何添加这些文件?

tan*_*oal 5

介绍

我假设您的目标不是使用ADD_CUSTOM_COMMAND,而是:

  • cmake 识别出您生成的文件依赖于生成脚本这意味着:当您的生成脚本发生更改时cmake --build,下次执行时会自动重新生成不同文件名的文件。
  • cmake 识别出您的可执行文件/库依赖于生成的文件,一旦这些文件重新生成,其文件名就会更改这意味着:您的可执行文件/库被重建并使用重新生成的文件作为相同调用的结果cmake --build

主要问题是文件名必须在 处已知configuration time,以便依赖项在 处已知build time。这意味着您需要将文件的生成configuration时间移动。

您要么需要获取文件名作为生成脚本的输出,要么使用文件通配符。通常我不推荐使用文件 globbing,因为它在正确依赖方面有一些缺点。在您的情况下,通配符增加了实际价值,但必须弥补劣势。

下面我编译了一个完整的示例项目,它展示了它是如何工作的。我不是说这是标准的做法,但我认为它很好地满足了要求。

示例设置

我创建了一个最小设置,使所有这些工作:

myProject
|- CMakeLists.txt
|- main.cpp
|- myClass.h
|- generate.sh
Run Code Online (Sandbox Code Playgroud)

我的类.h

#ifndef MY_CLASS_H
#define MY_CLASS_H
int do_something_a();
int do_something_b();
#endif // MY_CLASS_H
Run Code Online (Sandbox Code Playgroud)

主程序

#include "myClass.h"
#include <iostream>

int main(const int argc, const char **argv)
{
  int a = do_something_a();
  int b = do_something_b();
    
  std::cout << "A:" << a << ", B:" << b << std::endl;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

generate.sh 只创建 2 个 cpp 文件来实现do_something_a()do_something_b(). 生成的文件名包含一个随机数,该数也由do_something_*()函数返回。文件被放入子目录generated

myProject
|- CMakeLists.txt
|- main.cpp
|- myClass.h
|- generate.sh
Run Code Online (Sandbox Code Playgroud)

CMakeLists.txt

cmake_minimum_required (VERSION 3.10.2)

project(useGenerateSourcesAtBuildStepProj
  VERSION 0.0.0.1
  DESCRIPTION "Minimum Example: Use Generated Files as dependency"
  LANGUAGES CXX
)

# just needed to force re-configuration, if generate.sh has changed.
# that's the tweak to overcome glob disadvantage
configure_file(
  ${CMAKE_CURRENT_SOURCE_DIR}/generate.sh
  ${CMAKE_CURRENT_BINARY_DIR}/generate.sh
)

# regeneration command executed at configuration time
# note: cannot call ${CMAKE_CURRENT_BINARY_DIR}/generate.sh, because not yet existing
execute_process(
  COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/generate.sh
  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)

# globbing all generated files in sub directory `generated` at configuration time after execute_process
FILE(GLOB GENERATED_SRC_FILES ${CMAKE_CURRENT_BINARY_DIR}/generated/*)

# use generated files to build your executable
add_executable(useGenerateSourcesAtBuildStep main.cpp ${GENERATED_SRC_FILES})
target_include_directories(useGenerateSourcesAtBuildStep PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
Run Code Online (Sandbox Code Playgroud)

建造

配置:

../bin/Release$ cmake -G"Unix Makefiles" ../..
Run Code Online (Sandbox Code Playgroud)

输出:

-- The CXX compiler identification is GNU 7.5.0
-- 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done    
-- Configuring done
-- Generating done
-- Build files have been written to: <dir>/bin/Release
Run Code Online (Sandbox Code Playgroud)

建造:

../bin/Release$ make
Run Code Online (Sandbox Code Playgroud)

输出:

Scanning dependencies of target useGenerateSourcesAtBuildStep
[ 25%] Building CXX object CMakeFiles/useGenerateSourcesAtBuildStep.dir/main.cpp.o
[ 50%] Building CXX object CMakeFiles/useGenerateSourcesAtBuildStep.dir/generated/myClass.488106246.cpp.o
[ 75%] Building CXX object CMakeFiles/useGenerateSourcesAtBuildStep.dir/generated/myClass.490335510.cpp.o
[100%] Linking CXX executable useGenerateSourcesAtBuildStep
[100%] Built target useGenerateSourcesAtBuildStep
Run Code Online (Sandbox Code Playgroud)

生成的文件:

|- bin
    |- Release
        |- src
            |- generate.sh (due to configure_file)
            |- generated (directory containing all generated files)
            |   |- myClass.488106246.cpp
            |   |- myClass.490335510.cpp
            |- useGenerateSourcesAtBuildStep (your exectuable)
Run Code Online (Sandbox Code Playgroud)

更改 generate.sh 并使用 make 重建:

../bin/Release$ make
Run Code Online (Sandbox Code Playgroud)

输出:

您可以看到配置步骤再次完成并且生成的文件更改了它们的名称,但在将它们全部链接到您的可执行文件之前重建:

-- Configuring done
-- Generating done
-- Build files have been written to: /home/tangoal/Documents/data/300_Projects/_software/CPP/lib/test/bin/Release
Scanning dependencies of target useGenerateSourcesAtBuildStep
[ 25%] Building CXX object CMakeFiles/useGenerateSourcesAtBuildStep.dir/generated/myClass.565834060.cpp.o
[ 50%] Building CXX object CMakeFiles/useGenerateSourcesAtBuildStep.dir/generated/myClass.567160574.cpp.o

[ 75%] Linking CXX executable useGenerateSourcesAtBuildStep
[100%] Built target useGenerateSourcesAtBuildStep
Run Code Online (Sandbox Code Playgroud)

执行程序:

../Release/src$ ./useGenerateSourcesAtBuildStep
Run Code Online (Sandbox Code Playgroud)

输出:

A:565834060, B:567160574
Run Code Online (Sandbox Code Playgroud)

  • +1 详细答案。一项补充:为了在更改特定文件时强制重新配置,您还可以将该文件标记为配置依赖:`set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS &lt;file&gt;)` (2认同)