目录

词法

string

1、数据类型

2、特殊处理的内置变量

3、转义字符

关键字:包括语法关键字、特殊变量

语法

变量

变量、属性、环境变量

变量使用

全局变量作用域

函数定义和使用

判断语句和循环语句

判断语句

判断语句

条件分支

if

案例

循环语句

for(iterate,list)

for(ever)

for(var,forever)

break(),next(),return()

案例

qmake language相关的文件后缀

杂谈


说明:该文档主要是对qmake手册做一些补充

词法

词法阶段主要作用是将原始的qmake language写的代码全部转换成ProToken类型去。并存入Profile对象中去。

qmake中词法阶段识别出的类型(token type)有这些(一共32种):

// These token definitions affect both ProFileEvaluator and ProWriter
enum ProToken {TokTerminator = 0,  // end of stream (possibly not included in length; must be zero)TokLine,            // line marker:// - line (1)TokAssign,          // variable =TokAppend,          // variable +=TokAppendUnique,    // variable *=TokRemove,          // variable -=TokReplace,         // variable ~=// previous literal/expansion is a variable manipulation// - lower bound for expected output length (1)// - value expression + TokValueTerminatorTokValueTerminator, // assignment value terminatorTokLiteral,         // literal string (fully dequoted)// - length (1)// - string data (length; unterminated)TokHashLiteral,     // literal string with hash (fully dequoted)// - hash (2)// - length (1)// - string data (length; unterminated)TokVariable,        // qmake variable expansion   $$  $${}// - hash (2)// - name length (1)// - name (name length; unterminated)TokProperty,        // qmake property expansion   $$[]// - hash (2)// - name length (1)// - name (name length; unterminated)TokEnvVar,          // environment variable expansion  $$()// - name length (1)// - name (name length; unterminated)TokFuncName,        // replace function expansion// - hash (2)// - name length (1)// - name (name length; unterminated)// - ((nested expansion + TokArgSeparator)* + nested expansion)?// - TokFuncTerminatorTokArgSeparator,    // function argument separatorTokFuncTerminator,  // function argument list terminatorTokCondition,       // previous literal/expansion is a conditionalTokTestCall,        // previous literal/expansion is a test function call// - ((nested expansion + TokArgSeparator)* + nested expansion)?// - TokFuncTerminatorTokReturn,          // previous literal/expansion is a return valueTokBreak,           // break loopTokNext,            // shortcut to next loop iterationTokNot,             // '!' operatorTokAnd,             // ':' operatorTokOr,              // '|' operatorTokBranch,          // branch point:// - then block length (2)// - then block + TokTerminator (then block length)// - else block length (2)// - else block + TokTerminator (else block length)TokForLoop,         // for loop:// - variable name: hash (2), length (1), chars (length)// - expression: length (2), bytes + TokValueTerminator (length)// - body length (2)// - body + TokTerminator (body length)TokTestDef,         // test function definition:TokReplaceDef,      // replace function definition:// - function name: hash (2), length (1), chars (length)// - body length (2)// - body + TokTerminator (body length)TokBypassNesting,   // escape from function local variable scopes:// - block length (2)// - block + TokTerminator (block length)TokMask = 0xff,TokQuoted = 0x100,  // The expression is quoted => join expanded stringlistTokNewStr = 0x200   // Next stringlist element
};

string

1、数据类型

qmake language中数据类型只有字符串组(stringlist)类型(但是无法直接以下标的形式访问数组中单个元素,可以通过内置函数member来获取某个元素),qmake解析字符串时以空格或者换行符作为字符串分隔符。如果要在字符串中填入空格或其他特殊字符,避免被qmake误解析,可以用双引号将字符串引用起来。

