Tumgik
xfencodes · 3 years
Text
The ARM GCC cross-compiler saga
I love macOS and ever since I switched to it in 2018, it has become my favourite platform of all time. However, the thing is that I develop software for embedded Linux devices pretty often too.
Since the devices themselves usually have a stripped down firmware as well as are generally underpowered, the best way to speed up the development process and to make it easier and more comfortable in general is to use a cross-compiler toolchain. On Linux, it’s pretty easy to build one yourself or use Linaro’s pre-compiled GCC binaries if your target uses an ARM processor. On macOS, however, the building process does have some caveats.
One of the things that make compiling a cross-toolchain on macOS targeting Linux is that macOS by default uses a case-insensitive file system, which makes building glibc for the target almost impossible. This can be easily worked around by creating a read-write DMG image containing a single Mac OS Extended (Journaled, Case-sensitive) or APFS (Case-sensitive) partition, mounting it and storing the sources and build directories there.
Compiling the Linux kernel from macOS doesn't really work that well. Usually, you can't get past the configuration step successfully - even the install_headers target fails miserably. A workaround for that would be getting existing kernel headers as a package for the target system and unpacking it manually. For example, if your target runs a distro compatible with RHEL/Fedora, then you can get a pre-built kernel-headers package matching the kernel version of your Linux device and unpacking it manually. This will require compiling RPM, though, or installing it through Homebrew (which is faster).
When it comes to anything else, the build process is mostly similar to the one described in many many available guides on the net. But here is a short guided command-line snippet that will get you going with an ARM64 GCC toolchain for Fedora Linux 33 (use this as a reference). Just changing the toolchain target string ($LINUXARMBRAND) to the one matching your target platform should probably be enough in most cases to get a working toolchain for it.
# set the prefix and the target string variables accordingly $ export LINUXARMTC=/usr/local/builds/gcc-cross-arm64-linux $ export LINUXARMBRAND=aarch64-redhat-linux-gnu # get binutils and gcc $ curl -o- http://mirrors.dotsrc.org/gnu/binutils/binutils-2.36.tar.xz | tar -xvJf - $ curl -o- http://mirrors.dotsrc.org/gnu/gcc/gcc-9.1.0/gcc-9.1.0.tar.xz | tar -xvJf - # build rpm as well as some of its dependencies # 1. build libmagic $ curl -o- http://deb.debian.org/debian/pool/main/f/file/file_5.39.orig.tar.gz | tar -xvzf - $ cd file-5.39 && sh configure --prefix=$LINUXARMTC --enable-static --disable-shared && make -j6 && make install $ cd .. # 2. build openssl $ curl -o- https://www.openssl.org/source/openssl-1.1.1i.tar.gz | tar -xvzf - $ cd openssl-1.1.1i && perl Configure no-hw no-shared no-zlib no-asm --prefix=$LINUXARMTC darwin64-x86_64-cc && make -j6 && make install $ cd .. # 3. build rpm itself $ curl -o- http://ftp.rpm.org/releases/rpm-4.16.x/rpm-4.16.0.tar.bz2 | tar -xvjf - $ cd rpm-4.16.0 && CFLAGS="-I$LINUXARMTC/include" LDFLAGS="-L$LINUXARMTC/lib" LIBS="-lbz2 -lz" sh configure --prefix=$LINUXARMTC --disable-shared --enable-static --with-crypto=openssl --without-archive --disable-plugins --without-lua --disable-openmp $ echo 'void main() {}' > rpmspec.c && make -j6 && make install # 4. build make $ curl -o- http://mirrors.dotsrc.org/gnu/make/make-4.3.tar.gz | tar -xvzf - $ cd make-4.3 && sh configure --prefix=$LINUXARMTC && make -j6 && make install $ cd .. # 5. build bison $ curl -o- http://mirrors.dotsrc.org/gnu/bison/bison-3.7.5.tar.xz | tar -xvJf - $ cd bison-3.7.5 && sh configure --disable-nls --prefix=$LINUXARMTC && make -j6 && make install # get fedora kernel headers $ mkdir rpmextract && cd rpmextract $ curl -o kernel.rpm http://mirrors.dotsrc.org/fedora/linux/updates/33/Everything/aarch64/Packages/k/kernel-headers-5.10.11-200.fc33.aarch64.rpm $ $LINUXARMTC/bin/rpm2cpio kernel.rpm | tar -xvf - # install them into a sysroot $ mkdir -p $LINUXARMTC/$LINUXARMBRAND $ mv -v include $LINUXARMTC/$LINUXARMBRAND $ cd ../.. # build binutils $ cd binutils-2.36 && mkdir build && cd build && sh ../configure --target=$LINUXARMBRAND --prefix=$LINUXARMTC --disable-multilib --disable-werror --disable-libquadmath --disable-libquadmath-support && make -j6 && make install $ cd ../.. # build gcc (stage 1) $ export PATH="$LINUXARMTC/bin:$PATH" $ cd gcc-9.1.0 && sh contrib/download_prerequisites --no-isl --no-graphite && mkdir build && cd build && sh ../configure --prefix=$LINUXARMTC --target=$LINUXARMBRAND --with-static-standard-libraries --disable-libquadmath --disable-libquadmath-support --enable-ld=yes --enable-languages=c,c++ $ make -j6 all-gcc $ make install-gcc # bootstrap glibc $ cd glibc-2.32 && mkdir build && cd build && BISON=$LINUXARMTC/bin/bison MAKE=$LINUXARMTC/bin/make ../configure --prefix=$LINUXARMTC/$LINUXARMBRAND --host=$LINUXARMBRAND --target=$LINUXARMBRAND --with-headers=$LINUXARMTC/$LINUXARMBRAND/include --disable-multilib --disable-werror $ make install-bootstrap-headers=yes install-headers $ make -j6 csu/subdir_lib $ install csu/crt1.o csu/crti.o csu/crtn.o $LINUXARMTC/$LINUXARMBRAND/lib $ $LINUXARMTC/bin/aarch64-redhat-linux-gnu-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $LINUXARMTC/$LINUXARMBRAND/lib/libc.so # build gcc (stage 2) $ cd ../../gcc-9.1.0/build && touch /usr/local/builds/fedora33-arm64-gcc/aarch64-redhat-linux-gnu/include/gnu/stubs.h && make -j6 all-target-libgcc && make install-target-libgcc # finish glibc $ cd ../../glibc-2.32/build && touch testrun.shT debugglibc.shT iconvdata/MIK.so iconvdata/ISO_11548-1.so iconvdata/ISO8859-9E.so iconvdata/CP77{0,1,2,3,4}.so iconvdata/KOI8-RU.so iconvdata/MAC-CENTRALEUROPE.so && make -j6 && make install # build gcc (stage 3) $ cd ../../gcc-9.1.0/build && make -j6 && make install
Hope this works for you
4 notes · View notes
xfencodes · 3 years
Text
Dear larger firm, I have foiled your efforts to irritate me by writing a script that converts your 9000-page PDF into a CSV that contains only the names and addresses I actually needed, also I filtered out your weird templating errors that put unnecessary symbols in the middle of the names
20 notes · View notes
xfencodes · 3 years
Text
2 notes · View notes