KS02-06 一劳永逸:引入pri体系

版权声明

----------------------------------------------------------------

作者: 女儿叫老白

转载请注明出处!

网页版课程源码 提取码:1uy7


引言

----------------------------------------------------------------

上一节我们介绍了pri文件的作用与使用方法,在项目开发尤其是大型项目开发中,pri文件的使用是非常重要的。当我们开展不同的项目开发时,这些项目有非常多的配置项都是完全一样的。因此,建立一套完整的pri体系变得非常重要。

 

正文

----------------------------------------------------------------

    一般情况下,我们会建立一套常用的pri文件,他们各自负责不同的功能,比如有的负责处理编译选项;有的负责处理目录设置。为了方便,我们把这些不同的pri整合成一个文件来介绍,当然,大家也可以根据需要把这个文件拆成不同的pri文件。

    注:本节的内容默认您的项目使用gcc编译器。

    直接给出gui_base.pri文件:

 

代码清单02-06-01

1.      

2.      

3.      

4.      

5.      

6.      

7.      

8.      

9.      

10.   

11.   

12.   

13.   

14.   

15.   

16.   

17.   

18.   

19.   

20.   

21.   

22.   

23.   

24.   

25.   

26.   

27.   

28.   

29.   

30.   

31.   

32.   

33.   

34.   

35.   

36.   

37.   

38.   

39.   

40.   

41.   

42.   

43.   

44.   

45.   

46.   

47.   

48.   

49.   

50.   

51.   

52.   

53.   

54.   

55.   

56.   

57.   

58.   

59.   

60.   

61.   

62.   

63.   

64.   

65.   

66.   

67.   

68.   

69.   

70.   

71.   

72.   

73.   

74.   

75.   

76.   

77.   

78.   

79.   

80.   

81.   

82.   

83.   

84.   

85.   

86.   

87.   

88.   

89.   

90.   

91.   

92.   

93.   

94.   

95.   

96.   

97.   

98.   

99.   

100.

101.

102.

103.

104.

105.

106.

107.

108.

109.

110.

111.

112.

113.

114.

115.

116.

117.

118.

119.

120.

121.

122.

123.

124.

125.

126. 

###########################################################################

# 注意:此文件用于放置本次课程各子项目的公共设置,

# 在各子项目的 QT 工程文件中通过 include 语句包含该pri文件。

# 需要提前定义如下系统环境变量:

# TRAINDEVHOME   根目录:  其下是bin、lib、src等子目录。

# TRAINBUILDTYPE 编译版本: debug|release|all

# TRAINBUILDBIT  编译位数: 32|64

###########################################################################

 

# 需先通过环境变量 TRAINDEVHOME 指定开发目录

# 由于 isEmpty 函数不能直接对环境变量进行判断,所以先将其放入一个临时变量中

DEVHOME = $$(TRAINDEVHOME)

isEmpty(DEVHOME) {

    error('TRAINDEVHOME'环境变量必须被定义.)

}

# 设置变量:系统执行文件路径、库文件路径、临时文件生成路径、头文件包含路径

TRAIN_BIN_PATH = $$(TRAINDEVHOME)/bin

TRAIN_LIB_PATH = $$(TRAINDEVHOME)/lib

TRAIN_OBJ_PATH = $$(TRAINDEVHOME)/obj

TRAIN_SRC_PATH = $$(TRAINDEVHOME)/src

TRAIN_UIC_PATH = $$(TRAINDEVHOME)/obj/uic

TRAIN_INCLUDE_PATH = $$(TRAINDEVHOME)/include

 

# 设置所引用的库文件的路径

QMAKE_LIBDIR *= $$TRAIN_LIB_PATH

 

DEPENDPATH *=  .\

        $$TRAIN_INCLUDE_PATH

       

INCLUDEPATH *=  .\

        $$TRAIN_INCLUDE_PATH

 

##########################################################################

#

# 不同平台的编译器设置

#

##########################################################################

# 获取编译 Qt 的编译器类型

