The Crystal Programming Language Forum

Problem compiling crystal from source on RaspberryPI 4

Hi,

Out of curiosity I am trying to compile crystal on a RaspberryPI 4.
I followed the usual method of cross-compiling the compiler, linking on the PI.

When I then try to use that compiler to compile the same version of crystal on the PI that it was cross-compiled from i get this:

pi@ceres:~/crystal $ make
Using /usr/bin/llvm-config-8 [version=8.0.0]
CRYSTAL_CONFIG_PATH="/home/pi/crystal/src" CRYSTAL_CONFIG_LIBRARY_PATH="" CRYSTAL_CONFIG_BUILD_COMMIT="0e2e1d067" ./bin/crystal build  -o .build/crystal src/compiler/crystal.cr -D without_openssl -D without_zlib
GC Warning: Repeated allocation of very large block (appr. size 1052672):
	May lead to memory leak and poor performance
GC Warning: Repeated allocation of very large block (appr. size 1052672):
	May lead to memory leak and poor performance
Invalid memory access (signal 11) at address 0x0
[0xb6f33c] ???
[0xa843c0] __crystal_sigfault_handler +136
Invalid memory access (signal 11) at address 0x0
[0xb6f33c] ???
[0xa843c0] __crystal_sigfault_handler +136
Invalid memory access (signal 11) at address 0x0
[0xb6f33c] ???
[0xa843c0] __crystal_sigfault_handler +136
Invalid memory access (signal 11) at address 0x0
[0xb6f33c] ???
[0xa843c0] __crystal_sigfault_handler +136
Invalid memory access (signal 11) at address 0x0
[0xb6f33c] ???
[0xa843c0] __crystal_sigfault_handler +136
Invalid memory access (signal 11) at address 0x0
[0xb6f33c] ???
[0xa843c0] __crystal_sigfault_handler +136
Invalid memory access (signal 11) at address 0x0
[0xb6f33c] ???
[0xa843c0] __crystal_sigfault_handler +136
Invalid memory access (signal 11) at address 0x0
[0xb6f33c] ???
[0xa843c0] __crystal_sigfault_handler +136
Invalid memory access (signal 11) at address 0x0
[0xb6f33c] ???
[0xa843c0] __crystal_sigfault_handler +136
cc: error: _main.o: No such file or directory
cc: error: S-lice40U-I-nt841.o: No such file or directory
cc: error: P-ointer40U-I-nt841.o: No such file or directory
cc: error: A-rgumentE-rror.o: No such file or directory
cc: error: C-allS-tack.o: No such file or directory
cc: error: A-rray40P-ointer40V-oid4141.o: No such file or directory
cc: error: P-ointer40P-ointer40V-oid4141.o: No such file or directory

many more lines of the cc: errors, then:

cc: error: L-ibU-nwind5858A-ction.o: No such file or directory
cc: error: L-E-B-R-eader.o: No such file or directory
cc: error: C-allS-tack5858R-epeatedF-rame.o: No such file or directory
Error: execution of command failed with code: 1: `cc "${@}" -o '/home/pi/crystal/.build/crystal'  -rdynamic  /home/pi/crystal/src/llvm/ext/llvm_ext.o `/usr/bin/llvm-config-8 --libs --system-libs --ldflags 2> /dev/null` -lstdc++ -lpcre -lm /usr/local/lib/libgc.a -lpthread /home/pi/crystal/src/ext/libcrystal.a -levent -lrt -ldl -L/usr/lib -L/usr/local/lib`
make: *** [Makefile:132: .build/crystal] Error 1

Any ideas whats going wrong there?
It should work, right?
Or is there a reason why compiling crystal would fail on arm?

Compiling the compiler requires something between 4GB and 8GB of memory. Does your raspberry pi have that memory?

it has 4GB ram.

interesting. I’ll try to see if it hits that when compilig.

I’ll almost sure 4GB is not enough to compile the compiler.

For cross compiling into a raspberry pi you’ll want to compile your programs, not the compiler.

I did Cross compile the compiler. I was just curious if the new RaspberryPI 4 was ‘good enough’ to build crystal on it.

That would make it easy to build a debian package for Raspbian.

# mkswap?

I’ll try that soon, just have to dig up some USB harddrive somewhere, I don’t want to swap to the sdcard.