message(aa bb cc)   #输出:aa bb cc
message("aa,bb,cc") #输出:aa,bb,cc message只能输入一个参数,参数以空格隔开,多余一个参数会报错
var=aa bb cc          #将字符串组存放入变量var中,aa bb cc 会被解析成三个字符串
message($$var)        #输出aa bb cc
message($$size(var))  #输出3,表示变量var中存放了三个字符串
var="aa bb" cc        #"aa bb" cc 会被解析成两个字符串
message($$size(var))  #输出2,表示变量var中存放了两个字符串
var = "aa bb"" cc"    #"aa bb"" cc" 会被解析成一个字符串
message($$size(var))  #输出1,表示变量var中存放了一个字符串
var = "aa bb" " cc"   #"aa bb" " cc" 会被解析成两个字符串
message($$size(var))  #输出2,表示变量var中存放了两个字符串
var = "aa bb cc"      #"aa bb cc" 会被解析成一个字符串
message($$size(var))  #输出1,表示变量var中存放了一个字符串
var = "aa" "bb" "cc"  #"aa" "bb" "cc"会被解析成三个字符串
message($$size(var))  #输出3,表示变量var中存放了三个字符串var = aa,bb     #定义一个名字为var的变量,将字符串"aa,bb"赋予给它,等价于var= "aa,bb"。
message($$var)  #将字符串"aa,bb"打印出来。输出aa,bb,注意此时aa,bb已经在前面赋值的时候被解析成一个字符串了,此处作为内容传递时,不会被解析成两个参数。
var+= ,cc       #将字符串",cc"附加到var中。var:"aa,bb" ",cc"
message($$var)  #输出:aa,bb ,cc  注意",cc"前面有一个空格
var= aa bb cc   #将字符串组 aa bb cc存放到var中。var:aa bb cc
var*= aa dd     #将字符串组aa dd去除与var中内容相同的字符串单元后放到var中,字符串中的内容必须以空格隔开才被当做一个字符串单元。var:aa bb cc dd
message($$var)  #输出:aa bb cc dd
var-= aa cc     #将与字符串组aa cc中相同单元的内容从var中存放的字符串中去除。var:bb dd
message($$var)  #输出:bb dd
var = hello world,for fun
var~= s/l/t     #将字符串组hello world,for fun中的第一个字符串单元中的l替换成t
message($$var)  #输出:hetto world,for fun
var~= s/l/t/g   #将字符串组hello world,for fun中的所有字符串单元中的l替换成t
message($$var)  #输出:hetto wortd,for fun

qmake language ~= 字符串替换操作 正则表达式_丘上人的博客-CSDN博客

2、特殊处理的内置变量

_LINE_(当前行号)、_FILE_(当前文件名)、LITERAL_HASH(字符'#')、LITERAL_DOLLAR(字符'$')、LITERAL_WHITESPACE(制表符tab键'\t'),在词法阶段就直接替换成对应的值,相当于qmake language的预处理。

3、转义字符

qmake language对string中的字符转义是在词法分析阶段,转义字符包括:

//qmake QMakeParse.read中词法分析对转义操作的代码部分else if (c == '\\') {static const char symbols[] = "[]{}()$\\'\"";ushort c2;if (cur != end && !((c2 = *cur) & 0xff00) && strchr(symbols, c2)) {c = c2;cur++;} else {deprecationWarning(fL1S("Unescaped backslashes are deprecated"));}}

词法分析阶段不会对(\n,\t,\r)转义。如果要对(\n,\t,\r)转移,也就是获取到('\n','\r','\t'),需要用escape_expand(string)这个replace函数进行操作。('\n':换行,移动到下行;'\r':回车换行,移动到下行行首,移动到行首;'\t':tab键)

message("\[ \] \{ \} \( \) \$ \\ \' \" aa\nbb\rcc\tdd")
message($$escape_expand("\[ \] \{ \} \( \) \$ \\ \' \" aa\nbb\rcc\tdd"))  #字符串“\[ \] \{ \} \( \) \$ \\ \' \" aa\nbb\rcc\tdd”在词法分析阶段就被处理成:“[ ] { } ( ) $ \ ' " aa\nbb\rcc\tdd”。escape_expand再对\n \r \t 进行转移处理。

输出:

另外在词法处理时还会兼顾行延续功能:

var = aaaa  \
bbbb
message($$var)  #输出Project MESSAGE: aaaa bbbb

escape_expand所做的字符转义在qmake language中不作为字符串分隔符号,参看如下代码:

var=aaa bbb
message($$size(var))
var= aaa$$escape_expand(\n)bbb
message($$size(var))
var = aaa$$escape_expand(\t)bbb
message($$size(var))
var = aaa$$escape_expand(\r)bbb
message($$size(var))
#输出:
Project MESSAGE: 2
Project MESSAGE: 1
Project MESSAGE: 1
Project MESSAGE: 1

关键字:包括语法关键字、特殊变量

qmake language 关键字 true false host_build option return next break _LINE_ _FILE_ LITERAL_HASH LITERAL_DOLLAR LITERAL_WHITESPACE  CONFIG ARGS ARGC ever forever host_build TEMPLATE QMAKE_PLATFORM QMAKE_DIR_SEP QMAKESPEC REQUIRES :qmake language 关键字

语法

变量

qmake language变量分为内置变量和自定义变量,内置变量包括qmake在C++中定义的变量,和用qmake language写的配置文件定义的变量。在文档的目录:Qt 5.12->qmake Manual->Variables有对内置变量做了一些介绍。

qmake language中只有一种数据类型,字符串组(stringlist)类型。定义一个变量必须要有等号。
定义一个变量的表达式形式:variablename = [values]

var1 = aaa bbb #定义一个名字为var1的变量,用字符串组aaa bbb对其进行初始化
var2 =         #定义一个名字为var2的变量,初始化为空

变量、属性、环境变量区别

qmake language(属性property、变量variable、环境变量evironment variable) 讲述$$var 、$${var}、 $$[]、 $$() 、$()的区别及使用。

变量使用

