仓颉语言的编译和构建 [复制链接]
发表于 2026-2-27 08:55:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一、cjc 使用

cjc是仓颉编程语言的编译下令,其提供了丰富的功能及对应的编译选项,本章将对根本使用方法举行先容。
cjc-frontend (仓颉前端编译器)会随 cjc 一起通过 Cangjie SDK 提供,cjc-frontend 可以大概将仓颉源码编译至仓颉的中央表现 (LLVM IR)。 cjc-frontend 仅举行仓颉代码的前端编译,固然 cjc-frontend 和 cjc 共享部门编译选项,但编译流程会在前端编译竣事时克制。使用 cjc 时仓颉编译器会主动举行前端、后端的编译以及链接工作。cjc-frontend 仅作为前端编译器的实体表现提供,除编译器开发者外,仓颉代码的编译应优先使用 cjc 。
1.1 cjc 根本使用方法

想必你已经在学习仓颉的过程中实行着使用 cjc 了,我们先来看一下 cjc 的根本使用方法,假如你想相识具体的编译选项内容,请自行查阅“cjc 编译选项”章节。
cjc 的使用方式如下:
  1. cjc [option] file...
复制代码
假如我们有一个名为 hello.cj 的仓颉文件:
  1. main() {
  2.     println("Hello, World!")
  3. }
复制代码
我们可以使用以下下令来编译此文件:
  1. $ cjc hello.cj
复制代码
此时工作目次下会新增可实行文件 main ,cjc 默认会将给定源代码文件编译成可实行文件,并将可实行文件定名为 main。
以上为不给任何编译选项时 cjc 的默认举动,我们可以通过使用编译选项来控制 cjc 的举动,比方让 cjc 举行整包编译,又大概是指定输出文件的名字。
二、cjpm 先容

CJPM(Cangjie Package Manager) 是仓颉语言的官方包管理工具,用来管理、维护仓颉项目标模块体系,而且提供更浅显同一的编译入口,支持自界说编译下令。通过包管理器主动依赖管理实现对引入的多版本三方依赖软件举行分析归并,无需开发者担心多版本依赖辩论标题,大大减轻开发者负担;同时提供基于仓颉语言原生的自界说构建机制,允许开发者在构建的差别阶段增长预处置处罚和后处置处罚流程,实现构建流程可机动定制,可以大概满足开发者差别业务场景下的编译构建诉求。
2.1 cjpm 根本使用方法

通过 cjpm -h 即可查察主界面,由几个板块构成,从上到下分别是: 当前下令阐明、使用示例(Usage)、支持的可用下令(Available subcommands)、支持的设置项(Available options)、更多提示内容。
  1. Cangjie Package Manager
  2. Usage:
  3.   cjpm [subcommand] [option]
  4. Available subcommands:
  5.   init             Init a new cangjie module
  6.   check            Check the dependencies
  7.   update           Update cjpm.lock
  8.   tree             Display the package dependencies in the source code
  9.   build            Compile the current module
  10.   run              Compile and run an executable product
  11.   test             Unittest a local package or module
  12.   clean            Clean up the target directory
  13.   publish          Push a module to the repository
  14.   load             Load a module from the repository
  15.   list             Get module list from the repository
  16.   install          Install a cangjie binary
  17.   uninstall        Uninstall a cangjie binary
  18. Available options:
  19.   -h, --help       help for cjpm
  20.   -v, --version    version for cjpm
  21. Use "cjpm [subcommand] --help" for more information about a command.
复制代码
cjpm init 用来初始化一个新的仓颉模块大概工作空间。初始化模块时会默认在当前文件夹创建 cjpm.toml 文件,而且新建 src 源码文件夹,在 src 下天生默认的 main.cj 文件。自界说参数初始化功能支持可以通过cjpm init -h 查察。
比方:
  1. 输入: cjpm init
  2. 输出: cjpm init success
复制代码
cjpm build 用来构建当前仓颉项目,实行该下令前会先查抄依赖项,查抄通事后调用 cjc 举行构建。支持全量编译、增量编译、交织编译、并行编译等,更多编译功能支持可以通过cjpm build -h 查察。通过cjpm build -V 下令可以打印全部的编译过程下令。
比方:
  1. 输入: cjpm build -V
  2. 输出:
  3. compile package module1.package1: cjc --import-path target -p "src/package1" --output-type=staticlib -o target/release/module1/libmodule1.package1.a
  4. compile package module1: cjc --import-path target -L target/release/module1 -lmodule1.package1 -p "src" --output-type=exe --output-dir target/release/bin -o main
  5. cjpm build success