I had some more time (i.e. needed something to procrastinate) and added a usb3 ssd to my PI4.
It turns out I didn’t have to do that, because compiling crystal does not even touch the swapspace.

I also rebuild the GC with the latest code tagged with a version (v.8.0.4)
Build using llvm-8.

I even re-cross-compiled the compiler with --target armv6k-unknown-linux-gnueabihf because I noticed that the old PIs self-identified as armv6-unknown-linux-gnueabihf (armv6 vs. armv6k)

same result.

After that I also tried to run make compiler_spec and make spec but both also fail with the same error.
(or something so similar that I cant see a difference)

The reason I want to follow this up is 2 tings:

  • that I don’t see why this would not work unless the whole compiler is unreliable on RaspberryPI4 and that would be something someone would maybe want to fix.
  • I get very similar compile errors when I try to compile invidious on the PI (although that was quite hard to even get that far due to other problems, so I might have broken it.)

I don’t think I have the expertise to take this any further, but if anyone has any suggestions or things to try to provide more information, please tell me.

In my observations on macOS it uses 1.3GB of RAM during compiler compilation.

FWIW once https://github.com/crystal-lang/crystal/pull/9401 is merged, it should be possible to run Crystal HEAD on an AArch64 based OS on a RPi3/4. Alpine has a patched AArch64 Crystal 0.34.1 in the edge repos already, on ArchlinuxARM you can get a patched crystal-git from the AUR (atm probably broken for trying to apply already merged patches, I’ll update it once no patches are needed anymore). I’m also trying to land a port of the community/crystal package into the ArchlinuxARM repositories.

The situation for the armhf (32 bit) platform looks much more dire unfortunately.

1 Like

I tried to build it on my macOS then move crystal.o to my RPI4 8GB and finish it there but no much of luck. if I use aarch64-linux-gnu triplet it crashed during compilation:

sergey@Sergeys-MacBook-Pro crystal % ./bin/crystal build src/compiler/crystal.cr --cross-compile --target aarch64-linux-gnu -s -D without_openssl -D without_zlib --emit llvm-ir
Parse:                             00:00:00.000104893 (   0.25MB)
Semantic (top level):              00:00:00.694217083 ( 108.61MB)
Semantic (new):                    00:00:00.017195690 ( 108.61MB)
Semantic (type declarations):      00:00:00.055449222 ( 108.61MB)
Semantic (abstract def check):     00:00:00.015524817 ( 124.61MB)
Semantic (ivars initializers):     00:00:05.183965560 ( 864.55MB)
Semantic (cvars initializers):     00:00:00.006429322 ( 864.55MB)
Semantic (main):                   00:00:02.001984441 (1088.55MB)
Semantic (cleanup):                00:00:00.166551974 (1088.55MB)
Semantic (recursive struct check): 00:00:00.002065987 (1088.55MB)
Codegen (crystal):                 00:00:05.877934121 (1236.55MB)
Invalid memory access (signal 11) at address 0x0
[0x1012661b7] *Exception::CallStack::print_backtrace:Int32 +39
[0x1011a98aa] __crystal_sigfault_handler +522
[0x7fff6ffc95fd] _sigtramp +29
[0x1017690f6] _ZNK4llvm19AArch64CallLowering17splitToValueTypesERKNS_12CallLowering7ArgInfoERNS_15SmallVectorImplIS2_EERKNS_10DataLayoutERNS_19MachineRegisterInfoEj +366
[0x10176ae30] _ZNK4llvm19AArch64CallLowering9lowerCallERNS_16MachineIRBuilderERNS_12CallLowering16CallLoweringInfoE +164
[0x10183b96d] _ZNK4llvm12CallLowering9lowerCallERNS_16MachineIRBuilderENS_17ImmutableCallSiteENS_8ArrayRefINS_8RegisterEEENS4_IS6_EES5_NSt3__18functionIFjvEEE +1159
[0x101848967] _ZN4llvm12IRTranslator17translateCallSiteERKNS_17ImmutableCallSiteERNS_16MachineIRBuilderE +577
[0x101848c12] _ZN4llvm12IRTranslator13translateCallERKNS_4UserERNS_16MachineIRBuilderE +262
[0x10184ae18] _ZN4llvm12IRTranslator9translateERKNS_11InstructionE +1184
[0x10184bb4f] _ZN4llvm12IRTranslator20runOnMachineFunctionERNS_15MachineFunctionE +2299
[0x101b70b61] _ZN4llvm19MachineFunctionPass13runOnFunctionERNS_8FunctionE +239
[0x102227c25] _ZN4llvm13FPPassManager13runOnFunctionERNS_8FunctionE +499
[0x102227e80] _ZN4llvm13FPPassManager11runOnModuleERNS_6ModuleE +52
[0x1022281d4] _ZN4llvm6legacy15PassManagerImpl3runERNS_6ModuleE +662
[0x101ca7f6a] _ZL21LLVMTargetMachineEmitP23LLVMOpaqueTargetMachineP16LLVMOpaqueModuleRN4llvm17raw_pwrite_streamE19LLVMCodeGenFileTypePPc +191
[0x101ca7e29] LLVMTargetMachineEmitToFile +148
[0x100d8e656] *Crystal::Compiler#codegen<Crystal::Program, Crystal::ASTNode+, Array(Crystal::Compiler::Source), String>:(Tuple(Array(Crystal::Compiler::CompilationUnit), Array(String)) | Nil) +6278
[0x1011c4087] *Crystal::Compiler#compile<Array(Crystal::Compiler::Source), String>:Crystal::Compiler::Result +135
[0x1011af49d] *Crystal::Command#run:(Bool | Nil) +669
[0x1007f1312] __crystal_main +7938
[0x1007f3311] main +65

