agentzh さんのプロフィールHuman & Machineフォトブログリストその他 ツール ヘルプ

ブログ


3月25日

毕业设计开发周记(第 3 周)

过去一周工作的完成情况

过去的这一周大部分时间用来找工作了,呵呵。好在工作比想象中的好找, 所以也没有花费我太多的精力。

这些日子在毕业设计项目上取得了以下进展:

  • Makefile::Parser 开辟了 gmake-db分支
  • 在 GNU make database 的基础上设计出了 GNU make AST 的结构。它由下列几个类组成:
    • Makefile::AST

      总的 AST 类,提供节点的添加与查询,比如 add_implicit_rule,apply_implicit_rules,add_explicit_rule,apply_explicit_rules,add_var,add_auto_var,get_var,还有许多其他工具函数,比如计算变量最终值的方法 eval_var_value,有关局部变量作用域 Pad 的 enter_scopeleave_scope 方法,等等。

    • Makefile::AST::Rule::Base

      它是 AST 中规则节点的基类,包含 normal_prereqs,order_prereqs,commands,colon 这些属性。

    • Makefile::AST::Rule

      该类表示非隐式规则以及隐式规则“应用”之后的形式,从 Makefile::AST::Rule::Base 继承,并新增了 targetother_targets 属性。

    • Makefile::AST::Rule::Implicit

      该类表示 AST 中的隐式规则节点,从 Makefile::AST::Rule::Base 继承,并新增了 targets,match_anything,is_terminal 等属性。

    • Makefile::AST::StemMatch

      该类封装了含 % 的文件模式的匹配与 stem 替换算法。

    • Makefile::AST::Variable

      它表示 AST 中的变量节点,包含 name,value,flavor,origin 等属性。

  • 添加了 ast-basic.t,ast-rule.t,ast-var.t,和 ast-stem.t 脚本用于对 AST 及其相关类进行单元测试。
  • 实现了 Makefile::Parser::GmakeDB 类,用于解析由 make -qp 命令生成的 GNU make database,并构造出对应的 Makefile::AST 对象(即 GNU Make AST).

    有趣的是,GNU make 生成的 database 报表也是完全合法的 Makefile 格式,而且只使用最最基本的语法结构,因此 Makefile::Parser::GmakeDB 直接使用 MDOM::Document::Gmake 进行解析。

  • 实现了 Makefile::AST::Evaluator 类,用于按照 GNU make 的语义“执行”给定的 GNU make AST。

    值得一提的是,包括显隐式规则的应用在内的拓朴图的构建算法其实大部分实现在了 Makefile::AST 及其子节点类中了。

  • `make -pq`,Makefile::Parser::GmakeDB,和 Makefile::AST::Evaluator 三者串联了起来,组装成了一个完整的 make 工具,即 pgmake-db.

    该工具可以运行基于 IPC 的 GNU make 测试集。目前已通过了 sanity/func-refs.t 测试文件中 95% 以上的测试用例。

下一周的工作计划

下一周可能没有太多时间用来 hack 了,因为需要应付学校的结欠考试。但是顺着上一周的工作继续往下走应该是很容易的。我立刻能想到的工作有:

  • 添加 Makefile::AST::Command 类,用于将 Makefile 命令相关的处理封装起来,并为之添加文件名和行号的属性支持(file 和 line).
  • Makefile::AST::Variable 类添加 file 和 line 属性,以便能通过 func-refs.t 中余下的那些测试。
  • pgmake-db 通过尽可能多的 GNU make 测试集,同时根据 GNU make Manual 设计更多的有关变量和规则应用的综合测试用例,从而不断地完善 AST 的结构以及 AST 执行组件(evaluator)。
3月16日

毕业设计开发周记(第 2 周)


