通过交叉编译armv5的节点来兼容库

我尝试在我的Ubuntu 14.04桌面x64上为我的QNAP armv5te机器交叉编译节点 。

QAPP App-center中存在节点QPKG,但其版本较旧(0.8.22)。
以下是有关服务器的信息:

Linux SERVERNAME 3.4.6#1 Mon Dec 29 06:00:47 CST 2014 armv5tel未知
处理器名称 :Feroceon 88F6281 rev 1(v5l)@ 1.2 GHz
BogoMIPS :1196.85
特点 :swp half thumb fastmult edsp
CPU实现者 :0x56
CPU架构 :5TE
CPU变体 :0x2
CPU部分 :0x131
CPU修订版 :1
硬件 :Feroceon-KW
ARM版本 :0000
型号 :0000000000000000

这是我在桌面上使用的命令:

apt-get update apt-get upgrade apt-get install emdebian-archive-keyring apt-get install libc6-armel-cross libc6-dev-armel-cross apt-get install binutils-arm-linux-gnueabi apt-get install gcc-4.7-arm-linux-gnueabi apt-get install g++-4.7-arm-linux-gnueabi apt-get install u-boot-tools apt-get install libncurses5-dev ln -s /user/bin/arm-linux-gnueabi-gcc-4.7 /usr/bin/arm-linux-gnueabi-gcc ln -s /user/bin/arm-linux-gnueabi-g++-4.7 /usr/bin/arm-linux-gnueabi-g++ wget http://nodejs.org/dist/node-v0.10.35/node-v0.10.35.tar.gz tar -zxf node-v0.10.35.tar.gz cd node-v0.10.35 export TOOL_PREFIX="arm-linux-gnueabi" export CC="${TOOL_PREFIX}-gcc" export CXX="${TOOL_PREFIX}-g++" export AR="${TOOL_PREFIX}-ar" export RANLIB="${TOOL_PREFIX}-ranlib" export LINK="${CXX}" export CCFLAGS="-march=armv5te -mfpu=softfp -marm" export CXXFLAGS="-march=armv5te -mno-unaligned-access" export OPENSSL_armcap=5 export GYPFLAGS="-Darmeabi=soft -Dv8_can_use_vfp_instructions=false -Dv8_can_use_unaligned_accesses=false -Darmv7=0" export VFP3=off export VFP2=off ./configure --without-snapshot --dest-cpu=arm --dest-os=linux --prefix="/root/.nvm/v0.10.35" make -j 4 make install tar -zcf node-v0.10.35-linux-armv5.tar.gz v0.10.35 

编译未显示这些参数的任何失败。 所以在那之后我将tarball发送到我的QNAP服务器:

 scp /root/.nvm/node-v0.10.35-linux-armv5.tar.gz admin@SERVERNAME:/share/HDA_DATA/.qpkg/nodejs ssh SERVERNAME -l admin cd /share/HDA_DATA/.qpkg/nodejs tar -zxf node-v0.10.35-linux-armv5.tar.gz ln -s v0.10.35 node 

我的所有env变量都已在我的服务器上设置。 现在我可以测试节点二进制…

 # node -v node: /usr/lib/libstdc++.so.6: version `CXXABI_ARM_1.3.3' not found (required by node) node: /lib/libc.so.6: version `GLIBC_2.15' not found (required by node) node: /lib/libc.so.6: version `GLIBC_2.11' not found (required by node) node: /lib/libc.so.6: version `GLIBC_2.7' not found (required by node) 

最后我有一个错误,因为在Ubuntu和Qnap上的C库不一样,对于Ubuntu桌面,我有ldd (Ubuntu EGLIBC 2.19-0ubuntu6.5) 2.19和QNAP ldd (GNU libc) 2.5

libc-devlibstdc ++是由Qnap上的Optware ipkg处理的包(旧版本)。

我的问题是解决这个问题的更好方法是什么? 强制更新服务器上的lib? (以及如何做到这一点?)或者在编译期间可能使用静态库? (以及如何做到这一点?)或其他选择?


编辑:

在与无艺术噪声交谈后,我明白我有几种方法可以修复库依赖…

