apr
是apache
公司的一个支持跨平台编程的开源库,有很好的内存管理机制,支持Linux
、AIX
和Windows
等多操作系统。代码由C语言编写。
近期接到一个需求,由于我们的客户在powerpc
机器上安装了Redhat
,导致我们的程序无法运行,因此想到了交叉编译。
而我们的程序因为使用了apr
库,所以在所难免地,使用交叉编译的方式编译apr
也就成为了不可避免的工作。
环境搭建
我使用的apr版本为1.6.2
,编译环境为Ubuntu18.04
,GLIBC
版本为2.27
。通过拉起docker
容器的方式搭建编译环境。
docker run -itd --name power-linux --restart unless-stopped -w /var/apr-1.6.2 -v `pwd`:/var/apr-1.6.2 ubuntu:18.04
以上命令会在宿主机上拉起一个Ubuntu18.04
的container
,并将apr
的代码映射在/var/apr-1.6.2
目录下。
然后进入容器:
docker exec -it power-linux bash
由于这是一个全新的Ubuntu
环境,我们需要做一些基础的配置:
apt update
apt -y install vim
apt -y install openssh*
编译工具链安装
交叉编译主要使用gcc-powerpc64-linux-gnu
这个编译器,所以首先我们要下载该编译器:
apt -y install gcc-powerpc64-linux-gnu
同时,我们还需要安装一些其他编译工具:
apt -y install libtool automake autoconf
apt -y install make
apt -y install gcc
需要说明一下,前面已经安装了gcc-powerpc64-linux-gnu
,为什么这里还要安装gcc
?gcc
是为了编译在当前x86
环境可以运行的可执行程序用的,在后面会用到。
有一点要注意的是,gcc-powerpc64-linux-gnu
默认的是大端编译器,如果power
机器是小端的话,需要使用小端编译器,小端编译器为gcc-powerpc64le-linux-gnu
。
编译
通过configure生成Makefile
由于apr
是通过autoconf
的方式管理Makefile
的,所以首先需要使用configure
命令生成当前平台适用的Makefile
,命令如下:
./configure --disable-dso --prefix=/usr --host=powerpc-linux CC=/usr/bin/powerpc64-linux-gnu-gcc ac_cv_file__dev_zero=yes ac_cv_func_setpgrp_void=yes apr_cv_process_shared_works=yes apr_cv_mutex_robust_shared=no apr_cv_tcp_nodelay_with_cork=yes ac_cv_sizeof_struct_iovec=16 apr_cv_mutex_recursive=yes
执行完以上命令,Makefile
已经生成,此时,如果我们执行make
,会报错:
/bin/bash: tools/gen_test_char: cannot execute binary file: Exec format error
Makefile:143: recipe for target 'include/private/apr_escape_test_char.h' failed
make[1]: *** [include/private/apr_escape_test_char.h] Error 126
make[1]: Leaving directory '/root/apr-1.6.2'
/root/apr-1.6.2/build/apr_rules.mk:118: recipe for target 'all-recursive' failed
make: *** [all-recursive] Error 1
上面这个错误是由于执行gen_test_char
的时候发现执行不了造成的,因为gen_test_char
是用powerpc64-linux-gun-gcc
编译出来的,在当前环境当然执行不了,我们手动用gcc
编译一下就可以了。
进入tools
目录,执行:
cd tools
gcc gen_test_char.c -I"(where ever apr is)/apr/include" -o gen_test_char
修改完成后,退回上一级目录,继续make
,仍然报错:
./include/apr_want.h:94:8: error: redefinition of 'struct iovec'
struct iovec
^~~~~
In file included from /usr/powerpc64-linux-gnu/include/sys/socket.h:26:0,
from ./include/apr.h:168,
from ./include/apr_escape.h:22,
from encoding/apr_escape.c:28:
/usr/powerpc64-linux-gnu/include/bits/types/struct_iovec.h:26:8: note: originally defined here
struct iovec
^~~~~
/root/apr-1.6.2/build/apr_rules.mk:206: recipe for target 'encoding/apr_escape.lo' failed
make[1]: *** [encoding/apr_escape.lo] Error 1
make[1]: Leaving directory '/root/apr-1.6.2'
我们需要修改include/apr_want.h
文件:
vi include/apr_want.h
按照下面的方式修改:
原内容:
#ifndef APR_IOVEC_DEFINED
#define APR_IOVEC_DEFINED
struct iovec
{
void *iov_base;
size_t iov_len;
};
#endif /* !APR_IOVEC_DEFINED */
修改为:
#if 0
struct iovec
{
void *iov_base;
size_t iov_len;
};
#endif /* !APR_IOVEC_DEFINED */
再次make
,成功,然后执行make install
安装:
make
make install
我们进入到/usr/lib
目录下,可以看到libapr
的动态库已经生成了,通过file
命令去查看,可以看到确实是powerpc
的库文件:
root@61ca5c46b8ef:/usr/lib# file libapr-1.so.0.6.2
libapr-1.so.0.6.2: ELF 64-bit MSB shared object, 64-bit PowerPC or cisco 7500, version 1 (SYSV), dynamically linked, BuildID[sha1]=1f3dd3d15dbd80d5568544b1a81fae9d6d47cef4, with debug_info, not stripped
至此,apr
在powerpc64-linux
的交叉编译成功。