新开一个系列,分享一些仓颉编程语言的知识。
前言 仓颉编程语言是华为公司推出的产品,也是我在华为的重点工作内容之一,内部研发过程中多次保障它的网络安全,在2025年7月30日开源。
毫不夸张地说,我是全世界最懂仓颉安全的人,那么我也应当为之布道。
愿景:本系列不一定讲安全,想到什么讲什么,希望重铸 LLVM学习 系列的荣光,也希望仓颉语言能蒸蒸日上。
任务目标 创建cmake项目,编译一个so/dll,使用 cjc 编译器加载它,打印 CHIR 的基本信息。
环境准备 Linux可以,Windows不行,Mac不清楚。
当前 1.0.x 的LTS发布包里缺少include文件,需要从 https://gitcode.com/Cangjie/nightly_build/releases 下载一份daily-build,保证能找到对应的include文件。
1 2 3 4 5 6 7 8 9 tree cangjie/include/ cangjie/include/ ├── MetaTransform.h └── cangjie ├── AST │ ├── ASTCasting.h │ ├── ASTContext.h │ ├── ASTKind.inc │ ├── ASTTypeValidator.h
编写pass cmake项目依赖,添加头文件,链接路径。当前依赖的是 libcangjie-lsp.so,这个行为很逆天,已提 issue https://gitcode.com/Cangjie/cangjie_compiler/issues/460 。
1 2 3 4 5 6 7 8 9 10 11 12 cmake_minimum_required (VERSION 3.5 )project (HelloCjPlugin)set (CMAKE_CXX_STANDARD 17 )if ("$ENV{CANGJIE_HOME}" STREQUAL "" ) message (FATAL_ERROR "\n##### Please confirm cjc is well configured in current environment. #####" ) endif ()include_directories ($ENV{CANGJIE_HOME}/include )link_directories ($ENV{CANGJIE_HOME}/tools/lib)add_library (skeleton SHARED skeleton.cpp)target_link_libraries (skeleton PRIVATE cangjie-lsp)
MetaTransform.h 文件提供了一键注册的宏展开
1 #define CHIR_PLUGIN(plugin_name)
展开之后代码大约是
1 2 3 4 5 6 7 8 9 extern "C" MetaTransformPluginInfo getMetaTransformPluginInfo () { return { Cangjie::CANGJIE_VERSION.c_str (), [](MetaTransformPluginBuilder &mtBuilder) { mtBuilder.RegisterCHIRPluginCallback ([](CHIRPluginManager &mtm, CHIR::CHIRBuilder &builder) { mtm.AddMetaTransform (std::make_unique <plugin_name>(builder)); }); } }; }
简单写一个 FunctionPass(完整代码)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include "cangjie/Basic/Print.h" #include "cangjie/CHIR/IR/CHIRBuilder.h" #include "cangjie/MetaTransformation/MetaTransform.h" using namespace Cangjie;class PrintFuncNamePass final : public MetaTransform<CHIR::Func> {public : explicit PrintFuncNamePass (CHIR::CHIRBuilder &builder) : builder(builder) { } void Run (CHIR::Func &func) override { Infoln ("PrintFuncNamePass:" , func.GetRawMangledName ()); } private : CHIR::CHIRBuilder &builder; }; CHIR_PLUGIN (PrintFuncNamePass)
编译和运行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 cmake -S . -B b cmake --build b cjc test.cj --plugin=b/libskeleton.so info: PrintFuncNamePass:8std.core5Array<1>S info: PrintFuncNamePass:8std.core5Array<1>S info: PrintFuncNamePass:8std.core5Array<1>S info: PrintFuncNamePass:8std.core5Range<1>S info: PrintFuncNamePass:8std.core5Range<1>S info: PrintFuncNamePass:8std.core5Range<1>S info: PrintFuncNamePass:8std.core5Array<1>S info: PrintFuncNamePass:8std.core5Array<1>S info: PrintFuncNamePass:8std.core5Array<1>S ...... info: PrintFuncNamePass:7default12split_normalF6String6String$$9ArrayList <6String> info: PrintFuncNamePass:7default5splitF6String6String$$9ArrayList <6String> info: PrintFuncNamePass:7default4main
Windows环境呢 拼尽全力能编过,但拼尽全力加载一直失败,不清楚原因。。。
总结 还是很简单很容易上手的,完整代码就在文中,直接复制即可。