qt - 在 Qt Creator 中自动重建依赖项
问题描述
Qt Creator (4.6.1) 快把我逼疯了。我的申请分为 3 个部分:
- 应用程序
- 图书馆
- 一个单元测试应用
当我更改库中的文件并重建应用程序时,编译器不会重新编译库,而是链接到旧版本的库。
此外,当我更改库、重新编译它然后编译应用程序时,不会进行编译,因为它使用缓存的应用程序。
有设置可以改变吗?这是我的项目文件:
TEMPLATE = subdirs
SUBDIRS += \
app \
lib_mylib \
tests
app.depends = lib_mylib
tests.depends = lib_mylib
该库被构建为一个静态库:
TEMPLATE = lib
TARGET = mylib
CONFIG += staticlib
解决方案
我知道这有点晚了,但我想给出一个更广泛的答案,为什么会发生这种情况以及其他解决方案究竟如何提供帮助。
一个可行的解决方案是:您可以b.depends += a
像以前一样使用CONFIG += ordered
或者添加PRE_TARGETDEPS += ...
到b
. (旁注:不建议使用ordered,因为它会大大减慢您的构建速度,并且通常被认为是不好的做法)
TL;DR:需要这种特殊组合的原因:app.depends = lib_mylib
在 subdirs 项目中确保始终在构建应用程序之前构建库,并PRE_TARGETDEPS
确保每次库更改时应用程序实际上都在重新构建。
长解释:
要理解为什么会这样,我们需要了解 qmake 如何处理子目录。qmake 是一个 Makefile 生成器,这意味着它只会创建 makefile。所以所有的依赖排序必须使用方法 make prodives 来完成。要了解会发生什么,我们必须首先了解 make 的工作原理。
在make中,依赖比较简单:
some_target: dep1 dep2 dep3
some_command
意味着如果你想创建some_target
,make 将创建dep1
,dep2
并且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
运行 make 将创建这两个文件并打印这两个消息。第二次运行它不会有任何作用。这里的原因是 make 会跟踪已创建的文件和文件更改。由于hello.txt
已经存在,因此不会再次创建。而既然hello.txt
没有改变,也就没有必要再创造hello2.txt
。如果您现在从外部更改内容hello.txt
并再次运行 make,hello2.txt
将重新创建,您将看到该消息。
现在有了 subdirs 项目,这变得有点复杂,因为我们现在需要多个不同的 makefile 之间的依赖关系!这通常通过递归调用来解决。对于您的示例, qmake 创建以下代码(简化):
lib_mylib: FORCE
$(MAKE) lib_mylib/Makefile
app: lib_mylib FORCE
$(MAKE) app/Makefile
正如预期的那样,此代码将lib_mylib
首先创建(阻塞,即lib_mylib
只有在构建整个库后才会完成),然后再创建app
。依赖确保此FORCE
命令始终运行,即使目标已存在。
考虑到这些基础知识,我们现在可以重构 qmake 发生的事情。使用b.depends += a
将生成上述代码 - 它确保所有依赖项都以正确的顺序构建,但仅此而已!使用有序配置将简单地自动创建这些依赖规则,因此它们的工作方式没有逻辑差异。
但是,这还不足以app
在lib_mylib
更改时实际重建。它只确保lib_mylib
在 make 开始构建之前构建app
。
为了重建app
,我们使用PRE_TARGETDEPS
- 这将如前所示的依赖项添加到应用程序 makefile 中的 make 目标。
app.exe: mylib.lib:
#linker code
这意味着每次lib_mylib
更改时,app
现在也会重新构建。但是,在没有有序配置的情况下使用它可能会失败,因为 make 可能会首先尝试构建app
(它要么什么都不做,因为 lib 没有更改,或者如果 lib 不存在则将失败),然后再重新构建lib_mylib
。第二次运行 make 也将重建app
- 但那相当不方便。
所以,这就是为什么我们需要将这两者结合起来。我们需要控制不同 makefile 的执行顺序,并从其他 makefile 引用创建的工件——这正是这些命令的作用。
推荐阅读
- r - 将时间序列切割成特定的箱子并标记每个块
- go - 是否可以编写测试来测试记录的键的顺序
- node.js - 在 Linux Mint 19.3 上安装 nodejs 版本 >= 10 时出现问题,它顽固地安装 nodejs 8.10
- python - 运行多个进程时 CPU 关联性不会保持受限
- java - 以与机器无关的方式读取数据是什么意思?
- python-3.x - Python3:如何使用模块“导入点击”和解析命令行
- swift - 在 Swift 中多次运行的按键事件处理程序
- cordova - 科尔多瓦中的 inappbrowser 未从弹出窗口返回 3ds 付款数据
- charts - Plotly 错误消息错误:客户端错误:(413)请求实体太大
- swift - Swift:使嵌入在导航控制器中的 UITableViewController 的背景图片填满整个屏幕