This is still an unresolved issue with the newest version of Node (as of this writing, v0.12.2)
When browsing Node distributions, the latest ARM build is in v0.11.9, meaning you will currently need to compile from the source, if you want Node.js v0.12.
The following is only related to compiling from source in Raspbian.
Reason for 'Illegal instruction'
The V8 Javascript engine used by Node, is issuing ARMv7 CPU instructions, while the Raspberry Pi only understands v6 instructions (note: Raspberry Pi 2 uses an ARM v7 processor)
When compiling from source, V8 is compiled as well, and it does not detect and is not told, that the processor is ARMv6, so it is defaulting to ARMv7.
Test node
To test whether this is the reason you are experiencing the 'Illegal instruction' error, run
node --v8-options
and look at the second line. If it is:
ARMv7=1 VFP3=0 VFP32DREGS=0 NEON=0 SUDIV=0 ...
then the ARMv7=1
hints that V8 is compiled for ARMv7.
Raspberry Pi ARM version
To see which ARM version the processor supports, open /proc/cpuinfo
For Raspberry Pi model B (rev. 2), the model name is ARMv6-compatible processor rev 7 (v6l)
.
V8 ARM version detection
V8 tries to detect which ARM version to use, but in this case, it does not get it right. The detection happens in deps/v8/src/base/cpu.cc
(tip: search for v6l
- lowercase L). The area of interest is:
// Unfortunately, it seems that certain ARMv6-based CPUs
// report an incorrect architecture number of 7!
//
// ...
//
// We try to correct this by looking at the 'elf_format'
// field reported by the 'Processor' field, which is of the
// form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
// an ARMv6-one. For example, the Raspberry Pi is one popular
// ARMv6 device that reports architecture 7.
if (architecture_ == 7) {
char* processor = cpu_info.ExtractField("Processor");
if (HasListItem(processor, "(v6l)")) {
architecture_ = 6;
}
delete[] processor;
}
( See also V8 cpu.cc )
Even though it tries to detect the v6l
string in /proc/cpuinfo
, it is looking at the Processor field - but the info is in the model name field - as stated in the Raspberry Pi ARM version section of this post.
Node configure script
The configure script for Node also needs to be edited.
The code is:
if is_arch_armv7():
o['variables']['arm_version'] = '7'
elif is_arch_armv6():
o['variables']['arm_version'] = '6'
else:
o['variables']['arm_version'] = 'default'
o['variables']['arm_fpu'] = 'vfpv3' # V8 3.18 no longer supports VFP2.
o['variables']['arm_neon'] = int(is_arm_neon())
o['variables']['arm_thumb'] = 0 # -marm
o['variables']['arm_float_abi'] = arm_float_abi
Assuming vfpv3 seems to make V8 compile to ARMv7, and while the comment says:
# V8 3.18 no longer supports VFP2.
All I could find on the topic, is that V8 3.17 is that last version to support "no-VFPv2", which makes VFPv2 the minimum requirement for V8 3.18+.
Solution
- Run
make uninstall
- Run
make clean
- Edit the line in
deps/v8/src/base/cpu.cc
, from char* processor = cpu_info.ExtractField("Processor");
to char* processor = cpu_info.ExtractField("model name");
An even better solution would probably be to add a whole new check for model name, instead of replacing the Processor check.
- Edit the Node configure script, from
if is_arch_armv7():
o['variables']['arm_version'] = '7'
elif is_arch_armv6():
o['variables']['arm_version'] = '6'
else:
o['variables']['arm_version'] = 'default'
o['variables']['arm_fpu'] = 'vfpv3' # V8 3.18 no longer supports VFP2.
o['variables']['arm_neon'] = int(is_arm_neon())
o['variables']['arm_thumb'] = 0 # -marm
o['variables']['arm_float_abi'] = arm_float_abi
to
if is_arch_armv7():
o['variables']['arm_fpu'] = 'vfpv3'
o['variables']['arm_neon'] = int(is_arm_neon())
o['variables']['arm_version'] = '7'
else:
o['variables']['arm_fpu'] = 'vfpv2'
o['variables']['arm_neon'] = 0
o['variables']['arm_version'] = '6' if is_arch_armv6() else 'default'
o['variables']['arm_thumb'] = 0 # -marm
o['variables']['arm_float_abi'] = arm_float_abi
- Run
./configure --without-snapshot
- Run
make
- Run
make install
- Verify that
node --v8-options
has ARMv7=0
- Run
make test
to verify that the Node tests succeed.
Attribution and notes
- Many of the details in this post, are gathered from the identical io.js issue #283
- When running
make test
, I got 770 passed and 18 failed. The failures were mainly due to timeouts, which probably occurs because of limited resources on a Raspberry Pi.
- I successfully ran a small Node.js application on a Raspberry Pi, using this solution. However, I cannot guarantee that all functionality of Node will work.
Illegal Instruction
. I can paste you the strace of the execution if you want. – Eaque Oct 23 '14 at 15:48