如何创建一个创建自定义 make 目标的 qmake 函数?
How to create a qmake function that creates a custom make target?
我知道我们有 QMAKE_EXTRA_TARGETS
创建新的 makefile 目标,其用法如下(如 http://blog.qt.io/blog/2008/04/16/the-power-of-qmake/ 中所示):
conv.target=convert
conv.input=file.in
conv.output=file.out
conv.commands=convert.sh file.in file.out
QMAKE_EXTRA_TARGETS+=conv
在我的例子中,convert.sh
用于多个文件和目标。我想创建一个带有参数(target_name、input_file、output_file)的方法,它会为我创建任务,这样我就不必重复上面几行。
qmake的文档比较少,或者我没有找到正确的出处,但是据我了解,qmake中有两种函数:replace和test(http://doc.qt.io/qt-5/qmake-language.html#replace-functions),我们可以使用 defineReplace
和 defineTest
创建自定义的。
我试过:
defineTest(createConvertTask) {
custom.target = $
custom.input = $
custom.output = $
custom.commands = convert.sh $ > $
QMAKE_EXTRA_TARGETS += custom
}
但这并没有真正起作用,因为在多次调用 createConvertTask
之后,QMAKE_EXTRA_TARGETS
将只包含字符串 custom
.
的多个副本
然而,这个
defineTest(createConvertTask) {
$.target = $
$.input = $
$.output = $
$.commands = convert.sh $ > $
QMAKE_EXTRA_TARGETS += $
}
失败并出现错误 example.pro:2: error: Left hand side of assignment must expand to exactly one word.
关于如何处理这个问题有什么想法吗?
1.Option: 自定义编译器
像这样使用 custom compiler:
convert.input = LIST_OF_IN_FILES # note: no $$
convert.output = $${SOME_DIR}/${QMAKE_FILE_BASE}.ext
convert.commands = convert.sh ${QMAKE_FILE_IN} > $${SOME_DIR}/${QMAKE_FILE_BASE}.ext
convert.CONFIG += no_link target_predeps
QMAKE_EXTRA_COMPILERS += convert
变量 ${QMAKE_FILE_IN}
包含 当前 输入文件,与 ${QMAKE_FILE_BASE}
相同,但没有扩展名。在这里,输出文件名是根据输入文件生成的。 CONFIG
选项告诉 qmake 不要将输出文件添加到对象列表并将它们添加为主要目标的先决条件。此外,将生成一个 make
目标 compiler_convert_make_all
。
只需添加文件:
LIST_OF_IN_FILES += file1 file2
并制作
make compiler_convert_make_all
此选项还会将所有输出文件添加到 clean
目标(将在 make clean
上删除。
2.Option:使用eval()
和export()
要将变量用作左侧表达式,您可以使用 eval()
function,即 'Evaluates the contents of the string using qmake syntax rules'。
eval($.target = $)
由于这是在函数内部完成的,因此您需要 export()
所有变量到全局范围。
eval(export($.target))
然后添加目标并导出 QMAKE_EXTRA_TARGETS
:
QMAKE_EXTRA_TARGETS += $
export(QMAKE_EXTRA_TARGETS)
完成 replace function,return 值将添加到自定义 convert
目标的依赖项中:
convert.target = convert
defineReplace(createConvertTask) {
eval($_custom.target = $)
eval($_custom.depends = $)
eval($_custom.commands = convert.sh $ > $)
eval(export($_custom.target))
eval(export($_custom.depends))
eval(export($_custom.commands))
QMAKE_EXTRA_TARGETS += $_custom
export(QMAKE_EXTRA_TARGETS)
return($_custom)
}
convert.depends += $$createConvertTask(in_file_1, out_file_1)
convert.depends += $$createConvertTask(in_file_2, out_file_2)
QMAKE_EXTRA_TARGETS += convert
生成的结果Makefile
:
out_file_1: in_file_1
convert.sh in_file_1 > out_file_1
out_file_2: in_file_2
convert.sh in_file_2 > out_file_2
convert: out_file_1 out_file_2
这种方法更灵活,可以扩展以支持可变目标参数(此处为常量 convert
)。
我知道我们有 QMAKE_EXTRA_TARGETS
创建新的 makefile 目标,其用法如下(如 http://blog.qt.io/blog/2008/04/16/the-power-of-qmake/ 中所示):
conv.target=convert
conv.input=file.in
conv.output=file.out
conv.commands=convert.sh file.in file.out
QMAKE_EXTRA_TARGETS+=conv
在我的例子中,convert.sh
用于多个文件和目标。我想创建一个带有参数(target_name、input_file、output_file)的方法,它会为我创建任务,这样我就不必重复上面几行。
qmake的文档比较少,或者我没有找到正确的出处,但是据我了解,qmake中有两种函数:replace和test(http://doc.qt.io/qt-5/qmake-language.html#replace-functions),我们可以使用 defineReplace
和 defineTest
创建自定义的。
我试过:
defineTest(createConvertTask) {
custom.target = $
custom.input = $
custom.output = $
custom.commands = convert.sh $ > $
QMAKE_EXTRA_TARGETS += custom
}
但这并没有真正起作用,因为在多次调用 createConvertTask
之后,QMAKE_EXTRA_TARGETS
将只包含字符串 custom
.
然而,这个
defineTest(createConvertTask) {
$.target = $
$.input = $
$.output = $
$.commands = convert.sh $ > $
QMAKE_EXTRA_TARGETS += $
}
失败并出现错误 example.pro:2: error: Left hand side of assignment must expand to exactly one word.
关于如何处理这个问题有什么想法吗?
1.Option: 自定义编译器
像这样使用 custom compiler:
convert.input = LIST_OF_IN_FILES # note: no $$
convert.output = $${SOME_DIR}/${QMAKE_FILE_BASE}.ext
convert.commands = convert.sh ${QMAKE_FILE_IN} > $${SOME_DIR}/${QMAKE_FILE_BASE}.ext
convert.CONFIG += no_link target_predeps
QMAKE_EXTRA_COMPILERS += convert
变量 ${QMAKE_FILE_IN}
包含 当前 输入文件,与 ${QMAKE_FILE_BASE}
相同,但没有扩展名。在这里,输出文件名是根据输入文件生成的。 CONFIG
选项告诉 qmake 不要将输出文件添加到对象列表并将它们添加为主要目标的先决条件。此外,将生成一个 make
目标 compiler_convert_make_all
。
只需添加文件:
LIST_OF_IN_FILES += file1 file2
并制作
make compiler_convert_make_all
此选项还会将所有输出文件添加到 clean
目标(将在 make clean
上删除。
2.Option:使用eval()
和export()
要将变量用作左侧表达式,您可以使用 eval()
function,即 'Evaluates the contents of the string using qmake syntax rules'。
eval($.target = $)
由于这是在函数内部完成的,因此您需要 export()
所有变量到全局范围。
eval(export($.target))
然后添加目标并导出 QMAKE_EXTRA_TARGETS
:
QMAKE_EXTRA_TARGETS += $
export(QMAKE_EXTRA_TARGETS)
完成 replace function,return 值将添加到自定义 convert
目标的依赖项中:
convert.target = convert
defineReplace(createConvertTask) {
eval($_custom.target = $)
eval($_custom.depends = $)
eval($_custom.commands = convert.sh $ > $)
eval(export($_custom.target))
eval(export($_custom.depends))
eval(export($_custom.commands))
QMAKE_EXTRA_TARGETS += $_custom
export(QMAKE_EXTRA_TARGETS)
return($_custom)
}
convert.depends += $$createConvertTask(in_file_1, out_file_1)
convert.depends += $$createConvertTask(in_file_2, out_file_2)
QMAKE_EXTRA_TARGETS += convert
生成的结果Makefile
:
out_file_1: in_file_1
convert.sh in_file_1 > out_file_1
out_file_2: in_file_2
convert.sh in_file_2 > out_file_2
convert: out_file_1 out_file_2
这种方法更灵活,可以扩展以支持可变目标参数(此处为常量 convert
)。