我在接到任务的时候原以为蛮简单的,不就是从源码编译 PostgreSQL 嘛,谁知道这里面坑还不少,下面简要记录一下此次填坑过程。
既然是编译 PostgreSQL ,首先需要下载解压,这类操作就不细说了。在解压出来之后,按照常规的流程 configure, make, make install
走,谁知道第一步就出问题了,提示没有找到 readline 库。
既然没有,那就安装呗。我利用 sudo apt-get install libreadline-dev
很快就安装完了,然后重新执行 ./configure
,问题依然没有解决,还是提示无法找到 readline 库,这就奇了怪了,明明安装了却找不到。这时发现居然还没法找到突破口,然后就先丢开这个问题,使用 ./configure --without-readline
继续,这时又说没有 zlib
库。同样使用 sudo apt-get install zlib1g-dev
安装并重新 configure
同样是找不到 zlib
库。既然都已经放掉了一个 readline 也不差这个 zlib 了。 我就看看你到底却多少库,接着我使用 ./configure --without-readline --without-zlib
,这回它居然奇迹般的通过了, make && make install
也没有问题。那么问题来了,为什么安装了的库 configure
的时候却找不到呢?
为了测试为什么找不到已安装的库,我自己写了个测试程序用于测试 readline 库,如下所示:
#include
#include
int main()
{
char *msg = readline("Enter: ");
printf("Your input is %s\n", msg);
return 0;
}
编译命令如下:
$ gcc test.c -o test -lreadline
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../../aarch64-thunderx-linux-gnu/bin/ld: cannot find /lib64/libc.so.6
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../../aarch64-thunderx-linux-gnu/bin/ld: cannot find /usr/lib64/libc_nonshared.a
collect2: error: ld returned 1 exit status
这说明在链接的时候出错了,gcc 就连标准的 C 语言库都没法找到,而且这个路径也比较奇怪,因此我使用 type gcc
命令确定一下 gcc 相关信息。
$ type gcc
gcc is hashed (/opt/thunderx/toolchain/thunderx-tools/aarch64-thunderx-linux-gnu/sys-root/usr/bin/gcc)
$ gcc --version
gcc (Cavium Inc. Version 0.99 build 407) 5.2.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
gcc 版本是没有问题的,但是这个路径总感觉有点问题。随后我定位到 config.log
文件,发现它在测试 readline 库的时候加上了 --sysroot
选项,并且该选项的值为 /opt/thunderx/toolchain/thunderx-tools/aarch64-thunderx-linux-gnu/sys-root
。对这个选项的含义不太熟悉,于是通过 man gcc
查看了该选项的作用,如下所示:
--sysroot=dir
Use dir as the logical root directory for headers and libraries. For example, if the compiler normally searches for headers in /usr/include and libraries in /usr/lib, it instead searches dir/usr/include and dir/usr/lib.
If you use both this option and the -isysroot option, then the --sysroot option applies to libraries, but the -isysroot option applies to header files.
The GNU linker (beginning with version 2.16) has the necessary support for this option. If your linker does not support this option, the header file aspect of --sysroot still works, but the library aspect does not.
看了应该是这儿出了问题,于是我将示例程序的编译命令改为
$ gcc --sysroot=/opt/thunderx/toolchain/thunderx-tools/aarch64-thunderx-linux-gnu/sys-root test.c -o test -lreadline
这次提示无法找到 readline 库。问题基本上已经确定了,这是由于编译链接时的目录问题导致的,采用 apt-get
方式安装的软件没有办法指定安装路径,因此这里使用源码编译的方式安装。
由 --sysroot=dir
选项可知,它会在该选项指定的 dir/usr/include
和 dir/usr/lib
目录下查找头文件和库文件,而 apt-get
则是安装在 /usr/
目录下。因此我们需要将 zlib 库安装到 /opt/thunderx/toolchain/thunderx-tools/aarch64-thunderx-linux-gnu/sys-root/usr
目录下。
$ wget http://www.zlib.net/zlib-1.2.11.tar.gz
$ tar -zxvf zlib-1.2.11.tar.gz
$ cd zlib-1.2.11
$ ./configure --prefix=/opt/thunderx/toolchain/thunderx-tools/aarch64-thunderx-linux-gnu/sys-root/usr
$ make && make install
整个安装过程没有任何问题,在安装完成之后对 PostgreSQL 进行 configure 操作
$ ./configure --without-readline
这个过程也没有任何异常。zlib 库的问题就解决了。
在编译整个 PostgreSQL 10.0 的过程中, readline 库的安装是最折磨人的。原以为同样按照 zlib 的过程进行编译安装就可以了。
$ wget wget ftp://ftp.cwru.edu/pub/bash/readline-6.3.tar.gz
$ tar -zxvf readline-6.3.tar.gz
$ cd readline-6.3
$ ./configure --prefix=/opt/thunderx/toolchain/thunderx-tools/aarch64-thunderx-linux-gnu/sys-root/usr
$ make && make install
这个过程也没什么问题,然后就是对 PostgreSQL 进行 configure 操作
$ ./configure
这个时候还是提示,无法找到 readline 库,没办法只能又拿我的示例程序来定位了。
$ gcc --sysroot=/opt/thunderx/toolchain/thunderx-tools/aarch64-thunderx-linux-gnu/sys-root test.c -o test -lreadline
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../libreadline.so: undefined reference to `tputs'
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../libreadline.so: undefined reference to `tgoto'
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../libreadline.so: undefined reference to `tgetflag'
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../libreadline.so: undefined reference to `UP'
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../libreadline.so: undefined reference to `tgetent'
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../libreadline.so: undefined reference to `tgetnum'
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../libreadline.so: undefined reference to `PC'
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../libreadline.so: undefined reference to `tgetstr'
/opt/thunderx/toolchain/thunderx-tools-407/aarch64-thunderx-linux-gnu/sys-root/usr/bin/../lib/gcc/aarch64-thunderx-linux-gnu/5.2.0/../../../libreadline.so: undefined reference to `BC'
collect2: error: ld returned 1 exit status
这次问题不一样了,这次是能找到 readline 库,但是该库中引用的一些函数没有定义,搜索一下发现原来是 readline 库依赖于 ncurses 。因此需要安装 ncurses 。
我在编译安装 ncurses 时,主要遇到两个问题:
configure
是无法通过 config.guess
推断出平台信息make
编译时出错。configure 时出现如下错误:
configure: error: cannot guess build type; you must specify one
因此需要给出编译平台信息
$ ./configure --build=aarch64-unknown-linux-gnu --prefix=/opt/thunderx/toolchain/thunderx-tools/aarch64-thunderx-linux-gnu/sys-root/usr
这时 configure 过程可以通过,但是在 make 的时候出现错误
In file included from ../ncurses/curses.priv.h:283:0,
from ../ncurses/lib_gen.c:19:
_30111.c:835:15: error: expected ')' before 'int'
../include/curses.h:1594:56: note: in definition of macro 'mouse_trafo'
#define mouse_trafo(y,x,to_screen) wmouse_trafo(stdscr,y,x,to_screen)
^
make[1]: *** [../objects/lib_gen.o] Error 1
make[1]: Leaving directory `/home/japin/doc/ncurses-5.9/ncurses'
make: *** [all] Error 2
从错误日志中可以看出是 include/curses.h 文件中的宏定义出现问题,而该文件又是通过 include/Makefile 中由 curses.head curses.tail 等文件生成的。参考这个解决方案,修改 include/curses.tail
104 extern NCURSES_EXPORT(bool) mouse_trafo (int*, int*, bool); /* generated */
为
104 extern NCURSES_EXPORT(bool) mouse_trafo (int*, int*, bool);
前面的数字为行号。这应该是由于后面的注释引起的,但是具体问题不是很清楚。修改完成后,执行下面的命令安装:
$ make clean
$ make && make install
这次一切正常,此时,使用下面的命令编译示例程序,没有任何异常:
$ gcc --sysroot=/opt/thunderx/toolchain/thunderx-tools/aarch64-thunderx-linux-gnu/sys-root test.c -o test -lreadline -lncurses
到目前位置,编译安装 PostgreSQL 所需要的依赖都已安装,重新对 PostgreSQL 进行 configure 操作一切正常,编译后运行结果如下:
$ bin/psql postgres
psql (10.0)
Type "help" for help.
postgres=# select version();
version
------------------------------------------------------------------------------------------------------------------
PostgreSQL 10.0 on aarch64-unknown-linux-gnu, compiled by gcc (Cavium Inc. Version 0.99 build 407) 5.2.0, 64-bit
(1 row)
[1] https://www.douban.com/note/508827916/
[2] http://blog.csdn.net/velanjun/article/details/53102184