@babydragon
2016-01-09T11:44:40.000000Z
字数 2209
阅读 2756
未分类
expect是脚本处理有交互命令的利器,但是这货依赖tcl,并且默认没有安装。为了方便分发到测试服务器上,尝试了下静态编译。结果以失败告终。下面是整个编译的过程。
由于expect依赖tcl,必须先编译一个静态版本的tcl库。tcl的源码可以从阿里云镜像下载:
wget http://mirrors.aliyun.com/gentoo/distfiles/tcl-core8.6.4-src.tar.gz
编译的方式和编译普通应用类似,唯一需要注意的是,我们只需要编译出静态库即可。
tar vxf tcl-core8.6.4-src.tar.gz
cd tcl8.6.4/unix/
./configure --disable-shared --prefix=$HOME/source/target
make
make install
这里我们直接安装到指定的路径,并且关闭动态链接库的编译。这样在$HOME/source/target里面,就会tcl的静态库。
首先还是从镜像下载expect源码。
wget http://mirrors.aliyun.com/gentoo/distfiles/expect5.45.tar.gz
然后运行configure的时候,需要指定tcl的路径,并且关闭动态链接。
tar vxf expect5.45.tar.gz
./configure --with-tcl=$HOME/source/target --disable-shared
make
这里遇到了很多链接的问题。首先是
expect.c:(.text+0xbc):对‘tclStubsPtr’未定义的引用
exp_main_sub.c:(.text+0x6fb):对‘tclIntStubsPtr’未定义的引用
tclUnixThrd.c:(.text+0x31):对‘pthread_key_delete’未定义的引用
这些符号无法找到,无法进行链接。向上查找这些错误对应的编译命令,发现已经在链接最终的expect命令了。此时的编译命令为:
gcc \
-pipe -O2 -fomit-frame-pointer -Wall \
-Wl,--export-dynamic \
-o expect exp_main_exp.o \
-L/alidata1/6080/source/expect5.45 -lexpect5.45 \
-L/alidata1/6080/source/target/lib -ltcl8.6 \
-ldl -lieee -lm \
-Wl,-rpath,/alidata1/6080/source/target/lib \
-Wl,-rpath,/alidata1/6080/source/target/lib/expect5.45
查阅了tcl的faq,前面遇到无法链接的符号在tclstub库中,同时还发现少了pthread库的一些符号。加上这些之后,编译命令变成:
gcc \
-pipe -O2 -fomit-frame-pointer -Wall \
-Wl,--export-dynamic \
-o expect exp_main_exp.o \
-L/alidata1/6080/source/expect5.45 -lexpect5.45 \
-L/alidata1/6080/source/target/lib -ltcl8.6 \
-ldl -lieee -lm \
-Wl,-rpath,/alidata1/6080/source/target/lib \
-Wl,-rpath,/alidata1/6080/source/target/lib/expect5.45 -ltclstub8.6 -lpthread
此时tcl和一些基础库的链接失败消失,但是出现了
pty_termios.c:(.text+0x116):对‘openpty’未定义的引用
这个错误。同样需要去查找这个函数实现的库,最终定位到了libutil。
最终将编译命令修改成:
gcc \
-pipe -O2 -fomit-frame-pointer -Wall \
-Wl,--export-dynamic \
-o expect exp_main_exp.o \
-L/alidata1/6080/source/expect5.45 -lexpect5.45 \
-L/alidata1/6080/source/target/lib -ltcl8.6 \
-ldl -lieee -lm \
-Wl,-rpath,/alidata1/6080/source/target/lib \
-Wl,-rpath,/alidata1/6080/source/target/lib/expect5.45 -ltclstub8.6 -lpthread -lutil
终于能够正常编译出静态编译的expect命令了。
就在以为完事大吉的时候,发现这个静态编译的expect命令,虽然已经静态链接了tcl库,但是在其他没有tcl的机器上运行的时候,会提示:
Tcl_Init failed: Can't find a usable init.tcl in the following directories
原来为了支持扩展,tcl会要求初始化的时候执行这个初始化脚本。查阅了tcl的文档,要编译一个完全不依赖机器上tcl库的程序比较麻烦。最终,找到了一个简单的命令empty来处理命令的交互。