QMake project dependencies not detecting changes in static libs
-
Re: [SOLVED] Qt Creator - Project dependencies not detecting changes in static libs
Links in the above thread are obsolete, so there is no actual answer.
Advise would be greatly appreciated. -
Hi,
If memory serves well, it should be PRE_TARGETDEPS that you are looking for.
-
PRE_TARGETDEPS is not helping so far. With project files shown below, even with "rebuild" of MyDll, MyStaticLib doesn't get built. And with any source changes in MyStaticLib, MyDll doesn't get rebuilt either. Here is what I have:
**.\MyStaticLib\MyStaticLib.pro** TARGET = MyStaticLib TEMPLATE = lib CONFIG += staticlib CONFIG -= qt SOURCES += ... HEADERS += ... **.\MyDll\MyDll.pro** TARGET = MyDll TEMPLATE = lib CONFIG -= qt INCLUDEPATH += ../MyStaticLib SOURCES += ... HEADERS += ... PRE_TARGETDEPS += ../MyStaticLib LIBS += -lMyStaticLib
Is there something I'm not doing right?
-
If memory serves well, you need to list the actual library not the project.
-
No luck with this experiment either. Building MyDll doesn't trigger building MyStaticLib, and I'm getting "dependent D:\ROOT\output\bin\x64\Debug\MyStaticLib.lib does not exist". But if I build MyStaticLib explicitly, then MyDll builds OK.
BTW, adding TARGET.depends makes no difference either.
Note that I'm placing all generated files (objs, libs, bins) outside of the source tree. Is there a chance that qmake dependency tracking system assumes default locations for the generated files?**.\MyStaticLib\MyStaticLib.pro** TARGET = MyStaticLib TEMPLATE = lib CONFIG += staticlib CONFIG -= qt SOURCES += ... HEADERS += ... **.\MyDll\MyDll.pro** TARGET = MyDll TEMPLATE = lib CONFIG -= qt INCLUDEPATH += ../MyStaticLib SOURCES += ... HEADERS += ... PRE_TARGETDEPS += D:\ROOT\output\bin\x64\Debug\MyStaticLib.lib TARGET.depends += ../MyStaticLib LIBS += -lMyStaticLib
-
No luck with this experiment either. Building MyDll doesn't trigger building MyStaticLib, and I'm getting "dependent D:\ROOT\output\bin\x64\Debug\MyStaticLib.lib does not exist". But if I build MyStaticLib explicitly, then MyDll builds OK.
BTW, adding TARGET.depends makes no difference either.
Note that I'm placing all generated files (objs, libs, bins) outside of the source tree. Is there a chance that qmake dependency tracking system assumes default locations for the generated files?**.\MyStaticLib\MyStaticLib.pro** TARGET = MyStaticLib TEMPLATE = lib CONFIG += staticlib CONFIG -= qt SOURCES += ... HEADERS += ... **.\MyDll\MyDll.pro** TARGET = MyDll TEMPLATE = lib CONFIG -= qt INCLUDEPATH += ../MyStaticLib SOURCES += ... HEADERS += ... PRE_TARGETDEPS += D:\ROOT\output\bin\x64\Debug\MyStaticLib.lib TARGET.depends += ../MyStaticLib LIBS += -lMyStaticLib
There's no reason for the build of MyDLL to trigger other builds unless you are using a SUBDIRS project where you explicitly state the dependencies between projects.
-
Thanks! Full list of dependencies in the top level project did enable changes detection in the static library.
** MyProject.pro ** TEMPLATE = subdirs SUBDIRS += MyStaticLib \ MyDLL \ MyApp MyDLL.depends = MyStaticLib MyApp.depends = MyDLL
One problem remains: how to get full path to the static lib binary when we have only project name. I have $${DESTDIR}, but I don't know how to get output file name (MyStaticLib.lib vs libMyStaticLib.a)
BTW, inability to get full path to the TARGET output file is a big issue for writing QMAKE_POST_LINK. I'm using workaround by manually adding "lib" prefix and file extension depending on platform, but this is definitely a limitation.
Thanks again,
-
The OUT_PWD variable allows you to get the path to where you will find the build artifacts.
-
There is no problem with the output directory, the problem is with the file name.
Project MyStaticLib produces MyStaticLib.lib on Windows, and libMyStaticLib.a on Linux and Mac.
Project MyDLL produces MyDLL.dll on Windows, libMyDLL.so.1.0.0 on Linux, libMyDLL.1.0.0.dylib on Mac.
Is there a way to get these names without ugly workaround of manually adding prefix and extensions? -
I find the dependency handling between sub-projects better/easier with CMake over qmake's .pro projects.
-
If memory serves well, you can use
qtLibraryTarget(your_library_name)
-
qtLibraryTarget doesn't work for me as expected (in Qt 6.3)
**.\MyStaticLib\MyStaticLib.pro** TARGET = MyStaticLib TEMPLATE = lib CONFIG += staticlib CONFIG -= qt SOURCES += ... HEADERS += ... message($$qtLibraryTarget($$TARGET))
While running qmake, I'm getting (on Windows)
Project MESSAGE: MyStaticLib Project MESSAGE: MyStaticLibd Project MESSAGE: MyStaticLib
-
Do you have the same result with Qt 5 ?
-
Have you tried using QMAKE_EXTENSION_SHLIB and QMAKE_EXTENSION_STATICLIB?
-
Have you tried using QMAKE_EXTENSION_SHLIB and QMAKE_EXTENSION_STATICLIB?
@mchinand QMAKE_EXTENSION_STATICLIB could help, but it's defined only in context of MyStaticLib project, while I need it in context of another project that references MyStaticLib through PRE_TARGETDEPS.
Is there any way to export a variable from a project and make it visible on SUBDIRS level? export(variable) didn't work for me.
QMAKE_EXTENSION_SHLIB is less useful since in returns "so" and "dylib", while actual extensions are ".so.1.0.0" and ".1.0.0.dylib". So you still have to have platform specific hacks, which diminishes the whole purpose of this variable. -
Thanks @SGaist and @mchinand for the detailed discussion, let's wrap this up.
Summary
- PRE_TARGETDEPS helps detect changes in static libraries.
- QMake implements MyModule .depends, but it's missing MyModule. target_full_path which makes it inconvenient to use PRE_TARGETDEPS, and especially QMAKE_POST_LINK. Some platform specific hacks are necessary.
Working solution
Here is an example of a complete solution which detects source changes in all modules, including static libraries. The solution uses a project wide hack, which is not that bad after all.=== ./.qmake.conf === # # QMake will find .qmake.conf automatically. # PROJECT_ROOT = $$PWD === ./static_libs.conf === # # Assumes DESTDIR is configured project-wide so all binaries are written to one place. # windows { MyStaticLib_FULL_PATH = $$shell_path($$DESTDIR/MyStaticLib.lib) # ... Other static libraries in the project } else { MyStaticLib_FULL_PATH = $$shell_path($$DESTDIR/libMyStaticLib.a) # ... Other static libraries in the project } === ./MyStaticLib/MyStaticLib.pro === TARGET = MyStaticLib TEMPLATE = lib CONFIG += staticlib SOURCES += ... HEADERS += ... === ./MySharedLib/MySharedLib.pro === TARGET = MySharedLib TEMPLATE = lib INCLUDEPATH += ../MyStaticLib SOURCES += ... HEADERS += ... win32:DEF_FILE = MySharedLib.def LIBS += -lMyStaticLib # # NOTE the below 2 lines. # include($$PROJECT_ROOT/static_libs.conf) PRE_TARGETDEPS += MyStaticLib_FULL_PATH === ./MyApp/MyApp.pro === TARGET = MyApp TEMPLATE = app INCLUDEPATH += ../MySharedLib SOURCES += ... HEADERS += ... LIBS += -lMySharedLib === ./MyProject.pro === TEMPLATE = subdirs SUBDIRS += MyStaticLib \ MySharedLib \ MyApp MySharedLib.depends = MyStaticLib MyApp.depends = MySharedLib