过去一周计划的完成情况

  • 将已有的基于 Test::Base 的 GNU make 测试集加入到了 Makefile::DOM 模块的  SVN 仓库 的 gmake 分支 ,并进行简单的重构:

    http://svn.openfoundry.org/mdom/branches/gmake/t/

  • 放弃了整合 Adam Beauchamp 的状态机模式补丁的计划,因为我还是比较喜欢目前的解析策略。

  • 暂时取消了发布 Makefile::DOM 0.01 的计划。因为 Makefile::DOM 的设计还有许多问题,它的设计与实现均需要 未来用 Makefile::Parser 和 GNU make 测试集来进行指引和验证。

  • Makefile::Parser 0.11 的基础上比较完整地实现了下列 GNU make makefile 内建函数:

    subst, patsubst, strip, findstring, filter, filter-out, sort, word, words, wordlist, firstword, lastword, dir, notdir, suffix, basename, addsuffix, addprefix, join, wildcard, realpath, abspath, shell, if, and, or, error, warning, info, foreach

    另外还实现了所谓的“替换引用”(Substitution References),比如:

        $(c_files:.c=.o)

    它们的实现代码直接添加进了 Makefile::Parser 的 SVN 仓库的 trunk/ .

    限于 Makefile::Parser 旧引擎不支持“递归展开变量”,下列 GNU make 内建函数暂时无法恰当地实现:

    origin, value, call, flavor, and eval

    已支持函数的测试目前放置在 Makefile::DOM 的 gmake 分支中:

    http://svn.openfoundry.org/mdom/branches/gmake/t/gmake/sanity/func-refs.t

  • Makefile::Parser 模块实现了  plmake  脚本。 它是基于该模块的 make 命令行工具。该工具使得我可以在实现 GNU make 内建函数的时候运行基于  t::Gmake 的测试台。TDD 万岁!

  • Makefile::Parser 模块的 POD 文档中简单地提及了全新实现的基本计划,并对其中过时的和不准确的地方进行了更新。

  • 上述对 Makefile::Parser trunk 的扩展与改进先后以 0.12, 0.13, 0.14, 0.15, 0.16, 和 0.17 版的形式发布到了 CPAN.

  • 发布了 Makefile::GraphViz 的一些更新版本(当前 CPAN 上版本号为 0.16), 稍稍改进了一下 POD 文档,同时提升了所需的 Makefile::Parser 的最低版本号。

下一周及以后的工作计划

  • 继续发挥 Makefile::Parser 0.xx 旧引擎的余热, 借助于  plmake 实现基本的基于拓仆图的目标更新算法以及一些 GNU make 命令行选项。

  • 利用  plmake  编写 和运行更多的基于  t::Gmake 的 GNU make 测试,不断改进 Makefile::Parser 0.xx 的相关部件。

  • 利用 GNU make 的 -p 选项(即 --print-data-base 选项)取得它内部的数据库结构信息,以此为基础设计 出下一代 Makefile::Parser (即 1.x.x)所使用的 Makefile AST 结构。

  • 针对 Makefile AST 设计出纯 Perl 的运行时(Runtime),同时对 GNU make 进行包装,使之能 作为 makefile AST 生成器来使用。由此可以得到全功能的以 GNU make 为前端的 pgmake, 从而可以运行 GNU make 测试集。

    以 GNU make 为前端的 pgmake 的使命是为了得到纯 Perl 的 GNU make runtime (或者说是 AST Evaluator)

  • 另一种复用 GNU make 的技巧是将之用作纯的 Runtime. 具体做法是,从 Makefile AST 发射出 makefile 源代码,它只使用最最基本的 Makefile 语法结构,然后用下面的命令让 GNU make 去执行它:

        make -Rr -f foo.mk

    这儿的 foo.mk 便是 AST Dumper 生成的``基本 Makefile''.

    利用这种技术,我们可以得到以 GNU make 为后端,以 Makefile::DOM 和全新版 Makefile::Parser 为前端的 pgmake。同样也可以去运行整个 GNU make 测试集。

    该版本的 pgmake 的使命是驱动并验证 Makefile::DOM 和 Makefile::Parser 1.x.x 这两个模块的开发工作。

3月7日

毕业设计开发周记(第 1 周)


从现在起,每周三我都将为毕业设计拟定下一周的工作计划,同时对前一周的相关工作进行总结。