Do you think your PR will help to fix it?
I move crystal.ll file and then do llc to make object file and then trying to play with lld to link it. Most of the methods in libraries are incompatible :frowning:
Also if I try to compile it to older architecture object file on a macOS it cannot link it on RPI4 with the incompatible .o file error.

Yes, it’s exactly what it fixes. This and nothing else.

1 Like

Excellent! I will try your PR right now then.

You can also find a fully statically precompiled executable with the patch at https://dev.alpinelinux.org/archive/crystal/ However it comes without the standard library or anything else, so you would still need to clone the repo, place it at .build/crystal, run make deps and use the bin/crystal wrapper.

Cool! I will do that!

I tried to compile your branch on macOS and got this error:

sergey@Sergeys-MacBook-Pro jhass_crystal % CRYSTAL_ROOT=. CRYSTAL_HAS_WRAPPER=true LLVM_CONFIG=/usr/local/Cellar/llvm/10.0.0_3/bin/llvm-config make stats=1
Using /usr/local/Cellar/llvm/10.0.0_3/bin/llvm-config [version=10.0.0]
CRYSTAL_CONFIG_PATH="/Users/sergey/Projects/crystal/jhass_crystal/src" CRYSTAL_CONFIG_LIBRARY_PATH="/usr/local/Cellar/crystal/0.35.1/embedded/lib:/usr/lib:/usr/local/lib" CRYSTAL_CONFIG_BUILD_COMMIT="b0435958a" SOURCE_DATE_EPOCH="1591035414" ./bin/crystal build --stats  -o .build/crystal src/compiler/crystal.cr -D without_openssl -D without_zlib
Parse:                             00:00:00.000123824 (   0.25MB)
Semantic (top level):              00:00:00.497835475 ( 108.45MB)
Semantic (new):                    00:00:00.018879100 ( 108.45MB)
Semantic (type declarations):      00:00:00.052906647 ( 108.45MB)
Semantic (abstract def check):     00:00:00.013462519 ( 124.45MB)
Semantic (ivars initializers):     00:00:05.788797202 ( 864.38MB)
Semantic (cvars initializers):     00:00:00.006314962 ( 864.38MB)
Semantic (main):                   00:00:10.893857530 (1088.38MB)
Semantic (cleanup):                00:00:00.179418112 (1088.38MB)
Semantic (recursive struct check): 00:00:00.002256392 (1088.38MB)
Codegen (crystal):                 00:00:07.750236255 (1236.38MB)
Codegen (bc+obj):                  00:00:13.961979044 (1236.38MB)
Undefined symbols for architecture x86_64:
  "llvm::ARMInstPrinter::getRegisterName(unsigned int)", referenced from:
      llvm::ARMAsmPrinter::printOperand(llvm::MachineInstr const*, int, llvm::raw_ostream&) in libLLVMARMCodeGen.a(ARMAsmPrinter.cpp.o)
      llvm::ARMAsmPrinter::PrintAsmOperand(llvm::MachineInstr const*, unsigned int, unsigned int, char const*, llvm::raw_ostream&) in libLLVMARMCodeGen.a(ARMAsmPrinter.cpp.o)
      llvm::ARMAsmPrinter::PrintAsmMemoryOperand(llvm::MachineInstr const*, unsigned int, unsigned int, char const*, llvm::raw_ostream&) in libLLVMARMCodeGen.a(ARMAsmPrinter.cpp.o)
  "llvm::ARMInstPrinter::ARMInstPrinter(llvm::MCAsmInfo const&, llvm::MCInstrInfo const&, llvm::MCRegisterInfo const&)", referenced from:
      createARMMCInstPrinter(llvm::Triple const&, unsigned int, llvm::MCAsmInfo const&, llvm::MCInstrInfo const&, llvm::MCRegisterInfo const&) in libLLVMARMDesc.a(ARMMCTargetDesc.cpp.o)
  "llvm::MetadataTracking::track(void*, llvm::Metadata&, llvm::PointerUnion<llvm::MetadataAsValue*, llvm::Metadata*>)", referenced from:
      llvm::MetadataTracking::track(llvm::Metadata*&) in llvm_ext.o
  "llvm::X86ATTInstPrinter::getRegisterName(unsigned int)", referenced from:
      llvm::X86AsmPrinter::PrintAsmOperand(llvm::MachineInstr const*, unsigned int, unsigned int, char const*, llvm::raw_ostream&) in libLLVMX86CodeGen.a(X86AsmPrinter.cpp.o)
      printOperand(llvm::X86AsmPrinter&, llvm::MachineInstr const*, unsigned int, llvm::raw_ostream&, char const*, unsigned int) in libLLVMX86CodeGen.a(X86AsmPrinter.cpp.o)
      llvm::X86AsmPrinter::EmitInstruction(llvm::MachineInstr const*) in libLLVMX86CodeGen.a(X86MCInstLower.cpp.o)
      getShuffleComment(llvm::MachineInstr const*, unsigned int, unsigned int, llvm::ArrayRef<int>) in libLLVMX86CodeGen.a(X86MCInstLower.cpp.o)
  "llvm::AArch64InstPrinter::getRegisterName(unsigned int, unsigned int)", referenced from:
      (anonymous namespace)::AArch64AsmPrinter::PrintAsmOperand(llvm::MachineInstr const*, unsigned int, unsigned int, char const*, llvm::raw_ostream&) in libLLVMAArch64CodeGen.a(AArch64AsmPrinter.cpp.o)
      (anonymous namespace)::AArch64AsmPrinter::PrintAsmMemoryOperand(llvm::MachineInstr const*, unsigned int, unsigned int, char const*, llvm::raw_ostream&) in libLLVMAArch64CodeGen.a(AArch64AsmPrinter.cpp.o)
      (anonymous namespace)::AArch64AsmPrinter::printOperand(llvm::MachineInstr const*, unsigned int, llvm::raw_ostream&) in libLLVMAArch64CodeGen.a(AArch64AsmPrinter.cpp.o)
      (anonymous namespace)::AArch64AsmPrinter::printAsmMRegister(llvm::MachineOperand const&, char, llvm::raw_ostream&) in libLLVMAArch64CodeGen.a(AArch64AsmPrinter.cpp.o)
  "llvm::AArch64InstPrinter::AArch64InstPrinter(llvm::MCAsmInfo const&, llvm::MCInstrInfo const&, llvm::MCRegisterInfo const&)", referenced from:
      createAArch64MCInstPrinter(llvm::Triple const&, unsigned int, llvm::MCAsmInfo const&, llvm::MCInstrInfo const&, llvm::MCRegisterInfo const&) in libLLVMAArch64Desc.a(AArch64MCTargetDesc.cpp.o)
  "llvm::WriteBitcodeToFile(llvm::Module const&, llvm::raw_ostream&, bool, llvm::ModuleSummaryIndex const*, bool, std::__1::array<unsigned int, 5ul>*)", referenced from:
      _LLVMExtWriteBitcodeWithSummaryToFile in llvm_ext.o
  "llvm::X86IntelInstPrinter::getRegisterName(unsigned int)", referenced from:
      (anonymous namespace)::X86AsmParser::ParseOperand() in libLLVMX86AsmParser.a(X86AsmParser.cpp.o)
  "llvm::AArch64AppleInstPrinter::AArch64AppleInstPrinter(llvm::MCAsmInfo const&, llvm::MCInstrInfo const&, llvm::MCRegisterInfo const&)", referenced from:
      createAArch64MCInstPrinter(llvm::Triple const&, unsigned int, llvm::MCAsmInfo const&, llvm::MCInstrInfo const&, llvm::MCRegisterInfo const&) in libLLVMAArch64Desc.a(AArch64MCTargetDesc.cpp.o)
  "llvm::DebugLoc::get(unsigned int, unsigned int, llvm::MDNode const*, llvm::MDNode const*, bool)", referenced from:
      _LLVMExtSetCurrentDebugLocation in llvm_ext.o
  "llvm::DIBuilder::createFile(llvm::StringRef, llvm::StringRef, llvm::Optional<llvm::DIFile::ChecksumInfo<llvm::StringRef> >, llvm::Optional<llvm::StringRef>)", referenced from:
      _LLVMExtDIBuilderCreateFile in llvm_ext.o
      _LLVMExtDIBuilderCreateCompileUnit in llvm_ext.o
  "llvm::DIBuilder::createFunction(llvm::DIScope*, llvm::StringRef, llvm::StringRef, llvm::DIFile*, unsigned int, llvm::DISubroutineType*, unsigned int, llvm::DINode::DIFlags, llvm::DISubprogram::DISPFlags, llvm::MDTupleTypedArrayWrapper<llvm::DITemplateParameter>, llvm::DISubprogram*, llvm::MDTupleTypedArrayWrapper<llvm::DIType>)", referenced from:
      _LLVMExtDIBuilderCreateFunction in llvm_ext.o
  "llvm::DIBuilder::createBasicType(llvm::StringRef, unsigned long long, unsigned int, llvm::DINode::DIFlags)", referenced from:
      _LLVMExtDIBuilderCreateBasicType in llvm_ext.o
  "llvm::DIBuilder::createEnumerator(llvm::StringRef, long long, bool)", referenced from:
      _LLVMExtDIBuilderCreateEnumerator in llvm_ext.o
  "llvm::DIBuilder::createCompileUnit(unsigned int, llvm::DIFile*, llvm::StringRef, bool, llvm::StringRef, unsigned int, llvm::StringRef, llvm::DICompileUnit::DebugEmissionKind, unsigned long long, bool, bool, llvm::DICompileUnit::DebugNameTableKind, bool)", referenced from:
      _LLVMExtDIBuilderCreateCompileUnit in llvm_ext.o
  "llvm::DIBuilder::createEnumerationType(llvm::DIScope*, llvm::StringRef, llvm::DIFile*, unsigned int, unsigned long long, unsigned int, llvm::MDTupleTypedArrayWrapper<llvm::DINode>, llvm::DIType*, llvm::StringRef, bool)", referenced from:
      _LLVMExtDIBuilderCreateEnumerationType in llvm_ext.o
  "llvm::DIBuilder::DIBuilder(llvm::Module&, bool, llvm::DICompileUnit*)", referenced from:
      _LLVMExtNewDIBuilder in llvm_ext.o
  "llvm::CallBase::hasFnAttrOnCalledFunction(llvm::Attribute::AttrKind) const", referenced from:
      bool llvm::CallBase::hasFnAttrImpl<llvm::Attribute::AttrKind>(llvm::Attribute::AttrKind) const in llvm_ext.o
  "vtable for llvm::X86ATTInstPrinter", referenced from:
      createX86MCInstPrinter(llvm::Triple const&, unsigned int, llvm::MCAsmInfo const&, llvm::MCInstrInfo const&, llvm::MCRegisterInfo const&) in libLLVMX86Desc.a(X86MCTargetDesc.cpp.o)
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "vtable for llvm::X86IntelInstPrinter", referenced from:
      createX86MCInstPrinter(llvm::Triple const&, unsigned int, llvm::MCAsmInfo const&, llvm::MCInstrInfo const&, llvm::MCRegisterInfo const&) in libLLVMX86Desc.a(X86MCTargetDesc.cpp.o)
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: execution of command failed with code: 1: `cc "${@}" -o /Users/sergey/Projects/crystal/jhass_crystal/.build/crystal  -rdynamic -L/usr/local/Cellar/crystal/0.35.1/embedded/lib -L/usr/lib -L/usr/local/lib /Users/sergey/Projects/crystal/jhass_crystal/src/llvm/ext/llvm_ext.o `"/usr/local/Cellar/llvm/10.0.0_3/bin/llvm-config" --libs --system-libs --ldflags 2> /dev/null` -lstdc++ -lpcre -lgc -lpthread /Users/sergey/Projects/crystal/jhass_crystal/src/ext/libcrystal.a -levent -liconv -ldl`
make: *** [.build/crystal] Error 1