在文档目录:Qt 5.12->qmake Manual->qmake Language下有对变量使用做详细介绍
几个要点:
1、qmake language中的变量只有字符串组类型,没有bool、float、double类型!!
2、在赋值符号的右边的内容都会被当成字符串组,当在等号右边遇到$$ 符号时会提取该变量值或计算该replace函数结果后再赋值给变量。
3、双引号的作用在于传递函数参数的时候,可以将逗号作为字符串的一部分传入,但有多个函数参数时,函数参数需要用逗号隔开。
4、访问变量内容使用$$variablename 或者 $${variablename}。区别是$$var.de变量名是var.de,$${var}.de的变量名是var。 通过后者可以用于组装复杂的变量名,并获取其内容。
5、qmake language不允许变量名直接用$$ $$$${$$}的形式直接进行嵌套。但可以通过eval(expression)这个replace函数来达到目的。注意eval函数还可以是一个test函数。
qmake language eval(string) 函数_丘上人的博客-CSDN博客

qmake有提供加减运算的函数,num_add(arg1 [, arg2 ..., argn]),qmake对其实现是先将字符串转换成数值,再对数值进行操作,再将数值转换成字符串,再返回。

变量命名规则:以字母开头,后面可以有‘_’、‘.’、数字、字母,遇到其他字符表示变量命名截止。变量名区分大小写
VAR =       #定义一个名字为VAR的空变量,没有定义的变量也可以被调用VAR1:
VAR1 = tt1   #定义一个名字为VAR1的变量,并将字符串tt1赋予给它,等价于VAR1="tt1"。VAR1:"tt1"message(aa bb cc) #输出aa bb cc
message("$${VAR1} aa,bb")  #输出:"tt1 aa,bb"。需要注意的是message只能输入一个参数,函数参数以逗号隔开,要让message输出逗号,需要用双引号引起来
#$$varname 与 $${varname} 都是取出变量中存放的字符串,区别是$$var.de变量名是var.de,$${var}.de的变量名是var。 VAR = 3
VAR3=vvv
vvv.a = ttttttt
VARt = $$eval(VAR$${VAR}).a
message($$VARt)   #输出:vvv.a
message($$eval($$VARt))  #输出:ttttttt
message($$eval($$eval(VAR$${VAR}).a))输出:ttttttt 。 eval可以多重嵌套#qmake language 计算加减法
first=11
second=22
sum1 = $$num_add($$first, -$$second)second_neg = -$$second
second_neg ~= s/^--//  #正则表达式"^--" 的意思是如果开头有两个符号,就将两个符号变成空,也就是消掉--
sum2 = $$num_add($$first, $$second_neg)message("sum1=$$sum1 , sum2=$$sum2")  #输出:sum1=-11 , sum2=-11

快速查找qt pro文件中的用qmake language写的库函数和变量_丘上人的博客-CSDN博客

全局变量和函数内变量作用域

qmake language中与C++或java等他语言的变量作用域有点差异,变量作用域只有全局的和函数内的。用大括号"{}"括起来的代码无法构成局部变量。具体原因可以参考:m_valuemapStack

var1 = 1111
{#与C++或java不同,单纯的大括号内定义的变量也属于全局变量var2 = 2222
}
true:{  #条件分支中的变量也属于全局变量var3 = 3333
}
defineTest(ptestf){ #只有函数中定义的变量的作用于才只限定在函数中。var4 = 4444
}
defineReplace(prepf){#只有函数中定义的变量的作用于才只限定在函数中。但对变量进行export之后,该变量作用域就会变成全局作用域。var5 = 5555export(var5)  #将函数内的变量转变为全局变量。
}
ptestf()         #调用自定义的test函数
tvar = $$prepf() #调用自定义的replace函数,replace函数调用必须在等号右边!message($$var1)  #输出1111
message($$var2)  #输出2222
message($$var3)  #输出3333
message($$var4)  #输出空
message($$var5)  #输出5555

函数内定义的变量作用于只在函数内有效。全局变量作用范围为从声明开始到整个工程解析结束,export(variable)出的全局变量variable作用范围从第一次调用函数开始。如下,第一次调用ttfun开始。

message($$tt1)  #输出空
message($$tt2)  #输出空
message($$tt3)  #输出空
tt1=dae
defineTest(mytt){message($$tt1)message($$tt2)message($$tt3)
}
tt2=ge
mytt()            #输出dae#输出ge#输出空
tt3=eee
message($$tt1)   #输出dae
message($$tt2)   #输出ge
message($$tt3)   #输出eeedefineTest(ttfun){myvar.aa.cc=12345myvar.aa.bb=$${LITERAL_HASH}define TT 12345  #$${LITERAL_HASH}表示qmake language中输出#号export(myvar.aa.bb)
}message($$myvar.aa.bb)  #输出为空
ttfun()
message($$myvar.aa.cc)  #输出空,全局环境中没有名字为myvar.aa.cc的变量
message($$myvar.aa.bb)  #输出#define TT 12345,全局环境中有名字为myvar.aa.bb的变量且有值