过去一周已完成的工作

  • 先后发布了 Makefile::GraphViz 0.11, 0.12 和 0.13 版,主要是旧内核的例行维护,包括 为 gvmake 脚本添加了有用的 -a 选项(从而能绘制 Makefile 中所有的根目标),以及修复了 RT bug #24828#15070

  • 开发了针对 Module::Install 的脚本 releng , 用于自动化 CPAN 模块发布前繁杂的准备工作。

    我的 Makefile 项目涉及多个 CPAN 模块,每个模块需要发布的版本又是不计其数,因此 releng 脚本无疑会为我节省大量的时间。

  • 基于 Linux::Smaps 开发了一个在 Linux 上统计任意 shell 命令所占用的最大内存量的脚本,名为 smem . 测试显示,Ubuntu 的 System Monitor 使用的也是来自 smaps 的内存占用信息。我在该脚本中首次实用了 Perl 的 fork 函数(一直想用都没用上,因为前面一直用的都是 Windows)。

    鄙视 Linux 内核,因为至今它都没有完整地实现 getrusage 函数 , 从而使得 GNU time 在 Linux 上只能用来计时。同样的原因,CPAN 上的 BSD::Resource 在 Linux 上也没有太大的用处。

    我的 smem 脚本可用于统计 Makefile 项目中各模块的内存占用情况。

下一周的工作计划

  • 修改和应用 Adam Beauchamp 今年 1 月 13 日提供的针对 Makefile::Parser 的补丁到 SVN 仓库branches/states/ 分支 。 该补丁将使得 Makefile::Parser 内核基于标准的状态机模式。

  • branches/states 分支 成熟以后,将之融合到主流的 trunk/, 然后在不影响 Makefile::GraphViz 测试集的前提下,发布为 Makefile::Parser 0.12 版。随后取消 states/ 分支。

  • 开辟 /branches/refs 分支,以比较完整地实现 GNU make 的函数引用(function reference)和变量引用(variable reference),主要面向 RT bug #18229

  • 在 /branches/refs/ 分支成熟后,融合进主流的 trunk/,并发布新的 Makefile::Parser 至 CPAN.

  • 在最近的 Makefile::Parser 模块的 POD 文档中交代全新实现的基本计划。

  • 将已有的基于 Test::Base 的 GNU make 测试集加入到 Makefile::DOM 模块的 SVN 仓库gmake 分支 ,并进行简单的重构:

      t/Shell.pm
    t/Gmake.pm
    t/lib/Test/Make/Gmake.pm
    t/lib/Test/Make/Base.pm
    t/lib/Test/Make/Util.pm
    t/lib/Test/Util.pm
    t/gmake/syntax/
    t/gmake/features/
    t/gmake/...
  • 将新补充的测试用例添加进 Makefile::DOM 的单元测试集,将失败的测试标成``SKIP'',并为各个主要 .pm 文件添加 POD 文档,直至发布该模块的第 一个 CPAN 版本 0.0.1

  • 编写 newpm 脚本以自动为我创建 .pm 文件的代码和 POD 文档的骨架。

2月28日

Makefile 项目的开发计划


 

Makefile::DOM

第一阶段的工作将集中在 Makefile::DOM 的开发上。

该模块以及其他模块都将遵循“早发布,常发布”的原则,并使用先进的基于  Subversion  的  SVK 版本控制系统 进行源代码的管理。

Makefile::DOM 在  CPAN  发布的版本号,采用三段数的格式,比如 0.2.12。以此版本号为基础,可将该模块的开发工作分为下列里程碑:

  • 0.0.x

    从 0.0.1 开始,实现  MDOM::Document::Gmake  模块。它将逐步地支持 GNU make 几乎全部的词法和语法结构,完成相应的 POD 格式的英文文档,以及比较全面的基于 Test::Base 模块的  单元测试台

  • 0.1.x

    从 0.1.0 开始,逐步地在 MDOM (即 Makefile::DOM) 的基础上开发出 GNU make 的纯 Perl 实现(名叫 pgmake),从而得以运行  GNU make 官方的测试集 ,同时完善  MDOM::Document::Gmake ,进而确保并验证 MDOM 自身的完整性。

    考虑到 GNU make 官方测试集并不是很完整,因此还须根据  GNU make Manual  文档对该测试集进行扩充,以便尽可能多地覆盖 gmake 实际支持的特性集。

  • 0.2.x

    从 0.2.0 开始,逐步实现 MDOM::Document::Nmake 模块,使得它能支持微软 32 位 NMAKE 几乎全部的词法和语法结构,完成相应的 POD 格式的英文文档,以及比较全面的基于 Test::Base 模块的单元测试台。

  • 0.3.x

    从 0.3.0 开始,在 MDOM 基础上开发出 NMAKE 的纯 Perl 实现(名叫 pnmake),从而得以运行 NMAKE 测试集,同时完成 MDOM::Document::Nmake,进而确保并验证 MDOM 自身的完整性。

    由于微软的 NMAKE 不像 GNU make 那样是开源项目,我无法取得 NMAKE 官方的测试集,故必须按照 MSDN 网站上的  NMAKE Reference  文档自主设计测试用例。

  • 0.4.x

    将 GNU make 和 MS NMAKE 对应的基于 IPC::Run3 的测试集转换为针对 MDOM 的高度可移植的轻量级测试集。

  • 0.5.x 及其以后版本

    不断完善文档,不断修复自己发现的和其他用户报告的 bug,不断根据用户需求完善接口和实现。

