Qmake 配置自定义编译过程

需求:动态更换资源文件

在 Windows10 下编写 Qt 项目时,有这样的需求:

  • 程序用到的资源文件可以动态更换而不需要重新编译整个项目

解决方案 0.1

将所有的资源文件全部放到 qrc 文件中,由 Qt 负责管理资源文件。

但是这种方法在每次更改了 res 中的文件后都需要重新编译程序。比较麻烦。

新的需求

于是需求变成了:

  • 将源代码目录下的 res 文件夹下的 xml 文件全部复制到编译好的程序同级目录下

解决方案 1.0

最初的解决方案是在 res 目录下编写一个批处理文件:update.bat,然后每次更新了 xml 文件后,

手动执行这个批处理文件。由于 xml 文件写好后基本上不需要怎么修改,所以写完代码后在自己的环境中

运行起来没有问题,不会出现程序运行时找不到 xml 文件的情况。

该批处理文件的内容如下:

mkdir ../../build-DEMO-Desktop_Qt_5_6_3_MSVC2015_64bit-Debug/debug/res
copy /y *.xml ../../build-DEMO-Desktop_Qt_5_6_3_MSVC2015_64bit-Debug/debug/res
mkdir ../../build-DEMO-Desktop_Qt_5_6_3_MSVC2015_64bit-Release/realse/res
copy /y *.xml ../../build-DEMO-Desktop_Qt_5_6_3_MSVC2015_64bit-Release/realse/res

思路是这样的:

  1. 首先创建相应的目录
  2. 将项目下面所有的 xml 文件复制到指定的目录

在我的电脑环境中运行正常,但是问题很明显,如果我换了编译器,或者更换了构建目录,我就得去批处理文件中添加两行代码,

而且还得把所有的文件复制到好几个目录下面。非常麻烦!

我在把源代码拷给别人的时候,由于别人用的编译器是 MinGW 编译器,结果我的批处理文件没有办法直接使用。

所以在别人的编译环境中生成的程序由于缺少资源文件,程序运行不正常。

那么我需要找到一种方法,得到 Qt 构建项目的目录,并将需要的资源文件复制到相应目录下。

解决方案 2.0

QtCreator 编译项目时,IDE 会调用 qmake 根据项目 .pro 文件自动生成一个 Makefile

然后 IDE 就能根据这个 Makefile 对项目进行编译处理。

经过一番搜索,在 stackoverflow 上搜到了可用的内容,然后我在 .pro 文件末尾添加了这些内容(修改了部分内容):

