ARM (Command Line)
Crypto++ supports ARM platforms, including Linux, iOS, Windows Phone and Windows Store. Starting around 5.6.3, additional support was added for ARM, which included ARM NEON and ARMv8 CRC and Crypto extensions. BLAKE2 was the first class to receive the additional ARM support. Additional classes include GCM using NEON's 64x64 → 128-bit multiplier.
This wiki page is dedicated to performing native builds for IoT gadgets and selecting appropriate ARM options. IoT gadgets include BeagleBones, CubieTrucks, Banana Pis, HiKeys and other dev boards. In a native build, you will either (1) log into the device just like its a desktop computer, or (2) SSH into the device and then build the library just like its a desktop computer.
The ARM options presented below are suited for the device you are working on. They are not generic options like Android recommends because the options don't cater to a wide array of devices. Instead, the options are tuned for the host device, and they try to use its full capabilities, like all 32 vectorized registers from the FPU if its VFPv4 and NEON capable.
If you are build for Android or iOS, then there are separate pages for the platforms. The pages use the toolchains provided by AOSP and Apple. See Android (Command Line) and iOS (Command Line) for details. Also see ARM (Command Line), ARM Embedded (Command Line) and ARM Embedded (Bare Metal) if building with the arm-linux-gnueabi toolchain.
Here is a small list of CXXFLAGS tuned for the test devices used during Crypto++ testing. -mfloat is determined by the platform using CPU feature flags from /proc/cpuinfo, where the platform is the hardware/os/toolchain/applications combination. Modern platforms use hard floats because they are faster for procedural calls.
Wandboard Dual (ARMv7 with NEON):
-march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard
BeagleBone Black (ARMv7 with NEON and VFPv3):
-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard
CubieTruck 5 (ARMv7 with NEON and VFPv4):
-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard
Banana Pi (ARMv7 with NEON and VFPv4):
-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard
Raspberry Pi 3 (ARMv7 with NEON and VFPv4):
-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard
Raspberry Pi 3 (ARMv8/Aarch32, with CRC, without Crypto):
-march=armv8-a+crc -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard
ODROID C2 (ARMv8/Aarch64, with CRC, without Crypto):
PINE64 (ARMv8/Aarch64, with CRC and Crypto):
Applied Micro Mustang (ARMv8/Aarch64, without CRC and Crypto):
LeMaker HiKey (ARMv8/Aarch64, with CRC and Crypto):
Overdrive 1000 (ARMv8/Aarch64, with CRC and Crypto):
A native build does not use specialized CXXFLAGS on ARM. There's a few reasons the Makefile avoids selecting ARM options, but the short answer is: its not an easy problem because its the wild, wild west. Notice the build is missing some key options, like -march, -mcpu (or -mtune), -mfpu and -mfloat-abi.
git clone https://github.com/weidai11/cryptopp.git cd cryptopp make g++ -DNDEBUG -g2 -O2 -fPIC -c cryptlib.cpp g++ -DNDEBUG -g2 -O2 -fPIC -c cpu.cpp ...
What we really want is something like the following:
git clone https://github.com/weidai11/cryptopp.git cd cryptopp make g++ -DNDEBUG -g2 -O2 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -fPIC -c cryptlib.cpp g++ -DNDEBUG -g2 -O2 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -fPIC -c cpu.cpp ...
If you know the CXXFLAGS you need, then:
export CXXFLAGS="-DNDEBUG -g2 -O2 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard" make g++ -DNDEBUG -g2 -O2 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -fPIC -c cryptlib.cpp g++ -DNDEBUG -g2 -O2 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -fPIC -c cpu.cpp
The library's cryptest.sh attempts to set most of the ARM options to exercise the library under real world configurations. If you are in a jamb and want to get options that are mostly correct, then run cryptest.sh and observe the PLATFORM_CXXFLAGS it uses:
# Results from BeagleBone Black (ARMv7, 32-bit) $ ./cryptest.sh IS_LINUX: 1 IS_ARM32: 1 HAVE_ARMV7A: 1 HAVE_ARM_NEON: 1 HAVE_ARM_VFPV3: 1 ... PLATFORM_CXXFLAGS: -march=armv7-a -mfpu=neon -mfloat-abi=hard
# Results from Banana Pi (ARMv7, 32-bit) $ ./cryptest.sh IS_LINUX: 1 IS_ARM32: 1 HAVE_ARMV7A: 1 HAVE_ARM_NEON: 1 HAVE_ARM_VFPV3: 1 HAVE_ARM_VFPV4: 1 ... PLATFORM_CXXFLAGS: -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard
# Results from LeMaker HiKey (ARMv8, Aarch64) $ ./cryptest.sh IS_LINUX: 1 IS_ARM64: 1 HAVE_ARMV8A: 1 HAVE_ARM_CRC: 1 HAVE_ARM_CRYPTO: 1 ... PLATFORM_CXXFLAGS: -march=armv8-a+crc+crypto
Once you have your option set, add them to CXXFLAGS and then make as usual:
$ export CXXFLAGS="-DNDEBUG -g2 -O2 -march=armv7-a -mtune=cortex-a7 -mfpu=neon -mfloat-abi=hard" $ make g++ -DNDEBUG -g2 -O2 -march=armv7-a -mtune=cortex-a7 -mfpu=neon -mfloat-abi=hard -fPIC -pipe -c cryptlib.cpp g++ -DNDEBUG -g2 -O2 -march=armv7-a -mtune=cortex-a7 -mfpu=neon -mfloat-abi=hard -fPIC -pipe -c cpu.cpp ...
You should supply -march, -mcpu (or -mtune), -mfpu and -mfloat-abi when performing native ARM builds. There are two places you generally find the information you need. The first is /proc/cpuinfo and the second is the compiler. There's a third place, uname -m, and its usually good for determining Aarch32 (ARM32) and Aarch64 (ARM64).
/proc/cpuinfo provides most information on th CPU brand, architecture and feature flags. The problem with some of the fields is, they are not standard, so you may miss ARMv7a because a device uses suni8.
# Results from BeagleBone Black (Aarch32) $ cat /proc/cpuinfo processor : 0 model name : ARMv7 Processor rev 2 (v7l) BogoMIPS : 996.14 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x3 CPU part : 0xc08 CPU revision : 2 Hardware : Generic AM33XX (Flattened Device Tree) Revision : 0000 Serial : 0000000000000000
# Results from LeMaker HiKey (Aarch64) $ cat /proc/cpuinfo Processor : AArch64 Processor rev 3 (aarch64) processor : 0 processor : 1 processor : 2 processor : 3 processor : 4 processor : 5 processor : 6 processor : 7 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 CPU implementer : 0x41 CPU architecture: AArch64 CPU variant : 0x0 CPU part : 0xd03 CPU revision : 3 Hardware : HiKey Development Board
The compiler is useful for detecting the floating point ABI. If the target is armhf or gnueabihf, then you should use -mfloat-abi=hard. Otherwise, you should use -mfloat-abi=softfp.
ARM_HARD_FLOAT=$("$CXX" -v 2>&1 | "$GREP" 'Target' | "$EGREP" -i -c '(armhf|gnueabihf)') if [[ ("$ARM_HARD_FLOAT" -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-mfloat-abi=hard ") else PLATFORM_CXXFLAGS+=("-mfloat-abi=softfp ") fi
CPU and Tuning
To tune for a particular cpu, you need to determine the cpu hardware. You are looking for a string like Cortex-A9 or Cortext-A53. You can then specify it through -mcpu or -mtune.
As far as we know, there's no way to get the friendly name through commands. You need to know what the manufacturer puts on the board and use it for -mcpu or -mtune. Sometimes it s not easy to determine. For example, the HiKey may offer sun8i, which you need to know its an Allwinner SoC based on Cortex-A7 cores.
Once you determine the cpu, you can use it like -mtune=cortex-a7 or -mtune=cortex-a53.
You generally use ARMv7, ARMv7-a, ARMv8, ARMv8-a or ARMv8.1-a. You can usually detect it through uname and /proc/cpuinfo.
uname tells you if its ARMv7 (32-bit) or ARMv8 (64-bit). Both ARMv7 and ARMv8 need to be further refined with the cpu flags from /proc/cpuinfo.
/proc/cpuinfo tells you cpu and fpu features, like neon and crypto. Here's the logic from cryptest.sh that's used to determine PLATFORM_CXXFLAGS. Its awful, but you can se the options in the GCC manual at GCC ARM Options and GCC ARM64 Options.