在Qt Creator中自动重建依赖项

Geo*_*lly 8 qt dependencies compilation qt-creator

Qt Creator(4.6.1)让我疯狂.我的申请分为3部分:

  • 该应用程序
  • 图书馆
  • 一个单元测试应用程序

当我更改库中的文件并重建应用程序时,编译器不会重新编译库,而是链接旧版本的库.

此外,当我更改库,重新编译它然后编译应用程序时,不会进行编译,因为它使用缓存的应用程序.

有没有改变的设置?这是我的项目文件:

TEMPLATE = subdirs

SUBDIRS += \
    app \
    lib_mylib \
    tests

app.depends = lib_mylib
tests.depends = lib_mylib
Run Code Online (Sandbox Code Playgroud)

lib构建为静态库:

TEMPLATE = lib
TARGET = mylib
CONFIG += staticlib
Run Code Online (Sandbox Code Playgroud)

Xpl*_*rms 6

我已经使用 CONFIG +=ordered、DEPENDPATH 和 PRE_TARGETDEPS 来解决同样的问题。它适用于我在 linux 上和使用 MSVC 的 win。尝试一下。

在您的项目 pro 文件中添加:

CONFIG += ordered
Run Code Online (Sandbox Code Playgroud)

PS:您的库应该首先列出。喜欢 :

SUBDIRS += \
    lib \
    app \
    tests
Run Code Online (Sandbox Code Playgroud)

在您的 exe .pro 文件中添加正确的路径:

DEPENDPATH += $$PWD/../lib
PRE_TARGETDEPS += $$OUT_PWD/../lib/liblib.a
Run Code Online (Sandbox Code Playgroud)

可以在此处找到更多选项和标志

  • `PRE_TARGETDEPS` 是让它发挥作用的关键。谢谢!据我所知,Qt5 不再需要`DEPENDPATH`。 (3认同)
  • `CONFIG +=ordered` 不是必需的,也不会改变任何东西——它只会减慢构建速度(这与基于顺序的自动依赖基本相同)。然而,`DEPENDPATH` 和 `PRE_TARGETDEPS` 应该可以工作。 (2认同)

Fel*_*lix 6

我知道已经有点晚了,但是我想给出一个更广泛的答案,为什么会发生这种情况以及其他解决方案到底有什么帮助。

一个工作解决方案将是:您使用b.depends += a像之前或CONFIG += ordered 添加PRE_TARGETDEPS += ...b。(旁注:不建议您订购,因为它会大大减慢您的构建速度,通常被认为是不好的做法)

TL; DR:之所以需要这种特殊的组合,是因为:app.depends = lib_mylibsubdirs项目中的确保在开始构建应用程序之前始终构建库,并且PRE_TARGETDEPS确保每次更改库时应用程序实际上都在重新构建。


详细说明:

要了解其工作原理,我们需要了解qmake如何处理子目录。qmake是一个Makefile生成器,这意味着它将仅创建makefile。因此,必须使用make prodives方法完成所有依赖项排序。要了解发生了什么,我们必须首先了解make的工作原理。

在make中,依赖关系相对简单:

some_target: dep1 dep2 dep3
    some_command
Run Code Online (Sandbox Code Playgroud)

表示如果要创建some_target,make将创建dep1dep2然后dep3首先以未指定的顺序进行创建。一旦完成所有3个,some_command就执行。

但是,make会对文件进行优化。考虑以下内容:

hello.txt:
    echo "creating hello"
    echo "hello" > hello.txt

hello2.txt: hello.txt
    echo "creating hello2"
    echo "hello2" > hello2.txt
Run Code Online (Sandbox Code Playgroud)

运行make将创建两个文件并打印两个消息。第二次运行将无济于事。原因是make跟踪已创建的文件和文件更改。由于hello.txt已经存在,因此不会再次创建。并且由于hello.txt未更改,因此无需hello2.txt再次创建。如果现在从外部更改的内容hello.txt并再次运行make,hello2.txt将重新创建,并看到此消息。

现在有了subdirs项目,这变得有些复杂,因为我们现在需要多个不同的makefile之间的依赖关系!这通常通过递归make调用来解决。对于您的示例,qmake创建以下代码(简化):

lib_mylib: FORCE
    $(MAKE) lib_mylib/Makefile

app: lib_mylib FORCE
    $(MAKE) app/Makefile
Run Code Online (Sandbox Code Playgroud)

如预期的那样,此代码将lib_mylib首先创建(阻塞,即,lib_mylib仅在构建完整个lib之后才会完成),然后再创建app。该FORCEdepenency确保了此命令始终运行,即使目标已经存在。


有了这些基本知识,我们现在就可以重建qmake的情况了。使用b.depends += awill将生成上面的代码-确保所有依赖项都以正确的顺序构建,但没有别的!使用排序的配置将简单地自动创建那些依赖规则,因此它们的工作方式没有逻辑差异。

但是,这不足以applib_mylib更改时实际进行重建。它仅确保lib_mylib在make开始构建之前已构建app

为了进行重建app,我们使用PRE_TARGETDEPS-向应用程序makefile中的make目标添加一个如前所示的依赖项。

app.exe: mylib.lib:
    #linker code
Run Code Online (Sandbox Code Playgroud)

这意味着每次lib_mylib更改app都会立即重新构建。但是,在没有有序配置的情况下使用它可能会失败,因为make可能会首先尝试进行构建app(由于lib尚未更改,它什么都不做,或者如果lib不存在则失败),然后再进行构建lib_mylib。第二次运行也会重新生成app-但这很不方便。

因此,这就是为什么我们需要将两者结合在一起。我们需要控制执行不同makefile文件的顺序,并引用另一个makefile文件中创建的工件,而这正是这些命令的作用。