qmake 语言
与其说 qmake 是一个构建工具,倒不如说它是一种编译器,源文件是 pro,目标文件是 Makefile。我们知道 pro 文件需要一套语法进行书写,这套语法就是 qmake 语言语法。
在这种语法里面,也有变量的概念,有操作符,有可视域,条件表达式,还有函数定义。
qmake 内置两类函数,一类是条件测试类;另一类是扩展函数类。
qmake 可能只支持两种自定义函数:
一种是 "Replace Functions",一种是 "Test Functions"。
Replace 函数用于处理参数,并返回一个值,或者一个值列表。并把返回结果指定给一个变量。
Test 函数也有返回,但是它的返回指示“成功”或“失败”,多用于条件表达式。
内置函数在 qmake 被编译生成时被固化,自定义函数可以根据需要自由添加。
pro pri prf prl
qmake 的源文件不止 pro,还有 pri prf prl后缀文件。虽然后缀不同,文件内容语法都是一样的。
一般顶层文件必然是 pro。pri 文件往往被 include 进 pro。
prf 文件内多数定义一些函数,完成特定功能。例如 “qtbase/mkspecs/features/qt_configure.prf” 这个文件就定义了 configure 后半部分的操作。在目录 “qtbase/mkspecs/features/”下还有很多 prf 文件
prl 文件多数是动态库项目跟随动态库一块儿生成的。
自定义函数语法
1. defineTest(YOURFUNCNAME) { 2. YOUR FUNC BODY 3. } 4. defineReplace(YOURFUNCNAME) { 5. YOUR FUNC BODY 6. }
虽然这两种函数都有返回值,但是也可以不写 return,语法比较宽松。
configure.json
在 Qt5 源码目录下搜文件“configure.json”,可以找到二三十个结果,分别在不同目录下。
这些文件中跟配置相关性最高的就是里面定义的 features。
首先在 commandline 下定义选项的类型,有string、boolean、enum、addString和optionalString等等几种类型;然后在 features 下定义了每一个特性的依赖条件等等。
1 | $ ./configure -list-feature |
这个配置选项就是查看目前支持的所有特性列表。而从文件“configure.json”中,我们可以找到这个特性的依赖信息.
qtXXX-config.h
配置过程,除了生成 Makefile,还有一些很重要的头文件。这些头文件中整齐地定义了一些宏,而这些宏决定了源码中某些功能是否启用。有时候 configure 显示的信息并不那么完善,我们可以找到对应模块的 “qtXXX-config.h” 文件,打开文件查看里面定义了哪些特性,哪些特性被禁用了等等。
另外可以参考的文件还有“qtXXX-config_p.h”“qtXXX-config.pri”,还有 “qtbase/src/corelib/global/qconfig.h”等。
qmake 工作流程总结
qmake 根据配置选项参数中整理出所有特性相关的定义,从各个“configure.json”文件中查找是否定义了某特性,然后判断此特性依赖条件是否满足,最终决定是否启用此特性。然后把启用的特性和禁用的特性结果分别写到“qtXXX-config.h”“qtXXX-config_p.h”“qtXXX-config.pri”几个文件中。
Makefile 的生成可能就简单了,从 pro 文件和 pri 文件生成 Makefile。决定是否编译当前模块下的某个子模块,或者是否添加某些源码文件到 Makefile。
qmake 定义了一套语法规则,在这套规则之上可以定义一些函数,进而实现一些自动化业务。另外把源码以特性为最小单元进行划分,并使用 json 文件结构描述了特性,描述了整个源码框架。qmake 依此可以知道它的工作范围,最后生成 Makefile 文件和一些 h 文件。