Compiling for Synology DS509+

This article describes my infutile first attempt to compile a gcc 4 toolchain for my NAS DS 509+. Every step described works, but the endresult are binaries that do not run on my NAS. Never the less, this article may be worthwhile.
I purchased a NAS a Synology DiskStation 509+ to use as a Server. This NAS, as well as all others of the + series are based on a Freescale mpc8533 PowerPC with 64-Bit Memory Bus. The j series use the Freescale mpc8241 PowerPC with 32-Bit Memory Bus. Which are basically the same architecture (besides the Bus width). For the completeness sake is here a list of the products (up to 28.12.2009):
+-Series

  • DS109+
  • DS209+
  • DS209+II
  • DS409+
  • DS509+
  • RS409+
  • RS409RP+

j-Series

  • DS109j
  • DS209j

[Source: http://forum.synology.com/wiki/index.php/What_kind_of_CPU_does_my_NAS_have]
Now guess what: There is are no Java binaries out there that work. Therefore you have to compile your own. But surprise, the NAS has no compiler. (Well there is a guide for cross-compiling from Synology).

Getting a compiler

The first step is to enable the NAS to compile the sources on its own. For that I need a GCC compiler tool-chain on the NAS. The easiest way is probably to use the steps in the aforementioned document to cross-compile the compiler (we need binutils, gcc and glibc possible also the Linux headers). The problem with this is the need to manually tweak the configure script to comply to the target architecture.
Another path may be the use of sections of the Cross-Compiled Linux From Scratch, which is just a bit heavy weight since you don’t want to compile a whole system. Therefore this description must be tweaked also.
A third path may be the lightweight description found at http://www.pages.drexel.edu/~sg64/stuff/cross-compile.htm.
As usual I tried the easy way out but ended up following the Linux from Scratch way. Using an Ubuntu 32bit on a 64bit machine I had to install several packages to comply:

  • flex
  • texinfo
  • gawk
  • bison

On the NAS I created a tools directory that I mounted on my host under /media/tools. If you map your share to another directory or compile into a local directory be sure to replace ‚/media/tools‘ with the appropriate value.
I used the following steps after downloading the needed packages and extracting them. For further details please referre to the CLFS.

unset CFLAGS
unset CFLAGS
export CLFS_HOST="$(echo $MACHTYPE | \
    sed "s/$(echo $MACHTYPE | cut -d- -f2)/cross/")"
export CLFS_TARGET="powerpc64-unknown-linux-gnu"
export CLFS_TARGET32="powerpc-unknown-linux-gnu"
export BUILD32="-m32"
export BUILD64="-m64"
cd linux-2.6.24.7
install -dv ../tools/include
make mrproper

In scripts/unifdef.c I needed to replace all three instances of getline with lineread.

make ARCH=powerpc headers_check
make ARCH=powerpc INSTALL_HDR_PATH=dest headers_install
cp -rv dest/include/* ../tools/include
cd ..
mkdir cross-tools
cd file-4.23
./configure --prefix=/media/tools/cross-tools
make
make install
cd ..
cd binutils-2.18
patch -Np1 -i ../binutils-2.18-posix-1.patch
patch -Np1 -i ../binutils-2.18-branch_update-3.patch
patch -Np1 -i ../binutils-2.18-genscripts_multilib-1.patch
mkdir -v ../binutils-build
cd ../binutils-build
AR=ar AS=as ../binutils-2.18/configure --prefix=/media/tools/cross-tools --host=${CLFS_HOST} --target=${CLFS_TARGET} \
     --with-lib-path=/media/tools/tools/lib --disable-nls --enable-shared --enable-64-bit-bfd \
     --disable-info
make configure-host
export CFLAGS="-Wno-error -g -O2"
make
export CFLAGS=
make install
cp -v ../binutils-2.18/include/libiberty.h /media/tools/tools/include
cd ..
cd gcc-4.2.4
patch -Np1 -i ../gcc-4.2.4-specs-1.patch
patch -Np1 -i ../gcc-4.2.4-posix-1.patch
patch -Np1 -i ../gcc-4.2.4-cross_search_paths-1.patch
echo "
#undef STARTFILE_PREFIX_SPEC
#define STARTFILE_PREFIX_SPEC \"/media/tools/tools/lib/\"" >> gcc/config/rs6000/linux.h
echo "
#undef STARTFILE_PREFIX_SPEC
#define STARTFILE_PREFIX_SPEC \"/media/tools/tools/lib/\"" >> gcc/config/rs6000/linux64.h
cp -v gcc/Makefile.in{,.orig}
sed -e "s@\(^CROSS_SYSTEM_HEADER_DIR =\).*@\1 /media/tools/tools/include@g" \
    gcc/Makefile.in.orig > gcc/Makefile.in
mkdir -v ../gcc-build
cd ../gcc-build
../gcc-4.2.4/configure --prefix=/media/tools/cross-tools \
    --host=${CLFS_HOST} --target=${CLFS_TARGET} --with-local-prefix=/media/tools/tools --disable-nls --disable-shared \
    --disable-threads --enable-languages=c
make all-gcc
make install-gcc
cd ..
cd glibc-2.7
patch -Np1 -i ../glibc-2.7-branch_update-1A.patch
patch -Np1 -i ../glibc-2.7-libgcc_eh-1.patch
patch -Np1 -i ../glibc-2.7-localedef_segfault-1.patch
mkdir -v ../glibc-build
export PATH=$PATH:/media/tools/cross-tools/bin
cd ../glibc-build
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" >> config.cache
BUILD_CC="gcc" CC="${CLFS_TARGET}-gcc ${BUILD32}" \
    AR="${CLFS_TARGET}-ar" RANLIB="${CLFS_TARGET}-ranlib" \
    ../glibc-2.7/configure --prefix=/media/tools/tools \
    --host=${CLFS_TARGET32} --build=${CLFS_HOST} \
    --disable-profile --enable-add-ons \
    --with-tls --enable-kernel=2.6.0 --with-__thread \
    --with-binutils=/media/tools/cross-tools/bin --with-headers=/media/tools/tools/include \
    --cache-file=config.cache
make
make install
cd ..
cd glibc-2.7
patch -Np1 -i ../glibc-2.7-branch_update-1A.patch
patch -Np1 -i ../glibc-2.7-libgcc_eh-1.patch
patch -Np1 -i ../glibc-2.7-localedef_segfault-1.patch
mkdir -v ../glibc-build
cd ../glibc-build
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" >> config.cache
echo "slibdir=/media/tools/tools/lib64" >> configparms
BUILD_CC="gcc" CC="${CLFS_TARGET}-gcc ${BUILD64}" \
    AR="${CLFS_TARGET}-ar" RANLIB="${CLFS_TARGET}-ranlib" \
    ../glibc-2.7/configure --prefix=/media/tools/tools \
    --host=${CLFS_TARGET} --build=${CLFS_HOST} --libdir=/media/tools/tools/lib64 \
    --disable-profile --enable-add-ons \
    --with-tls --enable-kernel=2.6.0 --with-__thread \
    --with-binutils=/media/tools/cross-tools/bin --with-headers=/media/tools/tools/include \
    --cache-file=config.cache
make
make install
cd ..
cd gcc-4.2.4
patch -Np1 -i ../gcc-4.2.4-PR31490-1.patch
cp -v gcc/Makefile.in{,.orig}
sed -e "s@\(^CROSS_SYSTEM_HEADER_DIR =\).*@\1 /media/tools/tools/include@g" \
    gcc/Makefile.in.orig > gcc/Makefile.in
cp -v configure{,.orig}
sed -e  '/FLAGS_FOR_TARGET.*\/lib\//s@-B[^ ]*/lib/@@g' configure.orig > \
    configure
cd ../gcc-build
../gcc-4.2.4/configure --prefix=/media/tools/cross-tools \
    --target=${CLFS_TARGET} --host=${CLFS_HOST} \
    --with-local-prefix=/media/tools/tools --disable-nls --enable-shared \
    --enable-languages=c,c++ --enable-__cxa_atexit \
    --enable-c99 --enable-long-long --enable-threads=posix
make AS_FOR_TARGET="${CLFS_TARGET}-as" \
    LD_FOR_TARGET="${CLFS_TARGET}-ld"
make install

While configuring the glibc library I run into a snag that let me believe that I had to install autoconf for succesfull compilation. With autoconf installed the configuration would hang on „checking whether autoconf works“, which means that cd ../glibc-2.7 autoconf hangs. After removing autoconf from the system and fixing the original error (by installing gawk) everything was fine.
With that the cross compile tool chain is complete and this tool chain can now be set to use to compile the tools for the target system.

export CC="${CLFS_TARGET}-gcc"
export CXX="${CLFS_TARGET}-g++"
export AR="${CLFS_TARGET}-ar"
export AS="${CLFS_TARGET}-as"
export RANLIB="${CLFS_TARGET}-ranlib"
export LD="${CLFS_TARGET}-ld"
export STRIP="${CLFS_TARGET}-strip"
rm -Rdf binutils-build
mkdir binutils-build
cd binutils-build
CC="${CC} ${BUILD64}" \
    ../binutils-2.18/configure --prefix=/media/tools/tools \
    --libdir=/media/tools/tools/lib64 --with-lib-path=/media/tools/tools/lib \
    --build=${CLFS_HOST} --host=${CLFS_TARGET} --target=${CLFS_TARGET} \
    --disable-nls --enable-shared --enable-64-bit-bfd --disable-info
make configure-host
make
make install
cd ..

I had to replace the constant SSIZE_MAX in gcc-4.2.4/gcc/config/host-linux.c on line 207 with the constant LONG_MAX.

rm -Rdf gcc-build
cd gcc-4.2.4
cp -v gcc/cppdefault.c{,.orig}
sed -e '/#define STANDARD_INCLUDE_DIR/s@"/usr/include"@0@g' \
    gcc/cppdefault.c.orig > gcc/cppdefault.c
cp -v gcc/Makefile.in{,.orig}
sed -e 's@\(^NATIVE_SYSTEM_HEADER_DIR =\).*@\1 /media/tools/tools/include@g' \
    gcc/Makefile.in.orig > gcc/Makefile.in
cp -v gcc/Makefile.in{,.orig2}
sed -e "/MULTILIBS/s@\$(GCC_FOR_TARGET)@/media/tools/cross-tools/bin/${CC}@g" \
   gcc/Makefile.in.orig2 > gcc/Makefile.in
CC="${CC} ${BUILD64}" CXX="${CXX} ${BUILD64}" \
    ../gcc-4.2.4/configure --prefix=/media/tools/tools --libdir=/media/tools/tools/lib64 \
    --build=${CLFS_HOST} --host=${CLFS_TARGET} --target=${CLFS_TARGET} \
    --with-local-prefix=/media/tools/tools --enable-long-long --enable-c99 \
    --enable-shared --enable-threads=posix --enable-__cxa_atexit \
    --disable-nls --enable-languages=c,c++ --disable-libstdcxx-pch
make AS_FOR_TARGET="${AS}" \
    LD_FOR_TARGET="${LD}"
make install
cd ..

Now we are done with the compiling section. The next part is a bit tricky: We must integrate the compiled binaries into the running system. Because the ‚/media/tools‘ directory was a mapped directory on my NAS all binaries are already there (in a directory /volume1/cross_compile/tools). We have to ensure that the next action can be undone. There are two sets of possibilities:

  1. The binary does not already exist: Therefore it should be possible to remove the binary
  2. A binary with the same name (possibly another version) exists: The original must be backed up so that it can be restored.

For the purpose of the backup I created a directory under /root named backup_sys_gcc and a script rollback that can either remove the new version or replace it from the backup directory. As I walked through the directories only some libraries in lib were also in /lib. I figured to leave the original and delay any potential problems that may arise when they occur.

Schreibe einen Kommentar