Multi-library projects



  • I have an application that requires many libraries. I need to ensure that the libraries are built prior to the main executable, so they can be linked in. Some of the libraries have dependencies on other libraries, so they will need to have their dependencies built in advance as well.

    How do I accomplish this effectively with Qt using .pro files and qmake? I have an implementation that works using a SUBDIRS project template, but I get build warnings that apparently no one else has ever seen, so I must be doing something wrong.

    Thanks!



  • in linking the order of how you link is important. if you can share what types of errors you get we can investigate more into that.



  • @asanka424 Order is important because I found that Qt was not very good at figuring it out on its own, even with generated .prl files.

    I have a SUBDIRS project which includes several subdirectories. Each has its own .pro file and produces a statically linked library.

    CONFIG += c++11 ordered
    TEMPLATE = subdirs
    
    SUBDIRS += \
        aop_logger \
        aop_xml \
        aop_serial \
        aop_util \
        aop_measure \
        MoreMath \
        MathUtilities \
        DataCollection \
        DebugLogger \
        BufferedSharedMemory \
        AvionicsBus \
        AircraftDataModel \
        WindModel \
        TableLookups \
        configuration \
        AtosUtils \
        dna \
        aop_data \
        aop_comm \
        tap_data \
        tap_messaging \
        RouteContainer \
        arinc_io_adapter \
        aop_interface \
        tap_display_app
    

    The final subdirectory is the main application, which links in all the other libraries.

    Here's an example of one of the sub-projects:

    include(../top_srcdir.pri)
    
    QT       -= core gui
    
    TARGET = aop_logger
    TEMPLATE = lib
    CONFIG += staticlib create_prl link_prl c++11
    INCLUDEPATH += $$aop_logger_includes
    
    HEADERS += $$files($$aop_srcdir/core/aop_logger/*.hpp)
    SOURCES += $$files($$aop_srcdir/core/aop_logger/*.cpp)
    
    # target link libraries
    include(../ace_lib.pri)
    
    unix {
        target.path = $$PWD/lib
        INSTALLS += target
    }
    

    So, starting from the root directory, which contains my top-level .pro file (the SUBDIRS project), i issue:

    qmake -spec macx-xcode -recursive
    

    When I do this, I get a warning for every sub-project:

    WARNING: QMAKESPEC does not support multiple BUILDS
    

    When I open up the project in Xcode, I have to manually select the main executable project each time, as it doesn't know what the main project is, but everything else seems to work.


  • Qt Champions 2016

    @DRoscoe
    Hello,

    Order is important because I found that Qt was not very good at figuring it out on its own, even with generated .prl files.

    If you're building everything statically, as it seems to be the case from your example .prl-s are neither useful nor linked, since a static lib is a collection of translation units and nothing more. My advice, although unsolicited, is to start building your libraries dynamically instead of making one monster executable. Additionally, you don't seem to use Qt at all, only the qmake build system, is this correct, or is this only for the particular sub-project in question?

    Kind regards.



  • @kshegunov That's just for the particular sub-project. Almost all of the libraries are legacy from another project. The main app is heavily leveraged on Qt. I need to use the build system to create my Xcode project. The source tree supports Linux, Windows, MAC and iOS, so it doesn't make sense to version control project files from multiple build systems. We use CMake for everything but Mac/iOS

    Your advice is indeed solicited. I am building for iOS which until recently only allowed static linking. I don't want to change that unless it clear that it would have an impact on the problem.


  • Qt Champions 2016

    @DRoscoe
    Hello,
    Well then maybe this blog post will help you build up your dependency tree nicely.

    I don't want to change that unless it clear that it would have an impact on the problem.

    I wouldn't venture as far to say it will.

    Kind regards.



  • @kshegunov When I first started on this project I came across this blog. I may be mistaken, but it seemed to me that the ".depends" nomenclature was only valid for makefile-style projects. I am only using makefile-style projects for our Linux builds, so it didn't seem like a viable solution for generating my Xcode project file. Am I misunderstanding?

    I did not realize that the .prl files did not help me with determining link dependencies. This article led me to believe it did. In fact, it seemed to me that this approach was ONLY valid for static libraries.


  • Qt Champions 2016

    @DRoscoe said:

    I am only using makefile-style projects for our Linux builds, so it didn't seem like a viable solution for generating my Xcode project file.

    This should probably be answered by @SGaist or someone who actually uses macs for development, however as far as I understand the qmake build system it should be working independently of your IDE.

    I did not realize that the .prl files did not help me with determining link dependencies. This article led me to believe it did. In fact, it seemed to me that this approach was ONLY valid for static libraries

    You seem to be correct and I - wrong, although the "link_prl" should appear in the application's project where the actual linking is performed, or at least this is how I understand the text you sourced.


  • Lifetime Qt Champion

    Hi,

    One thing I've been doing for some times now for ordered subdir projects is to follow this blog post. As for the development, I've essentially used the clang mkspec and I haven't had the problem mentioned by @DRoscoe.



  • @SGaist So you are saying that the ".depends" nomenclature works for iOS projects? When you say you are using "clang mkspec", what do you mean? You are not using "-spec macx-xcode"? So you are not generating an Xcode project? How then, are you able to sign and deploy iOS apps?


  • Lifetime Qt Champion

    Yes it does, also for Android.

    I'm using the default macx-clang mkspec to build OS X projects and for iOS, it's the macs-ios-clang by default (as in: you don't set it explicitly on the command line).

    I use Qt Creator for development/deployment and it's working pretty well.



  • @SGaist Ok, thanks! The documentation really is poor in that regard. I came across several articles which basically said that ".depends" and that class of attributes was only for makefile-style projects. I am converting my project now and removing the ordered build. By specifying the dependencies in terms of subdirs, I am also hoping to eliminate the need for "-recursive" which I believe is causing the warnings I am seeing



  • @SGaist I have a follow-on question.

    I have a pre-compiled library I need to link several of my other libraries to: ace_lib. When I compile the first project that needs it, I get the following error:

    :-1: error: No rule to make target `ace_lib-make_first', needed by `sub-aop_logger-make_first'.  Stop.
    

    I am guessing it is giving me this error because it wants to BUILD ace_lib, but I don't want it to be built, but I DO want it to be recognized as a pre-existing library.

    How can I do that? For informational purposes, here is my top-level project file

    include(ace_lib.pri)
    #CONFIG += c++11 ordered
    CONFIG += c++11
    TEMPLATE = subdirs
    
    SUBDIRS += \
        aop_logger \
        aop_xml \
        aop_serial \
        aop_util \
        aop_measure \
        MoreMath \
        MathUtilities \
        DataCollection \
        DebugLogger \
        BufferedSharedMemory \
        AvionicsBus \
        AircraftDataModel \
        WindModel \
        TableLookups \
        configuration \
        AtosUtils \
        dna \
        aop_data \
        aop_comm \
        tap_data \
        tap_messaging \
        RouteContainer \
        arinc_io_adapter \
        aop_interface \
        tap_display_app
    
    aop_logger.depends = ace_lib
    aop_serial.depends = aop_logger aop_xml ace_lib
    aop_util.depends = aop_serial
    aop_measure.depends = aop_util
    MathUtilities.depends = MoreMath
    DataCollection.depends = MathUtilities
    AvionicsBus.depends = DebugLogger BufferedSharedMemory
    WindModel.depends = MoreMath
    configuration.depends = aop_serial aop_xml aop_util aop_measure aop_logger
    dna.depends = aop_xml aop_logger configuration aop_serial aop_util aop_measure AtosUtils
    aop_data.depends = aop_measure aop_util aop_serial aop_logger DataCollection \
                       TableLookups AvionicsBus WindModel AircraftDataModel aop_xml \
                       MoreMath MathUtilities
    aop_comm.depends = dna aop_data aop_measure aop_util aop_serial AvionicsBus
    tap_data.depends = aop_util aop_measure aop_serial aop_xml aop_data aop_logger \
                       TableLookups WindModel
    tap_messaging.depends = tap_data aop_serial aop_util aop_measure dna aop_xml aop_logger \
                            aop_comm aop_data
    arinc_io_adapter.depends = AvionicsBus aop_measure aop_util aop_serial aop_logger \
                            aop_data
    aop_interface.depends = AvionicsBus aop_comm dna aop_measure aop_util aop_serial \
                            aop_logger aop_data configuration aop_xml RouteContainer \
                            arinc_io_adapter
    tap_display_app.depends = tap_data tap_messaging aop_interface TableLookups WindModel
    

    and here is the content of the ace_lib.pri file:

    include (top_srcdir.pri)
    include (ace_path.pri)
    
    win32:CONFIG(release, debug|release): LIBS += -L$$SW_LIBRARY_PATH/ace/$$ACE_VER/lib/ -lACE
    else:win32:CONFIG(debug, debug|release): LIBS += -L$$SW_LIBRARY_PATH/ace/$$ACE_VER/lib/ -lACEd
    else:unix: LIBS += -L$$(ACE_LIB) -lACE
    
    win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$SW_LIBRARY_PATH/ace/$$ACE_VER/lib/libACE.a
    else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$SW_LIBRARY_PATH/ace/$$ACE_VER/lib/libACEd.a
    else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$SW_LIBRARY_PATH/ace/$$ACE_VER/lib/ACE.lib
    else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$SW_LIBRARY_PATH/ace/$$ACE_VER/lib/ACEd.lib
    else:unix: PRE_TARGETDEPS += $$(ACE_LIB)/libACE.a
    

  • Lifetime Qt Champion

    .depends is only for other projects that must be built before. If you have a "link only" lib, I'd put it in a 3rdparty folder with a corresponding .pri file that you would include in the projects needing to link to that library.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.