复制代码
2.2 cjpm.toml 设置文件阐明

设置文件 cjpm.toml 用来设置一些底子信息、依赖项、编译选项等内容,cjpm 紧张通过这个文件举行剖析实行。
设置文件代码如下所示:
  1. [package]
  2.   cjc-version = "0.49.1" # 所需 `cjc` 的最低版本要求,必须
  3.   name = "demo" # 模块名及模块 root 包名,必须
  4.   description = "nothing here" # 描述信息,非必须
  5.   version = "1.0.0" # 模块版本信息,必须
  6.   compile-option = "" # 额外编译命令选项,非必须
  7.   link-option = "" # 链接器透传选项,可透传安全编译命令,非必须
  8.   output-type = "executable" # 编译输出产物类型,必须
  9.   src-dir = "" # 指定源码存放路径,非必须
  10.   target-dir = "" # 指定产物存放路径,非必须
  11.   package-configuration = {} # 单包配置选项,非必须
  12. [workspace] # 工作空间管理字段,与 package 字段不能同时存在
  13.   members = []
  14.   build-members = []
  15.   test-members = []
  16.   compile-option = ""
  17.   link-option = ""
  18.   target-dir = ""
  19. [dependencies] # 源码依赖配置
  20.   aoo = { version = "1.0.0" } # 导入中心仓依赖
  21.   boo = "1.1.0"  # 导入中心仓依赖
  22.   coo = { git = "xxx",branch = "dev" , version = "1.0.0"} # 导入 `git` 依赖,`version`字段可缺省
  23.   doo = { path = "./pro1" ,version = "1.0.0"} # 导入源码依赖,`version`字段可缺省
  24. [test-dependencies] # 测试阶段的依赖配置
  25. [ffi.c] # 导入 `c` 库依赖
  26.   clib1.path = "xxx"
  27. [profile] # 命令剖面配置项
  28.   build = {}
  29.   test = {}
  30.   customized-option = {}
  31. [target.x86_64-unknown-linux-gnu] # 后端和平台隔离配置项
  32.   compile-option = "value1" # 额外编译命令选项,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必须
  33.   link-option = "value2" # 链接器透传选项,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必须
  34. [target.x86_64-w64-mingw32.dependencies] # 适用于对应 target 的源码依赖配置项,非必须
  35. [target.x86_64-w64-mingw32.test-dependencies] # 适用于对应 target 的测试阶段依赖配置项,非必须
  36. [target.cjvm.bin-dependencies] # 仓颉二进制库依赖,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必须
  37.   path-option = ["./test/pro0", "./test/pro1"]
  38. [target.cjvm.bin-dependencies.package-option]
  39.   "pro0.xoo" = "./test/pro0/pro0.xoo.cjo"
  40.   "pro0.yoo" = "./test/pro0/pro0.yoo.cjo"
  41.   "pro1.zoo" = "./test/pro1/pro1.zoo.cjo"
复制代码
三、条件编译

开发者可以通过预界说或自界说的条件完成条件编译;仓颉现在支持导入和声明的条件编译。
3.1 导入和声明的条件编译

仓颉支持使用内置编译标记 @When 来完成条件编译,编译条件使用 [] 括起来,[] 内支持输入一组或多组编译条件。@When 可以作用于导入节点和除 package 外的声明节点。
使用方法
以内置 os 编译条件为例,其使用方法如下:
  1. @When[os == "Linux"]
  2. class mc{}
  3. main(): Int64 {
  4.     var a = mc()
  5.     return 0
  6. }
复制代码
在上面代码中,开发者在 Linux 体系中可以正确编译实行;在 非 Linux 体系中,则会遇到找不到 mc 类界说的编译错误。
值得留意的是:


  • 仓颉不支持编译条件嵌套,以下写法均不允许:
  1. @When[os == "Windows"]
  2. @When[os == "Linux"]    // Error, illegal nested when conditional compilation
  3. import std.ast.*
  4. @When[os == "Windows"]
  5. @When[os == "Linux"]    // Error, illegal nested when conditional compilation
  6. func A(){}
