Get qmake to execute shell script after build finished on Mac - qt

After my release build is finished I would like to run a script.
I found this question How to execute shell command after compile finished from .pro in QT? but the answer doesn't work for me. I tried adding various modifications of this to my .pro file:
CONFIG(release, debug|release) {
mytarget.target = ./MyScript.sh
mytarget.commands = touch $$mytarget.target
QMAKE_EXTRA_TARGETS +=mytarget
QMAKE_POST_LINK += mytarget
}
But this always results with ":-1: error: mytarget: No such file or directory". Path is correct and 'MyScript.sh' works fine from command line.
Since this works for other people I guess I’m doing something wrong. I use Qt 4.7.2 on Mac.

Path is relative to build directory. If your script is not in your build directory,you have to change path.
Try using ../MyScript.sh
Why are you using target? If your only intent is to execute MyScript.sh after the build, you need only
QMAKE_POST_LINK += ./MyScript.sh

Related

How do I stop Qt Creator placing my executable in a "debug" subdirectory?

I'm building a project in Qt Creator, and while I don't care where the intermediate .obj files go it's important that the final executable be put in (and run from) a particular directory where the many dependency DLLs etc. are to be found.
So, in Qt Creator, I select the 'Shadow Build' option and specify the path to this directory.
What I always find, however, is that instead of being put into this directory, the final executable is always placed into
the_Directory_I_Actually_Want/debug
... which is no use to me because, when I then try to run or debug the program from within Qt Creator, it won't start because the DLLs that it depends on are all in the_Directory_I_Actually_Want and not in the /debug subdirectory.
I've tried setting DESTDIR within my .pro file to the the_Directory_I_Actually_Want, and I've tried setting TARGET within my .pro file to the_Directory_I_Actually_Want/projectName, and I've tried faddling around with the various options that are part of the 'kit' configuration, and nothing seems to let me have any control over this.
Is there a way of doing this, or am I going to have to change the rest of my build system around just for Qt Creator's benefit?
Three years later...
Just use:
CONFIG -= \
copy_dir_files \
debug_and_release \
debug_and_release_target
On Windows you can use DLLDESTDIR variable which specifies where to copy the target dll or exe. Just add this to your .pro :
CONFIG(release, debug|release): DLLDESTDIR += $$PWD/../exec
On Linux you can use QMAKE_POST_LINK variable which contains the command to execute after linking the TARGET together. So it is like:
CONFIG(release, debug|release): QMAKE_POST_LINK += $$quote(cp project $$PWD/../exec)
Here project is the name of the target file which you provide by TARGET = project
These will copy the executable binary to a directory named exec one level upper than the program working directory. You can have your arbitrary path.

How to use qmllint in Qt Creator?

