Építsünk saját GNU/Linux rendszert! #2

Ha még nem olvastad, akkor most az 1. részt elolvashatod.

Amint a hivatkozási kézikönyv tárgyalja, először létrehozunk egy ideiglenes rendszert a /tools könyvtárban, amely tartalmazza a szükséges eszközöket az alaprendszer buildeléséhez. Mivel ez a tools könyvtár egy üres partíción foglal helyet, amelybe bele fogunk chrootolni, ezért ennek önmagában konzisztensnek kell lennie. Hiszen a chroot leszigeteli a host rendszer csomagjait, így a chrootban nem fognak működni azok a parancsok, amelyek 1) a host rendszer library-jaihoz linkelődnek; 2) olyan parancsokat hívnak meg, amelyek hiányoznak a tools-ból.

Az LFS könyv egy kitaposott utat mutat erre. Létrehozunk egy lfs nevű felhasználót, melynek csinálunk egy tiszta environmentet (úgy értve mint shell environment variables), ez csökkenti a host rendszer hatását a tools-ra. Másfelől, mivel az lfs egy mezei felhasználó, így ez véd a host rendszer szétcseszése és teleszemetelése ellen, amelyek igencsak nem kívánatos dolgok. A linker hackelése és a GCC specs fájlnának módosításával pedig elérjük, hogy amit csak lehet, a /tools library-jaihoz linkeljen.

Persz ha valami nem található meg a tools-ban, de megtalálható a host rendszerben, akkor azt a host rendszerhez fogja linkelni, ez pedig nem kívánatos, mivel ezek akkor nem fognak majd a chrootban működni. Emiatt figyelni kell a ./configure kapcsolókra, hogy a fölösleges függőségeket kikapcsoljuk, valamint arra, hogy a fontos függőségek pedig telepítésre kerüljenek a tools-ban. Persze, amint már fenn írtam, a könyv egy kitaposott út; a problémákkal akkor találkozunk, amikor úgy döntünk, hogy letérünk erről a kitaposott útról, és mondjuk GNU tar helyett bsdtar-t teszünk a rendszerbe, meg adunk hozzá csomagkezelést.

Még egy kis magyarázat: Mivel a tools csak egy ideiglenes rendszer (később majd eltávolításra kerül), ezért annál még nem foglalkozunk csomagkezeléssel, csak a csomagkezelő behegesztésével a tools-ba, hogy a chrootban - ahol a valódi rendszert építjük, aminek már lesz csomagkezelése - már ott legyen a csomagkezelő.

Na ennyi bevezetés után lássuk, mit is csináltam! Kezdetben teljesen úgy jártam el, ahogyan a könyv legújabb stabil változatában leírja. Lássuk szépen a csomagokat az ideiglenes tools rendszerben:

  • Binutils-2.18 - Pass 1
  • GCC-4.3.2 - Pass 1
  • Linux-2.6.27.4 API Headers -- itt én a 2.6.27.11-et használtam
  • Glibc-2.8-20080929 -- itt meg a GLibC 2.8 legújabb heti snapshotját a RedHat-től letöltve
  • Adjusting the Toolchain
  • Tcl-8.5.5
  • Expect-5.43.0
  • DejaGNU-1.4.4
  • GCC-4.3.2 - Pass 2
  • Binutils-2.18 - Pass 2
  • Ncurses-5.6 -- itt a mostanában kiadott 5.7-et fordítottam
  • Bash-3.2
  • Bzip2-1.0.5 -- ezt nem pont úgy csináltam, ahogy a könyvben van
  • Coreutils-6.12
  • Diffutils-2.8.1
  • E2fsprogs-1.41.3
  • Findutils-4.4.0
  • Gawk-3.1.6
  • Gettext-0.17
  • Grep-2.5.3
  • Gzip-1.3.12
  • M4-1.4.12
  • Make-3.81
  • Patch-2.5.4
  • Perl-5.10.0
  • Sed-4.1.5
  • Tar-1.20 -- ezt kihagytam (bsdtar lesz helyette)
  • Texinfo-4.13a
  • Util-linux-ng-2.14.1

Lássuk, hogyan tértem le kitapasott útról! Ez két részre bontható: a libarchive/bsdtar története és a pacman hegesztése.

libarchive/bsdtar 2.6.0
================

Mivel a bsdtar a GNU tarral ellentétben nem a fork() rendszerhívással, hanem library hívásokkal használja a tömörítőalgoritmusokat, ráadásul a bsdtar csak egy front-end a libarchive-hoz, így a libarchive szépen integrálható más projektekbe, így azoknak sem kell fork()-kal meghívni a tar-t, hanem direkt függvényekkel használhatják a libarchive-ot. No emiatt a libarchive telepítése előtt feltelepítettem a tömörítők library-jeit (zlib, bzip2, lzma) mindenféle statikus, dinamikus könyvtárakkal meg headerekkel együtt.

