这里提到的源码是编译出 perl 的源码, 而不是用 perl 语言写的代码。
起因是最近制作 LFS (
http://www.linuxfromscratch.org/lfs/ ) 的时候发现 perl 没有什么用处,
但又是构建一些源码包的必要条件
于是想到是不是可以把 perl 换成基本版的,类似 busybox 那样的
但是步行没有找到其它实现,不过它自身有个 miniperl
miniperl 的功能也不错,想当然的以为它能替换系统的 perl, 而且它不到 3 MB. 感觉很美好.
编译出来替换原来的 perl 后, 能运行一些基本的程序.
于是用替换成 miniperl 的 host 来编译 LFS, 并把 LFS 自身的 perl 也 patch 成了 miniperl.
但是这个 miniperl 没有通过 LFS 构建脚本的版本检测, 原因是 perl -V:version 出错.
于是尝试解决这个问题, 先 strace 了一下, 发现是当前目录下没有 Config.pm 文件.
从原版 perl 那里复制这个文件过来就可以运行了, 也通过了 LFS 构建脚本检测, 但是只能放当前目录下.
通过搜索得知环境变量 PERL5LIB 可以解决 miniperl 的 Config.pm 路径问题.
本来到这里应该见好就收, 写个脚本 wrap 一下完事, 或者在代码中增加个 setenv() 也可以.
但是想挑战一下, 想直接去修改该源码, 噩梦也随之开始:
首先用 grep 搜索出错信息, 但是 .c .h 里都没有, 奇怪的文件里才有.
于是用跟踪代码和打印log法去找相关代码,
结果发现代码非常长 每个函数几千行是常事 好多层结构 缩进风格很凌乱 满屏的宏
还有宏封装的 longjump setjump 之类东西, 以及一些 yacc 生成的代码
愣是在这样的代码里穿梭了两个小时也没找到那个查找路径所在的位置, 应该是水平问题吧.
就在头大要放弃的时候无意发现了这个路径问题所在, 如下是fix这个问题的 patch
diff -Nauzp perl-5.32.0.orig/perl.c perl-5.32.0/perl.c
--- perl-5.32.0.orig/perl.c
+++ perl-5.32.0/perl.c
@@ -4734,7 +4734,7 @@ S_init_perllib(pTHX)
#endif /* VMS */
}
-#ifndef PERL_IS_MINIPERL
+/* #ifndef PERL_IS_MINIPERL */
/* miniperl gets just -I..., the split of $ENV{PERL5LIB}, and "." in @INC
(and not the architecture specific directories from $ENV{PERL5LIB}) */
@@ -4756,7 +4756,7 @@ S_init_perllib(pTHX)
INCPUSH_PERL_VENDORLIB_STEM
INCPUSH_PERL_OTHERLIBDIRS_ARCHONLY
-#endif /* !PERL_IS_MINIPERL */
+/* #endif */ /* !PERL_IS_MINIPERL */
if (!TAINTING_get) {
#if !defined(PERL_IS_MINIPERL) && defined(DEFAULT_INC_EXCLUDES_DOT)
但是这个代码和前面两个小时的穿梭跟踪没关系. 因为还是没发现 打开文件的那个位置.
其中一个歧途是用strace发现用了 stat() 调用, 但是代码里没有, 代码里应该是 fopen(), 而 glibc 的 fopen() 用了 stat()
随后弄好代码, 整合进 LFS, 准备构建 LFS.
构建脚本的版本检测通过了, 但是这个miniperl在后续过程依然出错, 原因是少了一些库或模块.
补全模块后 miniperl 依然有一些找不到模块的报错信息, 原版 perl 就没问题.
至此彻底放弃, 恢复用原始 perl 拉倒吧.
--
FROM 195.154.114.*