条件编译
开发者可以通过预定义或自定义的条件完成条件编译;仓颉目前支持顶层条件编译。
顶层条件编译
仓颉支持除 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