Megjegyzés: Az idézett paracsok úgy értendők, ahogyan az LFS könyvben van: először bele kell cd-zni a kitömörített forrásba, majd azután kiadni a leírt parancsokat.

bzip 1.0.5 -- Ez különben is kellett, csak másképp telepítettem most, mint ahogyan a könyvben van. Gyakolatilag az ideiglenes és a végleges rendszerre vonatkozó telepítési utasításokat kombináltam.

make -f Makefile-libbz2_so
make clean
make
make PREFIX=/tools install
cp -v bzip2-shared /tools/bin/bzip2
cp -av libbz2.so* /tools/lib
ln -sv libbz2.so.1.0 /tools/lib/libbz2.so
rm -v /tools/bin/{bunzip2,bzcat,bzip2}
ln -sv bzip2 /tools/bin/bunzip2
ln -sv bzip2 /tools/bin/bzcat
cp -v bzip2-shared /tools/bin/bzip2

zlib 1.2.3 -- Itt is a végleges rendszerhez tartozó utasításokat írtam át, hogy a /tools-ba telepítsen.

./configure --prefix=/tools --shared
make
make install
make clean
./configure --prefix=/tools
make install
chmod -v 644 /tools/lib/libz.a

lzma 4.32.7

./configure --prefix=/tools
make
make install

libarchive 2.6.0

./configure --prefix=/tools
make
make install
ln -vs bsdtar /tools/bin/tar

Ezek elég zökkenőmentesen mentek. Ez azt jelenti, hogy ezekre a lépésekre nem kellett még egyszer visszatérnem, elsőre jól sikerültek.

A bsdtar és az lzma kitömörítés rövid története
================================

A 2.6.0-s verzió már elvileg támogatja az lzma algoritmust kitömörítésnél. Igen ám, csakhogy ez a bsdtar olyan intelligens, hogy nem kell neki megmondani, hogy mi a tömörítőalgoritmus meg az archívum formátuma, hanem ő magától felismeri, és a helyeset használja. Valahogy nekem a .tar.lzma fájlokat sehogy nem akarta felismerni, így nyomozást indítottam az ügyben. Íme egy függvény a libarchive-2.6.0 forrásának libarchive/archive_read_support_compression_all.c fájlából:

int
archive_read_support_compression_all(struct archive *a)
{
#if HAVE_BZLIB_H
        archive_read_support_compression_bzip2(a);
#endif
        /* The decompress code doesn't use an outside library. */
        archive_read_support_compression_compress(a);
#if HAVE_ZLIB_H
        archive_read_support_compression_gzip(a);
#endif
#if HAVE_LZMADEC_H
        /* LZMA bidding is subject to false positives because
         * the LZMA file format has a very weak signature.  It
         * may not be feasible to include LZMA detection here. */
        /* archive_read_support_compression_lzma(a); */
#endif
        return (ARCHIVE_OK);
}

Megjegyzésbe van téve az a sor, amely meghívna az lzma felismerőt. Nagyszerű! Tehát szépen linkelődik az lzma-kezelés, tudná is használni, de soha nem fogja. Gyakorlatilag olyan, mint ha nem is lenne benne. Szép munka!

pacman 3.2.2
==========

Hát ez megszopatott rendesen. Negyedik nekifutásra sikerült a /tools építését úgy befejeznem, hogy elég jól mutasson ahhoz, hogy leközöljem ezt az epizódot. Közben már olyat is csináltam, hogy gdb-vel debugoltam a pacman-t, hogy rájöjjek mit csinál valójában, mert érthető hibaüzenetet nem adott, és fogalmam sem volt, hogy miért történik az, ami akkor történt - de ez a debugolós sztori már a sorozat következő részéhez tartozik. Itt felhívnám a figyelmet a /tools (és később majd nem csak a /tools) rendszeres backupjának fontosságára: hogy ne kelljen az egészet előlről kezdeni, ha valamit nagyon eltolunk, elég legyen csak a végét újracsinálni.

Hát a pacman-nek két függőségére hívja fel a figyelmet a ./configure: a libarchive-ra és a libfetch/libdownload-ra. Ez utóbbi a pacman internal downloaderjéhez kell. De mivel pacmannel úgy sem fogom netről más csomagjait töltögetni, ezért ezt a --disable-internal-download kapcsolóval letiltottam. A libarchive meg már telepítve lett.

Igen ám, csakhogy a pacman csomag részeként tálalt makepkg csomagkészítő bash script által meghívott parancsokra nem hívja fel a ./configure figyelmet - elég érthető okokból. Sajnos elég későn bukkantam rá, hogy a fájl tartalmaz egy listát a saját függőségeiről:

# makepkg uses quite a few external programs during its execution. You
# need to have at least the following installed for makepkg to function:
#   awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils),
#   getopt (util-linux), gettext, grep, gzip, openssl, sed

