如何创建一个创建自定义make目标的qmake函数?

时间:2016-06-03 12:54:51

标签: c++ qt makefile qmake

我知道我们有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)我们可以创建自定义那些使用defineReplacedefineTest的人。

我试过了:

defineTest(createConvertTask) {
    custom.target = $$1
    custom.input = $$2
    custom.output = $$3
    custom.commands = convert.sh $$2 > $$3
    QMAKE_EXTRA_TARGETS += custom
}

但这不起作用,因为多次调用createConvertTask后,QMAKE_EXTRA_TARGETS将只包含字符串custom的多个副本。

但是,这个

defineTest(createConvertTask) {
    $$1.target = $$1
    $$1.input = $$2
    $$1.output = $$3
    $$1.commands = convert.sh $$2 > $$3
    QMAKE_EXTRA_TARGETS += $$1
}

失败,错误为example.pro:2: error: Left hand side of assignment must expand to exactly one word.

有关如何处理此事的任何想法?

1 个答案:

答案 0 :(得分:3)

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.选项:使用eval()export()

要将变量用作左手表达式,您可以使用eval() function,即“使用qmake语法规则评估字符串的内容”。

eval($${1}.target = $$1)

由于这是在函数内部完成的,因此您需要export()所有变量到全局范围。

eval(export($${1}.target))

之后添加目标并导出QMAKE_EXTRA_TARGETS

QMAKE_EXTRA_TARGETS += $${1}
export(QMAKE_EXTRA_TARGETS)

使用replace function完成后,返回值将添加到自定义convert目标的依赖项中:

convert.target = convert

defineReplace(createConvertTask) {
    eval($${2}_custom.target = $$2)
    eval($${2}_custom.depends = $$1)
    eval($${2}_custom.commands = convert.sh $$1 > $$2)
    eval(export($${2}_custom.target))
    eval(export($${2}_custom.depends))
    eval(export($${2}_custom.commands))

    QMAKE_EXTRA_TARGETS += $${2}_custom
    export(QMAKE_EXTRA_TARGETS)
    return($${2}_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)。