TRAIN_QMAKESPEC = $$(QMAKESPEC)

 

#UNIX + gcc下声明使用预编译头文件

#GCC 3.4 及以后版本支持预编译头文件

unix{

    contains(   TRAIN_QMAKESPEC, g++ ) {

        CONFIG   *= precompile_header

    }

}

#WIN32下声明使用预编译头文件

win32{

    CONFIG   *= precompile_header

   

    # 去掉 strcpy 等编译警告

    QMAKE_CXXFLAGS   *= -wd4996

}

 

#UNIX下编译设置

unix{

    DEFINES   *= unix __unix 

}

 

#WIN32下编译设置

win32{

    DEFINES *= WIN32

}

 

#激活 STL、RTTI、EXCEPTIONS 支持

CONFIG *= stl exceptions rtti

#激活多线程、编译警告

CONFIG *= thread warn_on

 

# 不同编译版本相关的配置

BUILDTYPE = $$(TRAINBUILDTYPE)

equals(BUILDTYPE,debug){

    CONFIG   += debug

    CONFIG   -= release

}

equals(BUILDTYPE,release){

    CONFIG   += release

    CONFIG   -= debug

}

equals(BUILDTYPE,all){

    CONFIG   -= debug

    CONFIG   -= release

    CONFIG   += debug_and_release build_all

}

 

# 指定代码中宏定义

debug_and_release {

    CONFIG(debug,   debug|release) {

        DEFINES += TRAIN_DEBUG

    }

    CONFIG(release,   debug|release) {

        DEFINES += TRAIN_RELEASE

    }

} else {

    debug:   DEFINES += TRAIN_DEBUG

    release:   DEFINES += TRAIN_RELEASE

}

 

# 配置系统使用的编译位数类型

BUILDBIT = $$(TRAINBUILDBIT)

 

# 不同编译版本相关的配置

equals(BUILDBIT,32){

    # 扩展 32 位配置项

    CONFIG   *= x86

    DEFINES   *= TRAIN_32

}

equals(BUILDBIT,64){

    # 扩展 64 位配置项

    CONFIG   *= x64

    DEFINES   *= TRAIN_64

}

 

# 指定不同编译版本中间文件目录

debug_and_release {

    CONFIG(debug,   debug|release) {

        TRAIN_OBJ_PATH = $$TRAIN_OBJ_PATH/debug

    }

    CONFIG(release,   debug|release) {

        TRAIN_OBJ_PATH = $$TRAIN_OBJ_PATH/release

    }

} else {

    debug:TRAIN_OBJ_PATH   = $$TRAIN_OBJ_PATH/debug

    release:TRAIN_OBJ_PATH   = $$TRAIN_OBJ_PATH/release

}

    下面我们来详细介绍一下这个pri文件。

 

1,开头的声明

    首先,在pri文件开头有一个声明,指明了需要创建的环境变量。也就是说,这个pri文件依赖于环境变量值,当然,您也可以选择不用环境变量,而是通过修改pri文件中的相关内容来改变这些设置,但是使用环境变量会方便一些,因为不用每次都修改这个pri文件。

    这个pri文件用到的环境变量有3个,分别是:

    1)  TRAINDEVHOME

用来描述项目的根目录,目录结构如下:

$TRAINDEVHOME

------bin          编译好的运行程序所在目录

------lib          编译好的lib文件所在目录

------include      公共头文件目录,其下可以再分子目录

------src          源代码根目录

------temp          临时文件目录

 

2)  TRAINBUILDTYPE 

编译版本,取值:

debug       编译debug版本

release     编译release版本

all         同时编译debug、release版本,即两个版本都编译。

 

3)  TRAINBUILDBIT  

编译位数,取值:

32          编译成32位程序

64          编译成64位程序

 

    当然了,QTDIR、QMAKESPEC是安装完Qt后必不可少的环境变量,本文不再赘述。

 

2,环境变量检查

1.      

2.      

3.      

4.      

DEVHOME = $$(TRAINDEVHOME)