Ráadásul a fenti lista nem teljes, mivel a file nevű utility-t szintén használja a makepkg, és az itt nincs felsorolva. Ezek egy része már telepítve van, másokat meg eztán kell telepíteni. Nézzük, mik ezek!

util-linux-ng 2.14.1 -- a getopt miatt ismét elő kell venni

./configure --prefix=/tools
make -C getopt getopt
cp -v getopt/getopt /tools/bin/

fakeroot 1.12.1 -- a makepkg-nek kell, hogy tudjon privilégmentes felhasználó csomagot buildelni

./configure --prefix=/tools
make
make install

openssl 0.9.8j -- a makepkg-nek kell integritásellenőrzéshez. A fordítási instrukciók a BLFS könyv alapján készültek.

./config --openssldir=/tools/etc/ssl --prefix=/tools shared
make
install -vd /tools/etc/ssl
install -v ./apps/openssl.cnf /tools/etc/ssl/
make install

Update: Hát itt elég bénán ollóztam össze az utasításokat, mert aki kicsit utánanéz, az láthatja, hogy nem így kellett volna. De nem baj, így is működik, a fő, hogy a végleges rendszerben legyen rendes.

wget 1.11.4 -- a makepkg-nek kell fájlletöltéshez. A fordítási instrukciók a BLFS könyv alapján készültek.

./configure --prefix=/tools
make
make install

gettext 0.17 -- a makepkg-nek kell. Volt már ugyan, de csak egyetlen fájl telepítettünk belőle a könyv szerint, most felrakom az egészet.

./configure --prefix=/tools --docdir=/tools/doc/gettext-0.17
make
make install

file 4.26

sed -i -e '197,+1d' \
       -e '189,+1d' \
       -e 's/token$/tokens/' doc/file.man
./configure --prefix=/tools
make
make install

pacman 3.2.2

./configure --prefix="" --disable-{internal-download,rpath,nls,doc} --with-root-dir=/
make
make DESTDIR=/tools install

Itt a pacmannél a --prefix a pacman konfigurációs fájljának, adatbázisának, cache-ének gyökerét adja meg, a --with-root-dir a csomagok telepítésekor a gyökeret, amelybe a csomag kerül, és a végén a DESTDIR-rel irányítottam, hogy tényleg a /tools-ba kerüljön. Az első kettőnek értelemszerűen a gyökérkönyvtárnak kell lennie, hogy majd a chrootban jól működjön a pacman.

Két lépés marad még a könyv ötödik fejezetéből:

  • Stripping
  • Changing Ownership

Itt a vége a /tools építésének. Legközelebb már a valódi LFS rendszer alapjainak letételéről fogok beszámolni.

Hozzászólások

Kedves. Egyre inkább kedvet érzek én is hozzá. :)
--
Fight / For The Freedom / Fighting With Steel

Az első LFS rendszeremet még 3 éve építettem fel, ha jól emlékszem, és csomagkezelőnek az "AllInMyHead"-módszert alkalmaztam... Legutóbb valamikor tavaly év elején építettem egyet, de akkor már paco-t használtam csomagkezelőnek.
A bsdtar+lzma megoldásod mindenesetre nekem tetszik, és az 1.részben említett upstart-ra már nagyon kíváncsi vagyok!

---
Slackware 12.2 - 2.6.28 vanilla
A számítógép nem hibázik - csak hülye ül a gép előtt

Hát nem tudom mennyire voltam kivehető, a bsdtar+lzma kombó éppen hogy nem működik. Így most az

lzma -cd foo.tar.lzma | tar -xvf -

paranccsal bontom ki a .tar.lzma fájlokat. Viszont a GNU tar sem ismeri fel automatikusan az lzma tömörítést, ott talán a

tar --lzma -xvf foo.tar.lzma

kicsit rövidebb. Viszont a bsdtar egy rakás más formátumot ismer, pl. zip, cpio, de .iso fájlokból is tud kibontani.

Megjegyzésbe van téve az a sor, amely meghívna az lzma felismerőt. Nagyszerű! Tehát szépen linkelődik az lzma-kezelés, tudná is használni, de soha nem fogja

Nos igen, ezt a részt alaposan benéztem - bocsi, elsiklottam felette. :)

---
Slackware 12.2 - 2.6.28 vanilla
A számítógép nem hibázik - csak hülye ül a gép előtt

<hozzászólás törölve, mert nem igaz>

Na, a pacman engem is megszopatott. Minden egyes kis loszart kezzel kellett linkelnem a /tools-hoz, mert rossz helyen keresgelte a lzma libeket. :S Most megy a backup.
--


()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Igen, csak a libtool vegigparzolta a libarchive-t es abban valami eldugott sarokban talalt valami hihetetlen elbaszott, /tools/lib/../lib vagy ilyesmi borzadalom linkelest a liblzma-ra, es belehalt. Mivel nem volt kedvem vegignyomni a torkan, hogy mi az anyja kinja baja van, inkabb kezzel linkeltem be.
--


()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.