QMAKE: Visibility of variables defined in .pro file with SUBDIRS
-
I am using Qt Creator with QMake, latest version 17.0.2.
If I have a top-level .pro file with TEMPLATE = SUBDIRS, and I define a variable like this:
SOURCE_DIR = $${PWD}/src
Is this symbol still visible from the subproject's
.pro
files? Or are the parsing contexts of the subprojects completely encapsulated? -
Building on the answer from @SGaist
I learned the
.qmake.conf
trick from here: https://wiki.qt.io/QMake-top-level-srcdir-and-builddirAnd I also honed my SUBDIRS approach further with help from: https://www.toptal.com/qt/vital-guide-qmake
Once you have a top-level
.qmake.conf
you can define paths that all subsequent subdirpro
files can use, and you can combine that withinclude
to do things like:!include($$top_srcdir/compiler_flags.pri) { error() }
^^ CAVEAT: that snippet assumes you define
top_srcdir
in.qmake.conf
I definitely recommend making failed
include
an error (as in the preceding snippet).Many examples simplify to
include(../commonthing.pri)
, which can silently fail. -
@KH-219Design and @SGaist : Thank you very much! This is fantastic information. I assume that the syntax of the
.qmake.conf
file is the same as that of any.pro
file?I think my main problem is still not quite solved. I have a project where the directory structure looks like this:
Project_Dir |__app <== (under source-code management) |__src |__app.pro <== has "TEMPLATE=app" MyApp.pro <== has "TEMPLATE=subdirs", but is this OK?? |__3rd_party <== (also under SCM, but in a different repository) |__A_lib |__src A_lib.pro |__B_lib |__src B_lib.pro |__C_lib |__src C_lib.pro |__build <== (not under SCM) |__<QtVersion> |__Debug <== build folders for "MyApp" |__Release <== "" |__libs <== (build folder for "A_lib + B_lib + C_lib"
Each of the 3rd party projects is built as a static library. Presently, I have the default build folder in Qt Creator defined so that up to now, everything in 'MyApp' is built in the correct folder under 'Project_Dir/build'. But I include the source code of the libraries directly and up to now was not making static libraries. I can change the build folder for each of the libraries to get what I want, but I have to do that manually in Qt Creator for each library (only the Release configuration is built for the libraries).
How can I prevent
qmake
from creating a "build" folder for the libraries under the "3rd_party" folder which is under SCM and direct it to build under "Project_Dir/build/<QtVersion>/libs" instead, without requiring a manual edit of the shadow build folder in Qt Creator? Even with a.qmake.conf
file in each folder next to the lib's.pro
file, how would that work? I can useOBJECT_DIR
etc. to keep out the artifacts of the build, but the directory itself will be created to contain the Makefile.Maybe SUBDIRS is not the right way to do this, but using
.pri
to include the library projects instead of using subprojects? -
I would avoid having build directories within the sources at all.
You can use the OUT_PWD variable to abstract the actual build path to put your librairies where you want them.
You have yourMyApp.pro
at the wrong level. It should be at the root of your project sources so you can also properly set the build order to have first the static libraries and only after your application built. -
I would avoid having build directories within the sources at all.
You can use the OUT_PWD variable to abstract the actual build path to put your librairies where you want them.
You have yourMyApp.pro
at the wrong level. It should be at the root of your project sources so you can also properly set the build order to have first the static libraries and only after your application built.@SGaist said in QMAKE: Visibility of variables defined in .pro file with SUBDIRS:
I would avoid having build directories within the sources at all.
I probably didn't explain the setup as well as I should have, but this is exactly what I am trying to achieve.
-
@SGaist said in QMAKE: Visibility of variables defined in .pro file with SUBDIRS:
I would avoid having build directories within the sources at all.
I probably didn't explain the setup as well as I should have, but this is exactly what I am trying to achieve.
@Robert-Hairgrove I suspected that but I thought it was worth mentioning.
-
I have found a solution which involves two top-level
SUBDIRS
projects, one "app" project (i.e. with"TEMPLATE = app"
), and three"TEMPLATE = lib"
subprojects.It's actually quite possible to put the
app
project file in the same folder as the top-levelSUBDIRS
project if you use the.file
syntax on the target dependencies.Here is the directory structure, similar to my other post above, but a little different:
TOP_Project_Dir |__3rd_party |__A |__src |__A_lib.hpp |__A_lib.cpp A_lib.pro |__B <== (similar to A) |__C <== (similar to A) Libs.pro .qmake.conf |__app |__lib |__src App.pro Project.pro .qmake.conf |__build |__Project |__Qt-<version> |__Debug |__Release
Here is the top-level Project.pro file:
TEMPLATE = subdirs SUBDIRS = Libs App lessThan(QT_MAJOR_VERSION,6):CONFIG+=ordered APP_DIR = $$top_srcdir THIRD_DIR = $$clean_path($${APP_DIR}/../3rd_party) Libs.file = $${THIRD_DIR}/Libs.pro App.file = $${APP_DIR}/App.pro App.depends = Libs
The Libs.pro file:
TEMPLATE = subdirs SUBDIRS = \ A/A_lib.pro \ B/B_lib.pro \ C/C_lib.pro
Here it was more convenient to just refer directly to the file paths in the
SUBDIRS
section.
The A_lib.pro file (and almost exactly the same for B and C libraries):CONFIG -= qt TEMPLATE = lib CONFIG += static c++17 release SOURCES += \ src/A_lib.cpp HEADERS += \ src/A_lib.hpp TARGET = A PROJECT_DIR = $$clean_path($${top_srcdir}/../) APP_DIR = $${PROJECT_DIR}/app DESTDIR = $${APP_DIR}/lib
Finally, the App.pro file:
CONFIG -= qt TEMPLATE = app TARGET = MyApp CONFIG += c++17 console APP_DIR = $${top_srcdir} LIB_DIR = $${APP_DIR}/lib SRC_DIR = $${APP_DIR}/src THIRD_DIR = $$clean_path("$$top_srcdir/../3rd_party") OBJECTS_DIR = $${top_builddir}/.obj MOC_DIR = $${top_builddir}/.moc RCC_DIR = $${top_builddir}/.qrc UI_DIR = $${top_builddir}/.ui DESTDIR = $${top_builddir}/exec SOURCES += $${SRC_DIR}/theApp.cpp LIBS += -L"$${LIB_DIR}" -lA -lB -lC INCLUDEPATH += \ $${THIRD_DIR}/A/src \ $${THIRD_DIR}/B/src \ $${THIRD_DIR}/C/src
Here is the source of A_lib.hpp and A_lib.cpp which is about the same for B and C:
// A_lib.hpp #ifndef A_HPP #define A_HPP namespace A { void whoAmI(); } #endif // A_lib.cpp #include "A_lib.hpp" #include <iostream> namespace A { void whoAmI() { using namespace std; cout << "I'm in A lib" << endl; } }
Finally, theApp.cpp file:
#include "A_lib.hpp" #include "B_lib.hpp" #include "C_lib.hpp" int main() { A::whoAmI(); B::whoAmI(); C::whoAmI(); }
In the Qt Creator "Default Build Properties" under "Build & Run", I have this template set for the default build directory:
../build/%{Project:Name}/Qt-%{Qt:Version}/%{BuildConfig:Name}
This gives me for my little project this build directory in Debug mode:
$HOME/code/TOP_Project_Dir/build/Project/Qt-5.15.13/Debug
This is nice because "TOP_Project_Dir/3rd_party" and "TOP_Project_Dir/app" are under source-code management ("SCM", I am using Fossil for the real project) but in two different repositories, and everything under "build" gets ignored.
The information @KH-219Design and @SGaist gave me was important to making this work. The sticking point, though, was that both of the top-level
.pro
files withTEMPLATE=subdirs
needed to be parallel to each other, i.e. at the same level relative to theTOP_Project_Dir
folder. These also need to be under SCM, so if one was on a different level, the build output of one would have gotten in the way of the other.Marking this now as SOLVED!
-