我多次遇到同样的问题。
我完全按照您描述的方式使用它——(即为一组文件运行 "boringFunction(filename.cpp, "filename.cpp"))。
它用于生成将特定文件集中包含的代码“注册”到 std::map 的代码,以处理将用户编写的函数添加到库中而无需动态重新编译整个库或依赖 (可能是新手程序员)用户编写语法正确的 C++ 代码,例如实现类函数。
我已经通过两种方式解决了(基本上是等价的)
1) 一种纯粹的 C++“引导”方法,在编译过程中,make 编译一个简单的 C++ 程序,生成必要的文件,然后调用第二个 makefile,编译临时文件中生成的实际代码。
2) 一种基于 shell 的方法,它使用 bash 完成相同的事情(即使用简单的 shell 命令遍历文件并将新文件输出到临时位置,然后在输出上调用 make)。
函数可以分别输出到一个文件中,也可以输出到一个整体文件中进行第二次编译。
然后,函数可以动态加载(即它们被编译为共享库),或者我可以重新编译所有其余代码,并包含生成的函数。
唯一困难的部分是 (a) 找出唯一注册函数名称的方法(例如,使用预处理器 __COUNTER__ 仅在它是单个整体文件时才有效),以及 (b) 弄清楚如何可靠地调用在主makefile运行之前在makefile中生成函数。
纯 C++ 方法(与例如 bash 相比)的优势在于它可能在默认情况下不具有相同 bash linux shell 的系统上工作(例如 windows 或 macOS),在这种情况下当然会更复杂cmake方法是必要的..
我已经包含了 makefile 的困难部分以供后代使用:
第一个调用的makefile是:
# Dummy to compile filters first
$(MAKECMDGOALS): SCRIPTCOMPILE
make -f Makefile2 $(MAKECMDGOALS)
SCRIPTCOMPILE:
@sh scripts/filter_compiler_single.sh filter_stubs
.PHONY: SCRIPTCOMPILE
scripts/filter_compilr_single.sh 在哪里,例如:
BUILD_DIR="build/COMPILED_FILTERS";
rm -r $BUILD_DIR
mkdir -p $BUILD_DIR
ARGSET="( localmapdict& inputmaps, localmapdict& outputmaps, void*& userdata, scratchmats& scratch, const std::map<std::string,std::string>& params, const uint64_t& curr_time , const std::string& nickname, const std::string& desc )"
compfname=$BUILD_DIR"/COMPILED_FILTERS.cpp"
echo "//// START OF GENERATED FILE (this file will be overwritten!) ////" > $compfname #REV: first overwrites
echo "#include <salmap_rv/include/salmap_rv_filter_includes.hpp>" >> $compfname
echo "using namespace salmap_rv;" >> $compfname
flist=$(find $1 -maxdepth 1 -type f) #REV: add constraint to only find .cpp files?
for f in $flist;
do
compfnamebase=$(basename $f) #REV: includes .cpp
alg=${compfnamebase%.cpp}
echo $f " >> " $compfname
echo "void ""$alg""$ARGSET""{" >> $compfname
echo "DEBUGPRINTF(stdout, \"Inside algo funct "$alg"\");" >> $compfname; #REV: debug...
cat $f >> $compfname
echo "}""REGISTER_SAL_FILT_FUNC(""$alg"")" >> $compfname
done
echo "//// END OF GENERATED FILE ////" >> $compfname
第二个makefile Makefile2是正常的编译指令。
它并不漂亮,我很想找到一种更好的方法来做到这一点,但事实上,即使使用模板或 constexpr(例如一些宏函数接受__FILE__)。这将依赖于用户记住将特定的宏调用添加到他们的函数过滤存根中,这只是增加了额外的不必要的工作并要求引入拼写错误等。