qmake在源码端为qmake language定义的特殊变量: qmake language 关键字

函数定义和使用

1、函数定义的函数体或代码块必须用{}括起来,左括号“{”必须与函数名或者条件语句同行。如果不在同一行,必须要在后面加转义符号。


#defineReplace(repaceFunctionName){#defineReplace是关键字,表示定义replace函数。定义函数名字为repaceFunctionName的replace函数,函数的参数个数是不限制的,不需要列举参数名
defineReplace(repaceFunctionName)\
{
#.......#(函数体)函数体中语句结束不需要“;”!!!
}defineTest(testFunctionName){defineTest是关键字,表示定义test函数。定义函数名字为testFunctionName的test函数。
#.......
}

2、函数返回值必须要用括号括起来。test函数如果需要返回值,最好显示的"return (true)"或"return (false)"。replace函数没有返回值则默认返回为空。

3、代码中区分test函数和replace函数的两种方法:
(1)看函数定义,如果是defineTest()  defineReplace()分别是test函数和replace函数定义的标志
(2)replace函数使用时必须在前面加$$ 否则会被识别为test函数,如果不存在这样的test函数则会报错。 
4、test函数的返回值无法赋予给变量,也无法打印出来,只能直接将test函数当做条件来使用。对于复杂的判断语句也只能直接将函数名进行拼接。
5、内置的replace 和test函数,传入函数参数时需要注意,有的函数需要传入变量名,有的函数需要传入变量的内容,需要视情况而定。比如greaterThan($$ARGC,1)和count(ARGS,2,>=)这两个test函数的传入参数。常用的打印函数message(), 如果想获取变量中的内容,须传入变量中的内容。
6、函数参数的个数在定义时无法通过模式进行限制。但是可以在函数体种通过加入判断语句进行筛查。因为qmake language只有字符串类型数据,所以传入的参数只有字符串类型。如果函数体没有用逻辑进行筛查,理论是可以传入无数个参数的。函数参数用逗号隔开。如果直接传入字符串其字符串中含有逗号,需要用双引号引起来,否则字符串会被当成多个参数。
7、函数内部的ARGC表示参数个数,ARGS表示参数列表,用空格隔开。size(ARGS)不一定等于ARGC,因为传入的参数很可能有含有空格的字符串。第一个参数存放在变量名为1的变量中,第二个存放在2中,依次类推。

案例:

defineTest(mytestFun){ message("argc=$${ARGC} , args=$${ARGS}")count(ARGC,2){return (true)}else{return (false)}
}defineReplace(myreplaceFun){count(ARGC,1,>=){message($$1)}return ("$${ARGS} test")
}build_pass{mytestFun(1,2){message(here)}else{message(gggg)}
}
mytestFun(aa,bb);
var=$$myreplaceFun(aa,bb)
message($$var)输出:
Project MESSAGE: argc=2 , args=1 2
Project MESSAGE: gggg
Project MESSAGE: argc=2 , args=aa bb
Project MESSAGE: aa
Project MESSAGE: aa bb test

qmake language 内置函数 自定义函数 defineTest(testfunctionname) defineReplace(repacefunctionname)
快速查找qt pro文件中的用qmake language写的库函数_丘上人的博客-CSDN博客

判断语句和循环语句

判断语句的else和循环语句的for()后面的代码块如果没有{}括起来,必须要加冒号":",冒号的写法适合代码只有一行的代码块的简写。

判断语句

qmake中变量没有bool类型,也没有整数或浮点数的,只有字符串类型。qmake language中"true"和"false"都有两重意思,作为非判断语句的条件时,他们会被解析成字符串;作为判断语句的条件时,"true"和"false"才会被qmake做解释成C++bool类型,"true"会被解析成C++中的bool类型的true,"false"会被解析成C++中bool类型的false。"host_build"是与"true" "false"一样的关键字,也具有两重意思,区别在作为判断语句的条件时qmake根据配置情况将其解析成C++的bool类型的true或false。

判断语句

1、简单判断语句(样式:condition)
qmake language的condition可以是任何字符串。
(1)对于单独的字符串"true"会被解析成C++ bool类型的true
(2)对于单独的字符串"false"会被解析成C++bool的false
(3)对于单独的字符串"host_build"会根据情况解析成C++bool的true或false
(4)对于单独的字符串"build_pass"会在生成makefile的时候被解析成C++bool的true,其他时候被解析成C++bool的false
(5)对于CONFIG中存在的任何字符串,会被解析成C++bool的true:参考内建函数
(6)其他的任何字符串都会被解析成C++bool的false
(7)condition可以是test函数调用。根据函数返回解析成C++bool的true或false。test函数调用如果被双引号引用会被当做普通字符串。

var=aa"false"{message(true)}
else:message(false)"count(var,1)"{message(true)}
else:message(false)#输出
#Project MESSAGE: false
#Project MESSAGE: false

2、非语句(样式:!condition),对条件进行取反运算。比如 !count(var,1)
2、或语句(样式:condition1|condition2),对两个条件进行或运算。
3、与语句(样式:condition1:condition2),对两个条件进行与运算。
4、与或非各种条件语句的组合,对多个条件进行运算。
5、条件conditions 不能直接用括号括起来,但是可以借助if(conditions)来达到目的。

条件分支

qmake language的判断语句 条件分支 分为then分支(没有then关键字)和else分支,分支必须用{}括起来,样式为:

conditions{
#then 分支内容
}
else{
#else分支内容
}conditions:{} #不报错的冗余写法
else:{}conditions{} #简化写法
else:单条语句conditions:单条语句   #不报错的简化写法,但是不推荐,并且在某些条件语句组合下会出错!!!!
else:单条语句conditions:单条语句   #错误写法,可能会导致出错
conditions{}    #正确写法

if

if 在qmake language中是一个内置的test函数。样式为

if(conditions){
#then 分支
}
else{
#else 分支
}

案例

true{              #等价于if(true){      .  if()是个test函数#.....
}
else{#......
}!true{....}var1=true
var2=false
$$var1|$$var2{  #表示var1或var2中的一个为true时执行{}中的内容
......
}
$$var1:$$var2{  #表示var1和var2都为true是执行{}中的内容
.....
}isEmpty(PWD){#.....
}else{#......
}#var=$$isEmpty(PWD)   #函数返回值错误的使用方式 ,报错  #E:/workspace/QtWork/testEmpty/testEmpty.pro(24): 'isEmpty' is not a recognized replace function.#这里描述了一种函数返回值的正确使用方式
var=                  #定义一个名字为var的空变量。下面的操作实现将test函数返回值赋予var
isEmpty(PWD){var=true}
else{var=false}
$$var{#....
}else{#......
}!build_pass{             #build_pass特殊变量,该语句的意思在创建makefile时为true
var=
var1=isEmpty(var)
$$var1{message(empty)}     #$$只能取一次值,取值为isEmpty(var)后不会继续执行isEmpty(var),isEmpty(var)不是关键字,所以这里判断语句是有问题的!!
else{message(not empty)}var2=
isEmpty(var){var2=true}
else{var2=false}
$$var2{message(empty)}
else:message(not empty)
}
#输出:
#Project MESSAGE: not empty
#Project MESSAGE: empty

判断条件和else之后如果没有{},必须在其后加":"

true:message(1)
else:message(2)

循环语句

有三种:for(iterate,list)  for(ever) for(var,forever)。结合break(),next(),return() 进行使用

for(iterate,list)

for(iterate,list)是一个特殊的内建test函数,它直到枚举完list的内容或遇到break或return才跳出循环体。

!build_pass:{   #build_pass特殊变量,该语句的意思表示只执行一遍。var=11 22 33 44 55for(t,var):message($$t)message(end1)for(t,var){message($$t)equals(t,33){break()}}message(end2)for(t,var){message($$t)equals(t,33){return()}}message(end3)
}
message(end4)#输出:
#Project MESSAGE: 11
#Project MESSAGE: 22
#Project MESSAGE: 33
#Project MESSAGE: 44
#Project MESSAGE: 55
#Project MESSAGE: end1
#Project MESSAGE: 11
#Project MESSAGE: 22
#Project MESSAGE: 33
#Project MESSAGE: end2
#Project MESSAGE: 11
#Project MESSAGE: 22
#Project MESSAGE: 33
#Project MESSAGE: end4

for(ever)

没有遇到break(),无限循环,循环次数最多执行1000次(qmake中代码中写死),否则会报错

build_pass{  #循环var = 10for(ever){var=$$num_add($$var,-1)                  #减一操作equals(var,5)|lessThan(var,5){break()}    #当var<=5的时候退出message(here$$var)}
}

for(var,forever)

没有遇到break()\return()代码会无限循环,无限循环最高循环次数最多执行1000次(qmake中代码中写死),否则会报错。

传入的var作为内部存放计数器数值的变量,从0开始(原来的值会被qmake抹除,传入的var只是被当做一个计数器变量使用),运行一遍循环内容,计数器变量值就加1,并存入到变量中。循环内部修改var值无效!!!主要意义是将var作为传出参数查看执行次数。

build_pass{  #循环var = 0for(var,forever){                              #传入的var作为内部存放数值的变量,运行一遍循环内容就加1。循环内部修改var值无效!!!主要意义是将var作为传出参数查看执行次数。equals(var,5)|greaterThan(var,5){break()}    #当var<=5的时候退出message(here$$var)}
}

break(),next(),return()

分别表示:退出for循环、结束本次循环执行下一次循环、退出函数。

build_pass{for(var,forever){lessThan(var,3){next()}greaterThan(var,5){break()}message($$var)}
}
#Project MESSAGE: 3
#Project MESSAGE: 4
#Project MESSAGE: 5

for()之后如果没有{},for()后面必须加":"

list= 11 22 33 44
for(var,list):message($$var)

案例

defineTest(mytestFun){message(argc=$${ARGC}  args=$${ARGS}) #等价于message("argc=$${ARGC}  args=$${ARGS}")greaterThan($$ARGC,1){message(in greaterThan block:$$1)}count(ARGS,2,>=){message(in count block:$$2)}var=message("in for(var,list) block")for(var,ARGS):message($$var)message("in for(var,forever) block")for(var,forever){!lessThan(var,$$ARGC){break()}t=$$num_add($$var,1)message($${t}:$${eval($$t)})}
}mytestFun(aa,bb,11,3rr)输出:
Project MESSAGE: argc=4 args=aa bb 11 3rr
Project MESSAGE: in greaterThan block:aa
Project MESSAGE: in count block:bb
Project MESSAGE: in for(var,list) block
Project MESSAGE: aa
Project MESSAGE: bb
Project MESSAGE: 11
Project MESSAGE: 3rr
Project MESSAGE: in for(var,forever) block
Project MESSAGE: 1:aa
Project MESSAGE: 2:bb
Project MESSAGE: 3:11
Project MESSAGE: 4:3rr

qmake language相关的文件后缀

相关参考 qmake 与 配置文件

qmake language相关的文件后缀包括
.prf:project feature,用于存放全局定义的replace函数和test函数,以及达到目标设置而直接执行的代码逻辑。用于load()函数进行调用,可以加文件后缀名。load(feature[, ignore_errors=false])。也可以用include进行加载。对于比较庞大的工程,可以将自定义的replace函数和test函数放到自定义.prf文件,方便批处理,简化工程文件内容(就这一点功能,qt显得多次一举,明明makefile就能实现这样的功能,这样操作之后生成的makefile变得难以阅读了)。
.pri:project include,用于存放库信息及其依赖关系,包括名字、支持的功能特性(feature)、不支持的功能特性(feature),用include()函数进行调用,需要加后缀名。这里的feature是与qt模块的功能相关的,并且都有一个对应的.h文件,比如mkspecs/modules/qt_lib_widgets.pri,对应的qtwidget源码中的qtwidgets-config.h文件,每一个属性在.h中都有一个宏,用于控制代码逻辑,比如其中的dockwidget功能,可以通过修改对应的宏的值来达到禁用会启用对应的功能特性。QT_CONFIG

QT_CONFIG

\include\QtWidgets\qtwidgets-config.h

include(file [,into [,silent=false]])。qt为每个模块编写.pri文件,放置在mkspecs/modules中。
下面是qt_lib_core.pri的内容。qt模块对应的.pri文件的主要目的是方便在pro中对模块功能特性进行查询和确认。

#D:\Qt\Qt5.12.0\5.12.0\msvc2015_64\mkspecs\modules\qt_lib_core.pri
QT.core.VERSION = 5.12.0
QT.core.name = QtCore
QT.core.module = Qt5Core
QT.core.libs = $$QT_MODULE_LIB_BASE
QT.core.includes = $$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/QtCore
QT.core.frameworks =
QT.core.bins = $$QT_MODULE_BIN_BASE
QT.core.depends =
QT.core.uses = libatomic
QT.core.module_config = v2
QT.core.CONFIG = moc resources
QT.core.DEFINES = QT_CORE_LIB
QT.core.enabled_features = properties animation textcodec big_codecs codecs commandlineparser cxx11_future textdate datestring filesystemiterator filesystemwatcher gestures itemmodel proxymodel identityproxymodel library mimetype processenvironment process statemachine qeventtransition regularexpression settings sharedmemory sortfilterproxymodel std-atomic64 stringlistmodel systemsemaphore temporaryfile timezone topleveldomain translation xmlstream xmlstreamreader xmlstreamwriter
QT.core.disabled_features =
QT_CONFIG += properties animation textcodec big_codecs codecs textdate datestring doubleconversion filesystemiterator filesystemwatcher gestures itemmodel proxymodel identityproxymodel library mimetype process statemachine regularexpression settings sharedmemory sortfilterproxymodel stringlistmodel systemsemaphore temporaryfile translation xmlstream xmlstreamreader xmlstreamwriter
QT_MODULES += core

qt每个模块都有一个对应的private模块。比如widgets对应会有一个widgets-private,他们的pri分别为qt_lib_widgets.pri和qt_lib-widgets_private.lib。qt 私有头文件 private 
qt_configure.prf中存放了各种操作.pri内容的脚本函数,而该文件只在编译qt时会调用,用于生成库对应的pri文件。pri中的某个feature是否被支持,可以用脚本函数 qtConfig() 进行判断。pri中的feature相关的项主要用于在pro文件中进行查询,如果已经编译好的qt模块不支持要查询的特性,就可能需要重新配置和编译qt对应的模块。比如如果工程pro中的qtConfig(inputdialog)返回false,那么说明当前的工程不支持inputdialog特性。而inputdialog特性是在widgets模块中,如果工程中配置了widgets模块(QT+=widgets)而qtConfig(inputdialog)仍然返回false,就需要重新配置源码对应模块中的configure.json,然后编译Qt5WIdget.dll了。
qt模块feature QT_FEATURE_* qt_lib_*.pri QT_CONFG qtConfig

.prl:project library,用于描述该库的信息,包括编译该库的工程文件名*.pro、生成的lib的名字、版本、编译该库时配置的CONFIG值、依赖库等信息。该文件与.lib库文件一一对应的,方便用户在加载对应lib后,不需要额外对该lib所依赖的库再做操作,只需要将lib对应的prl放置在同一路径下即可,qmake会自动加载对应的prl文件,在调用lib的pro文件中配置CONFIG +=link_prl。qt为每个qt模块的lib编写对应的.prl文件,并与qt的模块的静态库“.lib”放置在同一个文件夹下。几个特殊的变量:QMAKE_PRL_TARGET、QMAKE_PRL_TARGET、QMAKE_PRL_DEFINES、QMAKE_PRL_CFLAGS、QMAKE_PRL_CXXFLAGS、QMAKE_PRL_CONFIG、QMAKE_PRL_LIBS、QMAKE_PRL_VERSION。

#D:\Qt\Qt5.12.0\5.12.0\msvc2015_64\lib\Qt5Core.prl
QMAKE_PRO_INPUT = corelib.pro
QMAKE_PRL_TARGET = Qt5Core.lib
QMAKE_PRL_CONFIG = lex yacc exceptions depend_includepath testcase_targets import_plugins import_qpa_plugin windows qt_build_extra file_copies qmake_use qt warn_on release link_prl flat debug_and_release precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe shared release no_plugin_manifest win32 msvc copy_dir_files sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 compile_examples f16c force_debug_info largefile precompile_header rdrnd shani x86SimdAlways prefix_build force_independent utf8_source create_prl link_prl prepare_docs qt_docs_targets no_private_qt_headers_warning QTDIR_build qt_example_installs testcase_exceptions warning_clean release ReleaseBuild Release build_pass c++11 win32-msvc2015 exceptions qt_tracepoints moc resources simd optimize_full no_core_dep pcre2 generated_privates relative_qt_rpath git_build qmake_cache target_qt c++11 strict_c++ qt_install_headers need_fwd_pri qt_install_module debug_and_release build_all create_cmake skip_target_version_ext release ReleaseBuild Release build_pass have_target dll exclusive_builds debug_info no_autoqmake arch_haswell thread
QMAKE_PRL_VERSION = 5.12.0

可以为自己创建的库创建.prl文件,如下,plugin或static至少配置一个。当然也可以为第三方的lib或dll添加.prl文件。

TEMPLATE      = lib
CONFIG       += plugin static create_prl

.conf:configuration,用于存放系统相关的配置文件,用include()函数进行调用,需要加后缀名。

杂谈

for被解析成特殊的test函数,不能作condition用。

qmake 源码中对判断语句的处理逻辑,正确的处理方式都是走入isAcitiveConfig()中。也就是说判断语句如果不是true、false、host_build以及函数返回值,则会判断该单词是不是存在CONFIG中!由此可知debug、CONFIG(debug)、isActiveConfig(debug)三者做判断语句时是等价的。

//E:\workspace\QtWork\qmake\library\qmakeevaluator.cpp
QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(const ushort *tokPtr)
{
.......case TokCondition:if (!m_skipLevel && okey != or_op) {if (curr.size() != 1) {if (!m_cumulative || !curr.isEmpty())evalError(fL1S("Conditional must expand to exactly one word."));okey = false;} else {okey = isActiveConfig(curr.at(0).toQStringRef(), true);traceMsg("condition %s is %s", dbgStr(curr.at(0)), dbgBool(okey));okey ^= invert;}} else {traceMsg("skipped condition %s", curr.size() == 1 ? dbgStr(curr.at(0)) : "<invalid>");}or_op = !okey; // tentatively force next evaluationinvert = false;curr.clear();continue;
.......
}--------------------
//E:\workspace\QtWork\qmake\library\qmakeevaluator.cpp
bool QMakeEvaluator::isActiveConfig(const QStringRef &config, bool regex)
{// magic types for easy flippingif (config == statics.strtrue)return true;if (config == statics.strfalse)return false;if (config == statics.strhost_build)return m_hostBuild;if (regex && (config.contains(QLatin1Char('*')) || config.contains(QLatin1Char('?')))) {QRegExp re(config.toString(), Qt::CaseSensitive, QRegExp::Wildcard);// mkspecsif (re.exactMatch(m_qmakespecName))return true;// CONFIG variableconst auto configValues = values(statics.strCONFIG);for (const ProString &configValue : configValues) {ProStringRoUser u1(configValue, m_tmp[m_toggle ^= 1]);if (re.exactMatch(u1.str()))return true;}} else {// mkspecsif (m_qmakespecName == config)return true;// CONFIG variableif (values(statics.strCONFIG).contains(config))return true;}return false;
}

build_pass:qt 工程构建过程 默认构建路径设置 通过Dos窗口运行命令编译_丘上人的博客

Qt qmake - 看企鹅编程网 
qmake对一个简单的pro文件(t.pro)的解析日志_丘上人的博客-CSDN博客

qmake language qt 工程文件 配置文件 .pro .prl .prf .pri 词法 语法 for循环 判断语句 函数定义相关推荐

  1. Qt工程文件(二)--pro文件详解

    PRO文件基本配置选项 QT:指定工程所要使用的Qt模块 VERSION:指定目标库版本号 TARGET:指定编译后生成的目标文件名称 TEMPLATE:指定编译的工程类型 A> app -建立 ...

  2. 解决qt工程文件.pro配置、LIBS添加、ld.so.conf文件添加、库文件权限设置等一系列问题

    对于Linux小白来说,使用Qt+官方提供的库和demo获取摄像头数据流居然都会到处碰壁,捯饬了一天才搞定,现在记录下所有的过程. 在大华官网下载的.run,安装挺顺利,由于版本问题,还卸载了两次,一 ...

  3. Qt工程文件Pro中判断Qt版本号

    需求 在Qt开发中,可能会有这样的需求,需要根据Qt版本来决定加载不同的库,或者定义宏.添加不同的文件等等,那这就需要在工程文件中对当前Qt版本进行判断了. 正文 Qt版本判断 最基础的需求,查看当前 ...

  4. Qt的工程文件讲解 .pro

    #------------------------------------------------- # # Project created by QtCreator 2020-04-03T14:24 ...

  5. 在Qt工程文件中根据不同版本号使用不同源码

    众所周知,qmake里是不提供 #if (QT_VERSION >= QT_VERSION_CHECK(4, 5, 0)) // - #endif 这种语法的 qmake的语法是 条件{ -执行 ...

  6. qmake生成vs2013工程文件

    qmake -spec win32-msvc2013 -r -tp vc xxx.pro

  7. 将Qt工程文件转成VC工程文件的小工具

    自己机器上的插件导入功能坏掉了,遍寻不到解决方案,直接搞了个图形界面的小工具来转好了. 源代码见附件. 编译好的可以在此地址下载. http://dl.dropbox.com/u/3577927/Pr ...

  8. Qt中使用的工程文件(.pro文件)

    第一种常用方式: #模块设置,一般设置为app(生成应用程序,默认),subdirs(生成makefile文件编译subdirs指定的子文件夹),lib(生成库文件) TEMPLATE = app # ...

  9. QT工程的pro文件详解

    文章目录 QT工程的pro文件解析 简单的Pro文件示例 PRO文件基本配置选项 添加配置选项 常用的配置编译选项 QMAKE 变量操作简介 pro文件引入FFmpeg第三方库 为了在QT工程中添加第 ...

最新文章

  1. 2022-2028年全球与中国人字拖市场研究及前瞻分析报告
  2. java9可执行jar_单个java文件打成可执行jar包
  3. 《UNIX环境高级编程》--符号链接
  4. 字符串中最后一个词组的长度 Length of Last Word
  5. {%extends bootstrap/base.html%}的添加,使得其他block无法继承
  6. 你所坚信的,就是你的生活
  7. 使用PyCharm运行第一行python代码
  8. python—单例模式与多例模式的区别与创建
  9. 软考中级-软件设计师-第1章 软件设计师考试介绍
  10. A+B问题的题目描述如下:给定两个整数A和B,输出A+B的值。保证A、B及结果均在整型范围内。
  11. 分析盘点44,630,000条攻击数据后,创宇蜜罐发现——
  12. word2007 正文自动变为大纲一级 问题
  13. 【编译原理】LL(1)语法分析器
  14. STM32触摸屏按下检测多次解决方案
  15. python编程入门第九讲_python 基础 19 习题9 讲解
  16. JPEG2000图像压缩算法学习
  17. java8 .map是什么意思_JDK8 stream().map() 作用
  18. ubuntu openpn 客户端连接
  19. 关于海外客户的设计交付体验与思考
  20. 2020-08-13

热门文章

  1. 五款服装类进销存软件大盘点,各类排名教你如何挑选
  2. ObjectMapper 的一个坑
  3. JAVAWEB第六天schema约束
  4. CSDN 上传图片取消自动加水印的方法
  5. Transformer小白入门
  6. 算法--运筹规划--pulp(一)
  7. 橡皮筋类CRectTracker
  8. Mstar的Monitor方案OSD 菜单制作(六)——绘制进度条
  9. 大学讲师评职称考计算机和英语,高校英语教师评讲师职称对第二外语的要求是什么?...
  10. The Path to Learning WR Python FPE.16