Makefile::DOM 的 SVN 仓库位于下面的位置:

http://svn.openfoundry.org/mdom/

其结构分为 trunk (主干)和若干个 branches (分支)。主干是主流的版本;CPAN 发布总是从主干产生。而各个分支主要用于试验和演化新特性,待成熟后才``融合''回主干中去。融合工作可以由 SVK 自动完成(利用 SVK 的 smerge 命令)。反过来,主干中的更新,借助于 SVK,也可以轻易地融合到各个分支中去。

本模块计划拥有以下分支:

  • /branches/gmake

    用于开发 Perl 版本的 GNU make 实现,pgmake,并将包含基于 IPC::Run3Test::Base 的 GNU make 测试集。

    pgmake 和使用了 IPC::Run3 的测试集将永不融入 /trunk,但将成为新一代 Makefile::Parser 的 Gmake 部分的原型(prototype)。

    该分支从 Makefile::DOM 0.1.x 起启用。

  • /branches/nmake

    用于开发 Perl 版本的 NMAKE 实现,pnmake,并将包含基于 IPC::Run3Test::Base 的 NMAKE 测试集。测试台框架将复用 /branches/gmake 中的 GNU make 测试台脚手架。

    类似地,pnmake 和基于 IPC 的测试集将永不融入 /trunk,但将成为新一代 Makefile::Parser 的 Nmake 部分的原型。

    该分支从 Makefile::DOM 0.3.x 起启用。

Makefile::Parser

历史遗留的旧实现

Makefile::Parser 一年多以前发布在 CPAN 上的 0.11 版的旧实现仍将继续演化。其中的改进内容,主要包括:

  • 整合 Adam Beauchamp 提供的基于状态机设计模式的补丁。

  • 修复一个用户在 RT 中  报告的bug ,提供对 GNU make 函数引用的支持。

  • 简单介绍新一代 Makefile::Parser 的开发现状和蓝图。

这些将以 0.xx 的版本号发布到 CPAN。

全新版本的实现

全新的实现将基于 Makefile::DOM,并保持接口的向下兼容。由于旧实现同时支持 GNU make 和 NMAKE 的常用语法,故要实现向后兼容,必须实现 Makefile 格式的自动识别。最简单的做法也许是先尝试用 Makefile::Parser::Gmake 进行处理,如果出现错误,就改用 Makefile::Parser::Nmake. 至于该做法的实际效果如何,只有留待实践的检验了。

基于 CPAN 发布的版本号的里程碑列表如下:

  • 1.0.x_01

    它们将整合 Makefile::DOM 的 /branches/gmake 分支的实现。版本号中的 _01 后缀将之标识为``Developer Release'';一般的 CPAN 升级工具将会忽略这样的发布,从而不致于突然破坏向下兼容。

  • 1.1.x_01

    它们将整合 Makefile::DOM 的 /branches/nmake 分支的实现代码。

  • 1.2.x

    它们将首次实现向下兼容,从而是 1.0.0_01 以来第一批 CPAN 正式发布版。

  • 1.3.x

    该系列将致力于把基于 IPC 的测试集转换为非 IPC 的版本,从而提高效率,增加可移植性。关于测试集可移植性的一个关键子项目是 Bourne Shell 的仿真。毕竟像 Win32 这样的平台,/bin/sh 一般是没有的。

Makefile::Parser 的 SVN 仓库位于:

