跳到主要内容

编译和构建

本章将详细介绍如何使用 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_64
  • x64-linux / x86_64-linux - Linux x86_64
  • arm64-linux / aarch64-linux - Linux ARM64
  • x64-macos / x86_64-macos - macOS x86_64
  • arm64-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 编译流程

  1. 词法分析:将源代码分解为标记
  2. 语法分析:构建抽象语法树(AST)
  3. 语义分析:类型检查和语义验证
  4. 代码生成:生成目标代码

原生编译流程

  1. 前端编译:生成 LLVM IR
  2. LLVM 编译:使用 llc 将 IR 编译为对象文件
  3. 链接:使用 clang 链接对象文件和运行时库
  4. 生成可执行文件

编译配置

运行时库路径

编译器会自动查找运行时库:

  1. 检查 SII_RUNTIME_DIR 环境变量
  2. 检查安装包的 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

解决方法:

  1. 确保运行时库在 lib/ 目录中
  2. 设置 SII_RUNTIME_DIR 环境变量
  3. 检查安装包是否完整

问题 2:LLVM 工具未找到

错误信息:

llc: command not found

解决方法:

  1. 安装 LLVM 工具链
  2. 确保 llcclang 在 PATH 中
  3. 使用 --llc--clang 指定路径

问题 3:链接错误

错误信息:

Undefined symbols for architecture

解决方法:

  1. 确保运行时库与目标平台匹配
  2. 检查 LLVM triple 是否正确
  3. 验证运行时库是否完整

构建最佳实践

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 模式
  • 库管理:库的查找和管理
  • 问题解决:常见编译问题和解决方法

下一章我们将学习部署和运行,了解如何将编译后的程序部署到生产环境。