isEmpty(DEVHOME) {

    error('TRAINDEVHOME'环境变量必须被定义.)

}

通过Qt的isEmpty()函数判断环境变量是否存在,如果为空,则输出错误信息并退出。

    因为isEmpty()只能使用自定义变量而无法使用环境变量,因此我们先定义了DEVHOME这个变量并赋值为环境变量值,然后用它进行判断。

 

3,公共目录

1.      

2.      

3.      

4.      

5.      

6.      

7.      

8.      

9.      

10.   

11.   

12.   

13.   

14.   

15.   

16.   

# 设置变量:系统执行文件路径、库文件路径、临时文件生成路径、头文件包含路径

TRAIN_BIN_PATH = $$(TRAINDEVHOME)/bin

TRAIN_LIB_PATH = $$(TRAINDEVHOME)/lib

TRAIN_OBJ_PATH = $$(TRAINDEVHOME)/obj

TRAIN_SRC_PATH = $$(TRAINDEVHOME)/src

TRAIN_UIC_PATH = $$(TRAINDEVHOME)/obj/uic

TRAIN_INCLUDE_PATH =   $$(TRAINDEVHOME)/include

 

# 设置所引用的库文件的路径

QMAKE_LIBDIR *= $$TRAIN_LIB_PATH

 

DEPENDPATH *=  .\

        $$TRAIN_INCLUDE_PATH

       

INCLUDEPATH *=  .\

        $$TRAIN_INCLUDE_PATH

    这里定义了可执行程序目录等路径,都依赖于TRAINDEVHOME环境变量,如果您不想用环境变量,可以使用自定义变量来替换(需要注意自定义变量的语法跟环境变量不同)。

    上述变量都是公共路径设置。在pro中引用本pri文件后,还可以继续对这些变量值进行引用加工(比如继续追加目录层级),从这些变量的名称就可以对其用途略知一二,现在我们分别看一下。

表02-06-01

关键字

含义

TRAIN_BIN_PATH

编译完成的可执行程序的存放路径

TRAIN_LIB_PATH

编译完成的lib文件的存放路径

TRAIN_OBJ_PATH

编译产生的临时文件的根目录

TRAIN_SRC_PATH

源代码的根目录

TRAIN_UIC_PATH

编译ui文件产生的临时文件根目录(它是TRAIN_OBJ_PATH目录的子目录)

TRAIN_INCLUDE_PATH

项目的公共include目录

QMAKE_LIBDIR

Qt关键字

设置所引用的库文件的路径。比如,编译某个exe时如果用到了dll文件,那么这个变量用来告诉编译器到哪个目录去找所需的lib文件。

DEPENDPATH

Qt关键字

用来指明所依赖的头文件路径

INCLUDEPATH

Qt关键字

用来告诉编译器头文件的搜索目录。

这样的话,在源代码中引用头文件时,就可以直接写文件名或者相对路径,比如:

    #include "header.h"

    #include "base/basedll/header.h"

此处的目录是相对于INCLUDEPATH,也就是:

    $INCLUDEPATH/base/basedll/header.h

           

4,编译器设置

1.      

2.      

3.      

4.      

5.      

6.      

7.      

8.      

9.      

10.   

11.   

12.   

13.   

14.   

15.   

16.   

# 获取编译 Qt 的编译器类型

TRAIN_QMAKESPEC   = $$(QMAKESPEC)

 

#UNIX   + gcc下声明使用预编译头文件

#GCC   3.4 及以后版本支持预编译头文件

unix{

    contains( TRAIN_QMAKESPEC, g++ ) {

        CONFIG *= precompile_header

    }

}

#WIN32下声明使用预编译头文件

win32{

    CONFIG *= precompile_header

   

    # 去掉strcpy等编译警告

    QMAKE_CXXFLAGS *= -wd4996

}

