使用未知输出文件CMake ADD_CUSTOM_COMMAND

时间:2015-10-05 13:05:48

标签: c++ cmake

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

1 个答案:

答案 0 :(得分:4)

简介

我认为您的目标不是使用ADD_CUSTOM_COMMAND,而是:

  • cmake识别出您生成的文件取决于生成脚本 这是:当您的生成脚本已更改时,当您下次执行cmake --build时,会使用不同的文件名自动重新生成文件。
  • cmake识别出您的可执行文件/库取决于生成的文件,这些文件的文件名在重新生成后即会更改。 这意味着:由于cmake --build
  • 的相同调用,您的可执行文件/库被重建并使用重新生成的文件

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

您需要获取文件名作为生成脚本的输出,或者使用文件遍历。通常,我不建议使用文件通配,因为它在适当依赖项方面存在一些缺点。在您的情况下,全球化可以增加实际价值,但必须弥补其不利之处。

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

示例性设置

我创建了一个最小设置,可以使所有这些工作正常进行:

myProject
|- CMakeLists.txt
|- main.cpp
|- myClass.h
|- generate.sh

myClass.h

#ifndef MY_CLASS_H
#define MY_CLASS_H
int do_something_a();
int do_something_b();
#endif // MY_CLASS_H

main.cpp

#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;
}

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

#!/usr/bin/env bash

# just creating a new subfolder; remove its contents if already existing
dir1="generated"
if [ ! -d ${dir1} ]; then mkdir ${dir1}; fi
rm -r ${dir1}/*

# just create a cpp file with random name and implement do_something_a()    
var1=`date +%N`
file1=${dir1}/myClass.${var1}.cpp
echo '#include "myClass.h"' > ${file1}
echo 'int do_something_a() { return '${var1}'; }' >> ${file1}

# just create a cpp file with random name and implement do_something_b()
var2=`date +%N`
file2=${dir1}/myClass.${var2}.cpp
echo '#include "myClass.h"' > ${file2}
echo 'int do_something_b() { return '${var2}'; }' >> ${file2}

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})

构建

配置:

../bin/Release$ cmake -G"Unix Makefiles" ../..

输出:

-- 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

内部版本:

../bin/Release$ make

输出:

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

生成的文件:

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

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

../bin/Release$ make

输出:

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

-- 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

执行程序:

../Release/src$ ./useGenerateSourcesAtBuildStep

输出:

A:565834060, B:567160574