http://svn.openfoundry.org/makefileparser/

未来该仓库将像 Makefile::DOM 那样分为 trunk 和若干个 branches.

Makefile::GraphViz

Makefile::Parser 类似,CPAN 上已有的 Makefile::GraphViz 实现将以 0.xx 的形式继续演化一段时间。这些发布将着力解决 Ken Williams 于几周前报告的那个有关 plot_all 方法的 bug:

http://rt.cpan.org/Ticket/Display.html

1.00 开始,它将使用 Makefile::Parser 1.2.x 及其以上版本。

Makefile::Compiler

该模块将支持 GNU make 和 MS NMAKE 两种格式的 Makefile 作为输入;输出将支持  Java 的 ANT,CPAN 上的 PBS,以及 GNU make 和 NMAKE 自身。该模块在早期将从 Makefile::Parser 产生的 AST 发射目标代码。该做法实现起来非常简单,虽然无法得到很``地道''的翻译,但却是``足够好的''。

有关该模块的计划目前无法确定下来,因为它强烈地依赖前几个模块的成果和经验。

2月7日

Makefile 项目的组成


该项目将由下列三部分组成:

Makefile::DOM

该模块将 Makefile 视为“文档”进行“无损”的解析,生成类似 DOM 的树形结构。DOM 树中将保留原输入文件中的所有信息,包括空格、空行、注释等。这意味着,从 DOM 树可以还原出原始的 Makefile 文件。另外 DOM 树自身的每个节点甚至整体都是可修改的,就像  PPI  和 HTML::TreeBuilder 那样。

Makefile::DOM 的接口完全模仿了  PPI  的 API 设计。事实上,我直接照搬了 PPI::Node, PPI::Element, PPI::Dumper 的源代码和 POD 文档(此举已得到  PPI  的作者 Adam Kennedy 的完全许可)。

Makefile::DOM 被设计成与具体的 Makefile 语法无关。同一套 DOM 节点类型将在不同格式的 Makefile DOM 生成器之间共享,比如, MDOM::Document::Gmake  负责对 GNU Makefile 进行解析,返回 MDOM::Document 类的实例(即 DOM 树的根);而 NMAKE Makefile 的解析器 MDOM::Document::Nmake 亦返回 MDOM::Document 类的实例。日后,还将考虑添加对 dmake 和 bsdmake 的支持。

目前 MDOM::Document::Gmake 已初具雏形,下面要做的就是添加遗漏的节点类型和进行综合测试。

测试 Makefile::DOM 最好的方法就是在其基础之上,开发出完整的 make 工具,然后通过对应 make 工具的测试集。比如,测试 MDOM::Document::Gmake 最好的方法就是利用它实现一个 pgmake 脚本,然后去跑 GNU make 官方测试集。类似地,我也需要开发出 pnmake 脚本。

Makefile::Parser

全新的 Makefile::Parser 实现不会在 API 上进行太大的改动。换言之,新版本的接口仍将基本按照  0.11版  也即  Make  模块的接口来设计。尽管如此,我仍会根据需要,对 API 进行扩展和补充。

Makefile::Parser 的任务在于,从 make 工具的视角,对 Makefile DOM 树进行深层的语法分析和语义脱糖。这意味着,得到的 AST 必然是“有损”的,而且必然包含了当前环境中的信息。这些环境信息包括系统中的环境变量设置、命令行选项、命令行传递的 Makefile 变量值、甚至磁盘文件的当前状态等。这种环境信息的依赖意味着 Makefile::Parser 并不适合进行严格意义上的 Makefile 翻译与转换工作。真正的翻译与转换要求 AST 是与上下文无关的,因此必须从 Makefile::DOM 出发重新开始。

Makefile::Parser 的用途很多,比如对 Makefile 中的依赖关系进行可视化(典型的应用就是 Makefile::GraphViz 这样的模块)。另外就是进行一些实用主义的翻译。当需要转换的 Makefile 并未使用强烈依赖于上下文的高级特性的时候,从 Makefile::Parser 产生的 AST 出发已经可以得到相当令人满意的翻译了。

Makefile::GraphViz

下一代的 Makefile::GraphViz 将基于 Makefile::DOM 和全新的 Makefile::Parser,同时保持向后兼容。