DESTDIR = $$OUT_PWD
defineTest(resToDestdir) {
files = $$1 for(FILE, files) {
DDIR = $$RAWDDIR # Replace slashes in paths with backslashes for Windows
win32:DDIR ~= s,/,\\,g
win32:FILE ~= s,/,\\,g QMAKE_POST_LINK += $$QMAKE_COPY $$quote($$FILE) $$quote($$DDIR) $$escape_expand(\\n\\t)
} export(QMAKE_POST_LINK)
return(true)
} # update xml files into proper folder
XML_FILES = $$PWD/res/*.xml ## note, if there is something wrong when compiling, annote following sentence
resToDestdir($$XML_FILES)

Qt 官方文档 里对这些用到的变量都有说明。

这里简单说一下。

  • DESTDIR: 指定放置 target 文件的位置
  • QMAKE_POST_LINK: 在链接 TARGET 后指定要执行的命令
  • export(variablename): 将 variablename 在函数的局域上下文中的值导出到全局上下文
  • defineTest:定义一个测试函数,以便复用代码(尽管这里并没有复用代码:))

经过几次尝试后,发现要运行 .pro 文件中的这段代码需要每次都重新编译。因为直接在 QtCreator 中点击编译会先比较

文件,如果没有更改源文件(或者说被依赖文件没有更新,那么编译就可以跳过)。而且每次更改了 .pro 文件都需要先运行

一次 qmake,确保 Makefile 是最新的。

解决方案 2.9

我对代码进行了修改,添加了创建目录的语句,并用 exists 函数判断是否存在目录,如果不存在就创建。

在 Windows 上,目录分隔符是反斜杠 "" ,因此直接利用 win32:DDIR 进行判断是否存在相应目录, exists 函数返回的都是 false。

官方文档 对此已经有说明了:

Note: "/" should be used as a directory separator, regardless of the platform in use.

即:

注意: 目录分隔符应该用 “/” ,不论你用的是什么平台。

所以判断目录是否已经存在需要用最开始的斜杠分隔符,但是创建目录的命令还是要用反斜杠(调用的是 Windows 的命令行)。

最终修改后的 qmake 代码:

#-----------------------------------
# @author BriFuture
# @details this is used for automated build
#
# Copies the given files to the destination directory
#----------------------------------- ## set destdir
DESTDIR = $$OUT_PWD
defineTest(resToDestdir) {
files = $$1
ddir = $$2 for(FILE, files) {
# Replace slashes in paths with backslashes for Windows
DDIR = $$DESTDIR/$$ddir
## if res folder is created, then no need to exec mkdir
## note, whatever the platform you are using( Windows, Linux, Mac),
## the directory seperator must be slash "/"
!exists($$DDIR) {
log($$DDIR not exists)
mkpath($$DDIR)
}
win32:DDIR ~= s,/,\\,g
win32:FILE ~= s,/,\\,g QMAKE_POST_LINK += $$QMAKE_COPY $$quote($$FILE) $$quote($$DDIR) $$escape_expand(\\n\\t)
# QMAKE_POST_LINK += echo $$FILE $$escape_expand(\\n\\t)
# message(FILE $$FILE)
} # QMAKE_POST_LINK += echo $$quote($$PWD == $$DESTDIR)
# message(LINK: $$QMAKE_POST_LINK)
export(QMAKE_POST_LINK)
return(true)
} # update xml files into proper folder
XML_FILES = $$PWD/res/*.xml ## note, if there is something wrong when compiling, annote following sentence
resToDestdir($$XML_FILES, res)

总结

最终这个代码可以完美的复制需要的资源文件到指定的目录下,但是还有一些小 bug,偶尔编译时会报错:

mkdir ..\debug\res 目录已经存在,遇到这种情况,重新执行一遍 qmake,再重新编译就好了。

虽然并不完美,但再深入就太累了。

当然还有一种思路,在 qmake 中执行已经写好的 bat 批处理文件,然后将构建目录作为参数传递给批处理文件。

时间有限,没有实现。

最新文章

  1. 1013. Battle Over Cities
  2. iPhone手机安全指南
  3. cms3.0——收获(1)
  4. mssql 置疑的处理
  5. HotSpot Builder Utility安装指南
  6. MVC 表单提交提示:已添加了具有相同键的项。
  7. verilog 数组参数
  8. JNI之有必要的优化设计
  9. Mac下Jekyll安装
  10. 201521123093 JAVA程序设计
  11. 单例模式的七种实现-Singleton(Java实现)
  12. 20165237 2017-2018-2《Java程序设计》课程总结
  13. Linux 目录结构详解
  14. talk with gao about qssp
  15. php curl中x-www-form-urlencoded与multipart/form-data 方式 Post 提交数据详解
  16. myCat知识笔记
  17. 总是Eqw
  18. Web项目开发流程 PC端
  19. <[长期赢利:股票价值投资方法]>读书笔记
  20. AugularJS, Responsive, phonegap, BAE, SAE,GAE, Paas

热门文章

  1. sqlserver高版本还原到低版本方法
  2. spring aop实现权限管理
  3. Data Base 常用数据库参数的前缀表示符合
  4. ubuntu - 14.04,解决Gnome桌面右键菜单失效问题!
  5. 浅谈《守望先锋》中的 ECS 构架
  6. luogu1891 疯狂lcm ??欧拉反演?
  7. luogu2513 逆序对数列
  8. atcoder 2579
  9. dedecms模板目录
  10. django文件配置