qmake SUBDIRS and diamond dependencies
-
I have a project that consists of different sub modules. Some of them have dependencies to others (no circular dependencies). Every sub module has a .pro that looks roughly like this one:
TEMPLATE = subdirs SUBDIRS += \ src \ aSub \ bSub \ src.file = src/src.pro aSub.file = src/a/aSub.pro bSub.file = src/b/bSub.pro src.depends += aSub src.depends += bSub
Comparable to what can be found here: https://wiki.qt.io/SUBDIRS_-_handling_dependencies
Expressed as a graph, some of the dependencies create a "diamond".
For example I have the modules src, a, b, and c.
src depends on a and b.
a and b depend both on c:src / \ a b \ / c
Compiling with 2 or more cores, I get compiler errors like
ln: failed to create symbolic link 'libcLib.so': File exists make[3]: [Makefile.cLib:76: libcLib.so.1.0.0] Error 1 (ignored) ln: failed to create symbolic link 'libcLib.so.1': File exists
This can be seen on both, windows and linux using Qt 5.12.4
The errors can differ, but they all seem to have in common that it looks like that c gets compiled twice, since both a and b have dependencies to it. The dependencies are set in the aSub.pro and bSub.pro files. When compiling with 1 core, the problem does not occur. Adding these dependency information to the src.pro file solves the problem:
TEMPLATE = subdirs SUBDIRS += \ src \ aSub \ bSub \ cSub \ src.file = src/src.pro aSub.file = src/a/aSub.pro bSub.file = src/b/bSub.pro cSub.file = src/c/cSub.pro src.depends += aSub src.depends += cSub aSub.depends += cSub bSub.depends += cSub
Is this the only why to solve it? It can be come every troublesome to keep track of dependencies this way. Is there a better way to solve it?
Kind regards
Hendrik
-
Hi and welcome to devnet forum
When using subdirs template I am typically ordering the sub folders already in the right sequence for compiling.
TEMPLATE = subdirs SUBDIRS += \ cSub \ aSub \ bSub \ src src.file = src/src.pro aSub.file = src/a/aSub.pro bSub.file = src/b/bSub.pro cSub.file = src/c/cSub.pro src.depends += aSub src.depends += cSub src.depends += bSub aSub.depends += cSub bSub.depends += cSub CONFIG += ordered
I am not sure if there is now too much done, but it is working in my cases.
BTW '' is the continuation character and used to concatinate with the next line. Sometimes you have to be careful with it. Anyway I am often using the continuation too much as well ;)
-
@koahnig said in qmake SUBDIRS and diamond dependencies:
CONFIG += ordered
No, please NOT! Don't do that.
Why do you specify dependencies and still use CONFIG+=ORDERED?
Please let the kitten live: https://blog.rburchell.com/2013/10/every-time-you-configordered-kitten-dies.html
-
I don't see a big problem in solving this dependency.
I guess the
src.file = src/src.pro
lines are the problem, as most often has been for me.The best tip I can give you: put all subdirs into a subdirectory with a pro file of the the same name, e.g.
src/
withsrc/src.pro
.In that case, the
sub.file
line is even unneeded!So the problems are most likely the a...c subdirs.
You can manage that with an hierarchy of subdirs:
main.pro (SUBDIRS) SUBDIRS += src src/src.pro (SUBDIRS) SUBDIRS += src aSub bSub cSub src.depends += aSub src.depends += cSub aSub.depends += cSub bSub.depends += cSub src/src/src.pro (app) src/baSub/aSub.pro (lib) src/bSub/bSub.pro (lib) src/cSub/cSub.pro (lib)
I hope you got the idea.
Regards
-
Thank you for the replies.
@aha_1980 : I got the idea, but I still need to manage all the dependencies in the top most project file. I had more in mind that I have a pool of modules that can be reused in different projects. And modules can depend on modules. Over time and with a growing amount of modules it will be inconvenient / difficult to set up all the dependencies. Therefore I would like to avoid it and pull out the dependencies automatically. But as I see it there is no build in way to do it? -
I'm not sure I can follow you. The dependencies for this project (call it ProjA) are now set up correctly.
If you include it in another project, you need to specify the dependencies to ProjA outside, i.e. one level up. However, ProjA is still self-contained.
Or what did you have in mind?
Regards
-
@aha_1980 said in qmake SUBDIRS and diamond dependencies:
@koahnig said in qmake SUBDIRS and diamond dependencies:
CONFIG += ordered
No, please NOT! Don't do that.
Why do you specify dependencies and still use CONFIG+=ORDERED?
Please let the kitten live: https://blog.rburchell.com/2013/10/every-time-you-configordered-kitten-dies.html
Thanks for hint.
Certainly it looked like a tautology to me therefore
@koahnig said in qmake SUBDIRS and diamond dependencies:
I am not sure if there is now too much done, but it is working in my cases.
However, I could get the kitten to fly finally with that "ordered" statement. Afterwards I was overwhelmed by pragmatism. ;)
It was some time back. Therefore, there might have been a bug in the template, if that is possible at all.
-
Hi @koahnig,
as I already wrote in the other post, the whole dependency handling in qmake is very fragile - I learned the hard way
You don't get a warning if you do it wrong, you build will just fail. Also, the wiki page is far from perfect with giving good examples.
Regards
-
@HendrikGerloff said in qmake SUBDIRS and diamond dependencies:
Thank you for the replies.
@aha_1980 : I got the idea, but I still need to manage all the dependencies in the top most project file. I had more in mind that I have a pool of modules that can be reused in different projects. And modules can depend on modules. Over time and with a growing amount of modules it will be inconvenient / difficult to set up all the dependencies. Therefore I would like to avoid it and pull out the dependencies automatically. But as I see it there is no build in way to do it?You do not need to define all dependencies for all of your applications.
I have a bunch of dlls and handle their compilation through one subdirs dlls.pro. Then I have a bunch of .pros (one for each application). All application .pros are summarized in another subdirs template .pro, which is the "main" project file for my handling. There I have only the dependency for each application with the dlls.pro.
The separation suggested by @aha_1980 is basically with my dlls.pro. However, I do not have my source there, which would be quite a nightmere to handle. I have the separate .pros of dlls.pro there. The source origins are handled through self-defined qmake macros. I do not consider this as optimal. The outcome is more shaped by legacy.
Therefore if you start freshly to setup things. I think the separation as suggested by @aha_1980 is certainly a very good approach.
-
@HendrikGerloff
if you want you can check my boilerpalte https://github.com/guerinoni/cpp-qt-project-structure-template.git -
@guerinoni Sorry, but a template using
CONFIG+=ordered
cannot be considered useful!Again: https://blog.rburchell.com/2013/10/every-time-you-configordered-kitten-dies.html
Regads
-
@aha_1980 said in qmake SUBDIRS and diamond dependencies:
@guerinoni Sorry, but a template using
CONFIG+=ordered
cannot be considered useful!Again: https://blog.rburchell.com/2013/10/every-time-you-configordered-kitten-dies.html
Regads
The referenced article is a good read. At least there is an argument that you might kill the multi-core capability with ordered statement.
-
Bad luck.
I am working currently with the large project in question. Basically I am using "CONFIG += ordered" in 2 subdirs template project files. Both statements have been commented out. All remains of previous qmake and adjacent compilations removed. Ran qmake and started build. It stopped pretty quickly. The hierachy is obviously not recognized because make complaints that the recipe for one of the targets is missing.
The same done and either of the statements reactivated. Basically the same problems remain, but certainly with different targets in complaints.I am using
SUBDIRS += statements
.subdir = statements
.depends = statementsEspecially the .depends statements shall be fine.
SUBDIRS += has the sequence of projects from deep down libs up to the applications requiring those libs. That exact sequence I would use when I have to recompile manually.My conclusion remains that the ordered statements are required. When those 2 statements have been reactivated, the whole compilation went smoothly through.
-
Please show your
.pro
file.My conclusion remains that the ordered statements are required.
It is definitely not required(1), and it kills parallel builds. That said, even in some Qt modules (e.g. websockets), you'll find this statement. Replacing it with proper dependency code seems to be an advanced topic ;)
Regards
(1) It took me some time to make the parallel build of a company project sane. The problems occurred because I did not understand the qmake Syntax and had errors within.
-
It is getting ridiculous.
TEMPLATE = subdirs SUBDIRS = App4Dll SUBDIRS += Dll4Dll SUBDIRS += dll_DO_ # where to find the sub projects - give the folders App4Dll.subdir = ./App4Dll Dll4Dll.subdir = ./Dll4Dll dll_DO_.subdir = ./dll_DO_ # what subproject depends on others App4Dll.depends = Dll4Dll Dll4Dll.depends = dll_DO_ CONFIG += ordered
That is all boiled down to the basic functionality. It should do all I need. dll_DO_ is another subdirs template. All sequence stuff is already reversed.
As shown as above qmake is working. When last line is commented, it will not worked anymore.
Error message is:18:59:23: Running steps for project ESAndroid... 18:59:23: Starting: "C:\Qt\5.14.1\android\bin\qmake.exe" E:\Source\Android\E\ES\ESAndroid.pro -spec android-clang "CONFIG+=qtquickcompiler" ANDROID_ABIS="armeabi-v7a" 18:59:23: The process "C:\Qt\5.14.1\android\bin\qmake.exe" exited normally. 18:59:23: Starting: "f:\Android\Sdk4Qt5.14.1\ndk-bundle\prebuilt\windows-x86_64\bin\make.exe" -f r:/build-ESAndroid-Android_for_armeabi_v7a_arm64_v8a_x86_x86_64_Clang_Qt_5_14_1_for_Android-Release/Makefile qmake_all make: *** No rule to make target 'sub---Dll4Dll-qmake_all', needed by 'sub-App4Dll-qmake_all'. Stop. 18:59:23: The process "f:\Android\Sdk4Qt5.14.1\ndk-bundle\prebuilt\windows-x86_64\bin\make.exe" exited with code 2. Error while building/deploying project ESAndroid (kit: Android for armeabi-v7a,arm64-v8a,x86,x86_64 (Clang Qt 5.14.1 for Android)) When executing step "qmake" 18:59:23: Elapsed time: 00:00.
-
@koahnig said in qmake SUBDIRS and diamond dependencies:
App4Dll.subdir = ./App4Dll
Dll4Dll.subdir = ./Dll4Dll
dll_DO_.subdir = ./dll_DO_These are your problems, 99% sure.
Please show the corresponding directory structure, and where all the pro files live.
-
You were pretty fast ;)
Here is the structure. For first dir of folder some entries removed.
Datentrger in Laufwerk E: ist DATA Volumeseriennummer: C265-8340 Verzeichnis von e:\Source\Android\E\ES 26.02.2020 19:11 <DIR> . 26.02.2020 19:11 <DIR> .. 26.02.2020 18:35 <DIR> App4Dll 26.02.2020 19:11 0 aus 25.02.2020 19:01 689 config.xml 28.10.2018 13:36 777 config_xml.in 26.02.2020 18:36 <DIR> Dll4Dll 26.02.2020 15:08 <DIR> dll_DO_ 26.02.2020 18:58 354 ESAndroid.pro 21.02.2020 18:36 101'017 ESAndroid.pro.user 8 Datei(en), 235'801 Bytes 12 Verzeichnis(se), 137'678'741'504 Bytes frei Datentrger in Laufwerk E: ist DATA Volumeseriennummer: C265-8340 Verzeichnis von e:\Source\Android\E\ES\App4Dll 26.02.2020 18:35 <DIR> . 26.02.2020 18:35 <DIR> .. 25.02.2020 16:08 5'376 App4Dll.pro 1 Datei(en), 5'376 Bytes 2 Verzeichnis(se), 137'678'741'504 Bytes frei Datentrger in Laufwerk E: ist DATA Volumeseriennummer: C265-8340 Verzeichnis von e:\Source\Android\E\ES\Dll4Dll 26.02.2020 18:36 <DIR> . 26.02.2020 18:36 <DIR> .. 24.02.2020 13:17 4'063 Dll4Dll.pro 1 Datei(en), 4'063 Bytes 2 Verzeichnis(se), 137'678'741'504 Bytes frei Datentrger in Laufwerk E: ist DATA Volumeseriennummer: C265-8340 Verzeichnis von e:\Source\Android\E\ES\dll_DO_ 26.02.2020 15:08 <DIR> . 26.02.2020 15:08 <DIR> .. 26.02.2020 15:08 2'076 dll_DO_.pro 25.02.2020 19:01 <DIR> EDll 25.02.2020 19:01 <DIR> IDll 25.02.2020 19:01 <DIR> NBDll 25.02.2020 19:01 <DIR> NDll 25.02.2020 19:01 <DIR> NIDll 25.02.2020 19:01 <DIR> NLibDO_ 22.02.2020 12:04 <DIR> QNtp 25.02.2020 19:01 <DIR> RLDO_A 25.02.2020 19:01 <DIR> RLDO_Bs 25.02.2020 19:01 <DIR> RLDO_Br 25.02.2020 19:01 <DIR> RLDO_M 25.02.2020 19:01 <DIR> RLDO_NR 25.02.2020 19:01 <DIR> RLDO_OO 25.02.2020 19:01 <DIR> RLDO_Ssr 25.02.2020 19:01 <DIR> SDll 1 Datei(en), 2'076 Bytes 17 Verzeichnis(se), 137'678'741'504 Bytes frei
-
@koahnig I happened to be around.
So, your subdirs have the same name as your pro files, like
App4Dll/App4Dll.pro
.I repeat it: in this case, the
App4Dll.subdir
line is superflous (and probably wrong, because this is hard to get right).As next step, remove these completely:
App4Dll.subdir = ./App4Dll Dll4Dll.subdir = ./Dll4Dll dll_DO_.subdir = ./dll_DO_
Also remove
CONFIG+=ordered
, clean everything and then rerun qmake and make.It should work.
-
TEMPLATE = subdirs SUBDIRS = App4Dll SUBDIRS += Dll4Dll SUBDIRS += dll_DO_ # where to find the sub projects - give the folders #App4Dll.subdir = ./App4Dll #Dll4Dll.subdir = ./Dll4Dll #dll_DO_.subdir = ./dll_DO_ # what subproject depends on others App4Dll.depends = Dll4Dll Dll4Dll.depends = dll_DO_ #CONFIG += ordered
This does work 8|
You are correct. Unbelievable.
Just ran qmake from creator and it worked. Also did a full compilation of my project.Thanks a lot for the hint.
-
I have modified also dll_DO_.pro which is also based on subdirs template.
The whole compilation with ordered modifier is sped up from approximately 9:30 to around 7:45. Therefore there is a significant increase in compilation speed of about 20-25% on an eight core Windows 64 bit machine for that specific project and tool chain.
However, as it turns out the use of .subdir does not work. I have 15 different subfolders and 1 of them would require the .subdir specification, since the name used in SUBDIRS has been different. However, I had to modify the name in SUBDIRS to make it homogenous with the subprojects. Otherwise the ordered modifier was required.