qmllint is a syntax checker for QML files written by KDAB which is shipped as a plugin with Qt 5.4. It's usage is based on command line like:
$ qmllint myFile.qml
Is it possible to use it directly in Qt Creator?
QtCreator
You can actually set custom commands in QtCreator to be run without cluttering your qmake file manually because that will effect all the other people in your project, too.
So, if you want to make sure that you only do it for yourself and not clutter it for others, using QtCreator's shiny GUI, I would suggest to follow this:
Projects (left pane)
Build & Run
Build Steps
Add Build Step
Here is the screen how exactly you can set up the command with the corresponding arguments:
With QtCreator's GUI, you can easily change the order with the same concept without touching your project file should you prefer that. There are use cases for that like:
You would not want to run any steps, not even qmake, before the qml file is properly validated
You only have C++ files, so there is no such a thing as "linkage".
etc.
qmake
There are other "generic" approaches useful outside QtCreator, although you asked about this IDE, like putting the command into variables like:
QMAKE_PRE_LINK
QMAKE_PRE_LINK = qmllint $$PWD/path/to/myFile.qml
QMAKE_POST_LINK
QMAKE_POST_LINK = qmllint $$PWD/path/to/myFile.qml
System command execution from your qmake project file
system("qmllint $$PWD/path/to/myFile.ml")
Adding custom targets with QMAKE_EXTRA_TARGETS
qmllinttarget.commands = qmllint $$PWD/path/to/myFile.qml
QMAKE_EXTRA_TARGETS += qmllinttarget
I believe the point in this question is not to have a check for a single file with known name, but to run qmllint on all qml files of a project. Ideally this should be done before building anything, because a build with erroneous qml files is likely to have no real value.
Extending lpapp's answer and playing around with qmake a bit, I came to this solution:
ALL_PWD_QML_FILES = $$files($${_PRO_FILE_PWD_}/*.qml , true)
# a command that creates an empty file with a given name.
win32 {
MY_TOUCH_CMD = copy NUL
} else {
MY_TOUCH_CMD = touch
}
qmllint.output = .qmllint/${QMAKE_FILE_BASE}.qmllint
qmllint.input = ALL_PWD_QML_FILES
qmllint.commands = qmllint ${QMAKE_FILE_NAME} && $${MY_TOUCH_CMD} ${QMAKE_FILE_OUT}
qmllint.CONFIG += no_link recursive target_predeps
QMAKE_EXTRA_COMPILERS += qmllint
This assumes that all qml files are either in the same directory as the .pro file or in subdirectories.
It will run qmllint on all qml files before the actual build, but only if any qml file has changed since a previous build.
Tested on Windows with Qt 5.11 and MSVC.
You can use QMAKE_POST_LINK variable in your .pro file like :
QMAKE_POST_LINK = qmllint $$PWD/QMLFiles/myFile.qml
This runs qmllint on your QML file when you build your project.

QTCreator copy files to output directory with INSTALLS

I have two sub directories docroot and config in my Qt project. Files in these directories shall be copied to the build directory whenever I build / debug the project.
As of https://stackoverflow.com/a/3991210/356726 this is possible by using INSTALLS (QtDoc), which seems to be much easier than running copy command (e.g here). A similar approach is described here.
config.path = $${DESTDIR}/config
config.files = config/*
docroot.path = $${DESTDIR}/docroot
docroot.files = docroot/*
INSTALLS += config docroot
However, when I run a build in Qt Creator nothing happens. This here says I need to run make install . Can I somehow trigger / do this from within Qt Creator automatically whenever I build. I would need always the latest version of the files.
EDIT: Eventually I have used $$OUT_PWD instead of $$DESTDIR
Original comment from Logan here:
"Just a note: I used $$OUT_PWD instead of $$DESTDIR to make it work. For reference $$OUT_PWD is the folder that the program is built to, and $$PWD is the folder that the program is Being built from -in other words it's where the .pro file is."
What you need is a custom build step.
Switch to Projects Mode: press Ctrl+5.
On Build Settings tab under Build Steps click on Add Build Step.
Choose Make from the menu.
Write install into Make arguments: text input box.
(The version where I checked these is Qt Creator 2.4.1.)
I was using Shadow Build on Window 7 and I ran into the same problem than you.
Moreover, after setting my INSTALLS and running make install I was having the following message :
Nothing to be done for `install'.
The reason is that you have to set $$DESTDIR yourself.
In my case I wanted to copy *.qml files, that's how I achieved it:
# if you are using Shadow build, you need to get the output folder
CONFIG(release, debug|release): DESTDIR = $$OUT_PWD/release
CONFIG(debug, debug|release): DESTDIR = $$OUT_PWD/debug
# if you are using normal build (non-shadow) that would have worked as well.
CONFIG(release, debug|release): DESTDIR = release
CONFIG(debug, debug|release): DESTDIR = debug
QmlFiles.path = $$DESTDIR/Qml
QmlFiles.files += $$files(Qml/*.qml)
INSTALLS += QmlFiles
EDIT :
I figure out that $$OUT_PWD can be use to find the Shadow Build Output path. So, I fixed the code which finally come close to what you were using.

Running a program/script from QMake

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?
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
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

qmake: How do I copy .dll/.so's to the output directory?

I have a Qt-project that builds a dll/shared-library and another Qt-project that tests the library.
Is there any good way to have qmake copy the dll to the output-folder of the test-project?
Add this to your pro file:
target.path = ../testProject/$$TARGET
INSTALLS += target
# Copy the dynamic library.
win32 {
QMAKE_PRE_LINK=copy /Y lib\qextserialport\src\build\qextserialportd.dll debug\ & copy /Y lib\qextserialport\src\build\qextserialport.dll release\
}
else {
# TODO: Unices
}
This works, for the QextSerialPort library. Supports Qt's debug_and_release mode.
QMAKE_POST_LINK also works, but will throw an error if you're trying to run the app immediately: then your .dll will be copied too late. QMAKE_PRE_LINK does copy it in time.
I use INSTALLS, like so. (qmake documentation)
This may not be a 'good' way but it may do the trick.
QMAKE_POST_LINK += some shell command to copy the dll
You can use DESTDIR keyword as it is said in qmake files documetation in Qt 4.
QMAKE_POST_LINK += $$QMAKE_COPY $$quote("yourSrcDir\your.dll") $$quote($$IN_PWD) $$escape_expand(\\n\\t)

Resources