文章目录
  1. 1. NETGEAR R6700/R6900/R7000能不能装NODE/NPM?
    1. 1.1. 事件回顾
    2. 1.2. 顺藤摸瓜
    3. 1.3. 直捣黄龙
      1. 1.3.1. 法1 路由器本地编译
      2. 1.3.2. 法2 交叉编译
  2. 2. 烦啦吧唧的错误
    1. 2.0.1. 法1 路由器本地编译中遇到的错误
    2. 2.0.2. 法2 交叉编译中遇到的错误

答案:可以,但仅限于低版本。


NETGEAR R6700/R6900/R7000能不能装NODE/NPM?

答案:能,但只能装v0.10.x版本。

两天了我就干了个这个。

事件回顾

1
2
3
4
# If I run below command
node -v
# I will get the tip unsurprisingly
Illegal instruction

R6700/R6900/R7000都使用了同款CPU——BCM4709。

然鹅,BCM4709的A9阉割了FPU(浮点运算单元),而除了那些早就被淘汰的低版本node,较新版本都需要FPU支持。

而似乎可以用softfp编译选项来拯救一下。

ARMCC和GCC编译ARM代码的软浮点和硬浮点问题

顺藤摸瓜

顺藤摸瓜,我在SNBForums又找到了新的收获,有人讲 The latest node 6.7 version for armv7(softfloat) will be uploaded after testing,并给出了链接。

node.js (v4 or later) and npm?

然而这是openwrt的make文件,不能马上拿来用的。

直捣黄龙

Looks like V8 requires VFP which the ARMv7 in the AC68U router doesn’t support - guess this is a dead end…

kun1he2 said:

Thanks, looks like all ASUS routers will only be able to use the legacy softfloat arch v0.10.x?

Yes. Right.

意思是,尽管node有softfloat,但是V8需要FPU支持,只有v0.10.x的版本的V8是不需要FPU支持的。

之前看到有人推荐v0.10.40和v0.10.45版本,还有人推v0.10.44和v0.10.48的,观众老爷都可以去试试。

法1 路由器本地编译

注意!!下面的编译十分耗时,以小时计!!请买好零食瓜子耐心等待!!

注意,博主使用此法未成功,建议使用法2。

于是按照思路,我们可以下载v0.10.45版本的node

1
curl -O http://nodejs.org/dist/v0.10.45/node-v0.10.45.tar.gz

解压,编译,添加如下编译选项

1
2
3
4
5
6
7
8
9
10
11
12
13
tar xzvf node-v0.10.45.tar.gz
cd node-v0.10.45
# 生产环境下能不要的都不要,缩短编译时间
python2 ./configure --dest-cpu=arm \
--dest-os=linux \
--without-snapshot \
#--shared-zlib \
#--shared-openssl \
--prefix=/opt \
--with-arm-float-abi=softfp \
--without-perfctr \
--without-dtrace \
--without-etw

在编译前,我们需要将cc指向gcc

1
ln -s gcc /opt/bin/cc