本部分内容用来处理预编译头文件的内容。gcc3.4及以后的版本支持预编译头文件,因此为了判断gcc编译器,我们使用了Qt的contains()函数。该函数也无法识别环境变量,因此我们定义了变量TRAIN_QMAKESPEC。 当unix(linux也走pri中的unix分支)的编译器为gcc时,CONFIG配置项就增加了预编译头文件的支持:

CONFIG *= precompile_header

windows下(pri中的win32分支,win32是Qt的关键字)默认提供预编译头文件支持,因此无条件增加precompile_header的选项。

为了消除strcpy造成的4996编译警告,我们增加如下语句:

    QMAKE_CXXFLAGS *= -wd4996

 

5,宏定义

1.      

2.      

3.      

4.      

5.      

6.      

7.      

8.      

9.      

#UNIX下编译设置

unix{

    DEFINES   *= unix __unix 

}

 

#WIN32下编译设置

win32{

    DEFINES *= WIN32

}

在代码中,我们经常需要判断当前运行程序的操作系统类型,因此需要预先定义操作系统类型宏,上述代码就给出了在unix以及windows下的定义操作系统类型宏的方法,使用了DEFINES语法,这样在源代码中,我们就可以直接使用这些宏进行判断了。本部分内容在上节进行过讲解,这里不再展开。

 

6,激活stl、rtti、exceptions支持

1.      

2.      

#激活 STL、RTTI、EXCEPTIONS 支持

CONFIG *= stl exceptions rtti

    如果您使用stl库,那么请激活stl支持。

    如果您使用异常处理,那么请激活exceptions。

    如果您需要运行时类型识别,那么请激活rtti。

    这些选项都是CONFIG配置项,可以单独配置。

 

7,激活多线程,编译

1.      

2.      

#激活多线程、编译警告

CONFIG *= thread warn_on

如果您的项目中用到多线程,请激活thread。因为本pri文件是公共pri,所以如果您的某个子模块用不到多线程支持,您可以在子模块的pro中禁用多线程,方法是在子模块的pro中使用如下语句:

CONFIG -= thread

 

8,编译成debug版还是release版本

1.      

2.      

3.      

4.      

5.      

6.      

7.      

8.      

9.      

10.   

11.   

12.   

13.   

14.   

15.   

# 不同编译版本相关的配置

BUILDTYPE = $$(TRAINBUILDTYPE)

equals(BUILDTYPE,debug){

    CONFIG   += debug

    CONFIG   -= release

}

equals(BUILDTYPE,release){

    CONFIG   += release

    CONFIG   -= debug

}

equals(BUILDTYPE,all){

    CONFIG   -= debug

    CONFIG   -= release

    CONFIG   += debug_and_release build_all

}

    如果需要对我们的程序进行调试,我们会选择debug版本,因为debug版的程序含有很多调试信息,而如果我们需要发布版则使用release版本,因为它的执行效率更高运行更快。此处我们使用了Qt的equals()函数来判断编译版本。同样这个函数也不识别环境变量,因此我们定义了BUILDTYPE变量来进行判断。请注意,equals()函数中的第二个参数中的debug、release只是个字符串,下列语句中的debug、release才是Qt的关键字。

CONFIG+=debug

    CONFIG -= release

   

9,程序运行时如何区分debug版还是releaes版

    有时候,我们在程序运行过程中,需要知道自己是debug版还是release版,该怎么做呢?

1.      

2.      

3.      

4.      

5.        

6.      

7.      

8.      

9.      

10.   

11.   

12.   

# 指定代码中宏定义

debug_and_release   {

    CONFIG(debug, debug|release) {

          DEFINES += TRAIN_DEBUG

    }

    CONFIG(release, debug|release) {

          DEFINES += TRAIN_RELEASE

    }

}   else {

    debug: DEFINES += TRAIN_DEBUG

    release: DEFINES += TRAIN_RELEASE

}

    上述语法是分支判断语法,其{}前面的字符串是CONFIG的配置项,比如此处的debug_and_release。我们使用上述方法得知当前编译版本并定义了相关的宏TRAIN_DEBUG、TRAIN_RELEASE。这样在源代码中就可以直接用这两个宏来区分debug版与release版本了。请大家务必注意下列代码的语法:

    CONFIG(debug, debug|release)

    上述语句用来判断是否正在编译debug版本。

    CONFIG(release, debug|release)

    上述语句用来判断是否正在编译release版本。

 

    而下面的语句用来区分debug编译分支和release编译分支,方法是在debug或者release后使用冒号(:)。