有问题的依赖关系:

 # ldd /opt/bin/node /opt/node/bin/node: /usr/lib/libstdc++.so.6: version `CXXABI_ARM_1.3.3' not found (required by /opt/node/bin/node) /opt/node/bin/node: /lib/libc.so.6: version `GLIBC_2.15' not found (required by /opt/node/bin/node) /opt/node/bin/node: /lib/libc.so.6: version `GLIBC_2.11' not found (required by /opt/node/bin/node) /opt/node/bin/node: /lib/libc.so.6: version `GLIBC_2.7' not found (required by /opt/node/bin/node) libdl.so.2 => /lib/libdl.so.2 (0xb6ed2000) librt.so.1 => /lib/librt.so.1 (0xb6ec3000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb6de2000) libm.so.6 => /lib/libm.so.6 (0xb6d32000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb6d1e000) libpthread.so.0 => /lib/libpthread.so.0 (0xb6cfe000) libc.so.6 => /lib/libc.so.6 (0xb6bca000) /lib/ld-linux.so.3 (0xb6ee4000) 
  • 将库从Ubuntu GCC复制到目标计算机,并覆盖默认值:
    它可能非常危险,可能会破坏系统。 更多的是,我的目标是为QNAP社区创建一个QPKG,因此要求人们覆盖他们的C libs并不是一个非常好的方法。

  • 复制库并与原始库共存:
    一个不错的方法,只需要将LD_LIBRARY_PATH设置为包含应用程序最新库的目录。 但我发现使用此方法时出现错误,再次使用c ++ lib。

错误:

 node: symbol lookup error: /opt/node/lib/c/libstdc++.so.6: undefined symbol: _ZNSt11__timepunctIcE2idE, version GLIBCXX_3.4 
  • 创建静态应用程序:
    最后,我找到了在编译期间以及在目标机器上执行期间没有任何错误的方法。 只需要添加一些标志。

新旗帜:

 export CCFLAGS="-march=armv5te -mfpu=softfp -marm -static-libgcc" export CXXFLAGS="-march=armv5te -mno-unaligned-access -static-libstdc++" export LDFLAGS="-static" 

检查动态库链接:

 # ldd /opt/bin/node not a dynamic executable # npm version { test: '1.0.0', npm: '2.3.0', ares: '1.9.0-DEV', http_parser: '1.0', modules: '11', node: '0.10.35', openssl: '1.0.1j', uv: '0.10.30', v8: '3.14.5.9', zlib: '1.2.8' } 

编辑:最后一个问题在这里,大多数节点function工作,但不是http

我测试了一个简单的脚本(来自NodeJS API)来获取有关网页的信息:

 http.get("http://www.google.com/index.html", function(res) { console.log("Got response: " + res.statusCode); }).on('error', function(e) { console.log("Got error: " + e.message); }); 

而且我得到了Got error: getaddrinfo ENOTFOUND ,是否可能因为节点是静态的某些function无法工作?

最后,我没有尝试更改库,而是决定使用更好的交叉编译器,它与我的目标完美匹配。

我使用了Crosstools-NG ,但我也可以使用官方的QNAP Maxwell-ARM工具链 (我看到它太晚了……)

 gcc (GCC) 4.2.4 g++ (GCC) 4.2.4 GNU ld (crosstool-NG 1.20.0) 2.19.1 ldd (crosstool-NG) 1.20.0 Python 2.7.6 (with gyp) 

但问题始终存在,有一个节点依赖( libuv ),它使用一个名为linux-atomic的库,该库是从版本4.4.X开始在GCC中引入的。 所以这是我修复它的解决方法:

 cd /src wget -q https://ftp.gnu.org/gnu/gcc/gcc-4.6.3/gcc-core-4.6.3.tar.gz tar -zxf gcc-core-4.6.3.tar.gz sed -i -e 's/define HIDDEN.*/define HIDDEN/' /src/gcc-4.6.3/gcc/config/arm/linux-atomic.c export CC=arm-none-linux-gnueabi-gcc export AR=arm-none-linux-gnueabi-ar export RANLIB=arm-none-linux-gnueabi-ranlib cd /src/gcc-4.6.3/gcc/config/arm libtool --tag=CC --mode=compile $CC -g -O2 -MT linux-atomic.lo -MD -MP -MF linux-atomic.Tpo -c -o linux-atomic.lo linux-atomic.c $AR cru /src/gcc-4.6.3/gcc/config/arm/.libs/liblinux-atomic.a /src/gcc-4.6.3/gcc/config/arm/.libs/linux-atomic.o $RANLIB /src/gcc-4.6.3/gcc/config/arm/.libs/liblinux-atomic.a # IMPORTANT: Assign environment variables like I made in my question above. # Go to node src dir and configure ./configure --without-snapshot --dest-cpu=arm --dest-os=linux --prefix="${PREFIX_DIR}" # When configuration is done, edit out/node.target.mk vi out/node.target.mk # Find LD_INPUTS files list and add your new library as last one: # -> /src/gcc-4.6.3/gcc/config/arm/.libs/liblinux-atomic.a # Now you can build node ! make -j4 #-jX where X is the number of available cores make install DESTDIR=$TEMPDIR # Use DESTDIR to avoid installation directly in $PREFIX_DIR path 

变通方法参考

通过该配置,我还可以使用GCC 4.1.3为x86处理器编译节点。 我为不想自己编译的QNAP用户制作了QPKG: https : //github.com/jbltx/nodejs-QPKG/tree/master/node-v0.10.35