Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    [SOLVED] Qt Quick SUBDIRS dependency problem

    General and Desktop
    2
    5
    2444
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D
      DRoscoe last edited by DRoscoe

      I have a large Qt Quick SUBDIRS project that is driving me nuts. I can find no clear way of specifying linking dependencies between subprojects. The project consists of many statically linked libraries and a single application which links them all:

      CONFIG += c++11
      TEMPLATE = subdirs

      SUBDIRS +=
      aop_logger
      aop_xml
      aop_serial
      aop_util
      aop_measure
      MathUtilities
      DataCollection
      DebugLogger
      MoreMath
      AvionicsBus
      AircraftDataModel
      WindModel
      TableLookups
      dna
      aop_data
      aop_comm
      tap_data
      configuration
      AtosUtils
      tap_messaging
      BufferedSharedMemory
      aop_interface
      tap_new_display_app

      According to the documentation I was able to find, I configured all of my library subprojects as:

      TEMPLATE = lib
      CONFIG += staticlib create_prl c++11

      I have confirmed that the .PRL files are being created.

      The application project, which is another subproject of the primary SUBDIRS project is configured as:

      TEMPLATE = app
      CONFIG += c++11 link_prl

      QT += qml quick widgets

      SOURCES += $$files(.cpp)
      HEADERS += $$files(
      .hpp)

      RESOURCES += qml.qrc

      QML_IMPORT_PATH =

      include(deployment.pri)

      All of the libraries compile as does the main app project. When Qt tries to link the projects, I get messages like these:

      Undefined symbols for architecture x86_64:
      "dna::Repository::Repository()", referenced from:
      ACE_Singleton<dna::Repository, ACE_Recursive_Thread_Mutex>::ACE_Singleton() in libaop_interface.a(FmcGeneralOutputChannelData.o)

      Here is the .PRO file for libaop_interface.a:

      include(../top_srcdir.pri)
      include(../ace_path.pri)

      QT -= core gui

      TARGET = aop_interface
      TEMPLATE = lib
      CONFIG += staticlib c++11 create_prl link_prl

      INCLUDEPATH += $$aop_srcdir/core/aop_comm
      $$aop_srcdir/core/configuration
      $$aop_srcdir/core/aop_data
      $$aop_srcdir/core/aop_data/nav_db
      $$aop_srcdir/core/aop_data/navigation
      $$aop_srcdir/core/aop_data/route
      $$aop_srcdir/core/aop_data/hazards
      $$aop_srcdir/core/dna
      $$aop_srcdir/core/aop_logger
      $$aop_srcdir/core/aop_interface
      $$aop_srcdir/core/aop_interface/exception
      $$aop_srcdir/core/aop_interface/data_format
      $$aop_srcdir/core/aop_measure
      $$aop_srcdir/core/aop_measure/dimensions
      $$aop_srcdir/core/aop_measure/properties
      $$aop_srcdir/core/aop_measure/units
      $$aop_srcdir/core/aop_serial
      $$aop_srcdir/core/aop_util
      $$aop_srcdir/core/aop_xml
      $$cto4_srcdir
      $$cto4_srcdir/Communication
      $$cto4_srcdir/Communication/AvionicsBus
      $$cto4_srcdir/RouteContainer

      SOURCES += $$files($$aop_srcdir/core/aop_interface/data_format/.cpp)
      SOURCES += $$files($$aop_srcdir/core/aop_interface/exception/
      .cpp)
      SOURCES += $$files($$aop_srcdir/core/aop_interface/*.cpp)

      HEADERS += $$files($$aop_srcdir/core/aop_interface/data_format/.hpp)
      HEADERS += $$files($$aop_srcdir/core/aop_interface/exception/
      .hpp)
      HEADERS += $$files($$aop_srcdir/core/aop_interface/*.hpp)

      unix {
      target.path = /usr/lib
      INSTALLS += target
      }

      The library libdna.a does exist and it has the symbol(s) mentioned above. The problem is that Qt doesn’t know how to link libdna from libaop_interface.a. Since the create_prl and link_prl semantics are supposed to allow Qt to follow library dependencies, I checked the .PRL file for libaop_interface.a and I see the following:

      QMAKE_PRL_BUILD_DIR = /Users/droscoe/Documents/workspace/dar_tap_display_20150209_view/aop/external/build-tap_new_display-Desktop_Qt_5_4_0_clang_64bit-Debug/aop_interface
      QMAKE_PRO_INPUT = aop_interface.pro
      QMAKE_PRL_TARGET = libaop_interface.a
      QMAKE_PRL_CONFIG = lex yacc debug exceptions depend_includepath testcase_targets import_plugins import_qpa_plugin sdk rez qt warn_on link_prl app_bundle incremental global_init_link_order lib_version_first plugin_no_soname clang_pch_style qpa no_mocdepend qt_framework osx macx mac darwin unix posix gcc clang llvm debug x86_64 declarative_debug qml_debug staticlib c++11 create_prl link_prl have_target static staticlib debug_info objective_c thread
      QMAKE_PRL_VERSION = 1.0.0
      QMAKE_PRL_LIBS =

      Notice, the QMAKE_PRL_LIBS line lists no libs. On a hunch, I manually added the path to libdna.a to QMAKE_PRL_LIBS and the problem was resolved. This is not a solution since this PRL will be re-created every time I run make or clean/rebuild the project.

      My questions are:

      1. How can I tell Qt that libaop_interface is dependent on libdna and several other libraries, such that the PRL file contains the correct library paths.

      2. Is there a better/preferred way to do this? I have read that I could modify the .depends of the library, but this only works for makefile-based projects. My project needs to run on Windows, MacOS and iOS and not all of these support make

      I appreciate any help.

      1 Reply Last reply Reply Quote 0
      • sierdzio
        sierdzio Moderators last edited by

        In a SUBDIRS project, you can use the "ordered" configuration to tell qmake to parse and build subdirs in the order they are specified:
        CONFIG+=ordered

        I think this should help you make sure everything is compiled when it should and has all the dependencies.

        (Z(:^

        1 Reply Last reply Reply Quote 0
        • D
          DRoscoe last edited by

          Ordering the build does not solve the problem. The individual libraries all build by themselves, regardless of order. Because they are statically linked, the dependencies are not checked until they are linked at the end. Its the linking at the end that isn't working.

          1 Reply Last reply Reply Quote 0
          • D
            DRoscoe last edited by

            I have some new information. Because some libraries are common to several other libraries, I have .pri files which handle setting up the library dependency information. For example, libdna, which is required by libaop_interface (see original post). Here is what the dna.pri file looks like:

            include (top_srcdir.pri)

            win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../dna/release/ -ldna
            else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../dna/debug/ -ldna
            else:unix: LIBS += -L$$OUT_PWD/../dna/ -ldna

            INCLUDEPATH += $$aop_srcdir/core/dna
            DEPENDPATH += $$aop_srcdir/core/dna

            win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../dna/release/libdna.a
            else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../dna/debug/libdna.a
            else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../dna/release/dna.lib
            else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../dna/debug/dna.lib
            else:unix: PRE_TARGETDEPS += $$OUT_PWD/../dna/libdna.a

            When I include this file in my aop_interface project file, I still have the same problem as stated above. Here is the resulting .PRL file for libaop_interface.a:

            QMAKE_PRL_BUILD_DIR = /Users/droscoe/Documents/workspace/dar_tap_display_20150209_view/aop/external/build-tap_new_display-Desktop_Qt_5_4_0_clang_64bit-Debug/aop_interface
            QMAKE_PRO_INPUT = aop_interface.pro
            QMAKE_PRL_TARGET = libaop_interface.a
            QMAKE_PRL_CONFIG = lex yacc debug exceptions depend_includepath testcase_targets import_plugins import_qpa_plugin sdk rez qt warn_on link_prl app_bundle incremental global_init_link_order lib_version_first plugin_no_soname clang_pch_style qpa no_mocdepend qt_framework osx macx mac darwin unix posix gcc clang llvm debug x86_64 declarative_debug qml_debug staticlib c++11 create_prl link_prl have_target static staticlib debug_info objective_c thread
            QMAKE_PRL_VERSION = 1.0.0
            QMAKE_PRL_LIBS =

            Note that QMAKE_PRL_LIBS is blank. However, if I use the Qt Creator "Add Library" wizard and specify "dna" as an internal library, the resulting .PRL appears to be correct:

            QMAKE_PRL_BUILD_DIR = /Users/droscoe/Documents/workspace/dar_tap_display_20150209_view/aop/external/build-tap_new_display-Desktop_Qt_5_4_0_clang_64bit-Debug/aop_interface
            QMAKE_PRO_INPUT = aop_interface.pro
            QMAKE_PRL_TARGET = libaop_interface.a
            QMAKE_PRL_CONFIG = lex yacc debug exceptions depend_includepath testcase_targets import_plugins import_qpa_plugin sdk rez qt warn_on link_prl app_bundle incremental global_init_link_order lib_version_first plugin_no_soname clang_pch_style qpa no_mocdepend qt_framework osx macx mac darwin unix posix gcc clang llvm debug x86_64 declarative_debug qml_debug staticlib c++11 create_prl link_prl have_target static staticlib debug_info objective_c thread
            QMAKE_PRL_VERSION = 1.0.0
            QMAKE_PRL_LIBS = -L/Users/droscoe/Documents/workspace/dar_tap_display_20150209_view/aop/external/build-tap_new_display-Desktop_Qt_5_4_0_clang_64bit-Debug/aop_interface/../dna/ -ldna

            This makes no sense to me. The effect of including the dna.pri file and using the wizard are virtually identical, yet one method produces the correct behavior and the other does not. Here is what the "Add Library" wizard added to my aop_interface.PRO file:

            win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../dna/release/ -ldna
            else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../dna/debug/ -ldna
            else:unix: LIBS += -L$$OUT_PWD/../dna/ -ldna

            INCLUDEPATH += $$PWD/../../../core/dna
            DEPENDPATH += $$PWD/../../../core/dna

            win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../dna/release/libdna.a
            else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../dna/debug/libdna.a
            else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../dna/release/dna.lib
            else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../dna/debug/dna.lib
            else:unix: PRE_TARGETDEPS += $$OUT_PWD/../dna/libdna.a

            The only difference between the two is the definition of $$aop_srcdir which is defined by including top_srcdir.pri. This is so I have a common starting point for relative paths. I have confirmed that the variable expands to be essentially the exact same location in the source tree, so the behavior baffles me

            1 Reply Last reply Reply Quote 0
            • D
              DRoscoe last edited by

              Ok, I think I have resolved the problem. Apparently, you have to make sure you explicitly tell qmake which libraries you depend on via "Add Library" or other means, such as my approach, which is including a common .pri file. The reason it didn't work before is because I did not re-run qmake after making the change. When I saved the file, It parsed the file, etc, but apparently did not completely rebuild the project files. The project previously built and run, but I was apparently not actually referencing any external library functions from my application and Qt was smart enough to know that there were no dependencies introduced. It wasn't until my application actually tried to use an imported library function that it started complaining.

              The documentation in this regard is really rather vague and I have found myself having to plod through, trying to figure this things out as I went along. In hindsight it makes sense that I should have to explicitly spell out the dependencies, otherwise how will qmake know what to add to the PRL file?

              1 Reply Last reply Reply Quote 0
              • First post
                Last post