目录: 点击这里
这一章介绍怎么构建 Musys 库, 以及如何使用 Musys 库写一个简单的 demo.
编译器、语言服务器与依赖问题
Musys-IR 是使用 Vala 编程语言 编写的, 依赖 Vala
编译器, 依赖 GLib
标准库与 Gee
数据结构库.
如果要语义高亮、智能提示等, 可以选择 vala-language-server
语言服务器,配合相关的扩展使用.
- 在 Ubuntu (24.04+) 操作系统上, 需要使用
apt
安装依赖: valac
meson
libglib2.0-dev
libgee-0.8-dev
. vala-language-server
需要根据 GitHub 给出的 OBS repo 链接自行安装.
- 在 Fedora 操作系统上, 需要
dnf
安装的依赖是: vala
libgee-devel
glib2-devel
meson
vala-language-server
. 没有需要额外安装的依赖.
- 在 Windows 操作系统上请使用 MSYS2 兼容环境 (清华镜像在此).
目前只有少数几个文本编辑器内置了对 Vala 编程语言的支持. 其中 KDE Kate 的支持相对完整, 只要装好 Vala 语言服务器就能用. VS Code 用户需要额外安装下面这两个扩展:
下载并构建 Musys-IR
Musys-IR 是共享库而不是可执行文件, 这里仅仅用于验证 Musys-IR 能否正常构建, 不能运行, 不建议安装. 若需要使用 Musys IR 写一个 demo, 建议跳转到下一节.
这里给出下载-构建的 Shell 命令。最后一行是测试安装使用的, 一般不执行:
1 2 3 4 5 6 7 8 9
| git clone -b adaptive-traced-cfg https://github.com/medihbt/musys-ir.git cd musys-ir
meson setup build && cd build
meson compile
meson install
|
上述命令执行顺利的话, meson compile
以后你就能在 build/src 目录下看到 libmusys-ir.so
MusysIR-0.0.1.gir
musys-ir.h
musys-ir.vapi
这几个文件.
基于 Musys-IR 编写一个简单的 Demo
上面的构建仅仅是测试而已,接下来所有的教程、用例等等都要使用以下构建方式: Meson Subprojects + Git submodules.
项目初始化
首先, 在你喜欢的目录下创建一个 musys-demo
用作项目开发目录, 然后初始化 Meson:
1 2 3
| mkdir musys-demo && cd musys-demo meson init -l vala --type executable --version 0.1 meson setup build
|
然后初始化 Git. .gitignore
文件参考如下:
1 2 3 4 5 6 7 8 9 10 11
| build/* builddir/* .vscode/* .DS_Store/* .cache/* *.o *.yy.c *.yy.h *.tab.c *.tab.h .clangd
|
Git & 子项目初始化命令如下:
1 2 3 4 5 6
| git init -b master git add .gitignore; git commmit
mkdir -p subprojects git submodule add -b adaptive-traced-cfg https://github.com/medihbt/musys-ir subprojects/musys-ir
|
接下来, 修改 meson.build
文件如下. 标有 ‘+’ 的是要补充的内容, 标有 ‘-‘ 的是要删除的内容.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| +musys_ir_subproj = subproject('musys-ir') +musys_ir_dep = musys_ir_subproj.get_variable('musys_ir_dep')
dependencies = [ dependency('glib-2.0'), dependency('gobject-2.0'), + dependency('gee-0.8'), + musys_ir_dep, ]
+sources = files([ + 'musys_demo.vala', +])
exe = executable('musys-demo', - 'musys_demo.vala', + sources, + dependencies : dependencies, install : true)
|
修改以后再做一次 commit:
完成.
怎么更新 Musys-IR?
Musys-IR 尚处于开发阶段, 其代码、仓库、分支等可能会频繁更新. 请使用 git submodule update
适时更新子项目.
第一个 Musys 前端
先从最简单的开始——用 Musys-IR 生成一个空的 Main 函数罢. 修改 musys_demo.vala
源文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| using Musys; using Musys.IR; using Musys.IRUtil;
void main() { var module = new Module("musys-demo-main"); TypeContext tctx = module.type_ctx;
IntType i32ty = tctx.get_int_type(32); FunctionType main_type = tctx.get_func_type(i32ty, null); var main_func = new Function.as_impl(main_type, "main"); module.global_def["main"] = main_func;
number_module(module); var writer = new IRUtil.Writer(module) { llvm_compatible = true }; writer.write_file(stdout); }
|
现在试着编译运行一下:
1 2 3
| cd build meson compile ./musys-demo
|
你应该能看到输出:
1 2 3 4 5 6
| define dso_local i32 @main () { 0: ret i32 0 }
|
成功! 接下来所有的实践内容都要在这个项目下进行了.
如果我就想用 C 语言怎么办?
我试着写一段等价的 C 程序罢. Musys 的 C API 是 Vala 自动生成的, 现在还不稳定, 这里图一乐就好.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <musys-ir.h>
int main(void) { MusysIRModule* module = musys_ir_module_new("musys-demo-main", sizeof(size_t), MusysPlatformEndianHost()); MusysTypeContext* tctx = musys_ir_module_get_type_ctx(module);
MusysType* i32ty = (MusysType*)musys_typecontext_get_int_type(tctx, 32); MusysFunctionType* main_type = musys_typecontext_get_func_type( tctx, i32ty, NULL, 0);
MusysIRFunction* main_func = musys_ir_function_new_as_impl(main_type, "main");
GeeTreeMap* global_def = musys_ir_module_get_global_def(module); gee_abstract_map_set((GeeAbstractMap*)global_def, "main", main_func);
musys_ir_util_number_module(module); MusysIRUtilWriter* writer = musys_ir_util_writer_new(module); musys_ir_util_writer_set_llvm_compatible(writer, true); musys_ir_util_writer_write_file(writer, stdout);
musys_ir_util_writer_unref(writer); g_object_unref(main_func); g_object_unref(module); return 0; }
|