如未记载的qmake中所述,我在qmake项目文件中声明了一个额外的编译器:
TEST = somefile.h
test_c.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_1.cpp
test_c.input = TEST
test_c.commands = C:/somedir/some.exe /i ${QMAKE_FILE_IN} /o ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_1.cpp
test_c.variable_out = SOURCES
test_c.name = MyTestC
QMAKE_EXTRA_COMPILERS += test_c
Run Code Online (Sandbox Code Playgroud)
这很好用.但我也想生成一个头文件.我可以轻松地创建第二个自定义工具来解析此文件(或文件,如果> 1将在TEST中),但我不想解析每个文件两次.我试过了:
test_c.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_1.cpp \
${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_2.cpp
Run Code Online (Sandbox Code Playgroud)
只是为了测试额外的编译器每次运行可以生成两个文件.我期待像" file somefile_2.cpp doesn't exist" 这样的错误,但项目编译没有错误,第二个输出文件被忽略.在Makefile somefile_2.cpp中不存在.
现在我想到两个变种:
创建一个额外的编译器来生成存档,其中所有需要的输出文件将立即保存.设置tool1.variable_out = TOOL_1_OUT并添加两个额外的编译器,toolN.input = TOOL_1_OUT只需"解压缩"存档文件(每个工具一个)并将它们附加到一些变量.
在这种情况下,每个输入文件将调用三次执行.这不是最佳的,但至少解析器每个文件只运行一次.
尝试.output_function选项.创建一个qmake函数,返回与.output现在相同的名称,但也附加第二个文件名HEADERS.
PS我使用的是MinGW x32 4.7,QtCreator 2.7.1,Qt 5.1.0,C++ 11.
这工作正常(变体#1):
MY_COMP = src/precompiled.h \
src/file2.h
GENERATE_FOLDER = generated/
# build package file
my_build.clean = $${GENERATE_FOLDER}gen_${QMAKE_FILE_BASE}.pack
my_build.depends = [somepath]/my_precompiler.exe
my_build.output = $${GENERATE_FOLDER}gen_${QMAKE_FILE_BASE}.pack
my_build.input = MY_COMP
my_build.commands = [somepath]/my_precompiler.exe /i ${QMAKE_FILE_IN} /o $${GENERATE_FOLDER}gen_${QMAKE_FILE_BASE}.pack
my_build.variable_out = MY_PACKAGES
my_build.name = "package build"
# unpack cpp
my_unpack_cpp.clean = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.cpp
my_unpack_cpp.depends = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h
my_unpack_cpp.output = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.cpp
my_unpack_cpp.input = MY_PACKAGES
my_unpack_cpp.commands = [somepath]/my_precompiler.exe /unpack cpp /i ${QMAKE_FILE_IN} /o $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.cpp
my_unpack_cpp.variable_out = GENERATED_SOURCES
my_unpack_cpp.dependency_type = TYPE_C
my_unpack_cpp.name = "unpack code"
my_unpack_cpp.CONFIG = no_link
# unpack header
my_unpack_h.clean = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h
my_unpack_h.output = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h
my_unpack_h.input = MY_PACKAGES
my_unpack_h.commands = [somepath]/my_precompiler.exe /unpack h /i ${QMAKE_FILE_IN} /o $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h
my_unpack_h.variable_out = HEADERS
my_unpack_h.name = "unpack header"
my_unpack_h.CONFIG = no_link
QMAKE_EXTRA_COMPILERS += my_build my_unpack_h my_unpack_cpp
Run Code Online (Sandbox Code Playgroud)
使用这种技术,每次解析的输出文件数量可能会有所不同,但当然对于项目中的所有文件来说可能是恒定的。
在my_precompiler我解析文件中,如果unpack未保留选项,并将两个文件(cpp + h)构建到两个 QBuffer 中。之后,我只需将构建的数据写入 QFile:
QDataStream ds(&file);
ds.setVersion(QDataStream::Qt_5_1);
ds << qCompress(output_cpp.data(), 9);
ds << qCompress(output_h.data(), 9);
file.close();
Run Code Online (Sandbox Code Playgroud)
事实上,现在 qCompress 无法盈利,因为生成的文件太小而无法压缩,大小超过了头文件 zlib 的大小 - sizeof(.pack) > size(.h + .h)。
拆箱:
QByteArray ba;
QDataStream ds(&file);
ds.setVersion(QDataStream::Qt_5_1);
ds >> ba;
if(unpack != "cpp")
{
ds >> ba;
}
file.close();
ba = qUncompress(ba);
file.setFileName(output);
if(!file.open(QFile::WriteOnly | QFile::Truncate)) return 1;
file.write(ba);
file.close();
Run Code Online (Sandbox Code Playgroud)
生成时:
因此我这样设置:
my_unpack_cpp.depends = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h
Run Code Online (Sandbox Code Playgroud)
因此 /unpack cpp (因此,构建)在构建所需的头文件后执行。和这个:
my_build.depends = [somepath]/my_precompiler.exe
Run Code Online (Sandbox Code Playgroud)
设置构建的包(以及因此生成的 cpp+h)取决于 my_precompiler,因此如果我修改并重建预编译器,所有内容都将被重建。
PS 恕我直言,这些线路在重建之前必须充当清洁工:
my_build.clean = $${GENERATE_FOLDER}gen_${QMAKE_FILE_BASE}.pack
my_unpack_cpp.clean = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.cpp
my_unpack_h.clean = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h
Run Code Online (Sandbox Code Playgroud)
但他们没有:( 目前我忽略了这一点,但现在如果构建 .pack 失败,则使用之前构建的包文件