17

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?

Tom Hennen
  • 4,746
  • 7
  • 34
  • 45

4 Answers4

17

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
Tom Hennen
  • 4,746
  • 7
  • 34
  • 45
9

Try the system() command. For example:

system(pwd)
tshepang
  • 12,111
  • 21
  • 91
  • 136
Arnold Spence
  • 21,942
  • 7
  • 74
  • 67
6

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 [...]
Ignitor
  • 2,907
  • 33
  • 50
1

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
Caleb Huitt - cjhuitt
  • 14,785
  • 3
  • 42
  • 49
  • This has the same problem that I outlined in my original question. The extra target won't run unless the .target is specified (you can't seem to just specify the commands) and the .target needs to actually be required by some other part of the Makefile, otherwise it won't run. – Tom Hennen Sep 02 '10 at 12:12