复制代码


  • @When[…] 作为内置编译标记,在导入前处置处罚,由宏睁开天生的代码中含有 @When[…] 会编译报错,如:
  1. @M0                     // macro which returns the input
  2. @When[os == "Linux"]    // Error, unexpected when conditional compilation directive
  3. func A(){}
复制代码
3.2 内置编译条件变量

仓颉提供了五个内置条件变量: os、 backend、 cjc_version、 debug 和 test。
3.2.1 os

os 表现目标平台的利用体系。os 支持 == 和 != 两种利用符。支持的利用体系有:Windows、Linux、macOS、HarmonyOS。
使用方式如下:
  1. @When[os == "Linux"]
  2. func foo() {
  3.     print("Linux, ")
  4. }
  5. @When[os == "Windows"]
  6. func foo() {
  7.     print("Windows, ")
  8. }
  9. @When[os != "Windows"]
  10. func fee() {
  11.     println("NOT Windows")
  12. }
  13. @When[os != "Linux"]
  14. func fee() {
  15.     println("NOT Linux")
  16. }
  17. main() {
  18.     foo()
  19.     fee()
  20. }
复制代码
假如在 Windows 环境下编译实行,会得到 Windows, NOT Linux 的信息;假如是在 Linux 环境下,则会得到 Linux, NOT Windows 的信息。
3.2 .2 backend

backend 是仓颉内置的条件。仓颉是多后端语言,支持多种后端条件编译。backend 条件支持 == 和 != 两种利用符。
支持的后端有:cjnative、cjnative-x86、cjnative-x86_64、cjnative-arm、cjnative-aarch64、cjvm、cjvm-x86、cjvm-x86_64、cjvm-arm、cjvm-aarch64。
当用户使用的条件为 cjnative/cjvm 时,arch 信息将会按编译器实行时环境信息主动补全。
使用方式如下:
  1. @When[backend == "cjnative"]
  2. func foo() {
  3.     print("cjnative backend, ")
  4. }
  5. @When[backend == "cjvm"]
  6. func foo() {
  7.     print("cjvm backend, ")
  8. }
  9. @When[backend != "cjnative"]
  10. func fee() {
  11.     println("NOT cjnative backend")
  12. }
  13. @When[backend != "cjvm"]
  14. func fee() {
  15.     println("NOT cjvm backend")
  16. }
  17. main() {
  18.     foo()
  19.     fee()
  20. }
复制代码
用 cjnative 后端的发布包编译实行,会得到 cjnative backend, NOT cjvm backend 的信息;用 cjvm 后端的发布包编译实行,则会得到 cjvm backend, NOT cjnative backend 的信息。
3.2.3 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。
使用方式如下:
  1. @When[cjc_version == "0.18.6"]
  2. func foo() {
  3.     println("cjc_version equals 0.18.6")
  4. }
  5. @When[cjc_version != "0.18.6"]
  6. func foo() {
  7.     println("cjc_version is NOT equal to 0.18.6")
  8. }
  9. @When[cjc_version > "0.18.6"]
  10. func fnn() {
  11.     println("cjc_version is greater than 0.18.6")
  12. }
  13. @When[cjc_version <= "0.18.6"]
  14. func fnn() {
  15.     println("cjc_version is less than or equal to 0.18.6")
  16. }
  17. @When[cjc_version < "0.18.6"]
  18. func fee() {
  19.     println("cjc_version is less than 0.18.6")
  20. }
  21. @When[cjc_version >= "0.18.6"]
  22. func fee() {
  23.     println("cjc_version is greater than or equal to 0.18.6")
  24. }
  25. main() {
  26.     foo()
  27.     fnn()
  28.     fee()
  29. }
复制代码
根据 cjc 的版本,上面代码的实行输出结果会有差别。
3.2.4 debug

debug 表现当前是否启用了调试模式即开启 -g 编译选项, 可以用于在编译代码时举行调试和发布版本之间的切换。debug 条件仅支持逻辑非运算符(!)。
使用方式如下:
  1. @When[debug]
  2. func foo() {
  3.     println("debug")
  4. }
  5. @When[!debug]
  6. func foo() {
  7.     println("NOT debug")
  8. }
  9. main() {
  10.     foo()
  11. }