Makefile::Compiler

该模块就是进行不同格式 Makefile 之间的转换,以及将某一种格式的 Makefile 转换成其他非 make 项目管理工具的配置文件,比如 PerlBuildSystem, Rake, 和 Ant.

正如前面提到的,这里最简单的做法就是从 Makefile::Parser 生成的“有损” AST 出发,进行代码生成。但是通过这种方式得到的目标代码强烈地依赖于进行翻译时刻的系统上下文,影响目标代码的通用性和可移植性。尽管如此,对于许多足够简单的 Makefile 而言,种用这种方法生成的目标代码已经足够好了。幸运的是,现实世界中的大部分 Makefile 都是足够简单的。

更完美的翻译方式当然是从最底层的 DOM 树出发,按照类似“程序形式化证明”的方法进行复杂的 AST 变换。利用此种手段可以得到相当“地道“的目标代码,其质量接近人类手写的代码,但是 AST 变换算法可能会极端复杂。届时可以考虑使用像属性文法这样的工具(Language::AttributeGrammar)。

在实际翻译中,有一个很重要的问题就是如何处理 Makefile 中内联的 shell 命令。毕竟任何一个 Makefile 文件中都包含至少两种“语言”:Makefile 本身的记法,以及命令中的 Shell 记法。比如 GNU makefile 中的 cp, mv 在 NMAKE makefile 中就不应当出现。这意味着,Makefile::Compiler 可能还得实现一个 shell 转换器以完成不同 shell 之间的编译工作……

Makefile 项目的历史与背景


在大三上学期的时候,即 2005 年国庆前后,我正在为我的计算机组成的课程设计项目 Salent 准备 报告 用的素材。那时我就想到从 Salent 项目自身的 Makefile 自动生成项目的 构造流程图 。毕竟 Makefile 文件中已经包含了项目文件间的依赖关系,以及从各组依赖项生成对应目标的 Shell 命令。

在这个应用中,我需要一个 Makefile 解析器以及一个有向图的示意图生成器。至于后者,AT&T 免费的 GraphViz 库可以很好地胜任。至于前者,我进行了大量的网络搜索。我试用了 CPAN 上的 Make 模块,但它不能很好地支持 NMAKE 语法的 Makefile,于是我就针对 Salent 项目的 Makefile 所使用的特性,同时综合了 GNU make 的一些常用特性,自主开发了 Makefile::Parser 模块,并发布到 CPAN。

很快地,以 Makefile::Parser 为基础,我推出了从 Makefile 自动生成构造流程图的 Makefile::GraphViz 模块。

有趣的是,CPAN 上也有一个所谓的 GraphViz::Makefile 模块。和我的不同的是,该模块是基于前面提到的 Make 模块的。因此与我的库实际上构成了``竞争''关系。

在随后的几周内,我开始根据 GNU make 手册 ,向我的 Makefile::Parser 不断地添加新特性。但我很快发现,已有的框架变得越来越难于扩展,根本无法胜任 gmake 庞大的特性集。因此当 Makefile::Parser 0.11 发布之后,我就放弃了旧的代码基础,开始另起炉灶了。

2006 年的冬天,我开始仔细阅读 GNU make 手册 ,并着手将 gmake 自身的测试集 移植到我自己的 Makefile::Parser 项目中来,以便采用测试驱动的方法来创建全新的 Makefile::Parser 实现。

虽然 gmake 官方的测试台亦是用 Perl 开发的,且亦可作用于任意的 make 可执行文件,但是它却使用的是过时的 Perl 4 语言,并大量调用了 sh, diff 等特定于 *NIX 的工具,从而变得高度不可移植。所以我才下决心使用现代的 Perl 5 自动化测试框架 Test::Base 对 gmake 已有的测试集进行改写,以期达到下列目标:

  • 可以不加修改地运行在 Win32, Cygwin, FreeBSD, NetBSD, OpenBSD, Linux, Solaris, Mac OS X 等多种类型操作系统上。

  • 测试用例采用声明性的记法,保证可读性、清晰性和简洁性。

  • 易于扩展,并可用于编写针对其他 make 工具(如 nmake, dmake, bsdmake)的测试集

  • 易于配置,可以指定任意的 shell 命令行作为 make 测试对象

