【问题标题】:How to create re-usable libraries based on qmake?如何基于 qmake 创建可重用的库?
【发布时间】:2015-07-22 13:13:58
【问题描述】:

我有多个应用程序将使用一个或多个通用库。甚至我的库也可以相互依赖。

这是文件树:

Libaries/
   Library1/
       Library1.pro
       Library1.cpp
       Library1.h
   Library2/
       Library2.pro
       Library2.cpp
       Library2.h
Applications/
   App1/
       App1.pro
       main.cpp
   App2/
       App2.pro
       main.cpp

App1 依赖于 Library1。 App2 依赖于 Library1 和 Library2。

我希望能够以一种简单的方式在 Qt creator 中进行开发,当我打开 Application1 时,我有以下行为:

  • Qt creator 中可用的 Application1 代码
  • Qt creator 中可用的库 1 代码
  • 编译 Application1 会自动编译 Library1 并将输出的 .dll/.so 文件放在与 Application1 .exe 相同的目录中。

这基本上是 Visual Studio 多年来能够做的事情,对我来说似乎是一件很基本的事情,以至于我不明白我是唯一遇到这个问题的人。

您对如何执行此操作有任何线索吗?我尝试了基于 SUBDIRS 的不同解决方案,但我从未达到上述所有 3 点。

编辑:澄清一点,我希望能够做类似的事情:

Application1.pro

include("Library1")

Application2.pro

include("Library1")
include("Library2")

并让所有工作自动运行。我找到了一个解决方案,它需要库中的文件才能知道“父”在做什么包含,这对我来说是无意义的,库不应该知道使用它的程序。

【问题讨论】:

    标签: c++ qt qt-creator qmake subdirectory


    【解决方案1】:

    你可以做一个这样的项目: 我的项目:

    • project.pro
      • 应用程序
        • App.pro
        • main.cpp
      • lib1
        • lib1.pro
        • lib1.pri
        • lib1.h
        • lib1.cpp
      • lib2
        • lib2.pro
        • lib2.pri
        • lib2.h
        • lib2.cpp

    project.pro

    TEMPLATE = subdirs
    CONFIG += ordered
    
    SUBDIRS += \
        lib1 \
        lib2 \
        App
    

    App.pro

    QT       += core
    
    QT       -= gui
    
    include(../lib1/lib1.pri)
    include(../lib2/lib2.pri)
    
    TARGET = App
    CONFIG   += console
    CONFIG   -= app_bundle
    
    TEMPLATE = app
    
    
    SOURCES += main.cpp
    

    main.cpp

    #include <QCoreApplication>
    #include "lib1.h"
    #include "lib2.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        Lib1 lib1();
    
        return a.exec();
    }
    

    lib1.pro

    QT       -= gui
    
    TARGET = lib1
    TEMPLATE = lib
    
    DEFINES += LIB1_LIBRARY
    
    SOURCES += lib1.cpp
    
    HEADERS += lib1.h\
            lib1_global.h
    
    DESTDIR = ../libs
    
    unix {
        target.path = /usr/lib
        INSTALLS += target
    }
    
    OTHER_FILES += \
        lib1.pri
    

    lib1.pri

    INCLUDEPATH += $$PWD/
    LIBS += -L$$OUT_PWD/../libs/ -llib1
    

    lib2.pro

    QT       -= gui
    
    TARGET = lib2
    TEMPLATE = lib
    
    DEFINES += LIB2_LIBRARY
    
    SOURCES += lib2.cpp
    
    HEADERS += lib2.h\
            lib1_global.h
    
    DESTDIR = ../libs
    
    unix {
        target.path = /usr/lib
        INSTALLS += target
    }
    
    OTHER_FILES += \
        lib2.pri
    

    lib2.pri

    INCLUDEPATH += $$PWD/
    LIBS += -L$$OUT_PWD/../libs/ -llib2
    

    【讨论】:

    • DEPENDPATH 也应该被添加,并且必须包含INCLUDEPATH 中的所有内容。否则,你会得到脆弱的构建。\
    • 我可以使用环境变量,而不是使用相对的 DESTDIR,这使得构建输出可以由应用程序配置。
    • @KubaOber 你确定吗?我在 stackoverflow 上读到它不再需要 qt5。
    • @ThibautD。也许吧,但两者仍然受到支持并被广泛使用,因此,作为一般建议,DEPENDPATH 是必需的。无论如何,最好转到qbs...
    • @KubaOber 如果 Qbs 取代了 qmake & make,为什么在最新的 Qt 5.5 & Qt creator 上默认不使用?我只能创建与 Qbs 一起使用的“非 qt”C++ 项目。
    【解决方案2】:

    App1Solution.pro

    TEMPLATE = subdirs
    CONFIG += ordered
    
    SUBDIRS += \
        ../../Libaries/Library1 \
        ../App1
    

    靠近App1.pro

    App2Solution.pro

    TEMPLATE = subdirs
    CONFIG += ordered
    
    SUBDIRS += \
        ../../Libaries/Library1 \
        ../../Libaries/Library2 \
        ../App2
    

    靠近App2.pro

    并将输出的 .dll/.so 文件放在与 Application1 .exe 相同的目录中

    这应该是不同的:

    1. 您可以根据某些变量设置DESTDIRLibrary&lt;i&gt;
    2. 您可以将 copy-lib 命令添加到 App&lt;i&gt; pro-file。

    【讨论】:

    • 这可行,但不符合所有要求:库将建在它们自己的目录中,而不是在 App1 目录中(App1.exe 附近)。
    • 你可以copy需要的文件before building app
    • 你可以根据一些变量设置图书馆的DESTDIR。
    【解决方案3】:

    添加到Thom's answer,能够使用限定前缀引用库头是有利的 - #include "lib1/lib1.h" 而不是#include "lib1.h"。否则,几乎不可能使用独立开发的库,你总是会遇到标题冲突。

    有两种方法可以做到这一点。

    首先,您可以向每个顶级项目文件添加一个公共变量,通过引用树根来指示其在项目树中的深度。然后将树根添加到包含和依赖路径。

    App.pro

    ROOT = ..
    include($$ROOT/lib1/lib1.pri)
    include($$ROOT/lib2/lib2.pri)
    
    INCLUDEPATH += $$ROOT
    DEPENDPATH += $$ROOT
    
    ...
    

    这样,单个库项目包含根本不必指定它们的包含。

    或者,每个库中的 INCLUDEPATH 应该指向一个文件夹 - 不要忘记 DEPENDPATH

    lib1.pri

    ROOT = ..
    INCLUDEPATH += $$PWD/$$ROOT
    DEPENDPATH += $$PWD/$$ROOT
    
    ...
    

    然后,在main.cpp 中,您可以有合理的前缀包含,即使lib1lib2 都提供相同的文件也不会冲突:

    main.cpp

    #include "lib1/easy.h"
    #include "lib2/easy.h"
    ...
    

    【讨论】:

      猜你喜欢
      • 2014-10-24
      • 1970-01-01
      • 2016-02-10
      • 1970-01-01
      • 2023-02-25
      • 2014-08-16
      • 2021-03-21
      • 2017-12-06
      • 2012-06-25
      相关资源
      最近更新 更多