仓颉语言的编译和构建

一、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 的使用方式如下:

cjc [option] file...

假如我们有一个名为 hello.cj 的仓颉文件:

main() {println("Hello, World!")
}

我们可以使用以下命令来编译此文件:

$ cjc hello.cj

此时工作目录下会新增可执行文件 main ,cjc 默认会将给定源代码文件编译成可执行文件,并将可执行文件命名为 main。

以上为不给任何编译选项时 cjc 的默认行为,我们可以通过使用编译选项来控制 cjc 的行为,例如让 cjc 进行整包编译,又或者是指定输出文件的名字。

二、cjpm 介绍

CJPM(Cangjie Package Manager) 是仓颉语言的官方包管理工具,用来管理、维护仓颉项目的模块系统,并且提供更简易统一的编译入口,支持自定义编译命令。通过包管理器自动依赖管理实现对引入的多版本三方依赖软件进行分析合并,无需开发者担心多版本依赖冲突问题,大大减轻开发者负担;同时提供基于仓颉语言原生的自定义构建机制,允许开发者在构建的不同阶段增加预处理和后处理流程,实现构建流程可灵活定制,能够满足开发者不同业务场景下的编译构建诉求。

2.1 cjpm 基本使用方法

通过 cjpm -h 即可查看主界面,由几个板块组成,从上到下分别是: 当前命令说明、使用示例(Usage)、支持的可用命令(Available subcommands)、支持的配置项(Available options)、更多提示内容。

Cangjie Package ManagerUsage:cjpm [subcommand] [option]Available subcommands:init             Init a new cangjie modulecheck            Check the dependenciesupdate           Update cjpm.locktree             Display the package dependencies in the source codebuild            Compile the current modulerun              Compile and run an executable producttest             Unittest a local package or moduleclean            Clean up the target directorypublish          Push a module to the repositoryload             Load a module from the repositorylist             Get module list from the repositoryinstall          Install a cangjie binaryuninstall        Uninstall a cangjie binaryAvailable options:-h, --help       help for cjpm-v, --version    version for cjpmUse "cjpm [subcommand] --help" for more information about a command.

cjpm init 用来初始化一个新的仓颉模块或者工作空间。初始化模块时会默认在当前文件夹创建 cjpm.toml 文件,并且新建 src 源码文件夹,在 src 下生成默认的 main.cj 文件。自定义参数初始化功能支持可以通过cjpm init -h 查看。

例如:

输入: cjpm init
输出: cjpm init success

cjpm build 用来构建当前仓颉项目,执行该命令前会先检查依赖项,检查通过后调用 cjc 进行构建。支持全量编译、增量编译、交叉编译、并行编译等,更多编译功能支持可以通过cjpm build -h 查看。通过cjpm build -V 命令可以打印所有的编译过程命令。

例如:

输入: cjpm build -V
输出:
compile package module1.package1: cjc --import-path target -p "src/package1" --output-type=staticlib -o target/release/module1/libmodule1.package1.a
compile package module1: cjc --import-path target -L target/release/module1 -lmodule1.package1 -p "src" --output-type=exe --output-dir target/release/bin -o maincjpm build success

2.2 cjpm.toml 配置文件说明

配置文件 cjpm.toml 用来配置一些基础信息、依赖项、编译选项等内容,cjpm 主要通过这个文件进行解析执行。

配置文件代码如下所示:

