条件编译
开发者可以通过预定义或自定义的条件完成条件编译;仓颉目前支持顶层条件编译。
顶层条件编译
仓颉支持除 package
声明以外的 Top Level
条件编译。
使用方法
以内置 os 编译条件为例,其 Top Level 使用方法如下:
@When[os == "linux"]
class mc{}
main(): Int64 {
var a = mc()
return 0
}
在上面代码中,开发者在 linux
系统中可以正确编译执行;在 非 linux
系统中,则会遇到找不到 mc
类定义的编译错误。
注:仓颉不支持顶层编译条件嵌套,以下写法均不允许
// 错误示例
@When[os == "windows"]
@When[os == "linux"] // error: illegal nested when conditional compilation macro
from std import ast.*
@When[os == "windows"]
@When[os == "linux"] // error: illegal nested when conditional compilation macro
func A(){}
内置条件
仓颉内置了一些条件供开发者直接使用。所有条件的变量都是以字符串的形式存在的。
os
os
是仓颉内置的条件,支持 ==
和 !=
两种操作符。支持的系统有:windows
、linux
、macOS
、hm
。
使用方式如下:
@When[os == "linux"]
func foo() {
print("linux, ")
}
@When[os == "windows"]
func foo() {
print("windows, ")
}
@When[os != "windows"]
func fee() {
println("NOT windows")
}
@When[os != "linux"]
func fee() {
println("NOT linux")
}
main() {
foo()
fee()
}
如果在 windows
环境下编译执行,会得到 windows, NOT linux
的信息;如果是在 linux
环境下,则会得到 linux, NOT windows
的信息。
backend
backend
是仓颉内置的条件。仓颉是多后端语言,支持多种后端条件编译。backend
条件支持 ==
和 !=
两种操作符。
支持的后端有:llvm
、llvm-x86
、llvm-x86_64
、llvm-arm
、llvm-aarch64
、cjvm
、cjvm-x86
、cjvm-x86_64
、cjvm-arm
、cjvm-aarch64
。
当用户使用的条件为 llvm
/cjvm
时,arch 信息将会按编译器执行时环境信息自动补全。
使用方式如下:
@When[backend == "llvm"]
func foo() {
print("llvm backend, ")
}
@When[backend == "cjvm"]
func foo() {
print("cjvm backend, ")
}
@When[backend != "llvm"]
func fee() {
println("NOT llvm backend")
}
@When[backend != "cjvm"]
func fee() {
println("NOT cjvm backend")
}
main() {
foo()
fee()
}
用 llvm
后端的发布包编译执行,会得到 llvm backend, NOT cjvm backend
的信息;用 cjvm
后端的发布包编译执行,则会得到 cjvm backend, NOT llvm backend
的信息。
cjc_version
cjc_version
是仓颉内置的条件,开发者可以根据当前仓颉编译器的版本选择要编译的代码。cjc_version
条件支持 ==
、!=
、>
、<
、>=
、<=
六种操作符,格式为 xx.xx.xx
支持每个 xx
支持 1-2 位数字,计算规则为补位 (补齐 2 位) 比较,例如:0.18.8 < 0.18.11
, 0.18.8 == 0.18.08
。
使用方式如下:
@When[cjc_version == "0.18.6"]
func foo() {
println("cjc_version equals 0.18.6")
}
@When[cjc_version != "0.18.6"]
func foo() {
println("cjc_version is NOT equal to 0.18.6")
}
@When[cjc_version > "0.18.6"]
func fnn() {
println("cjc_version is greater than 0.18.6")
}
@When[cjc_version <= "0.18.6"]
func fnn() {
println("cjc_version is less than or equal to 0.18.6")
}
@When[cjc_version < "0.18.6"]
func fee() {
println("cjc_version is less than 0.18.6")
}
@When[cjc_version >= "0.18.6"]
func fee() {
println("cjc_version is greater than or equal to 0.18.6")
}
main() {
foo()
fnn()
fee()
}
根据 cjc
的版本,上面代码的执行输出结果会有不同。
debug
debug
是仓颉内置的条件。debug
条件仅支持一元运算。
使用方式如下:
@When[debug]
func foo() {
println("cjc debug")
}
@When[!debug]
func foo() {
println("cjc NOT debug")
}
main() {
foo()
}
根据 cjc
是否是 debug
的版本,上面代码的执行输出结果会有不同。
如果是 debug
版本的 cjc
会输出 cjc debug
,如果是 release
版本的 cjc 则会输出 cjc NOT debug
。
自定义条件
仓颉允许开发者自定义编译的条件。
自定义的条件拥有和内置条件一样的作用,不同点在于自定义的条件需要开发者在编译程序时写在编译选项中。自定义条件支持 ==
和 !=
两种运算符。
假如开发者自定义条件为 feature
,使用方式和内置条件没有什么不同。使用如下:
//source.cj
@When[feature == "tiger"]
func foo() {
println("feature tiger")
}
@When[feature == "lion"]
func foo() {
println("feature lion")
}
main() {
foo()
}
上面这段代码,开发者想要顺利编译这段代码需要使用这段编译选项:
可以选择 feature == "tiger"
分支
cjc --conditional-compilation-config="(feature=tiger)" source.cj -o runner.out
或者选择 feature == "lion"
分支
cjc --conditional-compilation-config="(feature=lion)" source.cj -o runner.out
根据 feature
的值不同,编译运行上段代码的结果也会不同。
--conditional-compilation-config
此编译选项里的内容表示当前编译流程中 cjc
传递的自定义条件,cjc
会根据此编译选项的值来选择编译哪段代码。
这个选项中的值是以 key-value
来映射的,一个 key
只可以对应一个 value
;此选项也支持多个 key-value
结构,用 逗号 (,)
分割,例如:
cjc --conditional-compilation-config="(feature=lion, target=dsp)" source.cj -o runner.out
开发者编写的条件编译代码需要和 --conditional-compilation-config
里的值对应上,否则条件编译不会生效。例如:
//source.cj
@When[feature == "lion"]
func foo() {
print("feature lion, ")
}
@When[target == "dsp"]
func fee() {
println("target dsp")
}
main() {
foo()
fee()
}
使用如下编译命令编译运行上段代码,会得到输出结果:feature lion, target dsp
。
cjc --conditional-compilation-config="(feature=lion,target=dsp)" source.cj -o runner.out
而使用如下编译命令编译运行上段代码,会报错:error: undeclared identifier 'foo'
。
cjc --conditional-compilation-config="(feature=dsp,target=dsp)" source.cj -o runner.out
多条件
仓颉条件编译允许开发者自由组合多个条件编译选项。支持逻辑运算符组合多个条件,支持括号运算符明确优先级。
使用方式如下:
//source.cj
@When[feature == "tiger" || os == "windows"]
func foo() {
print("feature tiger, ")
}
@When[(debug || os == "linux") && cjc_version >= "0.18.6"]
func fee() {
println("feature lion")
}
main() {
foo()
fee()
}
使用如下编译命令编译运行上段代码,
cjc --conditional-compilation-config="(feature=tiger)" source.cj -o runner.out
会得到输出结果如下:
feature tiger, feature lion