自制编程语言编译环境搭建:crowbar与Diksam工具链配置指南

发布时间:2026/10/17 19:28:50
自制编程语言编译环境搭建:crowbar与Diksam工具链配置指南 简介面向编程语言学习者的自制语言开发资料系统讲解编程语言从设计、实现到使用的完整流程涵盖语法语义设计、编译器与解释器构建并以 crowbar 和 Diksam 两套自制语言为例展示基于 yacc/lex、bison/flex 以及 MinGW 工具链的具体实现思路同时覆盖 Linux 和 Windows 环境下的跨平台开发要点。资源以单个 PDF 文件呈现大小仅 2.38MB内容结构清晰便于集中阅读与检索已有 870 人浏览学习。读者可从中深入了解词法分析、语法分析、运行时环境等关键模块并跟随 crowbar 与 Diksam 从 0.1 到 0.4 各版本的演进看到从简单计算器到完整语言的逐步实现过程。无论是入门理解编译原理还是动手设计自己的编程语言这份资料都能提供较为系统的参考尤其适合对语言设计感兴趣的开发者、计算机专业学生及相关技术爱好者。1. 自制编程语言环境搭建从工具链到能跑通 crowbar 与 Diksam想跟着《自制编程语言》把 crowbar 和 Diksam 从源码编译出来卡在 Windows 环境上的人不在少数。最常见的翻车现场是m4: cannot open Files: No such file or directory——明明装了 bison一执行make就报路径被截断这种玄学错误十有八九是工具链安装路径带空格惹的祸。还有人在 Linux 下编译 crowbar_book_0_1 时遇到(0x0d)解析错误最后发现是 Windows 的 CRLF 换行符在捣乱。这套环境的难点不在语言本身而在 yacc/lex或 bison/flex和 GCC 工具链的版本匹配与参数配置。本文面向卡在编译阶段的开发者先把工具链选型和环境变量讲清楚再逐步落到每个源码包的构建命令最后给出验证跑通的方法。2. 工具链选型MinGW 与 Cygwin 怎么选版本差异踩过的坑2.1 两种 Windows 编译环境的核心差异搭建这套自制语言环境第一步不是急着下载源码而是想清楚在哪个编译环境下构建。书中源码同时提供了 Linux 的make.sh和 Windows 的make.bat但实际的构建脚本在 Windows 下依赖的是 Unix 风格的工具链。常见的做法有两种MinGW 和 Cygwin。MinGW 提供的是原生的 Windows 编译工具链编译出来的 exe 不依赖额外的 DLL。但它的问题是默认不带 make需要单独装 mingw32-make而且 bison/flex 这些生成器通常不在 MinGW 的默认安装包里。Cygwin 则是完整的 Unix 模拟环境自带 bison、m4、make编译方式几乎和 Linux 一致代价是生成的 exe 依赖 cygwin.dll。我一般建议新手直接走 Cygwin 路线。原因是书中crowbar_book_0_2之后的版本在链接阶段会遇到-lmsvcp60这类 MSVC 运行库的问题MinGW 下处理起来要手动找库文件Cygwin 下反而顺畅。MinGW 适合那些已经装了完整工具链、只想用mingw32-make.exe跑 Makefile 的熟手。2.2 源码包的结构与构建顺序源码压缩包里按版本组织目录核心是calc、mycalc、llparser三个前置练习然后是crowbar_book_0_1到crowbar_book_0_4最后是diksam_book_0_1到diksam_book_0_4。构建顺序必须从crowbar_book_0_1开始不要一上来就编 Diksam——后者依赖前者积累的代码基础。每个版本的 Makefile 针对 Linux 和 Windows 做了区分但 Windows 下要手动指定生成器。比如crowbar_book_0_1用 yacc/lex而crowbar_book_0_3起引入了 GC垃圾回收逻辑构建参数会多出-DDEBUG等选项。Diksam 从diksam_book_0_3开始改用手写的 main 函数不再完全依赖 yacc 生成的y.tab.c这会导致 Makefile 的目标依赖关系发生变化。# Linux 下编译某个版本的标准流程 cd crowbar_book_0_1 chmod x make.sh ./make.sh这个脚本做的事情是调用gcc编译lex.yy.c、y.tab.c以及main.c、interface.c等源文件最后链接成crowbar可执行文件。注意lex.yy.c和y.tab.c是 flex 和 bison 生成的中间文件Makefile 里会先执行bison --yacc -dv crowbar.y和flex crowbar.l来生成它们。2.3 正则库 oniguruma 的版本选择crowbar_book_0_4引入了正则表达式支持依赖 oniguruma 库。书中提供的版本是 5.9.4这是一个比较关键的版本——太新的版本在 configure 阶段可能因为编译器标准问题报错太老则缺少部分正则语法。Linux 下安装 oniguruma 是标准的三步走wget http://www.geocities.jp/kosako3/oniguruma/archive/onig-5.9.4.tar.gz tar -xvf onig-5.9.4.tar.gz cd onig-5.9.4 ./configure make make install这里的configure会检测当前环境是否具备 ANSI C 编译器、alloca 函数和标准头文件。如果之前装过其他版本的 oniguruma建议先make uninstall清理干净再装 5.9.4否则链接时可能出现符号冲突。装完后make install默认把库文件放到/usr/local/lib记得确认这个目录在动态链接器的搜索路径里。Windows 下用 Cygwin 编译 oniguruma 时我踩过一个坑在make install阶段报ranlib: /usr/local/lib/libonig.a: No such file。原因是 Cygwin 的安装路径里包含了 Windows 路径转换问题需要进入.libs目录手动执行ranlib libonig.a再把生成的静态库拷贝到/usr/local/lib。3. Windows 下 MinGW 完整安装从 mingw-get 到 make 的 PATH 配置3.1 下载与安装 mingw-get-setup.exeMinGW 的安装方式是下载mingw-get-setup.exe引导程序然后通过它在线拉取需要的组件。书中提到的官方源是http://www.mingw.org/但实际下载时经常跳转到 SourceForge 的镜像需要手动选一个可用镜像。安装过程的要点在 Installation Directory 这一步。很多人习惯默认装到C:\MinGW或者D:\Program Files (x86)\MinGW后者会埋下路径带空格的雷。我建议手动改成D:\MinGW这样的纯英文无空格路径因为 bison 和 m4 在解析 include 路径时不会对空格做转义处理。安装完成后打开 MinGW Installation Manager在左侧勾选mingw32-base和msys-base前者提供 GCC 编译器后者提供 make 和其他 Unix 工具。注意要点击Mark for Installation后再点菜单栏的Installation - Apply否则只是标记不会真正下载。3.2 把 make.exe 和 gcc.exe 加进 PATH装完 MinGW 后D:\MinGW\bin目录下会有mingw32-make.exe这个文件的名字很有迷惑性——它不是make.exe很多人在命令行里敲make发现提示找不到命令。解决办法有两个一是把D:\MinGW\bin加入系统 PATH二是把mingw32-make.exe复制一份改名为make.exe。# 把 MinGW 加入 PATHWindows 命令行 setx PATH %PATH%;D:\MinGW\bin # 验证 gcc 和 make 是否可用 gcc --version make --version如果通过setx设置后新开的命令行窗口仍然找不到命令检查一下是不是用了set PATH...而不是setx——前者只对当前窗口生效后者才会写入系统环境变量。另外如果系统装了 Git for Windows它自带的/usr/bin/make.exe可能会和 MinGW 的冲突PATH 顺序决定了先找到哪个。3.3 用 Makefile 构建时的目标依赖问题MinGW 下跑crowbar_book_0_1的 Makefile经常遇到的目标依赖报错是make: *** No targets specified and no makefile found。原因很直接当前目录没有Makefile文件。源码包里默认带的是make.sh和make.batMakefile是用make.bat里的命令从Makefile.in生成的或者直接解压后就有——取决于你下的是哪个版本包。D:\win_sjis\crowbar_book_0_1 D:\MinGW\bin\mingw32-make.exe bison --yacc -dv crowbar.y process_begin: CreateProcess(NULL, bison --yacc -dv crowbar.y, ...) failed. make (e2): 系统找不到指定的文件。这段报错的根因不是 Makefile 本身有问题而是 MinGW 的 make 在调用 bison 时去 PATH 里找bison.exe但没找到。MinGW 默认不包含 bison 和 flex它们属于 GnuWin32 项目需要单独下载安装。所以顺序应该是先装 bison/flex再跑 make否则 make 会在生成y.tab.c的第一步就失败。4. bison 与 flex 的安装细节GnuWin32 与 Cygwin 两条路线4.1 GnuWin32 的 bison 与 flex 安装步骤GnuWin32 项目提供了 Windows 原生版的 bison 和 flex下载地址在http://gnuwin32.sourceforge.net/packages/bison.htm和http://gnuwin32.sourceforge.net/packages/flex.htm。要选Complete package, except sources这个安装包它包含可执行文件和运行时 DLL纯源码包没有 exe 不能用。安装时同样要注意路径问题。GnuWin32 默认装到C:\Program Files (x86)\GnuWin32这个路径在 bison 调用 m4 时会导致经典报错m4: cannot open Files: No such file or directory m4: cannot open (x86)\GnuWin32\Bison/share/bison: No such file or directory原因分析bison 内部会调用 m4 来处理语法文件m4 在构造路径时把带空格的路径按空格拆开了。解决方法是把 GnuWin32 重装到C:\GnuWin32或者直接手动把bison.exe、m4.exe和相关的 DLL 拷贝到一个纯路径目录下再把这个目录加入 PATH。也有读者反馈直接改了环境变量后仍然报同样的错最后是把C:\GnuWin32\bin放到了 PATH 的最前面同时把C:\Program Files (x86)\GnuWin32\bin从 PATH 里移除才解决。这说明 PATH 里有多个 bison 版本时make 会按顺序找到第一个可用的如果你的 PATH 里恰好有旧版 bison 就会先命中它进而用不兼容的方式调用 m4。4.2 Cygwin 路线的安装配置如果不想跟 GnuWin32 的路径纠缠第二条路是装 Cygwin。到官网下载setup-x86_64.exe64 位系统安装时选择Install from InternetRoot Directory 可以改成C:\cygwin64Local Package Directory 是下载缓存的临时目录随便设一个。选包阶段需要勾选这三个组件Interpreters分类下的bisonDevel分类下的m4和makeDevel分类下的gcc-core如果没装的话Cygwin 安装完成后桌面上会出现Cygwin64 Terminal的快捷方式打开就是 bash 环境。在这个终端里执行bison --version能直接看到版本号说明工具链已经就位。此时进入源码目录运行./make.sh构建过程中如果报cannot find -lmsvcp60说明链接器在找 MSVC 的运行库——Cygwin 下需要在 Makefile 的LIBS变量里把-lmsvcp60换成-lonig如果你在编 crowbar_0_4 或 Diksam。4.3 生成文件缺失时的手动处理流程bison 和 flex 运行成功后会在源码目录生成y.tab.c、y.tab.h和lex.yy.c三个文件。如果 make 执行过程中途失败这三个文件可能不会完整生成后续 gcc 编译会报y.tab.h: No such file or directory。# 手动重新生成在源码目录下执行 bison --yacc -dv crowbar.y flex crowbar.l ls -la y.tab.c y.tab.h lex.yy.c这里bison --yacc -dv中的-d参数表示同时生成头文件y.tab.h-v输出详细错误信息。如果第一步 bison 就报错多半是crowbar.y里有语法冲突这时候不要硬着头皮往下跑先看报错行号定位是哪个规则写错了。flex 生成的lex.yy.c里如果报undefined reference to yywrap需要在链接时加-lfl或者-ly依赖 flex 库。5. 环境搭建常见问题排查五个高发报错的处理记录5.1 m4 路径空格报错现象执行make时出现m4: cannot open Files: No such file or directorybison 完全无法运行。原因bison 调用 m4 时把安装路径按空格切片了C:\Program Files (x86)\GnuWin32被拆成了C:\Program和Files两段。m4 无法解析带空格的文件路径。解决把 GnuWin32 重装到无空格路径并确认 PATH 里没有第二个 bison 干扰。安装后用where bison和where m4检查当前生效的是哪个版本。5.2 Linux 下解析 test.crb 报 0x0d现象在 Linux 下编译crowbar_book_0_1成功但运行./crowbar test/test.crb时报第 5 行解析错误错误码带(0x0d)。原因源码包中的test.crb是在 Windows 下打包的换行符是 CRLF。crowbar 的解释器在读文件时把\r当成非法字符。解决用dos2unix test/test.crb转成 LF 换行或者用sed -i s/\r$// test/test.crb手动去除。macOS 下如果遇到同样问题也适用此方法。5.3 make 报错 recipe for target crowbar failed现象MinGW 下编译进行到cd ./memory; gmake.exe时中断Makefile 报recipe for target crowbar failed。原因memory子目录有自己的 Makefile它调用的是gmake.exe而不是make.exe。MinGW 默认只有mingw32-make.exe没有名为gmake的入口。解决在D:\MinGW\bin下复制一份mingw32-make.exe并改名为gmake.exe或者把 Makefile 里的gmake替换成mingw32-make。5.4 oniguruma 安装后 ranlib 找不到静态库现象Cygwin 下make install执行到一半报ranlib: /usr/local/lib/libonig.a: No such file。原因libtool 生成的.a文件位于.libs子目录但make install阶段路径切换出了问题ranlib 在/usr/local/lib下找不到实际的库文件。解决进入.libs目录手动执行ranlib libonig.a再把libonig.a拷贝到/usr/local/lib然后重新运行make install。5.5 bison 不可用导致 y.tab.c 未生成现象make 报gcc: y.tab.c: No such file or directory但crowbar.y明明存在。原因bison 未安装或 PATH 没配置好make 在尝试生成y.tab.c的第一步就失败了后续的 gcc 编译因为缺少中间文件而跟着报错。解决先单独执行bison --yacc -dv crowbar.y确认能生成y.tab.c和y.tab.h后再执行 make。若 bison 本身报createprocess failed优先排查 PATH 中的 bison 路径是否完整。6. 装完怎么验证跑通从 mycalc 到 Diksam 的分级测试验证这套环境是否装对了不能只停留在能编译出 exe 的层面。按照书中源码的进阶路线我习惯分三个等级做验证每通过一级才进入下一级这样出问题能立刻定位是哪个环节挂了。第一级验证是calc和mycalc这两个是最简单的表达式计算器用 yacc/lex 生成解析器后通过 gcc 编译。mycalc的例子要生成y.tab.h所以 bison 必须带-d参数。运行mycalc.exe后输入一个四则运算表达式比如12*3期望输出7——注意这里*的优先级应该高于如果你的结果输出9说明语法文件的优先级规则没有生效。# 在源码目录下验证 mycalcWindows 命令行或 Cygwin 终端 echo 12*3 | ./mycalc正常输出是7如果报lex.yy.c: fatal error: y.tab.h: No such file or directory回到第 4 章重新生成中间文件。第二级验证是llparser和crowbar_book_0_1。llparser是手写的 LL(1) 解析器示例不依赖 yacc能跑通说明你的 C 编译器本身没有问题。而crowbar_book_0_1编出的 crowbar 解释器需要执行一个包含变量的脚本test.crb./crowbar test/test.crb如果前面的换行符问题已经处理干净这个脚本会输出一系列赋值和打印结果。看输出里有没有乱码或Segmentation fault一旦出现段错误优先检查 GC 相关的宏定义是否一致——crowbar_book_0_3以后引入了 GC编译时漏了-DDEBUG会导致运行时崩溃而不是编译失败。第三级验证是 Diksam 系列。diksam_book_0_1的 Makefile 目标依赖比较复杂需要确认 make 能正确找到编译器生成器。如果diksam_book_0_2编译通过但运行时报Diksam ver.0.2 无法加载 .dkm 文件多半是运行目录和工作目录不一致导致的相对路径问题。用./diksam test.dkm的完整路径方式运行即可。最后我个人的习惯是写一个最小脚本把整个链路过一遍从mycalc到llparser再到crowbar_book_0_4每个都执行一次编译和运行全程记录输出。环境配置这东西重装一次成本太高不如留一份完整的验证脚本下次换机器时直接跑一遍就知道缺什么依赖。从那以后我每次拿到新的自制语言源码都会强制走一遍这条验证链确保不是工具链的巧合掩盖了代码本身的问题。希望帮到你。本文还有配套的精品资源点击获取