I was able to pull crystal binary from alpine and use it to compile crystal locally:

ubuntu@ubuntu:~/Projects/crystal/crystal$ make stats=1
Using /usr/bin/llvm-config-10 [version=10.0.0]
CRYSTAL_CONFIG_LIBRARY_PATH="" CRYSTAL_CONFIG_BUILD_COMMIT="476486e0a" SOURCE_DATE_EPOCH="1592944761" ./bin/crystal build --stats  -o .build/crystal src/compiler/crystal.cr -D without_openssl -D without_zlib
./bin/crystal: 149: crystal: not found
Using compiled compiler at .build/crystal
Parse:                             00:00:00.000226701 (   0.25MB)
Semantic (top level):              00:00:01.702617799 ( 106.87MB)
Semantic (new):                    00:00:00.009913659 ( 106.87MB)
Semantic (type declarations):      00:00:00.142739112 ( 114.87MB)
Semantic (abstract def check):     00:00:00.043294210 ( 122.87MB)
Semantic (ivars initializers):     00:00:17.909682988 ( 902.81MB)
Semantic (cvars initializers):     00:00:00.019848244 ( 902.81MB)
Semantic (main):                   00:00:44.014340761 (1018.81MB)
Semantic (cleanup):                00:00:00.429412450 (1018.81MB)
Semantic (recursive struct check): 00:00:00.005561497 (1018.81MB)
Codegen (crystal):                 00:00:26.066860772 (1146.81MB)
Codegen (bc+obj):                  00:01:05.366619723 (1146.81MB)
Codegen (linking):                 00:00:01.252345600 (1146.81MB)

