Openssh移植经验谈
我们在移植一些较大的程序时,在host机上进行交叉编译后的可执行程序往往很多且需要分别安装到固定的目录中(如openssh ,编译后生成20几个文件且需要分别安装到bin 、sbin、share、libexec、etc 这5个目录) ,如何确定需要将哪些编译好的的可执行文件拷贝到target机上且安装到哪些目录中呢?
1.如何确定安装的目录? ./configure成功后,最后几行提示信息会告诉你需要在target机上创建哪些目录。 如:OpenSSH has been configured with the following options: User binaries: /usr/local/bin System binaries: /usr/local/sbin Configuration files: /usr/local/etc Askpass program: /usr/local/libexec/ssh-askpass Manual pages: /usr/local/share/man/manX PID file: /var/run Privilege separation chroot path: /var/empty sshd default user PATH: /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin ………… 可以依据上面的提示信息,在target机上创建相应的目录,然后把相应的文件拷进去。
2.如何确定拷贝到target机上的文件? 有三种方法: 方法一:查看./configure生成的Makefile 。 下面是openssh中生成的Makefile的一段: install-files: scard-install ………… $(INSTALL) -m 0755 $(STRIP_OPT) ssh $(DESTDIR)$(bindir)/ssh $(INSTALL) -m 0755 $(STRIP_OPT) scp $(DESTDIR)$(bindir)/scp $(INSTALL) -m 0755 $(STRIP_OPT) ssh-add $(DESTDIR)$(bindir)/ssh-add $(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent $(DESTDIR)$(bindir)/ssh-agent …… 红色字体部分即要拷的文件和拷贝到target机的目录。由于使用了很多变量,看起来不直观,所以通过Makefile查找不是很方便的办法。
方法二:make isntall -n 查看安装了哪些文件,这些文件即要拷贝到开发板上运行的文件。然后手动用交叉编译工具strip后安装到开发板。 (注:1.一定要strip ,make通常情况下默认是不执行strip的。 2.make的 –n 参数表示只显示要执行的命令,不实际执行。) 缺点:不太直观,且需要根据提示信息一个一个手动strip后拷贝到target板。
方法三:./confgiure时--prefix一个文件,#make install -i ,到prefix指定的的文件目录中查看安装好的文件,这些文件即需要在target板上安装的文件。用cross_tool strip一下,移植到开发板。 (注:make的 -i参数表示忽略安装过程中的错误,为什么要加-i参数呢?看下面分析) 优点:直观、方便、简单。 缺点:需要手动strip。不过不需要一个一个strip,可以直接arm-9tdmi-gnu-linux-strip * ,效率比方法二高多了。
3.使用Make的一点不足 通常我们编译好程序后执行make install时默认是调用host下的/usr/bin/install工具进行安装, 不是简单的cp所有文件到指定路径下。可以通过#make install –n查看。如: #make install -n …………………… /usr/bin/install -c -m 0755 -s ssh /work/ssh/install/openssh-4.6pl/bin/ssh /usr/bin/install -c -m 0755 -s scp /work/ssh/install/openssh-4.6pl/bin/scp ……………………………… 之所以调用install程序进行安装,是因为make好的程序默认是不进行strip的,运行install程序时其中-s参数会先调用默认的strip工具对其进行strip,然后拷贝到指定路径。Strace一下#strace –f –F –o logfile install –s ssh /work/tmp/ssh (strace是一个好工具,具体用法参考《用strace调试程序》),发现install会到系统默认路径(环境变量PATH)下查找strip工具,最终会调用到/usr/bin/strip程序进行strip。 这下大家可能就明白了,为什么上面的方法三执行make install时要加-i参数。因为我们make时是用的交叉编译工具,编译好的程序是在arm平台上运行的,make install默认调用/usr/bin/strip对其进行strip怎么会成功呢?所以会报错,如下所示: /usr/bin/install -c -m 0755 -s ssh /work/ssh/install/openssh-4.6pl/bin/ssh strip: Unable to recognise the format of the input file `/work/ssh/install/openssh-4.6pl/bin/ssh' /usr/bin/install: strip failed make: *** [install-files] Error 1
想修改Makefile使其make install时调用arm-linux-install也不行,因为crosstool里默认是不带install工具的,如下: [root@localhost ~]# cd /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/bin/ arm-9tdmi-linux-gnu-addr2line arm-9tdmi-linux-gnu-gprof arm-9tdmi-linux-gnu-ar arm-9tdmi-linux-gnu-ld arm-9tdmi-linux-gnu-as arm-9tdmi-linux-gnu-nm arm-9tdmi-linux-gnu-c++ arm-9tdmi-linux-gnu-objcopy arm-9tdmi-linux-gnu-c++filt arm-9tdmi-linux-gnu-objdump arm-9tdmi-linux-gnu-cpp arm-9tdmi-linux-gnu-ranlib arm-9tdmi-linux-gnu-g++ arm-9tdmi-linux-gnu-readelf arm-9tdmi-linux-gnu-gcc arm-9tdmi-linux-gnu-size arm-9tdmi-linux-gnu-gcc-3.4.1 arm-9tdmi-linux-gnu-strings arm-9tdmi-linux-gnu-gccbug arm-9tdmi-linux-gnu-strip arm-9tdmi-linux-gnu-gcov fix-embedded-paths [root@localhost ~]# cd /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/bin/ 所以修改Makefile不太容易实现。
总结:/configure脚本应该提供一个类似于--enable-strip的参数项供用户选择, 使其生成的Makefile在make时就可以调用交叉编译工具的strip进行strip。避免在将程序移植到目标板上时要手动执行strip。如果生成的binary比较少还可以,多的话strip起来还是比较耗时的。
附:具体移植过程可以参考Edwin的《移植sshd到jk2410开发板》,这篇文章写了非常好,包括将openssh移植到开发板上后碰到的一系列问题的解决方法,含盖了很多工作中的经验技巧,对于做嵌入式移植的人来说绝对值得一读。 |
|