复制代码
启用 -g 编译实行会得到 cjc debug 的信息,假如没有启用 -g 编译实行会得到 NOT debug 的信息。
3.2.5 test

test 表现当前是否启用了单位测试选项 --test。test 条件仅支持逻辑非运算符(!)。可以用于区分测试代码与寻常代码。
使用方式如下:
  1. @When[test]
  2. @Test
  3. class Tests {
  4.     @TestCase
  5.     public func case1(): Unit {
  6.         @Expect("run", foo())
  7.     }
  8. }
  9. func foo() {
  10.     "run"
  11. }
  12. @When[!test]
  13. main () {
  14.     println(foo())
  15. }
复制代码
使用 --test 编译实行得到的测试结果,不使用 --test 也可正常完成编译运行得到 run 的信息。
3.3 自界说编译条件变量

仓颉允许开发者自界说编译条件变量和取值,自界说的条件变量必须是一个合法的标识符且不允许和内置条件变量同名,其值是一个字符串字面量。自界说条件支持 == 和 != 两种运算符。和内置条件变量差别点在于自界说的条件须要开发者在编译时通过 --cfg 编译选项大概在设置文件 cfg.toml 中界说。
3.3.1 设置自界说条件变量

设置自界说条件变量的方式有两种:在编译选项中直接设置键值对或在设置文件设置键值对。
用户可以使用 --cfg 以键值对的情势向编译器转达自界说编译条件变量大概指定设置文件 cfg.toml 的搜刮路径。


  • 选项值须要使用双引号括起来
  • 若选项值中包罗 = 则会按照键值对的情势直接举行设置(若路径中包罗 = 则须要通过 \ 转义),多个键值对可以使用逗号 , 分隔。如:
  1. $ cjc --cfg "feature = lion, platform = dsp" source.cj
复制代码


  • 允许多次使用 --cfg 编译选项设置举行设置, 如:
  1. $ cjc --cfg "feature = lion" --cfg "platform = dsp" source.cj
复制代码


  • 不允许多次界说同一个条件变量, 如:
  1. $ cjc --cfg "feature = lion" --cfg "feature = meta" source.cj
  2. $ cjc --cfg "feature = lion, feature = meta" source.cj
复制代码
上述两条编译指令都会报错。


  • 若选项值中不包罗 = 或 存在通过 \ 转义的 = 则将选项值作为设置文件 cfg.toml 的搜刮路径转达给编译器,如:
  1. $ cjc --cfg "./cfg" source.cj
复制代码
若 ./cfg 目次下存在 cfg.toml 则在编译时,编译器会将 ./cfg/cfg.toml 中设置的自界说编译条件转达给编译器。cfg.toml 文件中应采取键值对的方式设置自界说条件变量,每个键值对独占一行, 健名是一个合法的标识符, 键值是一个双引号括起来的字符串。如:
  1. feature = "lion"
  2. platform = "dsp"
复制代码


  • 多次使用 --cfg 设置 cfg.toml 文件的搜刮路径时,按照传入的序次依次搜刮cfg.toml 文件,若在全部传入的搜刮路径下都没有找到 cfg.toml 文件,则在默认路径下搜刮设置文件 cfg.toml。
  • 多次使用 --cfg 编译选项举行设置时,若某次以键值对的情势直接举行设置,则会忽略设置文件 cfg.toml 中的设置。
  • 若没有使用 --cfg 编译选项,编译器会在默认路径(通过–package 或 -p 指定的 package 目次或 cjc 实行目次)下搜刮设置文件 cfg.toml。
3.4 多条件编译

仓颉条件编译允许开发者自由组合多个条件编译选项。支持逻辑运算符组合多个条件,支持括号运算符明白优先级。
使用方式如下:
  1. //source.cj
  2. @When[(test || feature == "lion") && !debug]
  3. func fee() {
  4.     println("feature lion")
  5. }
  6. main() {
  7.     fee()
  8. }
复制代码
使用如下编译下令编译运行上段代码,
  1. $ cjc --cfg="feature=lion" source.cj -o runner.out
复制代码
会得到输出结果如下:
  1. platform lion
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表