HLFS uClibc Built via CLFS Methods

The following are adapted instructions to build HLFS uClibc according to the Cross-LFS build method. This should result in a more robust toolchain and avoid possible breakage because we are building a fully cross-compiled temp system. These methods should also work regardless of whether the host is gnu or uclibc.

I have left out most descriptions as they are covered in the CLFS/HLFS books. I have also left out non-essential commands (ie, 'passwd hlfs' and 'echo $HLFS') for the sake of fluidity. Also, like the LFS book, these instructions assume you unpack the source archive and cd into its directory before running the related commands. No directories are kept for a later time and can be removed as soon as you install the package.

Necessary Patches

In addition to what the HLFS book mentions, you'll want to download the following patches (The gcc-3.4.4 patches will apply just fine to gcc-3.4.5):

binutils-2.16.1-posix-1.patch
gcc-3.4.4-posix-1.patch
gcc-3.4.4-cross_search_paths-1.patch

About $HLFS

export HLFS=/mnt/hlfs

Creating the $HLFS/tools Directory

mkdir $HLFS/tools
ln -s $HLFS/tools /
mkdir $HLFS/sources
chmod a+wt $HLFS/sources

Creating the $HLFS/cross-tools Directory

install -dv $HLFS/cross-tools
ln -sv $HLFS/cross-tools /

Adding the HLFS User

groupadd hlfs
useradd -s /bin/bash -g hlfs -m -k /dev/null hlfs
chown hlfs $HLFS/tools
chown hlfs $HLFS/cross-tools
chown hlfs $HLFS/sources
su - hlfs

Setting Up the Environment

cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF
cat > ~/.bashrc << "EOF"
set +h
umask 022
HLFS=/mnt/hlfs
LC_ALL=POSIX
PATH=/cross-tools/bin:/bin:/usr/bin
ldso=/tools/lib/ld-uClibc.so.0
export HLFS LC_ALL PATH ldso
EOF
source ~/.bash_profile

Build CFLAGS

unset CFLAGS
unset CXXFLAGS
echo unset CFLAGS >> ~/.bashrc
echo unset CXXFLAGS >> ~/.bashrc

Build Variables

export HLFS_HOST="`echo ${MACHTYPE} | sed 's/-pc-/-cross-/g'`"
export HLFS_TARGET="`echo ${MACHTYPE} | sed 's/-gnu/-uclibc/g'`"
echo export HLFS_HOST=\""${HLFS_HOST}\"" >> ~/.bashrc
echo export HLFS_TARGET=\""${HLFS_TARGET}\"" >> ~/.bashrc

Linux-Libc-Headers-2.6.12.0

patch --no-backup-if-mismatch -Np1 -i \
    ../linux-libc-headers-2.6.12.0-pseudo_random-1.patch
install -d /tools/include
cp -R include/asm-i386 /tools/include/asm
cp -R include/linux /tools/include

uClibc-0.9.28 Headers

patch -Np1 -i ../uClibc-0.9.28-config-2.patch
make KERNEL_SOURCE=/tools headers
rm include/{asm,asm-generic,linux}
make DEVEL_PREFIX=/tools/ install_dev

Cross Binutils-2.16.1

patch -Np1 -i ../binutils-2.16.1-uClibc_conf-1.patch
patch -Np1 -i ../binutils-2.16.1-posix-1.patch
mkdir ../binutils-build
cd ../binutils-build
../binutils-2.16.1/configure --prefix=/cross-tools \
   --host=${HLFS_HOST} --target=${HLFS_TARGET} --with-lib-path=/tools/lib \
   --disable-nls --enable-shared --disable-multilib
make configure-host
make
make install
cp -v ../binutils-2.16.1/include/libiberty.h /tools/include

Cross GCC-3.4.5 Static

patch -Np1 -i ../gcc-3.4.5-uClibc_conf-1.patch
patch -Np1 -i ../gcc-3.4.5-specs_x86-1.patch
patch -Np1 -i ../gcc-3.4.4-posix-1.patch
patch -Np1 -i ../gcc-3.4.4-cross_search_paths-1.patch
echo "
#undef STARTFILE_PREFIX_SPEC
#define STARTFILE_PREFIX_SPEC \"/tools/lib/\"" >> gcc/config/linux.h
cp gcc/Makefile.in{,.orig}
sed -e "s@\(^CROSS_SYSTEM_HEADER_DIR =\).*@\1 /tools/include@g" \
 gcc/Makefile.in.orig > gcc/Makefile.in
touch ${ldso}
mkdir ../gcc-build
cd ../gcc-build
../gcc-3.4.5/configure --prefix=/cross-tools \
    --host=${HLFS_HOST} --target=${HLFS_TARGET} --disable-multilib \
    --with-local-prefix=/tools --disable-nls --disable-shared \
    --disable-threads --enable-languages=c \
    --with-dynamic-linker=${ldso} --with-nostdinc
make all-gcc
make install-gcc

uClibc-0.9.28