Macro runs:
 - /home/ubuntu/Projects/crystal/crystal/src/ecr/process.cr: 00:00:35.263676765

Codegen (bc+obj):
 - no previous .o files were reused

Looks great so far!

That’s strange, not sure how you achieved that :P

1 Like

I just compiled it with your binary. :smiley:
Here is the version output to prove:

ubuntu@ubuntu:~/Projects/crystal/crystal$ .build/crystal -v
Crystal 1.0.0-dev [476486e0a] (2020-06-23)

LLVM: 10.0.0
Default target: aarch64-unknown-linux-gnu

This is debug version though. It fails to compile release version. I have no clue why.

When I tried to compile crystal with compiled crystal I’ve got this errors:

Using /usr/bin/llvm-config-10 [version=10.0.0]
g++ -c  -o src/llvm/ext/llvm_ext.o src/llvm/ext/llvm_ext.cc -I/usr/lib/llvm-10/include -std=c++14   -fno-exceptions -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
cc -fPIC    -c -o src/ext/sigfault.o src/ext/sigfault.c
ar -rcs src/ext/libcrystal.a src/ext/sigfault.o
CRYSTAL_CONFIG_LIBRARY_PATH="" CRYSTAL_CONFIG_BUILD_COMMIT="476486e0a" SOURCE_DATE_EPOCH="1592944761" ./bin/crystal build --stats --static  -o .build/crystal src/compiler/crystal.cr -D without_openssl -D without_zlib
./bin/crystal: 149: crystal: not found
Using compiled compiler at .build/crystal
Parse:                             00:00:00.000985708 (   0.25MB)
Semantic (top level):              00:00:06.140837930 ( 106.52MB)
Semantic (new):                    00:00:00.017234507 ( 106.52MB)
Semantic (type declarations):      00:00:00.534141551 ( 114.52MB)
Semantic (abstract def check):     00:00:00.159057541 ( 114.52MB)
Semantic (ivars initializers):     00:00:46.364741672 ( 870.46MB)
Semantic (cvars initializers):     00:00:00.063857394 ( 870.46MB)
Semantic (main):                   00:00:10.095377118 (1006.46MB)
Semantic (cleanup):                00:00:01.490965883 (1014.46MB)
Semantic (recursive struct check): 00:00:00.019939225 (1014.46MB)
Codegen (crystal):                 00:00:46.538646604 (1178.46MB)
Invalid memory access (signal 11) at address 0x0
[0xaaaada12adac] *Exception::CallStack::print_backtrace:Int32 +100
[0xaaaada116568] __crystal_sigfault_handler +320
[0xaaaadaf1d93c] sigfault_handler +40
[0xffffa350e5b0] ???
[0xffffa10c7c58] ???
Invalid memory access (signal 11) at address 0x0
[0xaaaada12adac] *Exception::CallStack::print_backtrace:Int32 +100
[0xaaaada116568] __crystal_sigfault_handler +320
[0xaaaadaf1d93c] sigfault_handler +40
[0xffffa350e5b0] ???
[0xffffa10c7c58] ???
Invalid memory access (signal 11) at address 0x0
[0xaaaada12adac] *Exception::CallStack::print_backtrace:Int32 +100
[0xaaaada116568] __crystal_sigfault_handler +320
[0xaaaadaf1d93c] sigfault_handler +40
[0xffffa350e5b0] ???
[0xffffa10c7c58] ???
Invalid memory access (signal 11) at address 0x0
[0xaaaada12adac] *Exception::CallStack::print_backtrace:Int32 +100
[0xaaaada116568] __crystal_sigfault_handler +320
[0xaaaadaf1d93c] sigfault_handler +40
[0xffffa350e5b0] ???
[0xffffa10c7c58] ???