debug: DEFINES += TRAIN_DEBUG

release: DEFINES += TRAIN_RELEASE

   

10,程序运行时如何区分32位程序还是64位程序

    程序运行的时候,有可能需要知道自己被编译成了32位还是64位,方法如下:

1.      

2.      

3.      

4.      

5.      

6.      

7.      

8.      

9.      

10.   

11.   

12.   

13.   

14.   

# 配置系统使用的编译位数类型

BUILDBIT = $$(TRAINBUILDBIT)

 

# 不同编译版本相关的配置

equals(BUILDBIT,32){

    #   32 位配置项

    CONFIG   *= x86

    DEFINES   *= TRAIN_32

}

equals(BUILDBIT,64){

    #   64 位配置项

    CONFIG   *= x64

    DEFINES   *= TRAIN_64

}

    方法与区分debug版本还是release版本类似,因此不再详述。

 

11,区分debug版本、release版本的临时文件

    编译程序时,编译同一个项目的debug版本与release版本会产生不同的临时文件,我们当然不希望这些临时文件会相互覆盖,因此我们需要为它们指定不同的目录。

1.      

2.      

3.      

4.      

5.      

6.      

7.      

8.      

9.      

10.   

11.   

12.   

# 指定不同编译版本中间文件目录

debug_and_release {

    CONFIG(debug,   debug|release) {

        TRAIN_OBJ_PATH = $$TRAIN_OBJ_PATH/debug

    }

    CONFIG(release,   debug|release) {

        TRAIN_OBJ_PATH = $$TRAIN_OBJ_PATH/release

    }

} else {

    debug:TRAIN_OBJ_PATH   = $$TRAIN_OBJ_PATH/debug

    release:TRAIN_OBJ_PATH   = $$TRAIN_OBJ_PATH/release

}

    从上述代码可以看出,debug版本与release版本产生的临时文件分别存放到obj下面的debug目录、release目录,这样就不会相互覆盖了。

 

结语

----------------------------------------------------------------

    本节详细介绍了如何为项目引入pri体系并且使它正常运转起来。本文提到的pri使用了比较多的配置项,大家可以根据个人的需求调整其中的配置项。但是其中最常被修改的可能也就下面3个:

TRAINDEVHOME   根目录,其下是bin、lib、src等子目录。

TRAINBUILDTYPE 编译版本: debug|release|all

TRAINBUILDBIT  编译位数: 32|64

    原因就是使用者可能根据自己的项目需求创建了不同的环境变量名(比如不是TRAINDEVHOME,而是SOURCEHOME),或者干脆不用环境变量仅仅使用自定义变量。如果仅仅使用自定义变量,那么就需要将本pri中所有使用环境变量的地方改成使用自定义变量,而且一定要注意自定义变量的使用语法跟环境变量不同:

    环境变量: $$(环境变量名)

变量:     $$变量名

    如果使用自定义变量,那么请注意项目的pro文件中,如果要引用该pri文件,那么也要进行相应修改:

代码清单02-06-01

myprogram.pro

1.      

2.      

PRI_FILE_PATH = ../../

include ($$PRI_FILE_PATH/src/gui_base.pri)

 

    本节内容比较多,请大家慢慢消化。如果还是不知道该怎样使用pri文件,请学习下节内容开始练手吧。

----------------------------------------------------------------

《Qt入门与提高-GUI产品开发》目录请添加链接描述
上一节:KS02-05 pri 文件有啥用?
下一节:


上一篇:1127 ZigZagging on a Tree (30 分)


下一篇:KS02-05 pri 文件有啥用?