patch -Np1 -i ../uClibc-0.9.28-arc4random-2.patch
patch -Np1 -i ../uClibc-0.9.28-config-2.patch
patch -Np1 -i ../uClibc-0.9.28-libc_stack_end-1.patch
install -m444 ../uClibc-locale-030818.tgz extra/locale/
cp Rules.mak{,.orig}
sed -e '/mpreferred-stack-boundary/d' \
    -e '/falign-jumps/d' Rules.mak.orig \
    -e 's/-Os,//' Rules.mak.orig > Rules.mak
cp .config{,.orig}
sed -e 's@.*SHARED_LIB_LOADER_P.*@SHARED_LIB_LOADER_PREFIX="/tools/lib"@g' \
    -e 's@.*RUNTIME_PREFIX.*@RUNTIME_PREFIX="/tools"@g' \
    -e 's@.*DEVEL_PREFIX.*@DEVEL_PREFIX="/tools/"@g' \
    -e 's@.*KERNEL_SOURCE.*@KERNEL_SOURCE="/tools"@g' .config.orig > .config
make CROSS=${HLFS_TARGET}- all
rm include/{asm,asm-generic,linux}
make install

Cross GCC 3.4.5 Final

patch -Np1 -i ../gcc-3.4.5-uClibc_conf-1.patch
patch -Np1 -i ../gcc-3.4.5-specs_x86-1.patch
patch -Np1 -i ../gcc-3.4.4-posix-1.patch
patch -Np1 -i ../gcc-3.4.4-cross_search_paths-1.patch
patch -Np1 -i ../gcc-3.4.5-uClibc_libstdc++-1.patch
patch -Np1 -i ../gcc-3.4.5-uClibc_locale-1.patch
echo "
#undef STARTFILE_PREFIX_SPEC
#define STARTFILE_PREFIX_SPEC \"/tools/lib/\"" >> gcc/config/linux.h
cp gcc/Makefile.in{,.orig}
sed -e "s@\(^CROSS_SYSTEM_HEADER_DIR =\).*@\1 /tools/include@g" \
 gcc/Makefile.in.orig > gcc/Makefile.in
cp configure{,.orig}
sed -e  '/FLAGS_FOR_TARGET.*\/lib\//s@-B[^ ]*/lib/@@g' configure.orig >configure
mkdir ../gcc-build
cd ../gcc-build
../gcc-3.4.5/configure --prefix=/cross-tools \
    --target=${HLFS_TARGET} --host=${HLFS_HOST} --disable-multilib \
    --with-local-prefix=/tools --disable-nls --enable-shared \
    --enable-languages=c,c++ --enable-__cxa_atexit \
    --enable-c99 --enable-long-long --enable-threads=posix \
    --with-dynamic-linker=${ldso} --with-nostdinc
make AS_FOR_TARGET="/cross-tools/bin/${HLFS_TARGET}-as" \
LD_FOR_TARGET="/cross-tools/bin/${HLFS_TARGET}-ld"
make install

Build Variables

export CC="${HLFS_TARGET}-gcc"
export CXX="${HLFS_TARGET}-g++"
export AR="${HLFS_TARGET}-ar"
export AS="${HLFS_TARGET}-as"
export RANLIB="${HLFS_TARGET}-ranlib"
export LD="${HLFS_TARGET}-ld"
export STRIP="${HLFS_TARGET}-strip"
echo export CC=\""${CC}\"" >> ~/.bashrc
echo export CXX=\""${CXX}\"" >> ~/.bashrc
echo export AR=\""${AR}\"" >> ~/.bashrc
echo export AS=\""${AS}\"" >> ~/.bashrc
echo export RANLIB=\""${RANLIB}\"" >> ~/.bashrc
echo export LD=\""${LD}\"" >> ~/.bashrc
echo export STRIP=\""${STRIP}\"" >> ~/.bashrc

Libintl: Gettext 0.14.5

cd gettext-runtime/
./configure --prefix=/tools --host=${HLFS_TARGET} \
    --with-included-gettext --without-csharp \
    --disable-libasprintf
make -C intl/
make -C intl/ install
SPECFILE=`${CC} --print-file specs`
cp $SPECFILE tempspecfile
sed 's/%{shared:-lc}/%{!nointl: -lintl} &/' tempspecfile >$SPECFILE
unset SPECFILE

Binutils 2.16.1

patch -Np1 -i ../binutils-2.16.1-uClibc_conf-1.patch
patch -Np1 -i ../binutils-2.16.1-pt_pax-1.patch
patch -Np1 -i ../binutils-2.16.1-posix-1.patch
mkdir ../binutils-build
cd ../binutils-build
../binutils-2.16.1/configure --prefix=/tools \
     --build=${HLFS_HOST} --host=${HLFS_TARGET} --target=${HLFS_TARGET} \
     --disable-nls --enable-shared --disable-multilib \
     --with-lib-path=/tools/lib
make configure-host
make
make install

GCC 3.4.5

