this article was written to be read alongside the LFS book.
myfn () { {partition, 3} # without this, mkfs will error sleep 1 {format, 3} {export variables, 3} {mount, 3} {sources, 3} {directory structure, 4} {lfs user, 4} # allow for passwordless login to new account passwd -d lfs } ssh root@127.0.0.1 -p 2222 "$(typeset -f myfn); myfn"
myfn () { {bash setup, 4} } ssh lfs@127.0.0.1 -p 2222 "$(typeset -f myfn); myfn" myfn2 () { cd /mnt/lfs/root/sources {pass 1 binutils, 5} {pass 1 gcc, 5} {linux api headers, 5} {glibc, 5} {libstdc++, 5} {m4, 6} {ncurses, 6} {bash, 6} {coreutils, 6} {diffutils, 6} {file, 6} {findutils, 6} {gawk, 6} {grep, 6} {gzip, 6} {make, 6} {patch, 6} {sed, 6} {tar, 6} {xz, 6} {pass 2 binutils, 6} {pass 2 gcc, 6} } ssh lfs@127.0.0.1 -p 2222 "$(typeset -f myfn2); myfn2"
myfn () { {revert dir ownership, 7} {mount device files, 7} } #ssh root@127.0.0.1 -p 2222 "source .bash_profile; $(typeset -f myfn); myfn" ssh root@127.0.0.1 -p 2222 << "EOF" source .bash_profile; myfn2 () { {chroot1, 7} } declare -f myfn2 > $ROOT/script.sh /usr/sbin/chroot "$ROOT" \ /usr/bin/env -i \ HOME=/root \ TERM="$TERM" \ PS1='(lfs chroot) \u:\w\$' \ PATH=/usr/bin:/usr/sbin \ /bin/bash -c "source script.sh; myfn2; rm script.sh" EOF ssh root@127.0.0.1 -p 2222 << "EOF" source .bash_profile; myfn2 () { {chroot2, 7} } declare -f myfn2 > $ROOT/script.sh /usr/sbin/chroot "$ROOT" \ /usr/bin/env -i \ HOME=/root \ TERM="$TERM" \ PS1='(lfs chroot) \u:\w\$' \ PATH=/usr/bin:/usr/sbin \ /bin/bash -c "source script.sh; myfn2; rm script.sh" EOF
#wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img --output-document host.img cp ../jammy-server-cloudimg-amd64.img host.img cp ../prepare-host.sh . qemu-img resize host.img 10G qemu-img create -f qcow2 lfs.img 30G cat > init.sh << "OUTER_EOF" growpart /dev/sda 1 resize2fs /dev/sda1 passwd -d root cat << "EOF" > /etc/ssh/sshd_config.d/lfs.conf PermitRootLogin yes PermitEmptyPasswords yes EOF systemctl restart sshd apt update apt install --yes --fix-missing binutils bison gawk gcc g++ m4 make texinfo ln -sf /bin/bash /bin/sh OUTER_EOF virt-customize --add host.img --firstboot init.sh
Used in section 1
now that our host system is ready, we'll boot it up and connect to it via ssh
qemu-system-x86_64 -m 8G -smp $(nproc) -accel kvm -cpu host \ -nic user,hostfwd=tcp::2222-:22 \ -hda host.img \ -hdb lfs.img \ -daemonize ssh root@127.0.0.1 -p 2222
Redefined in section 8
Used in section 1
from now on, all commands are run on our host through this ssh session, unless otherwise specified.
we need to partition lfs.img, which has been attached to our system at /dev/sdb. we won't bother creating a swap partition as we have provided plenty of memory to our host. for now, we'll just create boot and root partitions. https://www.gnu.org/software/parted/manual/parted.html
first we create a partition table on our blank disk. a GPT partition table reserves 34 sectors at the start and end of the disk.
you will have noticed the output Information: You may need to update /etc/fstab.
/etc/fstab (from 'filesystem table') is a configuration file which controls the mounting of filesystems when detected by a linux system on boot.
provided you complete your LFS build in one session this will not be necessary, but if you have to reboot at some stage there's a good chance you will forget to mount these partitions, so we will update our fstab later.
parted /dev/sdb mkpart boot fat32 34s 1GiB parted /dev/sdb set 1 esp on
Used in section 1
here we create a partition called "boot", with a filesystem type of fat32.
we start our partition at the first available sector, and end it 1 Gibibyte from the start.
the output will show Warning: The resulting partition is not properly aligned for best performance: 34s % 2048s != 0s
partition alignment is a little involved, and learning about it is out of scope, so we will ignore this.
we also set the esp flag to let our UEFI firmware know that this is an EFI System Partition.
then we create our root partition, starting from an offset of 1GiB and ending at the last available sector.
in bash and other shells the double dashes --
signify the end of command options, and are required to prevent -34s
from being interpreted by parted as an argument.
we can use parted /dev/sdb print
to confirm the disk was successfully partitioned.
the output should look something like this:
Model: ATA QEMU HARDDISK (scsi) Disk /dev/sdb: 32.2GB Sector size (logical/physical): 512B/512B Partition Table: gpt Disk Flags: Number Start End Size File system Name Flags 1 17.4kB 1074MB 1074MB boot boot, esp 2 1074MB 32.2GB 31.1GB ext4 root
we create filesystems on our new partitions and label them appropriately
echo "export BOOT=/mnt/lfs/boot ROOT=/mnt/lfs/root" >> /root/.bash_profile source .bash_profile
Used in section 1
export
does something
when we log in to our host system, bash executes commands found in the .bash_profile
file in the user's home directory.
this ensures that the variables will always be available, even if we disconnect from or reboot the host.
mkdir --parents $BOOT $ROOT mount /dev/sdb1 $BOOT mount /dev/sdb2 $ROOT cat >> /etc/fstab << "EOF" LABEL=ROOT /mnt/lfs/root ext4 defaults 0 0 LABEL=BOOT /mnt/lfs/boot vfat defaults 0 0 EOF
Used in section 1
we create two directories to which we mount our new filesystems, and add rules for mounting them to fstab.
mkdir $ROOT/sources chmod -v a+wt $ROOT/sources cd $ROOT/sources wget http://ftp.lfs-matrix.net/pub/lfs/lfs-packages/lfs-packages-12.0.tar tar --extract --file lfs-packages-12.0.tar
Redefined in section 8
Used in section 1
we create a directory sources
and modify its permissions such that other users can write to it, but only we (root) can delete files within it.
we download an archive of all the required packages from a mirror and extract it
we have finished preparing our disk, so it is time to start building our new linux system. https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html the FHS documents common practices at a given time and is updated as and when they change. thus most modern linux distributions deviate from the standard in some way, so while it is a useful convention, do not take it to be authoritative.
mkdir --parents $ROOT/{etc,var,lib64} $ROOT/usr/{bin,lib,sbin} for i in bin lib sbin; do ln -sv usr/$i $ROOT/$i done mkdir $ROOT/tools
Used in section 1
we begin by creating some required directories
/etc
is now used for storing configuration files, but historically it held that which did not belong elsewhere, hence the name (et cetera).
/var
is for storing variable data files; files generated during programs at runtime such as logs and caches.
/usr
is for shareable read-only data.
/usr/bin
is the primary store of executables.
/usr/lib
is for storing shared libraries.
/usr/sbin
is for storing binaries used for system administration.
in common with some other modern linux distributions, we will not differentiate between the bin
, lib
and sbin
directories under /usr
and those at the root of our filesystem.
however for compatibility reasons the directories are required, so we create symlinks instead.
finally we create a tools
directory, which will store the cross-compiler that we will use later
groupadd lfs useradd -s /bin/bash -g lfs -m -k /dev/null lfs chown lfs $ROOT/{usr{,/*},var,etc,lib64,tools} rm /etc/bash.bashrc
Used in section 1
to ensure a clean build environment, we create a new user.
we'll give it ownership of the directory structure we created.
we can now switch to our new user.
while we are still root, let's delete /etc/bash.bashrc
to prevent it contaminating our build environment.
su - lfs cat > ~/.bash_profile << "EOF" exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash EOF cat > ~/.bashrc << "EOF" set +h umask 022 BOOT=/mnt/lfs/boot ROOT=/mnt/lfs/root LC_ALL=POSIX LFS_TGT=$(uname -m)-lfs-linux-gnu PATH=/usr/bin if [ ! -L /bin ]; then PATH=/bin:$PATH; fi PATH=$ROOT/tools/bin:$PATH CONFIG_SITE=$ROOT/usr/share/config.site export BOOT ROOT LC_ALL LFS_TGT PATH CONFIG_SITE EOF source ~/.bash_profile
Redefined in section 8
Used in section 1
we create a .bash_profile
and .bashrc
, then read the new profile into our current shell with source
.
the details of these two files are explained in LFS.
cd $ROOT/sources tar --extract --file 12.0/binutils-2.41.tar.xz ( cd binutils-2.41 mkdir build ( cd build ../configure --prefix=$ROOT/tools \ --with-sysroot=$ROOT \ --target=$LFS_TGT \ --disable-nls \ --enable-gprofng=no \ --disable-werror make -j $(nproc) make install ) ) rm --recursive --force binutils-2.41
Used in section 1
tar --extract --file 12.0/gcc-13.2.0.tar.xz ( cd gcc-13.2.0 tar --extract --file ../12.0/mpfr-4.2.0.tar.xz mv mpfr-4.2.0 mpfr tar --extract --file ../12.0/gmp-6.3.0.tar.xz mv gmp-6.3.0 gmp tar --extract --file ../12.0/mpc-1.3.1.tar.gz mv mpc-1.3.1 mpc sed -e '/m64=/s/lib64/lib/' -i.orig gcc/config/i386/t-linux64 mkdir build ( cd build ../configure \ --target=$LFS_TGT \ --prefix=$ROOT/tools \ --with-glibc-version=2.38 \ --with-sysroot=$ROOT \ --with-newlib \ --without-headers \ --enable-default-pie \ --enable-default-ssp \ --disable-nls \ --disable-shared \ --disable-multilib \ --disable-threads \ --disable-libatomic \ --disable-libgomp \ --disable-libquadmath \ --disable-libssp \ --disable-libvtv \ --disable-libstdcxx \ --enable-languages=c,c++ make -j $(nproc) make install ) cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \ $(dirname $($LFS_TGT-gcc -print-libgcc-file-name))/include/limits.h ) rm --recursive --force gcc-13.2.0
Used in section 1
tar --extract --file 12.0/linux-6.4.12.tar.xz ( cd linux-6.4.12 make mrproper make headers find usr/include -type f ! -name '*.h' -delete cp --recursive usr/include $ROOT/usr ) rm --recursive --force linux-6.4.12
Used in section 1
tar --extract --file 12.0/glibc-2.38.tar.xz ( cd glibc-2.38 ln -sf ../lib/ld-linux-x86-64.so.2 $ROOT/lib64 ln -sf ../lib/ld-linux-x86-64.so.2 $ROOT/lib64/ld-lsb-x86-64.so.3 patch -Np1 -i $ROOT/sources/12.0/glibc-2.38-fhs-1.patch mkdir build ( cd build echo "rootsbindir=/usr/sbin" > configparms ../configure \ --prefix=/usr \ --host=$LFS_TGT \ --build=$(../scripts/config.guess) \ --enable-kernel=4.14 \ --with-headers=$ROOT/usr/include \ libc_cv_slibdir=/usr/lib make -j 1 make DESTDIR=$ROOT install ) sed '/RTLDLIST=/s@/usr@@g' -i $ROOT/usr/bin/ldd ) rm --recursive --force glibc-2.38
Used in section 1
echo 'int main(){}' | $LFS_TGT-gcc -xc - readelf -l a.out | grep ld-linux rm a.out
tar --extract --file 12.0/gcc-13.2.0.tar.xz ( cd gcc-13.2.0 mkdir build ( cd build ../libstdc++-v3/configure \ --host=$LFS_TGT \ --build=$(../config.guess) \ --prefix=/usr \ --disable-multilib \ --disable-nls \ --disable-libstdcxx-pch \ --with-gxx-include-dir=/tools/$LFS_TGT/include/c++/13.2.0 make -j $(nproc) make DESTDIR=$ROOT install ) rm $ROOT/usr/lib/lib{stdc++,stdc++fs,supc++}.la ) rm --recursive --force gcc-13.2.0
Used in section 1
tar --extract --file 12.0/m4-1.4.19.tar.xz ( cd m4-1.4.19 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force m4-1.4.19
Used in section 1
tar --extract --file 12.0/ncurses-6.4.tar.gz ( cd ncurses-6.4 sed -i s/mawk// configure mkdir build ( cd build ../configure make -C include -j $(nproc) make -C progs tic -j $(nproc) ) ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(./config.guess) \ --mandir=/usr/share/man \ --with-manpage-format=normal \ --with-shared \ --without-normal \ --with-cxx-shared \ --without-debug \ --without-ada \ --disable-stripping \ --enable-widec make -j $(nproc) make DESTDIR=$ROOT TIC_PATH=$(pwd)/build/progs/tic install echo "INPUT(-lncursesw)" > $ROOT/usr/lib/libncurses.so ) rm --recursive --force ncurses-6.4
Used in section 1
tar --extract --file 12.0/bash-5.2.15.tar.gz ( cd bash-5.2.15 ./configure --prefix=/usr \ --build=$(sh support/config.guess) \ --host=$LFS_TGT \ --without-bash-malloc make -j $(nproc) make DESTDIR=$ROOT install ln -s bash $ROOT/bin/sh ) rm --recursive --force bash-5.2.15
Used in section 1
tar --extract --file 12.0/coreutils-9.3.tar.xz ( cd coreutils-9.3 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) \ --enable-install-program=hostname \ --enable-no-install-program=kill,uptime \ gl_cv_macro_MB_CUR_MAX_good=y make -j $(nproc) make DESTDIR=$ROOT install mv $ROOT/usr/bin/chroot $ROOT/usr/sbin mkdir --parents $ROOT/usr/share/man/man8 mv $ROOT/usr/share/man/man1/chroot.1 $ROOT/usr/share/man/man8/chroot.8 sed -i 's/"1"/"8"/' $ROOT/usr/share/man/man8/chroot.8 ) rm --recursive --force coreutils-9.3
Used in section 1
tar --extract --file 12.0/diffutils-3.10.tar.xz ( cd diffutils-3.10 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(./build-aux/config.guess) make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force diffutils-3.10
Used in section 1
tar --extract --file 12.0/file-5.45.tar.gz ( cd file-5.45 mkdir build ( cd build ../configure --disable-bzlib \ --disable-libseccomp \ --disable-xzlib \ --disable-zlib make ) ./configure --prefix=/usr --host=$LFS_TGT --build=$(./config.guess) make -j $(nproc) FILE_COMPILE=$(pwd)/build/src/file make DESTDIR=$ROOT install rm $ROOT/usr/lib/libmagic.la ) rm --recursive --force file-5.45
Used in section 1
tar --extract --file 12.0/findutils-4.9.0.tar.xz ( cd findutils-4.9.0 ./configure --prefix=/usr \ --localstatedir=/var/lib/locate \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force findutils-4.9.0
Used in section 1
tar --extract --file 12.0/gawk-5.2.2.tar.xz ( cd gawk-5.2.2 sed -i 's/extras//' Makefile.in ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force gawk-5.2.2
Used in section 1
tar --extract --file 12.0/grep-3.11.tar.xz ( cd grep-3.11 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(./build-aux/config.guess) make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force grep-3.11
Used in section 1
tar --extract --file 12.0/gzip-1.12.tar.xz ( cd gzip-1.12 ./configure --prefix=/usr --host=$LFS_TGT make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force gzip-1.12
Used in section 1
tar --extract --file 12.0/make-4.4.1.tar.gz ( cd make-4.4.1 ./configure --prefix=/usr \ --without-guile \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force make-4.4.1
Used in section 1
tar --extract --file 12.0/patch-2.7.6.tar.xz ( cd patch-2.7.6 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force patch-2.7.6
Used in section 1
tar --extract --file 12.0/sed-4.9.tar.xz ( cd sed-4.9 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(./build-aux/config.guess) make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force sed-4.9
Used in section 1
tar --extract --file 12.0/tar-1.35.tar.xz ( cd tar-1.35 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force tar-1.35
Used in section 1
tar --extract --file 12.0/xz-5.4.4.tar.xz ( cd xz-5.4.4 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) \ --disable-static \ --docdir=/usr/share/doc/xz-5.4.4 make -j $(nproc) make DESTDIR=$ROOT install rm $ROOT/usr/lib/liblzma.la ) rm --recursive --force xz-5.4.4
Used in section 1
tar --extract --file 12.0/binutils-2.41.tar.xz ( cd binutils-2.41 sed '6009s/$add_dir//' -i ltmain.sh mkdir build ( cd build ../configure \ --prefix=/usr \ --build=$(../config.guess) \ --host=$LFS_TGT \ --disable-nls \ --enable-shared \ --enable-gprofng=no \ --disable-werror \ --enable-64-bit-bfd make -j $(nproc) make DESTDIR=$ROOT install ) rm -v $ROOT/usr/lib/lib{bfd,ctf,ctf-nobfd,opcodes,sframe}.{a,la} ) rm --recursive --force binutils-2.41
Used in section 1
tar --extract --file 12.0/gcc-13.2.0.tar.xz ( cd gcc-13.2.0 tar -xf ../12.0/mpfr-4.2.0.tar.xz mv -v mpfr-4.2.0 mpfr tar -xf ../12.0/gmp-6.3.0.tar.xz mv -v gmp-6.3.0 gmp tar -xf ../12.0/mpc-1.3.1.tar.gz mv -v mpc-1.3.1 mpc sed -e '/m64=/s/lib64/lib/' -i.orig gcc/config/i386/t-linux64 sed '/thread_header =/s/@.*@/gthr-posix.h/' \ -i libgcc/Makefile.in libstdc++-v3/include/Makefile.in mkdir build ( cd build ../configure \ --build=$(../config.guess) \ --host=$LFS_TGT \ --target=$LFS_TGT \ LDFLAGS_FOR_TARGET=-L$PWD/$LFS_TGT/libgcc \ --prefix=/usr \ --with-build-sysroot=$ROOT \ --enable-default-pie \ --enable-default-ssp \ --disable-nls \ --disable-multilib \ --disable-libatomic \ --disable-libgomp \ --disable-libquadmath \ --disable-libsanitizer \ --disable-libssp \ --disable-libvtv \ --enable-languages=c,c++ make -j $(nproc) make DESTDIR=$ROOT install ) ln -sv gcc $ROOT/usr/bin/cc ) rm --recursive --force gcc-13.2.0
Used in section 1
we are now going to chroot into our newly built environment
#exit chown --recursive root:root $ROOT/{usr,lib,var,etc,bin,sbin,lib64,tools}
Used in section 1
first we change ownership of all the directories we created back to root, as the LFS user was only needed temporarily for cleanly building the cross-toolchain and won't exist on our new system.
mkdir --parents $ROOT/{dev,proc,sys,run} mount --bind /dev $ROOT/dev mount --bind /dev/pts $ROOT/dev/pts mount --types proc proc $ROOT/proc mount --types sysfs sysfs $ROOT/sys mount --types tmpfs tmpfs $ROOT/run mount --types tmpfs --options nosuid,nodev tmpfs $ROOT/dev/shm
Used in section 1
we mount all our special device files
/usr/sbin/chroot "$ROOT" /usr/bin/env -i \ HOME=/root \ TERM="$TERM" \ PS1='(lfs chroot) \u:\w\$ ' \ PATH=/usr/bin:/usr/sbin \ /bin/bash --login
enter chroot
mkdir -pv /{boot,home,mnt,opt,srv} mkdir -pv /etc/{opt,sysconfig} mkdir -pv /lib/firmware mkdir -pv /media/{floppy,cdrom} mkdir -pv /usr/{,local/}{include,src} mkdir -pv /usr/local/{bin,lib,sbin} mkdir -pv /usr/{,local/}share/{color,dict,doc,info,locale,man} mkdir -pv /usr/{,local/}share/{misc,terminfo,zoneinfo} mkdir -pv /usr/{,local/}share/man/man{1..8} mkdir -pv /var/{cache,local,log,mail,opt,spool} mkdir -pv /var/lib/{color,misc,locate} ln -sfv /run /var/run ln -sfv /run/lock /var/lock install -dv -m 0750 /root install -dv -m 1777 /tmp /var/tmp
Used in section 1
ln -sv /proc/self/mounts /etc/mtab cat > /etc/hosts << EOF 127.0.0.1 localhost $(hostname) ::1 localhost EOF cat > /etc/passwd << "EOF" root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/dev/null:/usr/bin/false daemon:x:6:6:Daemon User:/dev/null:/usr/bin/false messagebus:x:18:18:D-Bus Message Daemon User:/run/dbus:/usr/bin/false systemd-journal-gateway:x:73:73:systemd Journal Gateway:/:/usr/bin/false systemd-journal-remote:x:74:74:systemd Journal Remote:/:/usr/bin/false systemd-journal-upload:x:75:75:systemd Journal Upload:/:/usr/bin/false systemd-network:x:76:76:systemd Network Management:/:/usr/bin/false systemd-resolve:x:77:77:systemd Resolver:/:/usr/bin/false systemd-timesync:x:78:78:systemd Time Synchronization:/:/usr/bin/false systemd-coredump:x:79:79:systemd Core Dumper:/:/usr/bin/false uuidd:x:80:80:UUID Generation Daemon User:/dev/null:/usr/bin/false systemd-oom:x:81:81:systemd Out Of Memory Daemon:/:/usr/bin/false nobody:x:65534:65534:Unprivileged User:/dev/null:/usr/bin/false EOF cat > /etc/group << "EOF" root:x:0: bin:x:1:daemon sys:x:2: kmem:x:3: tape:x:4: tty:x:5: daemon:x:6: floppy:x:7: disk:x:8: lp:x:9: dialout:x:10: audio:x:11: video:x:12: utmp:x:13: usb:x:14: cdrom:x:15: adm:x:16: messagebus:x:18: systemd-journal:x:23: input:x:24: mail:x:34: kvm:x:61: systemd-journal-gateway:x:73: systemd-journal-remote:x:74: systemd-journal-upload:x:75: systemd-network:x:76: systemd-resolve:x:77: systemd-timesync:x:78: systemd-coredump:x:79: uuidd:x:80: systemd-oom:x:81: wheel:x:97: users:x:999: nogroup:x:65534: EOF echo "tester:x:101:101::/home/tester:/bin/bash" >> /etc/passwd echo "tester:x:101:" >> /etc/group install -o tester -d /home/tester
Used in section 1
exec /usr/bin/bash --login touch /var/log/{btmp,lastlog,faillog,wtmp} chgrp -v utmp /var/log/lastlog chmod -v 664 /var/log/lastlog chmod -v 600 /var/log/btmp cd sources
tar --extract --file 12.0/gettext-0.22.tar.xz ( cd gettext-0.22 ./configure --disable-shared make -j (nproc) cp -v gettext-tools/src/{msgfmt,msgmerge,xgettext} /usr/bin ) rm --recursive --force gettext-0.22
tar --extract --file 12.0/bison-3.8.2.tar.xz ( cd bison-3.8.2 ./configure --prefix=/usr \ --docdir=/usr/share/doc/bison-3.8.2 make -j (nproc) make install ) rm --recursive --force bison-3.8.2
tar --extract --file 12.0/perl-5.38.0.tar.xz ( cd perl-5.38.0 sh Configure -des \ -Dprefix=/usr \ -Dvendorprefix=/usr \ -Duseshrplib \ -Dprivlib=/usr/lib/perl5/5.38/core_perl \ -Darchlib=/usr/lib/perl5/5.38/core_perl \ -Dsitelib=/usr/lib/perl5/5.38/site_perl \ -Dsitearch=/usr/lib/perl5/5.38/site_perl \ -Dvendorlib=/usr/lib/perl5/5.38/vendor_perl \ -Dvendorarch=/usr/lib/perl5/5.38/vendor_perl make -j (nproc) make install ) rm --recursive --force perl-5.38.0
tar --extract --file 12.0/Python-3.11.4.tar.xz ( cd Python-3.11.4 ./configure --prefix=/usr \ --enable-shared \ --without-ensurepip make -j (nproc) make install ) rm --recursive --force Python-3.11.4
tar --extract --file 12.0/texinfo-7.0.3.tar.xz ( cd texinfo-7.0.3 ./configure --prefix=/usr make -j (nproc) make install ) rm --recursive --force texinfo-7.0.3
tar --extract --file 12.0/util-linux-2.39.1.tar.xz ( cd util-linux-2.39.1 mkdir -pv /var/lib/hwclock ./configure ADJTIME_PATH=/var/lib/hwclock/adjtime \ --libdir=/usr/lib \ --runstatedir=/run \ --docdir=/usr/share/doc/util-linux-2.39.1 \ --disable-chfn-chsh \ --disable-login \ --disable-nologin \ --disable-su \ --disable-setpriv \ --disable-runuser \ --disable-pylibmount \ --disable-static \ --without-python make -j (nproc) make install ) rm --recursive --force util-linux-2.39.1
rm -rf /usr/share/{info,man,doc}/* find /usr/{lib,libexec} -name \*.la -delete rm -rf /tools
qemu-system-x86_64 -m 8G -smp $(nproc) -accel kvm -cpu host \ -nic user,hostfwd=tcp::2222-:22 \ -hda host.img \ -hdb lfs.img \ -daemonize
Used in section 1
mkdir $ROOT/sources chmod -v a+wt $ROOT/sources cd $ROOT/sources wget --progress=dot:giga http://ftp.lfs-matrix.net/pub/lfs/lfs-packages/lfs-packages-12.0.tar tar --extract --file lfs-packages-12.0.tar
Used in section 1
cat > ~/.bash_profile << "EOF" exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash EOF cat > ~/.bashrc << "EOF" set +h umask 022 BOOT=/mnt/lfs/boot ROOT=/mnt/lfs/root LC_ALL=POSIX LFS_TGT=$(uname -m)-lfs-linux-gnu PATH=/usr/bin if [ ! -L /bin ]; then PATH=/bin:$PATH; fi PATH=$ROOT/tools/bin:$PATH CONFIG_SITE=$ROOT/usr/share/config.site export BOOT ROOT LC_ALL LFS_TGT PATH CONFIG_SITE EOF
Used in section 1
tar --extract --file 12.0/ ( cd make -j $(nproc) make DESTDIR=$ROOT install ) rm --recursive --force