[package]cjc-version = "0.49.1" # 所需 `cjc` 的最低版本要求,必须name = "demo" # 模块名及模块 root 包名,必须description = "nothing here" # 描述信息,非必须version = "1.0.0" # 模块版本信息,必须compile-option = "" # 额外编译命令选项,非必须link-option = "" # 链接器透传选项,可透传安全编译命令,非必须output-type = "executable" # 编译输出产物类型,必须src-dir = "" # 指定源码存放路径,非必须target-dir = "" # 指定产物存放路径,非必须package-configuration = {} # 单包配置选项,非必须[workspace] # 工作空间管理字段,与 package 字段不能同时存在members = []build-members = []test-members = []compile-option = ""link-option = ""target-dir = ""[dependencies] # 源码依赖配置项aoo = { version = "1.0.0" } # 导入中心仓依赖boo = "1.1.0"  # 导入中心仓依赖coo = { git = "xxx",branch = "dev" , version = "1.0.0"} # 导入 `git` 依赖,`version`字段可缺省doo = { path = "./pro1" ,version = "1.0.0"} # 导入源码依赖,`version`字段可缺省[test-dependencies] # 测试阶段的依赖配置项[ffi.c] # 导入 `c` 库依赖clib1.path = "xxx"[profile] # 命令剖面配置项build = {}test = {}customized-option = {}[target.x86_64-unknown-linux-gnu] # 后端和平台隔离配置项compile-option = "value1" # 额外编译命令选项,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必须link-option = "value2" # 链接器透传选项,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必须[target.x86_64-w64-mingw32.dependencies] # 适用于对应 target 的源码依赖配置项,非必须[target.x86_64-w64-mingw32.test-dependencies] # 适用于对应 target 的测试阶段依赖配置项,非必须[target.cjvm.bin-dependencies] # 仓颉二进制库依赖,适用于特定 target 的编译流程和指定该 target 作为交叉编译目标平台的编译流程,非必须path-option = ["./test/pro0", "./test/pro1"]
[target.cjvm.bin-dependencies.package-option]"pro0.xoo" = "./test/pro0/pro0.xoo.cjo""pro0.yoo" = "./test/pro0/pro0.yoo.cjo""pro1.zoo" = "./test/pro1/pro1.zoo.cjo"

三、条件编译

开发者可以通过预定义或自定义的条件完成条件编译;仓颉目前支持导入和声明的条件编译。

3.1 导入和声明的条件编译

仓颉支持使用内置编译标记 @When 来完成条件编译,编译条件使用 [] 括起来,[] 内支持输入一组或多组编译条件。@When 可以作用于导入节点和除 package 外的声明节点。

使用方法
以内置 os 编译条件为例,其使用方法如下:

@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
import std.ast.*
@When[os == "Windows"]
@When[os == "Linux"]    // Error, illegal nested when conditional compilation
func A(){}
  • @When[…] 作为内置编译标记,在导入前处理,由宏展开生成的代码中含有 @When[…] 会编译报错,如:
@M0                     // macro which returns the input
@When[os == "Linux"]    // Error, unexpected when conditional compilation directive
func A(){}

3.2 内置编译条件变量

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

3.2.1 os

os 表示目标平台的操作系统。os 支持 == 和 != 两种操作符。支持的操作系统有:Windows、Linux、macOS、HarmonyOS。

使用方式如下:

@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 的信息。

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 信息将会按编译器执行时环境信息自动补全。

使用方式如下:

@When[backend == "cjnative"]
func foo() {print("cjnative backend, ")
}
@When[backend == "cjvm"]
func foo() {print("cjvm backend, ")
}
@When[backend != "cjnative"]
func fee() {println("NOT cjnative backend")
}
@When[backend != "cjvm"]
func fee() {println("NOT cjvm backend")
}
main() {foo()fee()
}

用 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。

使用方式如下:

@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 的版本,上面代码的执行输出结果会有不同。

3.2.4 debug

debug 表示当前是否启用了调试模式即开启 -g 编译选项, 可以用于在编译代码时进行调试和发布版本之间的切换。debug 条件仅支持逻辑非运算符(!)。

使用方式如下:

@When[debug]
func foo() {println("debug")
}
@When[!debug]
func foo() {println("NOT debug")
}
main() {foo()
}

启用 -g 编译执行会得到 cjc debug 的信息,如果没有启用 -g 编译执行会得到 NOT debug 的信息。