patch -Np1 -i ../gcc-3.4.5-uClibc_conf-1.patch
patch -Np1 -i ../gcc-3.4.5-uClibc_libstdc++-1.patch
patch -Np1 -i ../gcc-3.4.5-uClibc_locale-1.patch
patch -Np1 -i ../gcc-3.4.5-ssp-1.patch
patch -Np1 -i ../gcc-3.4.5-specs_x86-1.patch
patch -Np1 -i ../gcc-3.4.5-no_fixincludes-1.patch
patch -Np1 -i ../gcc-3.4.4-cross_search_paths-1.patch
patch -Np1 -i ../gcc-3.4.4-posix-1.patch
sed -e 's/%{shared:-lc}/%{!nointl: -lintl} &/' \
     -i gcc/config/linux.h
sed -e 's@gcc.gnu.org/bugs.html@wiki.linuxfromscratch.org/hlfs/@' \
        -e 's/3.4.5/3.4.5 (ssp)/' -i gcc/version.c
cp gcc/cppdefault.c{,.orig}
sed -e '/#define STANDARD_INCLUDE_DIR/s@"/usr/include"@0@g' \
   gcc/cppdefault.c.orig > gcc/cppdefault.c
cp gcc/Makefile.in{,.orig}
sed -e 's@\(^NATIVE_SYSTEM_HEADER_DIR =\).*@\1 /tools/include@g' \
   gcc/Makefile.in.orig > gcc/Makefile.in
cp gcc/mklibgcc.in{,.orig}
sed -e "s@\./xgcc@/cross-tools/bin/${CC}@g" \
   gcc/mklibgcc.in.orig > gcc/mklibgcc.in
mkdir ../gcc-build
cd ../gcc-build
../gcc-3.4.5/configure --prefix=/tools \
    --build=${HLFS_HOST} --host=${HLFS_TARGET} --target=${HLFS_TARGET} \
    --with-local-prefix=/tools --enable-long-long --enable-c99 \
    --enable-shared --enable-threads=posix --enable-__cxa_atexit \
    --disable-nls --enable-languages=c,c++ --disable-libstdcxx-pch \
    --with-dynamic-linker=${ldso} --with-nostdinc --enable-multilib=no
make AS_FOR_TARGET="/cross-tools/bin/${HLFS_TARGET}-as" \
LD_FOR_TARGET="/cross-tools/bin/${HLFS_TARGET}-ld"
make install
ln -s gcc /tools/bin/cc

Adding Hardened Specs

cat > hardened-specs.sh << "EOF"
#!/bin/sh
SPECFILE=`/tools/bin/gcc --print-file specs`
perl -pi -e 's@\*cc1:\n@$_%(cc1_ssp) @;' \
    $SPECFILE &&
perl -pi -e 's@\*cc1plus:\n@$_%(cc1_ssp) @;' \
    $SPECFILE &&
echo '*cc1_ssp: 
%{!fno-stack-protector*: -fstack-protector-all}
'    >> $SPECFILE
perl -pi -e 's@\*cc1:\n@$_%(cc1_pie) @;' \
    $SPECFILE &&
perl -pi -e 's@\*cc1plus:\n@$_%(cc1_pie) @;' \
    $SPECFILE &&
perl -pi -e 's@%{pie:-pie}@%(link_pie)@;' \
    $SPECFILE &&
perl -pi -e 's@pie:@!no-pie|pie:@g;' $SPECFILE &&
perl -pi -e 's@\*cpp:\n@$_%(cpp_pie) @;' $SPECFILE &&
echo '*cpp_pie: 
%{!static:%{!no-pie:%{!pie: -D__PIC__ -DPIC}}}
' >> $SPECFILE &&
echo '*cc1_pie: 
%{!static:%{!no-pie:%{!pie: -fPIC}}}
' >> $SPECFILE &&
echo '*link_pie: 
%{pie:-pie}%{!no-pie:%{!static:%{!Bstatic:%{!i:%{!r: %{!nonow: -z now} %{!norelro: -z relro} %{!shared:%{!Bshareable:%{!pie: -pie}}}}}}}}
' >> $SPECFILE
EOF
install hardened-specs.sh /tools/bin
/tools/bin/hardened-specs.sh

Testing GCC

cat > test.c << "EOF"
#include <stdio.h>
#include <unistd.h>
extern long __guard[];
int overflow(char *test) {
  char buffer[7];
  sprintf(buffer, "12345678901234567890123456789012345678901234567890");
  return(1234);
}
int main(int argc, char **argv) {
  printf("__guard\t=\t0x%08x;\n", __guard[0]);
  overflow("test");
  printf("This line should never get printed.\n");
}
EOF
/tools/bin/gcc -o test test.c
./test
/tools/bin/g++ -pie -fPIE -o test2 test.c
./test2
readelf -l test{,2} | grep -e ': /tools' -e 'Shared' \
    -e 'GNU_RELRO' -e 'PAX_FLAGS'
readelf -d test{,2} | grep -e 'BIND_NOW' -e 'TEXTREL'