Building node.js for ramips

Recent versions of node.js require a FPU, so packages related to node.js where deactivated on platforms that lack a FPU; so far, so good.

However (and this is a cloudy area for me), there is a kernel option (KERNEL_MIPS_FPU_EMULATOR) that could be used to enable in-kernel FPU emulation on these platforms. According to some sources, it should be possible to enable that option, and thus build node.js on ramips.

I am comfortable building and running my own modified images, I have done this in the past. But I am not sure whether this is possible, or if there are reasons to not use KERNEL_MIPS_FPU_EMULATOR at all, and this is indeed a lost cause.

In case this is doable, is it as simple as enabling this option, then configuring and building the image? Or are other tasks involved, that I should take into consideration?

It is doable, and that is everything needed.

The FPU emulation has been disabled on mips for two reasons:

  • it's not needed for typical routing related packages and avoiding those code paths does speed up all packages that do math, but don't strictly need floating point math
  • the mips FPU emulation is extremely slow and inefficient, things that will take a few seconds on a hardware FPU can (literally) take hours with KERNEL_MIPS_FPU_EMULATOR. This has e.g. bitten Debian in the past, with (predominantly) test suites timing out on the mips buildds, as individual test appeared to be stalled with no output for ages.

The emulations may help you to fullfill ISA requirements for packages that demand FPU support, but don't actually use it significantly, because otherwise performance would be too bad to be usable. Emulated FPU support is always bad, but it's particularly abysmal on mips.

Consider ARMv7/ ARMv8 based devices for anything that needs floating point math, there it is part of the ISA baseline and reasonably performant - and we have a number if interesting devices falling into that category (ipq40xx, ipq806x, ipq807x, mvebu, mt7622, filogic 820/ 830/ 880, sunxi, rockchip, RPi).

2 Likes

Many thanks for your answer!

I do not plan on doing any heavy calculations, I just want to try to run a specific node.js program, and I do not expect that this software will do much floating point, either.

I think it's worth a try, and see what happens. As a last resort, I will have to dedicate a RPi I have lying around here.

As I posted in another thread, I tried (and failed miserably)...

I first downloaded the sources:
git clone https://git.openwrt.org/openwrt/openwrt.git && cd openwrt

Then installed all the feeds:
./scripts/feeds update -a && ./scripts/feeds install -a

As I want to start with an image similar to an official build, I downloaded the configuration for my platform:
wget https://downloads.openwrt.org/snapshots/targets/ramips/mt7621/config.buildinfo -O .config

I tried to configure the kernel first:
make -j6 kernel_menuconfig

But this triggered the normal menuconfig first... I selected my device, then checked that node.js was disabled, as expected. After saving the config file, the process continued, then failed because some library was missing; I could fix this with:
export LD_LIBRARY_PATH=${PWD}/staging_dir/host/lib/

Back to kernel_menuconfig, and I could enable FPU emulation. I tried to go back to menuconfig and enable node.js, but it was still disabled. So, I edited the Makefile at feeds/packages/lang/node/, and changed the dependencies:

  • Before: DEPENDS:=@HAS_FPU @(i386||x86_64||arm||aarch64) \
  • After: DEPENDS:=@(i386||x86_64||arm||aarch64||mipssel) \

Back to menuconfig again, and this time I could enable the node.js package.
Next step was to build the image:
make -j6 download world

However, this fails (precisely on node.js) with this message:

  /home/eperez/Downloads/OpenWrt/openwrt/staging_dir/host/bin/g++ -m32 -o /home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0/out/Release/obj.host/simdutf/deps/simdutf/simdutf.o ../deps/simdutf/simdutf.cpp '-D_GLIBCXX_USE_CXX11_ABI=1' '-DNODE_OPENSSL_CONF_NAME=nodejs_conf' '-DICU_NO_USER_DATA_OVERRIDE' '-D__STDC_FORMAT_MACROS' -I/home/eperez/Downloads/OpenWrt/openwrt/staging_dir/target-mipsel_24kc_musl/usr/include -I../deps/simdutf  -pthread -Wall -Wextra -Wno-unused-parameter -m32 -O3 -fno-omit-frame-pointer -fno-rtti -fno-exceptions -std=gnu++17 -MMD -MF /home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0/out/Release/.deps//home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0/out/Release/obj.host/simdutf/deps/simdutf/simdutf.o.d.raw   -c
