1+1=10

扬长避短 vs 取长补短

qmake下的debug与release模式

捋完了CMake下的Debug与Release,同事突然问我一句,qmake下面的Debug与Release是怎么配置的,发现第一时间竟然想不起来了...

注:从cmake3.0开始,qmake已经没有多少优势了,Qt6自身也已经使用cmake构建,新的项目没必要再使用qmake。

本文内容:

  • qmake && make :默认是release。但如果.pro内添加了CONFIG+=debug,那么结果是debug。
  • qmake CONFIG+=debug && make:构建结果一定是 debug
  • qmake CONFIG+=release && make:构建结果一定是 release
  • 如果.pro内添加了CONFIG+=debug_and_release(不管是Windows下自动添加,还是Linux下你手动添加)

    • qmake && make debug:构建结果是 debug
    • qmake && make release:构建结果是 release
  • CONFIG += debug release debug release debug:要好好理解

  • CONFIG(debug, debug|release):很有用/很常用/也很晦涩难懂
  • build_pass:是否有用看是否关注了

qmake使用

qmake的使用很简单,创建工程文件 xxxx.pro后,直接

qmake
make

就行了。

但是这编译出的程序是 debug 版本 还是 release ??

  • 不严谨答案:release

  • 严谨答案:不一定。

取决于在.pro内配置

  • 在 xxxx.pro文件内添加 CONFIG += release 上面编译出来的就是 release

  • 在 xxxx.pro文件内添加 CONFIG += debug 上面编译出来的就是 debug

注意:这个是很反直觉的。如果类似语句可以多次添加(即使你没加,其他pri/prf/prl中也可能会加),此时,需要看谁在最后(如下,编译出来会是 release):

CONFIG += release
CONFIG += debug
CONFIG += debug release debug
CONFIG += release

所有的难以理解,都是从这个多次添加的用法开始的。命令行参数中的 CONFIG+= 也在干这个事情。

也可以命令行参数指定

除了可以在.pro内指定外,还可以使用qmake的命令行参数

如下命令,编译出来是debug:

qmake CONFIG+=debug
make

如下命令,编译出来是release:

qmake CONFIG+=release
make

还可以指定make的target

当在工程文件.pro内使用 debug_and_release选项(这是 Windows 下的默认选项)。那么Makefile会支持两个target,这样,就不用在乎qmake指定什么了...

构建debug版本:

qmake
make debug

构建release版本:

qmake
make release

当然,你也可以这么写(反正make后面的 target 说了算)

qmake CONFIG+=debug
make release

去掉make后面的target,才轮到CONFIG+=debug说了算

qmake CONFIG+=debug
make

qmake 之 CONFIG(debug, debug|release)

这个怪异的写法,是在解决一个很很常规的问题。

问题起源

在 Qt 编程中,10多年前,多数人用的都是 qmake,并编写相应pro文件。

实际中经常需要对 debug 与 release 两种编译模式 设置不同的选项,比方说链接不同库

遇到该问题,简单看看qmake的manual,不少人都会写出类似下面的内容:

debug {
    LIBS += -L../lib1 -lhellod
}
release {
    LIBS += -L../lib2 -lhello
}

很不幸,这么做通常不能正常工作。

如果打开看生成的makefile文件,会发现 无论是debug还是release,上面的两个语句都会同时起作用。也就是说,上面相当于

LIBS += -L../lib1 -lhellod -L../lib2 -lhello

原因

这是很违反直觉的,因为CONFIG可以同时定义 debug 和 release,但只有一个处于active(当两个互斥的值出现时,最后设置的处于active状态)

比如:

CONFIG = debug
CONFIG += release

这种情况下,release处于active状态,但,debug 和 release 都能通过上面的测试。

如何解决?

CONFIG(debug, debug|release) {
    LIBS += -L../lib1 -lhellod
} else {
    LIBS += -L../lib2 -lhello
}

CONFIG(debug, debug|release):LIBS += -L../lib1 -lhellod
CONFIG(release, debug|release):LIBS += -L../lib2 -lhello

那么,CONFIG(debug, debug|release) 这种语法是什么含义呢?

两个参数,前者是要判断的active的选项,后者是互斥的选项的一个集合。

什么叫active,也就是,最后一个给CONFIG添加的时debug还是release,下面例子:

CONFIG = debug release debug debug
CONFIG += debug
CONFIG += release

激活的是release

build_pass

qmake中反直觉的事情很多,build_pass算一个。

当在工程文件.pro内使用 debug_and_release选项(这是 Windows 下的默认选项)时,工程的.pro文件实际上会被处理三次:

  • 一次生成:Makefile
  • 一次生成: Makefile.Debug
  • 还一次: Makefile.Release

例如:

build_pass: message("build pass")
else: message("non build pass")

message("Hello dbzhang800!")

运行qmake x.pro,结果如下:

Project MESSAGE: non build pass
Project MESSAGE: Hello dbzhang800!
Project MESSAGE: build pass
Project MESSAGE: Hello dbzhang800!
Project MESSAGE: build pass
Project MESSAGE: Hello dbzhang800!

配合debug和release

pro文件内容:

build_pass: message("build pass")
else: message("non build pass")

CONFIG(debug, debug|release) {
    message("debug")
} else {
    message("release")
}
  • 直接运行qmake,结果:
Project MESSAGE: non build pass
Project MESSAGE: release
Project MESSAGE: build pass
Project MESSAGE: release
Project MESSAGE: build pass
Project MESSAGE: debug

此时打开Makefile文件:

MAKEFILE      = Makefile
first: release
...
  • 直接运行qmake CONFIG+=debug,结果:
Project MESSAGE: non build pass
Project MESSAGE: debug
Project MESSAGE: build pass
Project MESSAGE: debug
Project MESSAGE: build pass
Project MESSAGE: release

此时打开Makefile文件:

MAKEFILE      = Makefile
first: debug
...

参考

个人2010年前后在百度空间和CSDN中写过多篇qmake相关的blog,但是百度空间关闭后,很多记录找不回来了。本文是基于早期留存的记录片段进行整理而成。

由于不想重新查找资料并去一一核实,所以不贴参考链接了。

Qt qmake

Comments