我有一个工具来生成一些cpp和头文件,并希望使用ADD_CUSTOM_COMMAND添加它以在构建期间自动执行它并将文件添加到项目中。问题是预先不知道(大多数)输出文件的名称。我如何添加这些文件?
答案 0 :(得分:4)
我认为您的目标不是使用ADD_CUSTOM_COMMAND
,而是:
cmake --build
时,会使用不同的文件名自动重新生成文件。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