3.2.5 test

test 表示当前是否启用了单元测试选项 --test。test 条件仅支持逻辑非运算符(!)。可以用于区分测试代码与普通代码。

使用方式如下:

@When[test]
@Test
class Tests {@TestCasepublic func case1(): Unit {@Expect("run", foo())}
}func foo() {"run"
}@When[!test]
main () {println(foo())
}

使用 --test 编译执行得到的测试结果,不使用 --test 也可正常完成编译运行得到 run 的信息。

3.3 自定义编译条件变量

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

3.3.1 配置自定义条件变量

配置自定义条件变量的方式有两种:在编译选项中直接配置键值对或在配置文件配置键值对。

用户可以使用 --cfg 以键值对的形式向编译器传递自定义编译条件变量或者指定配置文件 cfg.toml 的搜索路径。

  • 选项值需要使用双引号括起来

  • 若选项值中包含 = 则会按照键值对的形式直接进行配置(若路径中包含 = 则需要通过 \ 转义),多个键值对可以使用逗号 , 分隔。如:

$ cjc --cfg "feature = lion, platform = dsp" source.cj
  • 允许多次使用 --cfg 编译选项配置进行配置, 如:
$ cjc --cfg "feature = lion" --cfg "platform = dsp" source.cj
  • 不允许多次定义同一个条件变量, 如:
$ cjc --cfg "feature = lion" --cfg "feature = meta" source.cj
$ cjc --cfg "feature = lion, feature = meta" source.cj

上述两条编译指令都会报错。

  • 若选项值中不包含 = 或 存在通过 \ 转义的 = 则将选项值作为配置文件 cfg.toml 的搜索路径传递给编译器,如:
$ cjc --cfg "./cfg" source.cj

若 ./cfg 目录下存在 cfg.toml 则在编译时,编译器会将 ./cfg/cfg.toml 中配置的自定义编译条件传递给编译器。cfg.toml 文件中应采用键值对的方式配置自定义条件变量,每个键值对独占一行, 健名是一个合法的标识符, 键值是一个双引号括起来的字符串。如:

feature = "lion"
platform = "dsp"
  • 多次使用 --cfg 配置 cfg.toml 文件的搜索路径时,按照传入的顺序依次搜索cfg.toml 文件,若在所有传入的搜索路径下都没有找到 cfg.toml 文件,则在默认路径下搜索配置文件 cfg.toml。

  • 多次使用 --cfg 编译选项进行配置时,若某次以键值对的形式直接进行配置,则会忽略配置文件 cfg.toml 中的配置。

  • 若没有使用 --cfg 编译选项,编译器会在默认路径(通过–package 或 -p 指定的 package 目录或 cjc 执行目录)下搜索配置文件 cfg.toml。

3.4 多条件编译

仓颉条件编译允许开发者自由组合多个条件编译选项。支持逻辑运算符组合多个条件,支持括号运算符明确优先级。

使用方式如下:

//source.cj
@When[(test || feature == "lion") && !debug]
func fee() {println("feature lion")
}
main() {fee()
}

使用如下编译命令编译运行上段代码,

$ cjc --cfg="feature=lion" source.cj -o runner.out

会得到输出结果如下:

platform lion

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/858196.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SSL/TLS、SSH、IPSec等安全协议的工作原理和实现方式

SSL/TLS、SSH、IPSec是三种广泛应用于网络通信中的安全协议&#xff0c;它们各自有不同的工作原理和实现方式。 SSL/TLS&#xff08;Secure Sockets Layer / Transport Layer Security&#xff09; 工作原理深入分析 1. 握手阶段 协议协商&#xff1a;客户端首先发送一个“Cl…

图像反转入门

