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}/srcIs this symbol still visible from the subproject's
.profiles? Or are the parsing contexts of the subprojects completely encapsulated? -
Building on the answer from @SGaist
I learned the
.qmake.conftrick 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.confyou can define paths that all subsequent subdirprofiles can use, and you can combine that withincludeto do things like:!include($$top_srcdir/compiler_flags.pri) { error() }^^ CAVEAT: that snippet assumes you define
top_srcdirin.qmake.confI definitely recommend making failed
includean 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.conffile is the same as that of any.profile?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
qmakefrom 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.conffile in each folder next to the lib's.profile, how would that work? I can useOBJECT_DIRetc. 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
.prito 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.proat 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.proat 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
SUBDIRSprojects, one "app" project (i.e. with"TEMPLATE = app"), and three"TEMPLATE = lib"subprojects.It's actually quite possible to put the
appproject file in the same folder as the top-levelSUBDIRSproject if you use the.filesyntax 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 |__ReleaseHere 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 = LibsThe Libs.pro file:
TEMPLATE = subdirs SUBDIRS = \ A/A_lib.pro \ B/B_lib.pro \ C/C_lib.proHere it was more convenient to just refer directly to the file paths in the
SUBDIRSsection.
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}/libFinally, 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/srcHere 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/DebugThis 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
.profiles withTEMPLATE=subdirsneeded to be parallel to each other, i.e. at the same level relative to theTOP_Project_Dirfolder. 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!
-
R Robert Hairgrove has marked this topic as solved on