Qt MOC Filename Collisions using multiple .pri files - qt

In order to keep my Qt project somewhat organized (using Qt Creator), I've got one .pro file and multiple .pri files. Just recently I added a class to one of my .pri files that has the same filename as a class that already existed in a separate .pri file.
The file structure and makefiles generated by qmake appear to be oblivious to the filename collision that ensues. The generated moc_* files all get thrown into the same subdirectory (either release or debug, depending) and one ends up overwriting the other. When I try to make the project, I get several warnings that look like this:
Makefile.Release:318: warning: overriding commands for target `release/moc_file.cpp`
And the project fails to link.
Here is a simple example of what I'm talking about.
Directory structure:
+ project_dir
| + subdir1
| | - file.h
| | - file.cpp
| + subdir2
| | - file.h
| | - file.cpp
| - main.cpp
| - project.pro
| - subdir1.pri
| - subdir2.pri
Contents of project.pro:
TARGET = project
TEMPLATE = app
include(subdir1.pri)
include(subdir2.pri)
SOURCES += main.cpp
Contents of subdir1.pri:
HEADERS += subdir1/file.h
SOURCES += subdir1/file.cpp
Contents of subdir2.pri:
HEADERS += subdir2/file.h
SOURCES += subdir2/file.cpp
Is there a way to tell qmake to generate a system that puts the moc_* files from separate .pri files into separate subdirectories?

In subdir1.pri try appending
MOC_DIR = "subdir1/MOCFiles"
Also for subdir2.pri give
MOC_DIR = "subdir2/MOCFiles"
It isn't tested. Just check it out. Hope it will work.
Edit 1 : Where MOCFiles is your desired folder for your moc files to get into.
Edit 2 : I just stopped mentioning with the MOC files directory since that has been asked specifically in the question. But additionally you may also have to add the following to each of the pri files. (Make sure that the folders are different for different *.pri files)
RCC_DIR = "subdir1/RCCFiles"
UI_DIR = "subdir1/UICFiles"
OBJECTS_DIR = "subdir1/ObjFiles"
I believe having multiple pri files can work without collisions by having the same file names. Since you have accepted an answer (which states it is not possible), make the above changes and give a try. Do let know if it isn't working.

Best thing to do is to make sure that all files have a unique name. There are other tools besides qmake which will also break when you try to do what you're doing; you also potentially make it confusing for yourself (e.g. understanding what #include "file.h" does is more difficult).

I have tried this before. The short answer is to name them differently somehow. Another answer would be to treat each subdirectory as a separate library, with its own .pro file, and use a subdirs type to compile all the library directories.
If you really want to investigate a full answer, you can specify the tool to be used for moc. In this situation, you might be able to mangle the name so that a slightly different name is used for the two different files. However, you would then also need to make sure each differently-named file is added to the list of files to compile and link, and the originally-named moc file is not (or your build will fail).

Related

Adding custom commands to existing targets in qmake

