Skip to content

Instantly share code, notes, and snippets.

@FiloSottile
Created September 5, 2012 22:12
Show Gist options
  • Save FiloSottile/3646033 to your computer and use it in GitHub Desktop.
Save FiloSottile/3646033 to your computer and use it in GitHub Desktop.
Building the Armory Bitcoin client for the Raspberry Pi

Armory on the RPi

Building the Armory Bitcoin client for the Raspberry Pi

This is how I got Armory (etotheipi/BitcoinArmory; http://bitcoinarmory.com/) cross-compiled for the Raspberry Pi.

This is a great way to keep an air-gapped offline wallet for only $30 dollars for the RPi (that you can also use for other things; experiment, it's awesome) and $7 for a Class 10 4GB SD card, really easy to keep in a safe and secret place.

Dependencies

On my Ubuntu box, I had to apt-get install these packages. Your mileage may vary.

bison flex texinfo libtool automake libncurses5-dev gperf python-pyopencl git-core build-essential pyqt4-dev-tools swig libqtcore4 libqt4-dev python-qt4 python-dev python-twisted

The cross-compiling toolbox

Chris Boot has an awesome post on how to setup a cross-compiler for the RPi, follow it:

http://www.bootc.net/archives/2012/05/26/how-to-build-a-cross-compiler-for-your-raspberry-pi/

But note that during the menuconfig you have to go into C-compilerAdditional supported languages and enable C++.

If you want, you can skip steps 2 to 14 (the whole menuconfig) of the second block by placing the .config file attached to this gist into the folder where you run ct-ng.

BUILD IT!

Now that you have your arm-unknown-linux-gnueabi-g++ working in your $PATH, clone the Armory repo

git clone git://github.com/etotheipi/BitcoinArmory.git
cd BitcoinArmory

Apply the attached patch to the two Makefiles (a smarter patch might be merged in the repo in the future)

patch -p1 < CXX.patch

And MAKE

CXX=arm-unknown-linux-gnueabi-g++ make

Finally, create a tarball to move to your shiny Raspberry

mkdir -p BitcoinArmoryRPi/img/
cp *.py *.so README LICENSE BitcoinArmoryRPi/
cp img/* BitcoinArmoryRPi/img/
tar cvfz BitcoinArmoryRPi.tar.gz BitcoinArmoryRPi

That's all folks!

Tip jar: 18p7pUqqxPYtDaK3GytdVxdSKZzs25SihS (If you feel to tip me, don't forget to tip also etotheipi, the creator of this awesome client: 1ArmoryXcfq7TnCSuZa9fQjRYwJ4bkRKfv)

http://www.pytux.it https://github.com/FiloSottile

CT_CONFIGURE_has_xz=y
CT_CONFIGURE_has_cvs=y
CT_CONFIGURE_has_svn=y
CT_MODULES=y
CT_EXPERIMENTAL=y
CT_LOCAL_TARBALLS_DIR=""
CT_WORK_DIR="${CT_TOP_DIR}/.build"
CT_PREFIX_DIR="/opt/cross/x-tools/${CT_TARGET}"
CT_INSTALL_DIR="${CT_PREFIX_DIR}"
CT_RM_RF_PREFIX_DIR=y
CT_REMOVE_DOCS=y
CT_INSTALL_DIR_RO=y
CT_STRIP_ALL_TOOLCHAIN_EXECUTABLES=y
CT_CONNECT_TIMEOUT=10
CT_OVERIDE_CONFIG_GUESS_SUB=y
CT_PATCH_BUNDLED=y
CT_PATCH_ORDER="bundled"
CT_PARALLEL_JOBS=0
CT_LOAD=0
CT_USE_PIPES=y
CT_EXTRA_FLAGS_FOR_HOST=""
CT_CONFIG_SHELL_BASH=y
CT_CONFIG_SHELL="${bash}"
CT_LOG_INFO=y
CT_LOG_LEVEL_MAX="INFO"
CT_LOG_PROGRESS_BAR=y
CT_LOG_TO_FILE=y
CT_LOG_FILE_COMPRESS=y
CT_ARCH="arm"
CT_ARCH_SUPPORTS_BOTH_MMU=y
CT_ARCH_SUPPORTS_BOTH_ENDIAN=y
CT_ARCH_SUPPORTS_32=y
CT_ARCH_SUPPORTS_WITH_ARCH=y
CT_ARCH_SUPPORTS_WITH_CPU=y
CT_ARCH_SUPPORTS_WITH_TUNE=y
CT_ARCH_SUPPORTS_WITH_FLOAT=y
CT_ARCH_SUPPORTS_WITH_FPU=y
CT_ARCH_SUPPORTS_SOFTFP=y
CT_ARCH_DEFAULT_HAS_MMU=y
CT_ARCH_DEFAULT_LE=y
CT_ARCH_DEFAULT_32=y
CT_ARCH_ARCH=""
CT_ARCH_CPU=""
CT_ARCH_TUNE=""
CT_ARCH_FPU=""
CT_ARCH_LE=y
CT_ARCH_32=y
CT_ARCH_BITNESS=32
CT_ARCH_FLOAT_HW=y
CT_TARGET_CFLAGS=""
CT_TARGET_LDFLAGS=""
CT_ARCH_arm=y
CT_ARCH_alpha_AVAILABLE=y
CT_ARCH_arm_AVAILABLE=y
CT_ARCH_avr32_AVAILABLE=y
CT_ARCH_blackfin_AVAILABLE=y
CT_ARCH_m68k_AVAILABLE=y
CT_ARCH_mips_AVAILABLE=y
CT_ARCH_powerpc_AVAILABLE=y
CT_ARCH_s390_AVAILABLE=y
CT_ARCH_sh_AVAILABLE=y
CT_ARCH_sparc_AVAILABLE=y
CT_ARCH_x86_AVAILABLE=y
CT_ARCH_USE_MMU=y
CT_ARCH_ENDIAN="little"
CT_ARCH_FLOAT="hard"
CT_ARCH_ARM_MODE="arm"
CT_ARCH_ARM_MODE_ARM=y
CT_ARCH_ARM_EABI=y
CT_FORCE_SYSROOT=y
CT_USE_SYSROOT=y
CT_SYSROOT_NAME="sysroot"
CT_SYSROOT_DIR_PREFIX=""
CT_WANTS_STATIC_LINK=y
CT_TOOLCHAIN_PKGVERSION=""
CT_TOOLCHAIN_BUGURL=""
CT_TARGET_VENDOR="unknown"
CT_TARGET_ALIAS_SED_EXPR=""
CT_TARGET_ALIAS=""
CT_CROSS=y
CT_TOOLCHAIN_TYPE="cross"
CT_BUILD=""
CT_BUILD_PREFIX=""
CT_BUILD_SUFFIX=""
CT_KERNEL_SUPPORTS_SHARED_LIBS=y
CT_KERNEL="linux"
CT_KERNEL_VERSION="3.5"
CT_KERNEL_linux=y
CT_KERNEL_bare_metal_AVAILABLE=y
CT_KERNEL_linux_AVAILABLE=y
CT_KERNEL_V_3_5=y
CT_KERNEL_mingw32_AVAILABLE=y
CT_SHARED_LIBS=y
CT_KERNEL_LINUX_VERBOSITY_0=y
CT_KERNEL_LINUX_VERBOSE_LEVEL=0
CT_KERNEL_LINUX_INSTALL_CHECK=y
CT_ARCH_BINFMT_ELF=y
CT_BINUTILS_V_2_21_1a=y
CT_BINUTILS_VERSION="2.21.1a"
CT_BINUTILS_2_21_or_later=y
CT_BINUTILS_2_20_or_later=y
CT_BINUTILS_2_19_or_later=y
CT_BINUTILS_2_18_or_later=y
CT_BINUTILS_HAS_HASH_STYLE=y
CT_BINUTILS_HAS_GOLD=y
CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
CT_BINUTILS_HAS_PLUGINS=y
CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
CT_BINUTILS_FORCE_LD_BFD=y
CT_BINUTILS_LINKER_LD=y
CT_BINUTILS_LINKERS_LIST="ld"
CT_BINUTILS_LINKER_DEFAULT="bfd"
CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
CT_CC="gcc"
CT_CC_VERSION="linaro-4.6-2012.07"
CT_CC_gcc=y
CT_CC_GCC_SHOW_LINARO=y
CT_CC_V_linaro_4_6_2012_07=y
CT_CC_GCC_4_2_or_later=y
CT_CC_GCC_4_3_or_later=y
CT_CC_GCC_4_4_or_later=y
CT_CC_GCC_4_5_or_later=y
CT_CC_GCC_4_6=y
CT_CC_GCC_4_6_or_later=y
CT_CC_GCC_HAS_GRAPHITE=y
CT_CC_GCC_HAS_LTO=y
CT_CC_GCC_HAS_PKGVERSION_BUGURL=y
CT_CC_GCC_HAS_BUILD_ID=y
CT_CC_GCC_USE_GMP_MPFR=y
CT_CC_GCC_USE_PPL_CLOOG=y
CT_CC_GCC_USE_MPC=y
CT_CC_GCC_HAS_LIBQUADMATH=y
CT_CC_SUPPORT_CXX=y
CT_CC_SUPPORT_FORTRAN=y
CT_CC_SUPPORT_JAVA=y
CT_CC_SUPPORT_ADA=y
CT_CC_SUPPORT_OBJC=y
CT_CC_SUPPORT_OBJCXX=y
CT_CC_LANG_CXX=y
CT_CC_LANG_OTHERS=""
CT_CC_ENABLE_CXX_FLAGS=""
CT_CC_CORE_EXTRA_CONFIG_ARRAY=""
CT_CC_EXTRA_CONFIG_ARRAY=""
CT_CC_STATIC_LIBSTDCXX=y
CT_CC_GCC_USE_GRAPHITE=y
CT_CC_GCC_USE_LTO=y
CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
CT_CC_CXA_ATEXIT=y
CT_CC_GCC_SJLJ_EXCEPTIONS=m
CT_CC_GCC_LDBL_128=m
CT_LIBC="eglibc"
CT_LIBC_VERSION="2_16"
CT_LIBC_eglibc=y
CT_LIBC_eglibc_AVAILABLE=y
CT_LIBC_EGLIBC_V_2_16=y
CT_LIBC_EGLIBC_2_16_or_later=y
CT_LIBC_EGLIBC_2_15_or_later=y
CT_LIBC_EGLIBC_2_14_or_later=y
CT_LIBC_EGLIBC_2_13_or_later=y
CT_LIBC_EGLIBC_2_12_or_later=y
CT_LIBC_EGLIBC_2_11_or_later=y
CT_LIBC_EGLIBC_2_10_or_later=y
CT_LIBC_EGLIBC_2_9_or_later=y
CT_LIBC_EGLIBC_HAS_PKGVERSION_BUGURL=y
CT_EGLIBC_REVISION="HEAD"
CT_LIBC_glibc_AVAILABLE=y
CT_LIBC_mingw_AVAILABLE=y
CT_LIBC_newlib_AVAILABLE=y
CT_LIBC_none_AVAILABLE=y
CT_LIBC_uClibc_AVAILABLE=y
CT_LIBC_SUPPORT_THREADS_ANY=y
CT_LIBC_SUPPORT_NPTL=y
CT_LIBC_SUPPORT_LINUXTHREADS=y
CT_THREADS="nptl"
CT_THREADS_NPTL=y
CT_LIBC_XLDD=y
CT_LIBC_GLIBC_MAY_FORCE_PORTS=y
CT_LIBC_glibc_familly=y
CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY=""
CT_LIBC_GLIBC_CONFIGPARMS=""
CT_LIBC_GLIBC_EXTRA_CFLAGS=""
CT_LIBC_EXTRA_CC_ARGS=""
CT_LIBC_OLDEST_ABI=""
CT_LIBC_GLIBC_FORCE_UNWIND=y
CT_LIBC_GLIBC_USE_PORTS=y
CT_LIBC_ADDONS_LIST=""
CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y
CT_LIBC_GLIBC_MIN_KERNEL="3.5"
CT_COMPLIBS_NEEDED=y
CT_GMP_NEEDED=y
CT_MPFR_NEEDED=y
CT_PPL_NEEDED=y
CT_CLOOG_NEEDED=y
CT_MPC_NEEDED=y
CT_COMPLIBS=y
CT_GMP=y
CT_MPFR=y
CT_PPL=y
CT_CLOOG=y
CT_MPC=y
CT_GMP_V_5_0_2=y
CT_GMP_VERSION="5.0.2"
CT_MPFR_V_3_1_0=y
CT_MPFR_VERSION="3.1.0"
CT_PPL_V_0_11_2=y
CT_PPL_VERSION="0.11.2"
CT_PPL_0_11=y
CT_PPL_NEEDS_LIBPWL=y
CT_CLOOG_V_0_15_11=y
CT_CLOOG_VERSION="0.15.11"
CT_CLOOG_0_15_1x=y
CT_CLOOG_NEEDS_AUTORECONF=y
CT_MPC_V_0_9=y
CT_MPC_VERSION="0.9"
diff --git a/cppForSwig/Makefile b/cppForSwig/Makefile
index d5b4340..2453ffc 100755
--- a/cppForSwig/Makefile
+++ b/cppForSwig/Makefile
@@ -1,9 +1,9 @@
-COMPILER = g++
+COMPILER = $(CXX)
#COMPILER_OPTS = -c -g -Wall -fPIC -D_DEBUG
COMPILER_OPTS = -c -O2 -pipe -fPIC
#**************************************************************************
-LINKER = g++
+LINKER = $(CXX)
OBJS = UniversalTimer.o BinaryData.o FileDataPtr.o BtcUtils.o BlockObj.o BlockUtils.o EncryptionUtils.o libcryptopp.a
@@ -22,7 +22,7 @@ all :
make BlockUtilsTest.out
swig : $(OBJS) CppBlockUtils_wrap.o
- g++ -shared $(LIBRARY_OPTS) $(OBJS) $(STATICPYTHON) CppBlockUtils_wrap.o -o ../_CppBlockUtils.so
+ $(CXX) -shared $(LIBRARY_OPTS) $(OBJS) $(STATICPYTHON) CppBlockUtils_wrap.o -o ../_CppBlockUtils.so
pyrcc4 -o ../qrc_img_resources.py ../imgList.xml
BlockUtilsTest.out : $(OBJS) BlockUtilsTest.cpp
diff --git a/cppForSwig/cryptopp/Makefile b/cppForSwig/cryptopp/Makefile
index 581d1aa..c75bdaf 100755
--- a/cppForSwig/cryptopp/Makefile
+++ b/cppForSwig/cryptopp/Makefile
@@ -38,7 +38,7 @@ ifeq ($(UNAME),Darwin)
CXXFLAGS += -arch x86_64 -arch i386
else
#CXXFLAGS += -march=native
-CXXFLAGS += -mtune=generic
+#CXXFLAGS += -mtune=generic
endif
endif
swig -c++ -python -classic -outdir ../ -v CppBlockUtils.i
Language subdirectory: python
Search paths:
./
./swig_lib/python/
/usr/share/swig2.0/python/
./swig_lib/
/usr/share/swig2.0/
Preprocessing...
Starting language-specific parse...
EncryptionUtils.h:178: Warning 362: operator= ignored
Processing types...
EncryptionUtils.h:133: Warning 402: Base class 'BinaryData' is incomplete.
BtcUtils.h:63: Warning 402: Only forward declaration 'BinaryData' was found.
C++ analysis...
Generating wrappers...
BlockUtils.h:326: Warning 472: Overloaded method AddressBookEntry::AddressBookEntry(BinaryData) with no explicit typecheck typemap for arg 0 of type 'BinaryData'
BlockUtils.h:378: Warning 472: Overloaded method BtcAddress::BtcAddress(BinaryData) with no explicit typecheck typemap for arg 0 of type 'BinaryData'
BlockUtils.h:378: Warning 472: Overloaded method BtcAddress::BtcAddress(BinaryData) with no explicit typecheck typemap for arg 0 of type 'BinaryData'
BlockUtils.h:378: Warning 472: Overloaded method BtcAddress::BtcAddress(BinaryData) with no explicit typecheck typemap for arg 0 of type 'BinaryData'
BlockUtils.h:378: Warning 472: Overloaded method BtcAddress::BtcAddress(BinaryData) with no explicit typecheck typemap for arg 0 of type 'BinaryData'
BlockUtils.h:378: Warning 472: Overloaded method BtcAddress::BtcAddress(BinaryData) with no explicit typecheck typemap for arg 0 of type 'BinaryData'
BlockUtils.h:414: Warning 509: Overloaded method BtcAddress::addTxIO(TxIOPair &) effectively ignored,
BlockUtils.h:413: Warning 509: as it is shadowed by BtcAddress::addTxIO(TxIOPair *).
BlockUtils.h:413: Warning 509: Overloaded method BtcAddress::addTxIO(TxIOPair *,bool) effectively ignored,
BlockUtils.h:414: Warning 509: as it is shadowed by BtcAddress::addTxIO(TxIOPair &,bool).
BlockUtils.h:459: Warning 472: Overloaded method BtcWallet::addAddress(BinaryData) with no explicit typecheck typemap for arg 1 of type 'BinaryData'
BlockUtils.h:459: Warning 472: Overloaded method BtcWallet::addAddress(BinaryData) with no explicit typecheck typemap for arg 1 of type 'BinaryData'
BlockUtils.h:459: Warning 472: Overloaded method BtcWallet::addAddress(BinaryData) with no explicit typecheck typemap for arg 1 of type 'BinaryData'
BlockUtils.h:459: Warning 472: Overloaded method BtcWallet::addAddress(BinaryData) with no explicit typecheck typemap for arg 1 of type 'BinaryData'
BlockUtils.h:459: Warning 472: Overloaded method BtcWallet::addAddress(BinaryData) with no explicit typecheck typemap for arg 1 of type 'BinaryData'
BtcUtils.h:956: Warning 472: Overloaded method BtcUtils::verifyProofOfWork(BinaryDataRef,BinaryDataRef) with no explicit typecheck typemap for arg 0 of type 'BinaryData'
@vhaasteren
Copy link

Thanks for the great tutorial. Is there any specific version of Armory you did this for? With the latest one of the git repo (2013-01-15), I got stuck at the following. Any ideas? Cheers,

Rutger

[ rvhaas stark ~/raspberrypi/armory-crosscompile/BitcoinArmory ] CXX=arm-unknown-linux-gnueabi-g++ make

cd cppForSwig; make swig
make[1]: Entering directory /home/rvhaas/virtualisation/raspberrypi/armory-crosscompile/BitcoinArmory/cppForSwig' arm-unknown-linux-gnueabi-g++ -I"/usr/include/pythonpython -c 'import sys; print str(sys.version_info[0]) + "." + str(sys.version_info[1])'" -c -O2 -pipe -fPIC -Icryptopp -DUSE_CRYPTOPP -D__STDC_LIMIT_MACROS -lpthread CppBlockUtils_wrap.cxx In file included from /usr/include/python2.7/Python.h:58:0, from CppBlockUtils_wrap.cxx:151: /usr/include/python2.7/pyport.h:849:2: error: #error "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)." make[1]: *** [CppBlockUtils_wrap.o] Error 1 make[1]: Leaving directory/home/rvhaas/virtualisation/raspberrypi/armory-crosscompile/BitcoinArmory/cppForSwig'
make: *** [all] Error 2

@miguelp95
Copy link

I get all the way to the step where I need to apply the CXX.patch file, then I get this error. I'm using the latest version as of 2013-03-11. Can you help me out, please?

miguel@STORMTROOPER-ubuntu:~/crosstool/armory/BitcoinArmory$ patch -p1 < CXX.patch
patching file cppForSwig/Makefile
Hunk #2 FAILED at 22.
1 out of 2 hunks FAILED -- saving rejects to file cppForSwig/Makefile.rej
patching file cppForSwig/cryptopp/Makefile
patch unexpectedly ends in middle of line

@mr-e-
Copy link

mr-e- commented Jul 27, 2013

I am on the last step of setting up my crossbuild, "ct-ng build" but I am receiving the error:

[ERROR] Build failed in step ''
[ERROR] Error happened in '/opt/cross/lib/ct-ng-1.9.3/scripts/functions' in function 'CT_DoExecLog' (line unknown, sorry)
[ERROR] called from '/opt/cross/lib/ct-ng-1.9.3/scripts/crosstool-NG.sh' at line # 248 in function 'main'
[ERROR] Look at '' for more info on this error.
[ERROR](elapsed: 0:00.37)
[00:01] / make: *** [build] Error 1

Any idea what could be causing this?

@orweinberger
Copy link

@R3AP3R @WalrusCode @vhaasteren I've compiled Bitcoin Armory 0.88 for Raspbian and made it available for download on http://coldpi.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment