编译和构建
本章将详细介绍如何使用 Sii 2 编译器(siic)将 Sii 源代码编译为不同的目标格式,以及各种编译选项和构建配置。
编译器概述
Sii 2 编译器 siic 是一个命令行工具,支持将 Sii 源代码编译为多种目标格式:
- JavaScript (
.js) - 默认目标 - TypeScript (
.ts) - WebAssembly (
.wat) - LLVM IR (
.ll) - 原生可执行文件 - 直接编译为平台特定的可执行文件
基本用法
查看版本
siic -v
# 或
siic --version
基本编译
# 编译为 JavaScript(默认)
siic input.sii
# 指定输出文件
siic input.sii output.js
# 编译为 TypeScript
siic input.sii output.ts --ts
# 编译为 WebAssembly
siic input.sii output.wat --wasm
# 编译为 LLVM IR
siic input.sii output.ll --llvm
编译目标
JavaScript 编译
# 默认编译为 JavaScript
siic hello.sii
# 显式指定 JavaScript
siic hello.sii --js
# 指定输出文件
siic hello.sii hello.js
输出示例:
// hello.js
const sii = { /* ... */ };
// 编译后的代码
TypeScript 编译
# 编译为 TypeScript
siic hello.sii hello.ts --ts
# 编译后运行 TypeScript 类型检查
siic hello.sii hello.ts --ts --tsc
输出示例:
// hello.ts
const sii: any = { /* ... */ };
// 编译后的代码
WebAssembly 编译
# 编译为 WebAssembly (WAT 格式)
siic hello.sii hello.wat --wasm
输出示例:
(module
(func $main (result i32)
i32.const 0
)
(export "main" (func $main))
)
LLVM IR 编译
# 编译为 LLVM IR
siic hello.sii hello.ll --llvm
输出示例:
; ModuleID = 'hello.sii'
target triple = "x86_64-apple-darwin"
define i32 @main() {
ret i32 0
}
原生编译
基本用法
# 编译为原生可执行文件
siic native hello.sii -o hello
# 指定目标平台(简化格式)
siic native hello.sii -o hello -t=arm64-macos
siic native hello.sii -o hello -t=x64-linux
siic native hello.sii -o hello -t=x64-windows
目标平台
支持的目标平台(简化格式):
x64-windows/x86_64-windows- Windows x86_64x64-linux/x86_64-linux- Linux x86_64arm64-linux/aarch64-linux- Linux ARM64x64-macos/x86_64-macos- macOS x86_64arm64-macos/aarch64-macos- macOS ARM64 (Apple Silicon)
完整 LLVM Triple 格式
# 使用完整的 LLVM triple
siic native hello.sii -o hello --triple=x86_64-pc-windows-msvc
siic native hello.sii -o hello --triple=aarch64-unknown-linux-gnu
siic native hello.sii -o hello --triple=x86_64-apple-darwin
自定义工具路径
# 指定 llc 和 clang 路径
siic native hello.sii -o hello --llc=/usr/local/bin/llc --clang=/usr/local/bin/clang
编译模式
Watch 模式
自动监视文件变化并重新编译:
# Watch 模式
siic watch input.sii output.js
# Watch 模式,编译为 TypeScript
siic watch input.sii output.ts --ts
Serve 模式
启动开发服务器,支持热重载:
# 默认端口 4173
siic serve input.sii output.js
# 指定端口
siic serve input.sii output.js --port=3000
# 配置代理
siic serve input.sii output.js --proxy=http://localhost:8080
库管理
列出本地库
siic lib list
查找最佳匹配的库
# 查找最新版本
siic lib best math
# 查找指定版本
siic lib best math 0.0.1
编译选项
类型检查
# TypeScript 编译后运行类型检查
siic input.sii output.ts --ts --tsc
编译流程
JavaScript/TypeScript 编译流程
- 词法分析:将源代码分解为标记
- 语法分析:构建抽象语法树(AST)
- 语义分析:类型检查和语义验证
- 代码生成:生成目标代码
原生编译流程
- 前端编译:生成 LLVM IR
- LLVM 编译:使用
llc将 IR 编译为对象文件 - 链接:使用
clang链接对象文件和运行时库 - 生成可执行文件
编译配置
运行时库路径
编译器会自动查找运行时库:
- 检查
SII_RUNTIME_DIR环境变量 - 检查安装包的
lib/和bin/目录
环境变量
# 设置运行时库目录
export SII_RUNTIME_DIR=/path/to/runtime
# 设置编译器路径
export SII_LLC_PATH=/usr/local/bin/llc
export SII_CLANG_PATH=/usr/local/bin/clang
常见编译问题
问题 1:找不到运行时库
错误信息:
Runtime static library not found
解决方法:
- 确保运行时库在
lib/目录中 - 设置
SII_RUNTIME_DIR环境变量 - 检查安装包是否完整
问题 2:LLVM 工具未找到
错误信息:
llc: command not found
解决方法:
- 安装 LLVM 工具链
- 确保
llc和clang在 PATH 中 - 使用
--llc和--clang指定路径
问题 3:链接错误
错误信息:
Undefined symbols for architecture
解决方法:
- 确保运行时库与目标平台匹配
- 检查 LLVM triple 是否正确
- 验证运行时库是否完整
构建最佳实践
1. 项目结构
my-project/
├── src/
│ ├── main.sii
│ ├── utils.sii
│ └── config.sii
├── lib/
│ └── math/
│ └── math-0.0.1.sii
├── output/
│ ├── main.js
│ └── main.ts
└── README.md
2. 构建脚本
build.sh (Unix/Linux/macOS):
#!/bin/bash
siic src/main.sii output/main.js --js
siic src/main.sii output/main.ts --ts
build.bat (Windows):
@echo off
siic src/main.sii output/main.js --js
siic src/main.sii output/main.ts --ts
3. 开发工作流
# 开发模式:使用 watch 模式
siic watch src/main.sii output/main.js --js
# 生产构建:编译为 TypeScript 并检查类型
siic src/main.sii output/main.ts --ts --tsc
# 原生构建:编译为可执行文件
siic native src/main.sii -o dist/myapp -t=arm64-macos
性能优化
编译优化
- 使用
--llvm生成优化的 LLVM IR - 原生编译时使用 LLVM 优化选项
- 减少不必要的依赖
运行时优化
- 使用原生编译获得最佳性能
- 优化算法和数据结构
- 减少不必要的 I/O 操作
小结
本章介绍了 Sii 2 编译器的使用:
- 基本用法:编译命令和选项
- 编译目标:JavaScript、TypeScript、WASM、LLVM IR、原生
- 原生编译:跨平台编译配置
- 编译模式:Watch 和 Serve 模式
- 库管理:库的查找和管理
- 问题解决:常见编译问题和解决方法
下一章我们将学习部署和运行,了解如何将编译后的程序部署到生产环境。