现代的代码项目都使用git管理,qt也不例外,如果一个项目由很多子项目组成,可以使用git的submodule机制.
git官方的发布仓库在http://code.qt.io,这是一个只读的仓库镜像,作为一个具有规模的项目,成员之间的合作需要遵循一些流程,虽然这会看起来有些麻烦.如果想给Qt贡献代码,稍微有些麻烦,具体见 http://wiki.qt.io/Qt_Contribution_Guidelines
下面分析Qt项目的结构,以Qt5.7为例.
是Qt的主仓库,包含coin持续集成脚本,configure脚本,仓库初始化脚本和其它子模块的引用.
如果使用git从这里下载代码,则下载后需要使用下载其它子仓库,该工具还包含了更新仓库等其它帮助命令.如果不是给Qt贡献代码或者想自己编译一个开发中的版本,不建议使用git仓库.如果是开发版的话,可能因为代码不稳定,编译的时候会出现各种问题.我们使用官方正式发布某个版本时自带的打包好的源码进行学习和分析.
顶级目录分析
├── coin 持续集成脚本
├── gnuwin32 用于win32的构建工具 ├── qtbase Qt基础仓库 ├── qtdoc 主帮助文档项目 ├── qttools Qt各种工具,如帮助系统/设计器/语言家/部署帮助等,一般生成后在Qt的bin目录 ├── qttranslations 翻译文件 ├── ****** └── 其它Qt子模块Qt5分为Essential和Add-Ons两个部分, 前者包含Qt最核心的功能,后者为非必要或不常用模块.Essential包含了qtbase和其它几个核心仓库.
构建分析
代码根目录下有一个README文件,描述了编译Qt所需要的环境和依赖.qt的每个模块代码都是一个Qt项目,使用pro项目维护.但是我们要编译Qt就要从新开始,而不是用Qt编译Qt.
根目录下提供了unix类系统和windows系统的配置文件configure,它指向了qtbase下的同名文件.真正的配置脚本在这里.详细的配置选项可以通过./configure --help > help.txt输出到文件查看.
如果想编译源码,建议不要在源码目录之间编译,而是单独建立一个build目录,然后在build目录执行配置脚本.如
../qtsrc/configure -prefix $PWD/qtbase -developer-build -opensource -confirm-license -opengl es2 -nomake examples -nomake tests
配置文件指定了各个工具和模块的编译顺序,依赖满足情况,编译参数等.当然也可以指定仅需也的模块和排除某些模块.
当然在真正配置和编译前,我们需要参考https://wiki.qt.io/Building_Qt_5_from_Git 来安装必要的依赖包,否则不能编译或者某些模块不会被编译.执行configure命令后,脚本会首先检查各个模块所需有的环境是否满足.如果某个需要的模块不满足依赖我们需要安装对应的环境.
配置好后,可以通过make -jN来构建全部或make -jN module-xxxx构建部分模块
对于一些不成熟的版本或模块进行编译时,建议使用构建版本参数使用 -developer-build,这样一些私有的模块和头文件会包含进来.
构建后的目录
├── bin 可执行文件
├── config.tests ├── include 所有模块的头文件 ├── lib 所以模块的库文件 ├── mkspecs ├── plugins Qt插件 ├── qmake ├── qml qml插件和资源 └── src 编译过程中使用的makefile等qtbase目录
qtbase既是最基本的源码目录,也是编译生成文件的存放目录,如果编译时版本选型为-developer-build,则其它模块生成的库和头文件也会安装在此目录,从而无需执行make install即可
├── bin 编译后的可执行文件
├── config.tests 编译条件测试文件 ├── dist 修改记录 ├── doc 文档 ├── examples 实例 ├── include 头文件 ├── lib 编译生成的lib文件 ├── mkspecs 编译器参数配置文件 ├── qmake qmake工具 ├── src base模块代码 ├── tests ├── tools └── util模块目录
Qt的每个模块目录结构基本一样,
├── dist 修改记录
├── doc ├── examples ├── include 头文件 ├── src └── tests关于头文件
每个模块的头文件在模块目录下的include文件夹,在编译的时候,将里面全部内容拷贝到qtbase下的include内. 在模块开发中,既用到了目录内的公共头文件,也用到了私有头文件.
私有头文件一般在include/分组名称/Qt版本号/分组名称/privte目录,其中前半部分include/分组名称/Qt版本号 被添加进构建系统的include变量,所以模块中一般包含的私有头文件为 分组名称/privte/xxx_p.h这样的形式.