章节目录

运行代码

本节阅读量:

这一节只解决一个很实际的问题:

1
看到课程里的命令时,知道自己在运行什么。

下面的示例默认你已经打开 Linux、macOS 或 WSL 的终端,并且当前目录是本课程仓库的根目录,也就是能看到 code/ 和 doc/ 的位置。

进入代码目录

每章代码都放在:

1
code/<chapter>/

例如第一章代码是:

1
code/01_numbers/

所以先进入第一章代码目录:

1
cd code/01_numbers

这里的 cd 是 change directory,意思是切换当前目录。后面的命令都会在这个目录里执行。

如果终端提示找不到这个目录,先检查自己是不是站在仓库根目录。命令里的相对路径,都是从“当前目录”开始寻找的。

构建 mini

进入章节代码目录后,运行:

1
make

它会读取当前目录下的 Makefile,把这一章的 C++ 代码编译成一个小程序:

1
mini

mini 就是这一章的命令行工具。每章都有自己的 mini,所以读哪一章,就先进入哪一章的代码目录再运行 make。

如果想清理生成出来的文件,可以运行:

1
make clean

然后再重新构建:

1
make

平时修改代码后直接再运行 make 就可以,不需要每次先 make clean。本章最后一节会单独解释 make 怎样判断是否需要重新构建。

运行 mini

构建成功后,当前目录会出现:

1
mini

运行解释器:

1
./mini run examples/add.lang

这里的意思是:

1
2
3
./mini                 运行当前目录下的 mini
run                    使用解释器模式
examples/add.lang      输入程序文件

开头的 ./ 表示“当前目录里的”。Unix 风格 shell 通常不会自动到当前目录寻找程序,所以这里不能只写 mini。

查看 AST:

1
./mini ast examples/add.lang

查看 IR:

1
./mini ir examples/add.lang

生成汇编:

1
./mini compile examples/add.lang -o out.s

这里的 -o out.s 表示:

1
把输出写到 out.s。

汇编怎么执行

out.s 还不是可以直接运行的程序。它只是汇编文本。

在 Linux、WSL 或常见 x86-64 环境里,完整流程是:

1
2
3
4
5
./mini compile examples/add.lang -o out.s
cat out.s
cc out.s -o out
./out
echo $?

其中:

1
2
3
4
cat out.s          查看生成的汇编文本
cc out.s -o out    把汇编组装、链接成可执行文件 out
./out              运行生成出来的程序
echo $?            查看上一个程序的退出码

如果 examples/add.lang 的内容是:

1
(+ 40 2)

最后应该看到:

1
42

注意,运行 ./out 时不会显示任何内容。这里的 42 是随后执行的 echo $? 打印出来的退出码,不是 ./out 主动打印的结果。

退出码通常只能可靠地观察 0 到 255 之间的小整数。例如语言里的结果是 300 或 -1 时,echo $? 看到的数字会不同。第一章会专门留一道练习观察这个现象。

先分清四个程序

这一串命令里出现了几个容易混在一起的名字:

名字 谁提供 在这里做什么
make 开发工具 根据 Makefile 构建课程代码
mini 本课程 解释小语言,或把它编译成汇编
cc 系统工具链 把汇编组装、链接成可执行文件
out cc 的输出 真正运行编译后的小语言程序

因此,完整关系是:

1
2
C++ 源码 --make--> mini
小语言源码 --mini compile--> out.s --cc--> out

这条最短流程适用于目前正在使用的第一章快照。第九章加入垃圾回收以后,collector 会成为单独的 C++ runtime object;届时每章的 make 还会生成 gc_runtime.o,链接命令变成:

1
c++ out.s gc_runtime.o -o out

out.s 负责生成程序和 root 协议,gc_runtime.o 提供分配器与 collector。教程到第九章时会完整解释这条新边界;现在只需知道,mini compile 在任何章节都不替你链接。

macOS 上的差异

macOS 上,程序入口名字通常是 _main,Linux 上通常是 main。mini compile 会按当前系统自动选择。也可以手动指定目标:

1
2
./mini compile examples/add.lang -o out.s --target macos
./mini compile examples/add.lang -o out.s --target linux

如果你在 Apple Silicon Mac 上,cc 默认可能按 arm64 汇编。但本课程生成的是 x86-64 汇编,所以链接时可以写:

1
cc -arch x86_64 out.s -o out

如果系统没有 x86-64 工具链或 Rosetta,这一步可能会失败。可以先换到 x86-64 Linux、Intel Mac,或者装好对应工具后再继续。

常见问题

如果看到:

1
make: command not found

说明当前命令行环境里没有 make。

如果看到:

1
c++: command not found

说明当前环境里没有 C++ 编译器,或者编译器不在 PATH 里。

如果构建成功,但运行 cc out.s -o out 时看到:

1
cc: command not found

说明当前环境缺少负责组装和链接汇编的 C 编译器驱动。

这些问题都不是课程代码本身的错误,而是命令行环境还没有准备好。继续之前,请确认当前环境能找到 make、c++ 和 cc;Linux、macOS 或装好开发工具的 WSL 都可以完成后面的步骤。

到这里,只要能在 code/01_numbers 中完成 make、mini run、mini compile 和 cc 这四步,运行环境就准备好了。暂时看不懂 AST、IR 和汇编输出没有关系,后面的正文会逐层把它们拆开。


0.0 路线图

上一节

0.2 命令是怎么进入代码的

下一节