It was built not from your PR branch though. I will compile it from your mranch and will give it a try.

Ok. When I took your unadulterated PR branch, it was not able to compile on RPI4.
I rebased it on top of current crystal master and then I was able to compile it without release mode.
Then I built release mode. Here are stats:

ubuntu@ubuntu:~/Projects/crystal/jhass_crystal$ make release=1 stats=1 threads=4
Using /usr/bin/llvm-config-10 [version=10.0.0]
g++ -c  -o src/llvm/ext/llvm_ext.o src/llvm/ext/llvm_ext.cc -I/usr/lib/llvm-10/include -std=c++14   -fno-exceptions -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
cc -fPIC    -c -o src/ext/sigfault.o src/ext/sigfault.c
ar -rcs src/ext/libcrystal.a src/ext/sigfault.o
CRYSTAL_CONFIG_LIBRARY_PATH="" CRYSTAL_CONFIG_BUILD_COMMIT="ac2f09b2f" SOURCE_DATE_EPOCH="1593053404" ./bin/crystal build --release --stats --threads 4  -o .build/crystal src/compiler/crystal.cr -D without_openssl -D without_zlib
./bin/crystal: 149: crystal: not found
Using compiled compiler at .build/crystal
Parse:                             00:00:00.000987400 (   0.25MB)
Semantic (top level):              00:00:06.156439840 ( 106.51MB)
Semantic (new):                    00:00:00.017225678 ( 106.51MB)
Semantic (type declarations):      00:00:00.541826466 ( 114.51MB)
Semantic (abstract def check):     00:00:00.161030743 ( 114.51MB)
Semantic (ivars initializers):
Semantic (ivars initializers):     00:00:46.641534106 ( 870.45MB)
Semantic (cvars initializers):     00:00:00.065024134 ( 870.45MB)
Semantic (main):                   00:00:10.503646576 (1006.45MB)
Semantic (cleanup):                00:00:01.534222038 (1014.45MB)
Semantic (recursive struct check): 00:00:00.019617808 (1014.45MB)
Codegen (crystal):                 00:00:35.935198876 (1170.45MB)
Codegen (bc+obj):                  00:28:09.142844564 (1170.45MB)
Codegen (linking):                 00:00:00.707672549 (1170.45MB)

