Question

We have a fairly large code-base. The vast majority of the code is compiled using qmake to produce the makefiles. However, there are some sub-projects that get produced by running batch files or running other programs.

I'd like to be able to have everything compiled using qmake, but I can't figure out how to get qmake to simply run a script.

One thing that I've tried is using QMAKE_EXTRA_TARGETS in my pro file, like so:

TEMPLATE = lib
SOURCES = placeholder.cpp
CONFIG += no_link staticlib
batch_runner.target   = placeholder.cpp
batch_runner.commands = my_batch_file.bat
QMAKE_EXTRA_TARGETS   = batch_runner

I then have to have the batch file produce placeholder.cpp like so:

# do the real work here
# ...
# create placeholder.cpp so qmake and nmake are happy
echo // dummy >> placeholder.cpp

This seems to work fine. The trouble is that it is somewhat hokey. If I don't specify batch_runner.target (i.e. I leave it blank) or don't put placeholder.cpp in SOURCES then the batch file never gets run. This is because qmake isn't making batch_runner.commands the action for any other dependency in the Makefile.

Is there any better way to get QMake to construct a Makefile such that a script is run when the Makefile executes?

Was it helpful?

Solution

It looks like QMAKE_POST_LINK works well for this sort of thing.

This seems to get the job done. my_batch_file.bat runs when nmake runs (rather than when qmake runs) and I don't need to do anything funny with placeholder targets or files.

It's quite likely that I don't need all of the items listed in 'CONFIG'.

TEMPLATE = lib
TARGET   = 
CONFIG  += no_link target_predeps staticlib

QMAKE_POST_LINK  = my_batch_file.bat
QMAKE_CLEAN     += batch_output.obj

OTHER TIPS

Try the system() command. For example:

system(pwd)

Here is another solution:

TEMPLATE = aux
OBJECTS_DIR = ./
DESTDIR = ./

first.commands = my_batch_file.bat
QMAKE_EXTRA_TARGETS += first
QMAKE_CLEAN += batch_output.obj

The template aux basically produces a makefile which does nothing when run without specifying a target. The OBJECTS_DIR and DESTDIR variables are set to the current directory to prevent that qmake creates the debug and release directories (it's important to set them to ./ and not just to .; at least on Windows). Then, using QMAKE_EXTRA_TARGETS, we redefine the target first to run the custom command when the makefile is invoked without target.

It's a bit hacky but it gets the job done.

Addition: If you want to prevent the generation of three makefiles (Makefile, Makefile.Debug, Makefile.Release), you can add

CONFIG -= debug_and_release

However, if you use this and depending on how the makefile is invoked (always invoked manually, invoked by parent directory's "subdirs" *.pro file, ...), it might be necessary to create fake debug and release targets to avoid "no rule to make target..." errors. For example:

release.target = release
release-clean.target = release-clean
release-install.target = release-install
[...]
debug.target = debug
debug-clean.target = debug-clean
debug-install.target = debug-install
[...]
QMAKE_EXTRA_TARGETS += release release-clean release-install [...]
QMAKE_EXTRA_TARGETS += debug debug-clean debug-install [...]

You could use the SUBDIRS configuration to run multiple different targets, even from the same makefile. This might work especially well with your extra targets, as a subdir configuration can specific a specific target in the makefile to run (see undocumented qmake for details). In this case, I would put all of the "regular" build commands in one .pro file, the external build commands in another, and a subdirs .pro file to build all of them. I haven't tested anything quite like this, but it should work.

regular.pro:

SOURCES += main.cpp
TARGET = regular.exe

external.pro:

batch_runner.commands = my_batch_file.bat
QMAKE_EXTRA_TARGETS   += batch_runner

other_runner.commands = other_batch_file.bat
QMAKE_EXTRA_TARGETS   += other_runner

do_it_all.pro:

TEMPLATE = subdirs
CONFIG += ordered

regular.file = regular.pro
SUBDIRS += regular

batch.file = external.pro
batch.target = batch_runner
SUBDIRS += batch

other.file = external.pro
other.target = other_runner
SUBDIRS += other
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top