In file included from /usr/include/features.h:515,
                 from /usr/include/c++/13/x86_64-redhat-linux/32/bits/os_defines.h:39,
                 from /usr/include/c++/13/x86_64-redhat-linux/32/bits/c++config.h:679,
                 from /usr/include/c++/13/cstring:41,
                 from ../deps/simdutf/simdutf.h:5,
                 from ../deps/simdutf/simdutf.cpp:3:
/usr/include/gnu/stubs.h:7:11: fatal error: gnu/stubs-32.h: No such file or directory
    7 | # include <gnu/stubs-32.h>
      |           ^~~~~~~~~~~~~~~~
compilation terminated.

And I got stuck at this point, because I do not know whether this is related to forcing the compilation, or if the package is failing for everybody...

I am a bit confused that the compilation seems to be using includes from my OS, instead of the ones downloaded from OpenWrt... But I cannot blame the changes I made, so I decided to install the 32bit headers and try again:

/home/eperez/Downloads/OpenWrt/openwrt/staging_dir/host/bin/g++ -m32 -o /home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0/out/Release/node_js2c -pthread -rdynamic -pthread -m32  -Wl,--start-group /home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0/out/Release/obj.host/node_js2c/tools/js2c.o /home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0/out/Release/obj.host/deps/simdutf/libsimdutf.a /home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0/out/Release/obj.host/deps/uv/libuv.a -L/home/eperez/Downloads/OpenWrt/openwrt/staging_dir/target-mipsel_24kc_musl/usr/lib -lm -ldl -lrt -Wl,--end-group
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-redhat-linux/13/libstdc++.so when searching for -lstdc++
/usr/bin/ld: cannot find -lstdc++: No such file or directory
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-redhat-linux/13/libstdc++.so when searching for -lstdc++
collect2: error: ld returned 1 exit status

So... for some reason that I cannot understand, the build process is trying to use the headers and libraries from my OS, and that does not work at all, obviously. I have to figure out what did I do to wreck the compilation.

I the following line to "build_dir/target-mipsel_24kc_musl/node-v20.11.0/deps/simdutf/simdutf.gyp", and the compilation continued past the previous error:

      'include_dirs!': [ '<!@(echo "$STAGING_DIR"/usr/include)' ],

I'm still not sure whether I did something wrong or is a bug in the code...

However, now the compilation fails with this error (that I also cannot explain):

make[4]: Entering directory '/home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0'
/home/eperez/Downloads/OpenWrt/openwrt/staging_dir/hostpkg/bin/python3.11 tools/gyp_node.py -f make
gyp: Undefined variable python in /home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0/tools/v8_gypfiles/v8.gyp
make[4]: *** [Makefile:176: out/Makefile] Error 1
make[4]: Leaving directory '/home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0'
make[3]: *** [Makefile:171: /home/eperez/Downloads/OpenWrt/openwrt/build_dir/target-mipsel_24kc_musl/node-v20.11.0/.built] Error 2
make[3]: Leaving directory '/home/eperez/Downloads/OpenWrt/openwrt/feeds/packages/lang/node'
time: package/feeds/packages/node/compile#0.81#0.25#0.93
    ERROR: package/feeds/packages/node failed to build.
make[2]: *** [package/Makefile:128: package/feeds/packages/node/compile] Error 1
make[2]: Leaving directory '/home/eperez/Downloads/OpenWrt/openwrt'
make[1]: *** [package/Makefile:122: /home/eperez/Downloads/OpenWrt/openwrt/staging_dir/target-mipsel_24kc_musl/stamp/.package_compile] Error 2
make[1]: Leaving directory '/home/eperez/Downloads/OpenWrt/openwrt'
make: *** [/home/eperez/Downloads/OpenWrt/openwrt/include/toplevel.mk:232: world] Error 2

Recent node.js does not support mips32.

FYI:

https://groups.google.com/g/v8-dev/c/AU49K-sysjY

1 Like

Ok, thanks for the heads up... I hoped that the limitation was on the FPU, but if the CPU is no longer supported, I guess my quest is useless.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.