Macro runs:
 - /home/ubuntu/Projects/crystal/jhass_crystal/src/ecr/process.cr: reused previous compilation (00:00:00.076088250)

Codegen (bc+obj):
 - no previous .o files were reused

Then I used this release mode to compile unoptimised build:

ubuntu@ubuntu:~/Projects/crystal/jhass_crystal$ make stats=1
Using /usr/bin/llvm-config-10 [version=10.0.0]
g++ -c  -o src/llvm/ext/llvm_ext.o src/llvm/ext/llvm_ext.cc -I/usr/lib/llvm-10/include -std=c++14   -fno-exceptions -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
cc -fPIC    -c -o src/ext/sigfault.o src/ext/sigfault.c
ar -rcs src/ext/libcrystal.a src/ext/sigfault.o
CRYSTAL_CONFIG_LIBRARY_PATH="" CRYSTAL_CONFIG_BUILD_COMMIT="ac2f09b2f" SOURCE_DATE_EPOCH="1593053404" ./bin/crystal build --stats  -o .build/crystal src/compiler/crystal.cr -D without_openssl -D without_zlib
./bin/crystal: 149: crystal: not found
Using compiled compiler at .build/crystal
Parse:                             00:00:00.000159276 (   0.25MB)
Semantic (top level):              00:00:01.591822734 ( 106.25MB)
Semantic (new):                    00:00:00.009546962 ( 106.25MB)
Semantic (type declarations):      00:00:00.135793270 ( 114.25MB)
Semantic (abstract def check):     00:00:00.041995078 ( 114.25MB)
Semantic (ivars initializers):     00:00:18.467985897 ( 870.18MB)
Semantic (cvars initializers):     00:00:00.019008092 ( 870.18MB)
Semantic (main):                   00:00:04.732183966 (1014.18MB)
Semantic (cleanup):                00:00:00.426420567 (1022.18MB)
Semantic (recursive struct check): 00:00:00.005346884 (1022.18MB)
Codegen (crystal):                 00:00:23.774189551 (1154.18MB)
Codegen (bc+obj):                  00:00:44.216395835 (1154.18MB)
Codegen (linking):                 00:00:01.266158452 (1154.18MB)