Is there a way to specify, in a .pro file, extra commands to be added to a standard target in the Makefile that qmake generates? For example, consider distclean, extra commands might be desired to:
Remove *~ files.
Clean out runtime-generated output files from the source tree.
Etc.
I want to use the normal target and not a custom target because I want this to be completely transparent in my workflow. That is (again using distclean as an example), I don't want to...
... require knowledge in a multi-project setup that certain Makefiles use a custom rule instead of distclean.
... document custom rules, even for stand-alone projects, as distclean is already well-known and intuitive†.
I found How to add custom targets in a qmake generated Makefile?, but this describes adding custom targets (which is already documented, even back in 4.6) rather than adding rules to existing targets. While it does contain some hints, all of them require adding new custom targets, as specifying the same target more than once in a Makefile replaces (not adds) commands from the previous target.
The only thing I could really think of to try was to add target.commands += new commands to the .pro file as a wild guess (e.g distclean.commands += rm \"*~\"). This has no effect.
How can I transparently add custom commands to existing targets with qmake?
† For the distclean example: While maintainer-clean is also on that "standard target" list, in practice I have found it to be rarely used, and in any case qmake doesn't generate it by default; I consider it to be unsuitable.
There are two straightforward ways to accomplish this, depending on how self-contained / portable you want your solution to be and how lenient you want to be with the order of command execution.
Option 1
The first option is to create a custom target in the .pro file for the new commands, then add that target as a prerequisite to the standard target that you are modifying. Going back to the distclean example, let's say you want to add a command to remove all *~ files:
Create a custom target in your .pro file. Note that you have to escape quotes and slashes in .pro files. For example, add:
extraclean.commands = find . -name \"*~\" -exec rm -v {} \\;
Add this target as a dependency of the target you are modifying:
distclean.depends = extraclean
This won't actually modify the distclean rule just yet, as this method can't be used to modify existing rules. However...
Add both your new target and the target you are modifying as extra targets:
QMAKE_EXTRA_TARGETS += distclean extraclean
This will add a second specification of distclean to the Makefile, but this works because you can add dependencies to existing targets in make in separate rules, even though you can't add commands that way. If you were to also specify distclean.commands in your .pro file, you would break the existing distclean by replacing its default recipe.
So, putting that all together, in the .pro file:
extraclean.commands = find . -name \"*~\" -exec rm -v {} \\;
distclean.depends = extraclean
QMAKE_EXTRA_TARGETS += distclean extraclean
Where extraclean is some custom target with the commands you want to add, and distclean is the existing target that you wish to modify.
Pros:
Completely self-contained in a .pro file.
As portable as you can get, leaves the actual Makefile syntax and generation up to qmake.
Cons:
Your new commands aren't appended to the existing recipe. Rather, they happen after all prerequisite targets are satisfied but before the existing recipe. In the distclean example, with the version of qmake that I'm using, this places the commands after the source tree clean but before Makefile itself is deleted (which is the only action the default recipe takes). This is not an issue for this example, but may be an issue for you.
Option 2
The second option is to change the name of the Makefile that qmake generates, and create your own custom Makefile that defers to the generated one, rather than includes + overrides it. This is also a straightforward option; while not as self-contained as option 1, it gives you the ability to execute commands both before and after the default generated recipe.
You don't want to include + override the existing Makefile, because you don't want to replace the default recipes. If you do, you have to re-implement the default, but this can be an issue as that default may change (and you have to keep up with the changes). It's best to let qmake do as much work as possible, and not repeat its work.
To do this:
First, change the name of the file that qmake generates. This can be accomplished by adding a line such as this to the .pro file:
MAKEFILE = RealMakefile
That will cause qmake to output RealMakefile instead of Makefile.
The next step is to create your own Makefile with your custom commands. However, there are some caveats here. First, a full example, again using distclean. In a file named Makefile:
.DEFAULT_GOAL := all
%:
#$(MAKE) -f RealMakefile $#
distclean:
#$(MAKE) -f RealMakefile $#
#find . -name "*~" -exec rm -v {} \;
Some notes about this:
We set .DEFAULT_GOAL because otherwise distclean would be the default. An alternative to this, if you're not comfortable with .DEFAULT_GOAL, is to specify an all rule using #$(MAKE) -f RealMakefile $# as the recipe.
The % target matches any target that isn't otherwise defined in this Makefile. It simply delegates processing to RealMakefile.
The distclean target is where we add our commands. We still need to delegate to RealMakefile, but additional commands can be added both before and after that happens.
Pros:
More control over command order. Commands can be added both before and after the default recipe.
Cons:
Not self-contained in a .pro.
Not as portable: It doesn't leave all Makefile generation up to qmake, and also I'm not actually sure what parts are specific to GNU make here (comments welcome).
So, while this answer may be a little long, both of these methods are very straightforward. I would prefer option 1 unless the command execution order is an issue.
Another solution is to add files you want to delete to the QMAKE_CLEAN and QMAKE_DISTCLEAN qmake variables.
build_tests {
TINYORM_SQLITE_DATABASE = $$quote($$TINYORM_BUILD_TREE/tests/q_tinyorm_test_1.sqlite3)
QMAKE_CLEAN = $$TINYORM_SQLITE_DATABASE
QMAKE_DISTCLEAN = $$TINYORM_SQLITE_DATABASE
}
It is relevant only, when do you know files you want to delete, so in this case, you can not use rm command or some sort of globbing.

qmake: generate include other Makefile in Makefile

Is there a way to tell qmake to add to Makefile an include directive to include other Makefile.
I need at the beginning of generated Makefile added one line:
include custom.inc
Maybe there is just a way to output text to Makfiles from qmake but I could not find.
You can use the undocumented QMAKE_EXTRA_INCLUDES variable, like
QMAKE_EXTRA_INCLUDES += /path/to/your/file.mk
you can define a new target into make file and then tell what that target does:
mytarget.target = .buildfile
mytarget.commands = make -f AnotherMakeFile
QMAKE_EXTRA_TARGETS += mytarget
PRE_TARGETDEPS += .buildfile
last 2 statements add your target .buildfile to Makefile and mytarget to Qt compiling process
here you can get further info: http://qt-project.org/doc/qt-4.8/qmake-environment-reference.html
I haven't found a way to include a Makefile, but I have had a similar problem where I wanted one file to contain a common set of build variables. The solution I came up with was to use the QMake command include(filename.pro) (see QMake reference page). This causes QMake to include another project file. In my case, that contained all of the common settings.

GNU Make global variables updated in sub-makes

I need some help with my Makefile for a project. The source directory looks something like this.
|-- Makefile
|-- drivers
| |-- Makefile
| |-- tty
| |-- Makefile
| |-- console.c
| |-- keyboard.c
|-- kernel
| |-- Makefile
| |-- kmain.c
In the top Makefile, I have exported a variable OBJECTS that I want to populate with object files so I can build and link them together in the top Makefile.
I want to update OBJECTS in, say, drivers/tty/Makefile by doing something like this:
OBJECTS += $(CURDIR)console.o
OBJECTS += $(CURDIR)keyboard.o
But the change to OBJECTS does not bubble up to the top Makefile. I've been looking at the Makefiles in the Linux source tree, and they seem to be doing something similar. However, I can't get it to work. Am I missing something here?
You appear to be using Make recursively, something like
# Makefile:
export OBJECTS :=
all:
$(MAKE) -C drivers/tty
#echo OBJECTS is $(OBJECTS)
# drivers/tty/Makefile:
OBJECTS += $(CURDIR)console.o
all:
whatever
This doesn't work, because each Make has its own OBJECTS; the child Make can't modify variables in the parent Make. It's export, not import/export or share (there's no such thing as import/export or share, I'm just trying to illustrate).
You can get the effect you want by including the other makefiles instead of invoking them:
# Makefile:
OBJECTS :=
all: DRIVERS_TTY
#echo OBJECTS is $(OBJECTS)
include drivers/tty/Makefile
# drivers/tty/Makefile:
OBJECTS += drivers/tty/console.o
DRIVERS_TTY:
whatever
You'll notice there is some unpleasant location-dependency there; drivers/tty/Makefile has "drivers/tty" spelled out inside it, which makes maintenance a pain. There are ways to fix that, once you have this basic include trick working.
When you recursively run make it opens a new subshell for each subsequent call to make so you can't go back up the chain with your exports. One method would be for each call to a submake to append to an object list file and then possibly include that file. A better solution is to probably do something along the lines of having your main makefile include each of these submake files directly instead of calling make on them. This method allows the OBJECTS variable to be built up using the each of the submake files with your OBJECTS += statements. Another added benefit is that you are running just one instance of make instead of multiple submakes which allows make to do better dependency generation. Take a look at "Recursive make considered harmful" http://aegis.sourceforge.net/auug97.pdf
One cool makefile build system that was posted up here before by user Dan Moulding https://stackoverflow.com/users/95706/dan-moulding really showed off a lot of the cool stuff you can do with submake files all while having just one master makefile. Dan's boilermake project is here: https://github.com/dmoulding/boilermake

how to avoid creating Makefile for an subdir in QT pro file

Before compile my program ,I need to compile a 3rd party library,but it is not writen in QT ,it has a Makefile to build itself . so if I write a pro file like this:
TEMPLATE = subdirs
SUBDIRS += image myapp
(image directory is the 3rd party library)
then qmake,make
it always report "Cannot find file: image.pro"
if I write a pro file inside image, it will create a Makefile which will overwrite the original Makefile.
any suggestions?
Thanks in advance
You could try several things, depending on what you want:
Use QMAKE_MAKEFILE to rename the qmake-generated makefile so that is won't overwrite the other one.
do some fancy stuff to create something like a QMAKE_PRE_BUILD sort of thing (this variable does not exist in qmake):
makefile.target = Makefile
makefile.depends += prebuild
prebuild.target = prebuild
prebuild.depends = FORCE
prebuild.commands = #echo before build (to replace)
QMAKE_EXTRA_TARGETS += makefile
QMAKE_EXTRA_TARGETS += prebuild
Source: http://forum.qtfr.org/viewtopic.php?id=10686 (read post two and three (google translate) and keep in mind that "défaut" wich means defect gets translated as default :) )
These should be able to solve the problem you're having.

qt qmake extra compilers with dependencies among generated files

Can qmake handle dependencies of generated source files?
We have a prf file like this:
idl_h.name = Generate .H file for ${QMAKE_FILE_BASE}.idl
idl_h.input = IDLS # variable containing our input files
idl_h.variable_out = HEADERS
idl_h.commands = <command that takes .idl and genrates .h>
idl_h.output = $$IDL_GEN_DIR/${QMAKE_FILE_BASE}.h
QMAKE_EXTRA_COMPILERS += idl_h
This generation works fine and creates .h files at make time. The problem is that the input files ($$IDLS) depend on each other, and are not always built in the correct order. We have something like app.idl, containing:
#include "common.idl"
It seems the following should work
idl_h.depend_command = g++ -EE ... $$IDL_GEN_DIR/${QMAKE_FILE_BASE}.h
but apparently the depend_command is not actually executed.
Another idea would be to parse the dependencies out of the original idl:
idl_h.depends = $$system(cat ${QMAKE_FILE_IN} | grep "^#include" | sed -re 's/#include\s+["<]([^.]+)\.idl[">]/\1.h/')
but it seems my qmake syntax is failing me.
Try adding
idl_h.dependency_type = TYPE_C
to your prf, and drop the .depend_command and .depends

Resources