为了确保新的 gmake 测试集的可移植性,我自己用纯 Perl 开发了一个 Bourne Shell 虚拟机 。毕竟,Windows 的 Shell 语法和行为与 Bourne Shell 是如此地不同。另外,其他系统中默认的 shell 也有可能是像 csh 这样的东西。由于该 sh 虚拟器是为 Makefile::Parser 的测试集服务的,因此只需要实现 Bourne Shell 特性的一个很小的子集,即 gmake 测试用例中实际使用到的特性集。

目前,gmake 测试集的转换工作正在进行中,您可以从下面的位置看到已完成转换的 gmake 测试脚本:

http://svn.berlios.de/svnroot/repos/makefileps/t/gnu/

从那以后,迫于江大日益繁重的课业负担,Makefile::Parser 一直进展缓慢。在过去的一年中,有许多人向我表达了各种各样有趣的需求,这驱使我不断地调整项目的设计与目标。

  • AT&T 用户 Billy Patton 向我表达了他的一个有趣的需求:他希望能通过编程方式,读取一个 Makefile 文件,然后进行一些修改,再写回磁盘。他说,他希望通过 GUI 菜单来帮助没有 Makefile 使用经验的用户来操纵 Makefile。这个需求意味着,读取 Makefile 的过程必须是``无损''的,即我的库不可以扔掉包括注释、空行在内的任何东西,同时我还必须提供相应的接口将修改过的 Makefile AST 写回磁盘,即提供一种 Makefile Writer。

  • Gurets Maxim 通过 CPAN RT 向我 传达了 这样一个需求:他希望看到 Makefile::Parser 拥有 GNUMake, NMake, BSDMake 等多个子类,从而能解析各种已知格式的 Makefile. 他认为现有的 Makefile::Parser 实现将 NMAKE 和 GNU make 的特性杂糅在一起的做法并不可取。我表示赞同,因为 NMAKE 和 gmake 在行为上有许多矛盾之处。

  • 微软公司 Unix 互操作团队的 Madhuri Mandava 和 Pugs 团队的 Christopher Malon 更乐衷于看到将 NMAKE 的 Makefile 转换为 gmake 格式的 Makefile,或者相反。这种需求要普遍得多,毕竟有太多太多基于 Linux 的开源项目需要移植到 Win32,而 Makefile 的翻译往往是很重要的组成部分。比如我自己就曾经吃力地将 Judy 库 的 Makefile 翻译为 NMAKE 接受的版本--唔,那可真是枯燥之极。

  • 这个世界上除了 make 还有许多其他的项目构造和管理工具,比如 Ruby 世界里的 Rake , Java 里的 Ant,以及 CPAN 上的 PerlBuildSystem (PBS) 。PBS 的作者之一,瑞典的 Nadim Khemir 和我一直保待着通信联系。他非常希望看到,gmake 等其他 make 工具的 Makefile 文件能通过我的 Makefile::Parser 或者类似的东西,自动地转换为 PBS 自己的配置文件 (pbsfile)。

  • Adam Beauchamp 用标准的状态机设计模式对我的 Makefile::Parser 0.11 进行了改写,并通过了我所有的回归测试。可惜的是,他工作在了一个早已废弃了的实现上,但是他的想法真的很有趣。经过他改写的版本看上去更加“面向对象”了,而且原先极为臃肿的 parse 方法也变得简洁了许多。我对他的方式的唯一顾虑就是执行效率。

在 Nadim Khemir 的大力推动下,我于大四上学期的前一两个月,启动了 Makefile::DOM 项目。该项目受 Adam Kennedy (Alias) 的 PPI 模块的启发,将 Makefile 视为“文档”而非程序进行解析,解析的结果是一棵类似 DOM 的树型数据结构。该项目由于能无损地对 Makefile 进行解析,故可以很好地满足前面 Billy Patton 等人的需求。从 DOM 树写回 Makefile 也是极容易的。同时 Makefile::DOM 亦可作为其他所有需求及应用的基础,因为它实际上完成的是 Makefile 的词法分析以及一部分简单的语法分析任务。

Makefile::DOM 的进展非常迅速,目前已经支持了 Gnu Makefile 的大部分语言结构。我以为至少 0.0.1 版已经可以在近期发布到 CPAN 了。