Macro runs:
 - /home/ubuntu/Projects/crystal/jhass_crystal/src/ecr/process.cr: reused previous compilation (00:00:00.035639202)

Codegen (bc+obj):
 - no previous .o files were reused

so it works like a charm. I will run tests now to see how it handles it.

By some reason it cannot find libz.a so it is not able to make static executable for tests. Compiler was built without static so it compiled properly. Here is the error:

ubuntu@ubuntu:~/Projects/crystal/jhass_crystal$ make spec
Using /usr/bin/llvm-config-10 [version=10.0.0]
CC="cc -fuse-ld=lld" CRYSTAL_CONFIG_LIBRARY_PATH="" CRYSTAL_CONFIG_BUILD_COMMIT="ac2f09b2f" SOURCE_DATE_EPOCH="1593053404" ./bin/crystal build  --exclude-warnings spec/std --exclude-warnings spec/compiler -o .build/all_spec spec/all_spec.cr
./bin/crystal: 149: crystal: not found
Using compiled compiler at .build/crystal
bin/crystal: 149: crystal: not found
Using compiled compiler at .build/crystal
GC Warning: Repeated allocation of very large block (appr. size 69632):
	May lead to memory leak and poor performance
ld.lld: error: unable to find library -lz (this usually means you need to install the development package for libz)
collect2: error: ld returned 1 exit status
Error: execution of command failed with code: 1: `cc -fuse-ld=lld "${@}" -o /home/ubuntu/Projects/crystal/jhass_crystal/.build/all_spec  -rdynamic -lgmp -lxml2 -lyaml -lz `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libssl || printf %s '-lssl -lcrypto'` `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libcrypto || printf %s '-lcrypto'` /home/ubuntu/Projects/crystal/jhass_crystal/src/llvm/ext/llvm_ext.o `"/usr/bin/llvm-config-10" --libs --system-libs --ldflags 2> /dev/null` -lstdc++ -lpcre -lm -lgc -lpthread /home/ubuntu/Projects/crystal/jhass_crystal/src/ext/libcrystal.a -levent -lrt -ldl`
make: *** [Makefile:110: .build/all_spec] Error 1

I do have it installed though:

ubuntu@ubuntu:~/Projects/crystal/jhass_crystal$ sudo apt search libz | grep installed

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

libarchive13/focal,now 3.4.0-2ubuntu1 arm64 [installed,automatic]
libz3-4/focal,now 4.8.7-4build1 arm64 [installed,automatic]
libz3-dev/focal,now 4.8.7-4build1 arm64 [installed,automatic]
libzstd1/focal,now 1.4.4+dfsg-3 arm64 [installed,automatic]```