文章目录 1.实验目的2.需求3.代码4.运行结果图 1.实验目的 熟练掌握图像像素操作API 2.需求 自己构造一个纯黑图像,通过多种方法进行反转,最终生成一个纯白图像 3.代码 """ Time : 2024/6/23 下午3:46 Author : chensong File : 自己创建一个图像并…

Minillama3->dpo训练

GitHub - leeguandong/MiniLLaMA3: llama3的迷你版本,包括了数据,tokenizer,pt的全流程llama3的迷你版本,包括了数据,tokenizer,pt的全流程. Contribute to leeguandong/MiniLLaMA3 development by creating an account on GitHub.https://github.com/leeguandong/MiniLL…

[保姆级教程]uniapp自定义导航栏

文章目录 导文隐藏默认导航栏&#xff1a;全局隐藏当前页面隐藏 添加自定义导航栏视图&#xff1a;手写导航栏组件导航栏 导文 在 UniApp 中&#xff0c;自定义导航栏通常涉及到隐藏默认的导航栏&#xff0c;并在页面顶部添加自定义的视图组件来模拟导航栏的功能。 隐藏默认导航…

C++11 标准库头文件模拟实现

系列文章目录 文章目录 系列文章目录前言● 智能指针模板● Vector1. 简单版本2. X 总结 前言 暂不考虑支持多线程 常用STL的简单实现&#xff0c;主要内容百行左右完成&#xff0c;意在理解STL的原理 ● 智能指针模板 SharedPtr #include <assert.h> #include <ato…

用python打印——九九乘法表

# 定义外层循环的控制变量 i 1 while i < 9:# 定义内层循环的控制变量j 1while j < i:# 内层循环的print语句不要换行&#xff0c;通过\t制表符对齐print(f"{j} * {i} {j * i}\t", end)j 1i 1print() # print空内容&#xff0c;就是输出一个换行以下是…

文本三剑客

文本三剑客 sed awk grep grep就是查找文本当中的内容&#xff0c;扩展正则表达式。 sed sed是一种流编辑器&#xff0c;一次处理一行内容。 如果只是展示&#xff0c;会放到缓冲区&#xff08;模式空间&#xff09;&#xff0c;展示结束之后&#xff0c;会从模式空间把操作结…

[15] 使用Opencv_CUDA 模块实现基本计算机视觉程序

使用Opencv_CUDA 模块实现基本计算机视觉程序 CUDA提供了出色的接口,发挥GPU的并行计算能力来加速复杂的计算应用程序利用CUDA和Opencv的功能实现计算机视觉应用1. 对图像的算术和逻辑运算 两个图像相加#include <iostream> #include "opencv2/opencv.hpp" #i…

Linux运维面试--yum安装和编译安装区别

风吹哪页读哪页&#xff0c;花开何时看何时。 目录 # 1.安装方式差异 ## 1.1 yum安装 ## 1.2 源码编译安装 # 2.优缺点分析 ## 2.1 yum安装优缺点 ### 2.1.1 yum安装优点 ### 2.1.2 yum安装缺点 ## 2.2 源码安装优缺点 ### 2.2.1 源码安装优点 ### 2.2.2 源码安装缺点…

JS 实现复制文本到剪贴板

方式一&#xff1a;使用 Clipboard API 方式 /** 将文本复制到剪贴板* param e 要复制的内容*/ copyTextToClipboard(e) {const navClipboard navigator.clipboardif (!navClipboard) {console.log(浏览器不支持 Clipboard API 方式)return}navClipboard.writeText(e).then((…

主数据驱动的数据治理:技术解析与实践探索

数字化转型行业小伙伴可以加入我的星球&#xff0c;初衷成为各位数字化转型参考库&#xff0c;星球内容每周更新 个人工作经验资料全部放在这里&#xff0c;包含数据治理、数据要素、数据质量、数据安全、元数据、主数据、企业架构、DCMM、DSMM、CDGA、CDGP等各种数据相关材料 …

使用Python脚本预测天气预报的技术指南

一、引言 随着大数据和机器学习技术的快速发展&#xff0c;天气预报的准确性得到了显著提升。Python作为一种强大的编程语言&#xff0c;提供了丰富的库和工具&#xff0c;使得构建和训练预测模型变得更加容易。本文旨在介绍如何使用Python脚本进行天气预报的预测&#xff0c;…

抖音多功能全自动引流工具,支持评论关注私信留痕点赞等,让你的抖音粉丝暴涨!

随着短视频行业的火爆&#xff0c;越来越多的人开始关注抖音这个平台。然而&#xff0c;如何在抖音上获得更多的关注和粉丝&#xff0c;成为了许多人面临的难题。为了帮助大家解决这个问题&#xff0c;今天我们将为大家推荐一款抖音多功能全自动引流脚本&#xff0c;这款脚本可…

HarmonyOS SDK助力鸿蒙原生应用“易感知、易理解、易操作”

6月21-23日&#xff0c;华为开发者大会&#xff08;HDC 2024&#xff09;盛大开幕。6月23日上午&#xff0c;《HarmonyOS开放能力&#xff0c;使能应用原生易用体验》分论坛成功举办&#xff0c;大会邀请了多位华为技术专家深度解读如何通过根技术、开放能力、场景化控件等亮点…

vue3 antdv Select 实现输入关键词,通过服务器去查询数据,并显示到表格中的实现思路。

实现思路&#xff1a; 1&#xff09;输入关键词&#xff0c;通过Select的查询事件&#xff08;onSearch&#xff09;来到服务器查询数据。 2&#xff09;根据查询到的数据显示到表格中&#xff0c;然后通过表格的&#xff08;cellClickEvent&#xff09;事件来选择相关的用户…

Python武器库开发-武器库篇之ThinkPHP 5.0.23-RCE 漏洞复现(六十四)

Python武器库开发-武器库篇之ThinkPHP 5.0.23-RCE 漏洞复现&#xff08;六十四&#xff09; 漏洞环境搭建 这里我们使用Kali虚拟机安装docker并搭建vulhub靶场来进行ThinkPHP漏洞环境的安装&#xff0c;我们进入 ThinkPHP漏洞环境&#xff0c;可以 cd ThinkPHP&#xff0c;然…

嵌入式学习——数据结构(队列)——day50

1. 查找二叉树、搜索二叉树、平衡二叉树 2. 哈希表——人的身份证——哈希函数 3. 哈希冲突、哈希矛盾 4. 哈希代码 4.1 创建哈希表 4.2 5. 算法设计 5.1 正确性 5.2 可读性&#xff08;高内聚、低耦合&#xff09; 5.3 健壮性 5.4 高效率&#xff08;时间复杂度&am…

【Java】pcm 与 wav 格式互转工具类 (附测试用例)

文章目录 1. 前言1.1 背景1.2 目标1.3 亮点 2. 用例说明3. 补充验证4. 相关链接 1. 前言 git 仓库 https://github.com/ChenghanY/pcm-wav-converter 1.1 背景 系统新接入语音引擎。 语音引擎只认 pcm 格式数据。前端只认 wav 格式 。 需要后端对 pcm 和 wav 格式实现互转&a…

2.超声波测距模块

1.简介 2.超声波的时序图 3.基于51单片机实现的代码 #include "reg52.h" #include "intrins.h" sbit led1P3^7;//小于10&#xff0c;led1亮&#xff0c;led2灭 sbit led2P3^6;//否则&#xff0c;led1灭&#xff0c;led2亮 sbit trigP1^5; sbit echo…

Adobe XD最新2023资源百度云盘下载(附教程)

如大家所了解的&#xff0c;Adobe XD是一种基于矢量的UI和UX设计工具&#xff0c;可用于设计从智能手表应用程序到成熟网站的任何内容&#xff0c;功能非常强大且操作便捷。目前最新已推出2023版本。 Adobe XD解决了Photoshop和其他图形应用程序无法解决的两个主要问题&#xf…