I know that we have QMAKE_EXTRA_TARGETS
to create new makefile targets, that is used as follows (as seen in 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
In my case, convert.sh
is used for multiple files and targets. I would like to create a method with arguments (target_name, input_file, output_file), that creates the task for me, so that I don't have to repeat the above lines.
The documentation on qmake is quite lacking, or I haven't found the correct source, but to my understanding, there are two types of functions in qmake: replace and test (http://doc.qt.io/qt-5/qmake-language.html#replace-functions) and we can create custom ones using defineReplace
and defineTest
.
I have tried:
defineTest(createConvertTask) {
custom.target = $$1
custom.input = $$2
custom.output = $$3
custom.commands = convert.sh $$2 > $$3
QMAKE_EXTRA_TARGETS += custom
}
but that doesn't really work, as after calling createConvertTask
multiple times, QMAKE_EXTRA_TARGETS
will just contain multiple copies of the string custom
.
However, this
defineTest(createConvertTask) {
$$1.target = $$1
$$1.input = $$2
$$1.output = $$3
$$1.commands = convert.sh $$2 > $$3
QMAKE_EXTRA_TARGETS += $$1
}
fails with error example.pro:2: error: Left hand side of assignment must expand to exactly one word.
Any ideas on how to approach this?
Use a custom compiler like this:
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
The variables ${QMAKE_FILE_IN}
contains the current input file, same as ${QMAKE_FILE_BASE}
but without extension. Here, the output filenames are generated out of the input files. The CONFIG
options tell qmake not to add the output files to the objects list and to add them as prerequisites of the main target. Additionally a make
target compiler_convert_make_all
will be generated.
Just add files:
LIST_OF_IN_FILES += file1 file2
and make
make compiler_convert_make_all
This option also adds all output files to the clean
target (will be deleted on make clean
.
eval()
and export()
To use variables as left hand expression you can use the eval()
function, that 'Evaluates the contents of the string using qmake syntax rules'.
eval($${1}.target = $$1)
Since this is done inside a function you need to export()
all variables to the global scope.
eval(export($${1}.target))
Afterwards add target and export QMAKE_EXTRA_TARGETS
as well:
QMAKE_EXTRA_TARGETS += $${1}
export(QMAKE_EXTRA_TARGETS)
Complete with a replace function, the return value will be added to the dependencies of the custom convert
target:
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
The results in the generated 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
This approach is more flexible and can be extended to support the a variable target parameter (here constant convert
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With