最好创建一下交换空间 [方法见 <路由器本地编译中遇到的错误 问题2>](#法1 路由器本地编译中遇到的错误)

现在请火力全开编译吧!(CPU支持几线程就开几线程)

1
2
3
4
# 为了避免ssh出现timeout中止make,建议通过screen而非直接执行下述命令,方法见<法1 路由器本地编译中遇到的错误 问题3>
make -j$(grep 'processor' /proc/cpuinfo | sort -u | wc -l)

# 注意,火力全开可能会导致一些make问题,见<路由器本地编译中遇到的错误 问题4>

如果你闲得无聊,可以再启一个ssh观看256MB的内存是如何和交换空间共舞的

1
2
# 如果你在等待编译的过程中闲得无聊
watch -d free -h

经过漫长而焦急的等待后(我太难了)

1
make install

最后记得添加环境变量。

博主最后遇到了[<路由器本地编译中遇到的错误 问题7>](#法1 路由器本地编译中遇到的错误)然后放弃了,所以请最终走完流程的人麻烦告诉我一下解决方案谢谢。

法2 交叉编译

此法避免了在路由器中编译出现的各种内存不足引发的问题

先下载GNU交叉编译器,具体为AArch32 target with soft float (arm-linux-gnueabi)

但出于[<交叉编译中遇到的错误 问题2>](#法2 交叉编译中遇到的错误)的考虑,建议使用低版本的GNU-A交叉编译器,下载地址见问题中描述。

假设已解压并将其放入*/usr/gcc-arm-linux-gnueabi*

并且当前目录为node的源代码目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
export GCC_ARM_LINUX=/usr/gcc-arm-linux-gnueabi
export PATH=$PATH:$GCC_ARM_LINUX/bin
export AR="arm-linux-gnueabi-ar"
export CC="arm-linux-gnueabi-gcc"
export CXX="arm-linux-gnueabi-g++"
export LINK="arm-linux-gnueabi-g++"
export CPP="arm-linux-gnueabi-gcc -E"
export LD="arm-linux-gnueabi-ld"
export AS="arm-linux-gnueabi-as"
export NM="arm-linux-gnueabi-nm"
export STRIP="arm-linux-gnueabi-strip"
export OBJCOPY="arm-linux-gnueabi-objcopy"
export RANLIB="arm-linux-gnueabi-ranlib"
export CFLAGS=-static
export CXXFLAGS=-static
export LDFLAGS=-static
export TARGET=$HOME/arm-node # 编译好的node放在~/arm-node
mkdir $TARGET
# 能阉割就阉割,反正运行在生产环境,编译快就行了
python2 ./configure --dest-cpu=arm \
--dest-os=linux \
--without-snapshot \
--prefix=$TARGET \
--with-arm-float-abi=softfp \
--with-mips-float-abi=soft \
--without-perfctr \
--without-dtrace \
--without-etw
# 火力全开
make -j$(grep 'processor' /proc/cpuinfo | sort -u | wc -l)

好的,一鼓作气

1
2
make install
cd $TARGET

愉快!

……

后面把文件scp到路由器,然后把node和npm加入到PATH里去就好了。

烦啦吧唧的错误

法1 路由器本地编译中遇到的错误

  1. ValueError: unsupported hash type md5

    重装libopenssl解决

    1
    2
    opkg remove --force-depends libopenssl
    opkg install libopenssl
  2. g++: internal compiler error: Killed (program cc1plus)

    内存不足。话不多说,先开个512MB的交换空间吧。

    1
    2
    3
    dd if=/dev/zero of=/tmp/mnt/sda1/swapfile bs=64M count=8
    mkswap /tmp/mnt/sda1/swapfile
    swapon /tmp/mnt/sda1/swapfile

    检查一下:

    1
    free -h

    如果想开机自启交换空间

    1
    echo "/tmp/mnt/sda1/swapfile swap swap defaults 0 0" >> /etc/fstab && cat /etc/fstab
  3. Timeout, server 192.168.50.1 not responding.

    如果你不幸遇到这样的问题,不要惊慌,不要失措,虽然make会中断,但是毕竟是可以断点重make的……

    没办法通过修改sshd配置来延长timeout时间,所以只能曲线救国,通过screen将进程转到physical terminal运行。

    screen - 4.6.2-3 - Screen is a full-screen window manager that multiplexes a physical terminal between several processes, typically interactive shells.

    下面给出screen的基础用法

    1
    2
    # 安装screen
    opkg install screen

    创建会话

    1
    2
    3
    4
    # 创建一个会话,命名为node
    screen -S node

    # 此时会进入到一个新的physical terminal中,在此terminal中进行make不会受到ssh连接中断影响

    切出会话

    1
    # 按下 ctrl + a + d 即可切出会话

    查看会话

    1
    screen -ls

    返回会话

    1
    2
    # screen -r <会话名或会话id>
    screen -r node
  4. …/deps/v8/src/crankshaft/hydrogen-instructions.h:5560:3: internal compiler error: Segmentation fault

    多线程make导致内存不足,改用单线程

    1
    make

    虽然慢但更稳定。

    然而有时上述方法仍然不能解决内存不足的问题,可路由器没办法扩充物理内存,那就只能多make几遍了,总有一次是成功的。

  5. …/src/node_crypto.h:20:10: fatal error: openssl/ssl.h: No such file or directory

    手动编译openssl似乎因为perl的原因行不大通,那就直接安装编译版吧

    1
    2
    cp -r deps/openssl /opt/
    export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/opt/openssl/openssl/include

    注:此方法可能导致了问题7,建议后来者头铁编译openssl

  6. …/src/node.cc:47:10: fatal error: zlib.h: No such file or directory

    同上

    1
    2
    cp -r deps/zlib /opt/
    export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/opt/zlib

    注:此方法可能导致了问题7,建议后来者头铁编译zlib

  7. 1
    2
    3
    4
    5
    /opt/bin/ld: warning: libdl.so.0, needed by /usr/lib/libcrypto.so, may conflict with libdl.so.2
    /opt/bin/ld: warning: libc.so.0, needed by /usr/lib/libcrypto.so, may conflict with libc.so.6
    /opt/bin/ld: errno@@GLIBC_PRIVATE: TLS definition in /tmp/mnt/sda1/entware/bin/../lib/gcc/arm-openwrt-linux-gnueabi/7.4.0/libc.so.6 section .tbss mismatches non-TLS definition in /lib/libc.so.0 section .bss
    /lib/libc.so.0: error adding symbols: Bad value
    collect2: error: ld returned 1 exit status

    我怀疑是因为问题5和问题6使用了非共享库导致的。

    法1不想搞了,诸君加油。

2 交叉编译中遇到的错误

  1. 1
    2
    3
    4
    5
    6
      File "<string>", line 1
    import sys; print sys.byteorder
    ^
    SyntaxError: invalid syntax
    gyp: Call to 'python -c "import sys; print sys.byteorder"' returned exit status 1 while in /home/mzz/test/node-v6.11.2/deps/v8/tools/gyp/v8.gyp. while loading dependencies of /home/mzz/test/node-v6.11.2/node.gyp while trying to load /home/mzz/test/node-v6.11.2/node.gyp
    Error running GYP

    这是python被默认指定为python3的锅,暂时把python链接到python2

    1
    PYPATH=$(which python) && sudo rm $PYPATH && sudo ln -s python2 $PYPATH
  2. 1
    2
    FATAL: kernel too old
    Aborted

    对不起你用了高档货的gcc了,比方说arm-linux-gnueabi-gcc 8.2.0是Debian 9原装货,它的glibc只能向下兼容到3.2.0版kernel 引用源

    解决办法是使用低版本的gcc,据上述引用源说,4.8.3最好,但是目前很难找到了。

    这里给出官方珍藏的历史版本们:Linano Releases

    我们这里使用4.9.4版本就好了 我是下载地址

文章目录
  1. 1. NETGEAR R6700/R6900/R7000能不能装NODE/NPM?
    1. 1.1. 事件回顾
    2. 1.2. 顺藤摸瓜
    3. 1.3. 直捣黄龙
      1. 1.3.1. 法1 路由器本地编译
      2. 1.3.2. 法2 交叉编译
  2. 2. 烦啦吧唧的错误
    1. 2.0.1. 法1 路由器本地编译中遇到的错误
    2. 2.0.2. 法2 交叉编译中遇到的错误