原文 2015-09-23 23:48:54 发表于 CSDN,这里对以前写的文章做下收录。
skynet 下载编译过程对系统环境有很大依赖性,编译说明过于简单,没有提及到。所以,文章这里总结 skynet 比较常见的编译问题,希望有所帮助。
skynet 的编译过程:
git clone https://github.com/cloudwu/skynet.git cd skynet make linux
简单3步,对于很多高版本的系统来说,可能就这3步。但是,低版本系统可能无法编译,如下:
1. gcc 版本问题
2. 缺少 readline
3. 缺少 ncurses
4. 缺少 git (非必要项,则要手动下载skynet及3rd下的jemalloc)
5. 缺少 autoconf 等等
所以,这里以 CentOS5.5 系统做说明,这系统不具备以上几个条件,甚至连 git 都无法通过包管理来安装。在 skynet 的编译过程中,如果在 make 步骤出现错误,要用 make cleanall 清除已编译的文件,不然会出现莫名其妙的错误。
在早期的 skynet 版本,lua 不能清除干净,若是这样,执行:cd 3rd/lua && make clean
问题1:缺少git
# git clone https://github.com/cloudwu/skynet.git bash: git: command not found
解决:
这里要安装git,在安装git过程中,非常重要一步是安装curl,而这一步会把git所有的依赖装上,如curl和openssl,而git编译时也要找到curl库
yum -y install curl curl-devel wget --no-check-certificate https://www.kernel.org/pub/software/scm/git/git-2.5.2.tar.gz tar -zxf git-2.5.2.tar.gz cd git-2.5.2 ./configure --prefix=/usr make make install
问题2:git https 错误
# git clone https://github.com/cloudwu/skynet.git Cloning into 'skynet'... fatal: Unable to find remote helper for 'https'
解决:
很多网友都是说把 https 换成 git 解决,但也只是暂时性的。 报错是 git 编译时系统缺少 curl 导致的,参考问题1重装 git
重装git后,如果还不行, 应该是 git 软连接问题,如下修正:
ln -sf /usr/bin/git /bin/git
问题3:缺少readline
lua.c:81:31: error: readline/readline.h: No such file or directory lua.c:82:30: error: readline/history.h: No such file or directory lua.c: In function ‘pushline’: lua.c:311: warning: implicit declaration of function ‘readline’ lua.c:311: warning: assignment makes pointer from integer without a cast lua.c: In function ‘addreturn’: lua.c:342: warning: implicit declaration of function ‘add_history’ make[3]: *** [lua.o] Error 1 make[3]: Leaving directory `/data/git-2.5.2/skynet/3rd/lua' make[2]: *** [linux] Error 2 make[2]: Leaving directory `/data/git-2.5.2/skynet/3rd/lua' make[1]: *** [3rd/lua/liblua.a] Error 2 make[1]: Leaving directory `/data/git-2.5.2/skynet' make: *** [linux] Error 2
解决:
yum -y install readline-devel
问题4:缺少 ncurses
cc -std=gnu99 -o lua lua.o liblua.a -lm -Wl,-E -ldl -lreadline /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../libreadline.so: undefined reference to `PC' /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../libreadline.so: undefined reference to `tgetflag' /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../libreadline.so: undefined reference to `tgetent' /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../libreadline.so: undefined reference to `UP' /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../libreadline.so: undefined reference to `tputs' /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../libreadline.so: undefined reference to `tgoto' /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../libreadline.so: undefined reference to `tgetnum' /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../libreadline.so: undefined reference to `BC' /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../libreadline.so: undefined reference to `tgetstr' collect2: ld returned 1 exit status make[3]: *** [lua] Error 1 make[3]: Leaving directory `/data/skynet/3rd/lua' make[2]: *** [linux] Error 2 make[2]: Leaving directory `/data/skynet/3rd/lua' make[1]: *** [3rd/lua/liblua.a] Error 2 make[1]: Leaving directory `/data/skynet' make: *** [linux] Error 2
解决:
很多网友说修改Makefile,在SYSLIBS变量中追加" -lncurses "选项,但这样不方便,以后还会遇到这个问题。所以这里建议手动安装readline
yum -y install ncurses-devel wget ftp://ftp.gnu.org/gnu/readline/readline-6.2.tar.gz tar -zxf readline-6.2.tar.gz cd readline-6.2 ./configure --prefix=/usr make SHLIB_LIBS=-lncurses make install ldconfig
备注:
1、国内连接gnu.org网站不是很稳定,可能wget要多试几次。
2、通过ldconfig -p |grep readline可以测试readline的库是否成功加载
3、如果还无法解决,执行以下命令(建议先备份下):
rm -rf /usr/lib/libreadline*
ldconfig
如果是64位机器:
rm -rf /usr/lib64/libreadline*
ldconfig
问题5:lua 整数编译报错
3rd/lua/luaconf.h:560:2: error: #error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" In file included from skynet-src/malloc_hook.c:5: 3rd/lua/lua.h:93: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘lua_Integer’ 3rd/lua/lua.h:96: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘lua_Unsigned’ 3rd/lua/lua.h:182: warning: type defaults to ‘int’ in declaration of ‘lua_Integer’ 3rd/lua/lua.h:182: error: ‘lua_Integer’ declared as function returning a function 3rd/lua/lua.h:182: warning: parameter names (without types) in function declaration 3rd/lua/lua.h:226: error: expected declaration specifiers or ‘...’ before ‘lua_Integer’ 3rd/lua/lua.h:244: error: expected declaration specifiers or ‘...’ before ‘lua_Integer’ 3rd/lua/lua.h:246: error: expected declaration specifiers or ‘...’ before ‘lua_Integer’ 3rd/lua/lua.h:261: error: expected declaration specifiers or ‘...’ before ‘lua_Integer’ 3rd/lua/lua.h:263: error: expected declaration specifiers or ‘...’ before ‘lua_Integer’ skynet-src/malloc_hook.c: In function ‘update_xmalloc_stat_alloc’: skynet-src/malloc_hook.c:55: warning: value computed is not used skynet-src/malloc_hook.c: In function ‘update_xmalloc_stat_free’: skynet-src/malloc_hook.c:65: warning: value computed is not used skynet-src/malloc_hook.c: In function ‘dump_mem_lua’: skynet-src/malloc_hook.c:237: error: too many arguments to function ‘lua_pushinteger’ skynet-src/malloc_hook.c:238: error: expected ‘)’ before ‘data’ skynet-src/malloc_hook.c:238: error: too many arguments to function ‘lua_rawseti’ In file included from skynet-src/skynet_log.c:1: skynet-src/skynet_log.h:14:7: warning: no newline at end of file make[1]: *** [skynet] Error 1 make[1]: Leaving directory `/data/skynet' make: *** [linux] Error 2
解决:
这个是skynet最常见的编译失败了,和gcc版本有关,升级gcc可以解决问题。
最简单的方法:修改Makefile,在CFLAGS 加入 -std=gnu99
如果不想手动改,可用以下命令:
sed -i "s|CFLAGS =|CFLAGS = -std=gnu99 |" Makefile
如果是升级gcc参考问题6的解决方式。
问题6:gcc 编译器问题
/data/skynet/skynet-src/skynet_server.c:211: undefined reference to `__sync_sub_and_fetch_4' /tmp/ccC4fGch.o: In function `cmd_logoff': /data/skynet/skynet-src/skynet_server.c:589: undefined reference to `__sync_bool_compare_and_swap_4' /tmp/ccC4fGch.o: In function `cmd_logon': /data/skynet/skynet-src/skynet_server.c:568: undefined reference to `__sync_bool_compare_and_swap_4' /tmp/ccaeanLP.o: In function `reserve_id': /data/skynet/skynet-src/socket_server.c:241: undefined reference to `__sync_add_and_fetch_4' /data/skynet/skynet-src/socket_server.c:247: undefined reference to `__sync_bool_compare_and_swap_2' /data/skynet/skynet-src/socket_server.c:243: undefined reference to `__sync_and_and_fetch_4' /tmp/ccs12kTV.o: In function `get_allocated_field': /data/skynet/skynet-src/malloc_hook.c:36: undefined reference to `__sync_bool_compare_and_swap_4' /data/skynet/skynet-src/malloc_hook.c:40: undefined reference to `__sync_bool_compare_and_swap_4' collect2: ld returned 1 exit status make[1]: *** [skynet] Error 1 make[1]: Leaving directory `/data/skynet' make: *** [linux] Error 2
解决:
这是gcc版本问题,解决方法就是到高版本(如gcc4.5)下载一个linux_atomic.c文件,将其编译为一个静态库链接到你的项目代码,具体做法也比较麻烦。所以,这里推荐重装gcc。
另外,编译skynet建议gcc最低版本4.6.0,可自动下载并更新依赖包。安装gcc过程会比较久,要耐心等待
安装gcc步骤如下:( 确保磁盘可用空间至少4G)
wget http://mirrors.ustc.edu.cn/gnu/gcc/gcc-4.6.0/gcc-4.6.0.tar.gz tar -zxf gcc-4.6.0.tar.gz cd gcc-4.6.0 ./contrib/download_prerequisites mkdir build cd build ../configure --prefix=/usr -enable-checking=release -enable-languages=c,c++ -disable-multilib make make install
注意了,要确保 download_prerequisites 安装成功。因为国内连接gnu.org网站不是很稳定,可能出现类似错误:
Resolving gcc.gnu.org... 209.132.180.131 Connecting to gcc.gnu.org|209.132.180.131|:21... connected. Logging in as anonymous ... Logged in! ==> SYST ... done. ==> PWD ... done. ==> TYPE I ... done. ==> CWD /pub/gcc/infrastructure ... done. ==> SIZE mpfr-2.4.2.tar.bz2 ... 1077886 ==> PASV ... couldn't connect to 209.132.180.131 port 10179: Connection refused
如果重试了很多次都无法成功,尝试手动安装吧,主要就3个依赖gmp和mpfr、mpc,装好后再继续执行gcc ../configure及后面的步骤。
wget http://ftp.gnu.org/gnu/gmp/gmp-4.2.2.tar.bz2 tar -jxf gmp-4.2.2.tar.bz2 cd gmp-4.2.2 ./configure --prefix=/usr make && make install wget http://mpfr.loria.fr/mpfr-2.3.2/mpfr-2.3.2.tar.gz tar -zxf mpfr-2.3.2.tar.gz cd mpfr-2.3.2 ./configure --prefix=/usr make && make install wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-0.8.1.tar.gz tar -zxf mpc-0.8.1.tar.gz cd mpc-0.8.1 ./configure --prefix=/usr make && make install
问题7:缺少 autoconf
make all PLAT=linux SKYNET_LIBS="-lpthread -lm -ldl -lrt" SHARED="-fPIC --shared" EXPORT="-Wl,-E" MALLOC_STATICLIB="3rd/jemalloc/lib/libjemalloc_pic.a" SKYNET_DEFINES="" make[1]: Entering directory `/data/skynet' cd 3rd/jemalloc && ./autogen.sh --with-jemalloc-prefix=je_ --disable-valgrind autoconf ./autogen.sh: line 5: autoconf: command not found Error 0 in autoconf make[1]: *** [3rd/jemalloc/Makefile] Error 1 make[1]: Leaving directory `/data/skynet' make: *** [linux] Error 2
解决:
yum -y install autoconf
问题8:链接错误
n -sf libjemalloc.so.2 lib/libjemalloc.so ln: creating symbolic link `lib/libjemalloc.so' to `libjemalloc.so.2': Operation not supported make[3]: *** [lib/libjemalloc.so] Error 1 make[3]: Leaving directory `/mnt/hgfs/vm/skynet/3rd/jemalloc' make[2]: *** [3rd/jemalloc/lib/libjemalloc_pic.a] Error 2 make[2]: Leaving directory `/mnt/hgfs/vm/skynet' make[1]: *** [linux] Error 2 make[1]: Leaving directory `/mnt/hgfs/vm/skynet' make: *** [default] Error 2
解决:
虚拟机共享目录不能设置软连接,选择其他目录安装
最后语
如果还遇到其他错误,可以评论一起讨论,正好我也一起整理下。另外,文章主要在总结skynet遇到的问题,实际上也讨论了lua5.3的安装问题,以及gcc安装问题,希望有所帮助。