Merknader om å Bygge Programvare

De personene som har bygget et LFS system kan være klar over de generelle prinsippene for nedlasting og utpakking av programvare. Noe av denne informasjonen gjentas her for de som er nye i byggingen av deres egen programvare.

Hvert sett med installasjonsinstruksjoner inneholder en URL hvor du kan laste ned pakken. Oppdateringer; lagres imidlertid på LFS servere og er tilgjengelige via HTTP. Disse er referert etter behov i installasjonsinstruksjoner.

Selv om du kan beholde kildefilene hvor som helst du vil, antar vi at du har pakket ut pakken og endret til mappen opprettet av utpakkingsprosessen (kildemappen). Vi antar også at du har dekomprimerte eventuelle nødvendige oppdateringer, og de er i mappen rett over kildemappen.

Vi kan ikke understreke sterkt nok at du bør ta utgangspunkt i et rent kildetre hver gang. Dette betyr at hvis du har hatt en feil under konfigurasjon eller kompilering, er det vanligvis best å slette kildetreet og pakke den ut på nytt før du prøver igjen. Dette gjelder åpenbart ikke hvis du er en avansert bruker som er vant til å hacke Makefileer og C kode, men hvis du er i tvil, start fra et rent tre.

Bygge Programvare som en Uprivilegert (ikke-root) Bruker

Den gylne regelen for Unix System Administrasjon er å bruke dine superkrefter bare når det er nødvendig. Derfor anbefaler BLFS at du bygger programvaren som en uprivilegert bruker og bare bli root bruker når du installerer programvaren. Denne filosofien følges i alle pakkene i denne boken. Med mindre annet er spesifisert, skal alle instruksjoner utføres som en uprivilegert bruker. Boken vil gi deg råd om instruksjoner som trenger root privilegier.

Pakke ut Programvaren

Hvis en fil er i .tar formatet og komprimert, pakkes den ut ved å kjøre en av følgende kommandoer:

tar -xvf filename.tar.gz
tar -xvf filename.tgz
tar -xvf filename.tar.Z
tar -xvf filename.tar.bz2
[Note]

Note

Du kan utelate å bruke v parameteren i kommandoene vist over og under hvis du ønsker å undertrykke den detaljerte listen over alle filene i arkivet etter hvert som de pakkes ut. Dette kan bidra til å øke hastigheten på utpakkingen samt gjøre eventuelle feil som oppstår under utpakkingen mer tydelig for deg.

Du kan også bruke en litt annen metode:

bzcat filename.tar.bz2 | tar -xv

Til slutt, noen ganger har vi en komprimert oppdateringsfil i .patch.gz eller .patch.bz2 formatet. Den beste måten å anvende oppdateringen på er å kanalisere utdataen av dekomprimeringen til patch verktøyet. For eksempel:

gzip -cd ../patchname.patch.gz | patch -p1

Eller for en oppdatering komprimert med bzip2:

bzcat ../patchname.patch.bz2 | patch -p1

Verifiserer Filintegritet

Generelt, for å bekrefte at den nedlastede filen er fullstendig, mange pakkevedlikeholdere distribuerer også md5sum av filene. For å bekrefte md5sum av de nedlastede filene, last ned både filen og tilsvarende md5sum fil til samme katalog (helst fra en annen nettplasseringer), og (forutsatt file.md5sum er md5sum filen lastet ned) kjør følgende kommando:

md5sum -c file.md5sum

Hvis det er noen feil, vil de bli rapportert. Merk at BLFS boken også inkluderer md5sum for alle kildefilene. For å bruke BLFS medfølgende md5sum, kan du opprette en file.md5sum (plasser md5sum dataene og det nøyaktige navnet på den nedlastede filen på samme linje i en fil, atskilt med mellomrom) og kjør kommandoen vist ovenfor. Alternativt kan du bare kjøre kommandoen vist nedenfor og sammenligne utdataene til md5sum dataene vist i BLFS boken.

md5sum <navn_på_nedlastet_fil>

MD5 er ikke kryptografisk sikker, så md5summene er kun for å oppdage uønskede endringer i filinnholdet. For eksempel en feil eller avkorting som ble introdusert under nettverksoverføring, eller en stealth oppdatering til pakken fra oppstrøms (oppdaterer innholdet i en utgitt tarball i stedet for å lage et nytt slipp riktig).

Det er ingen måte å være 100% sikker på ektheten til kildefilene. Forutsatt at oppstrøms styrer nettstedet deres riktig (den private nøkkelen lekkes ikke og domenet ikke er kapret), og tillitsankrene er satt opp riktig ved hjelp av make-ca-1.14 på BLFS systemet kan vi med rimelighet stole på nedlastings URL-er til oppstrøms offisielle nettsted med https protokoll. Noter at selve BLFS boken er publisert på en nettside med https, så du bør allerede ha litt tillit til https protokollen, ellers ville du ikke stole på bokens innhold.

Hvis pakken er lastet ned fra et uoffisielt sted (for eksempel et lokalt speil), kontrollsummer generert av kryptografisk sikre sammendragsalgoritmer (for eksempel SHA256) kan brukes til å bekrefte ektheten av pakken. Last ned kontrollsumfilen fra oppstrøms offisielle nettsted (eller et sted du kan stole på) og sammenligne sjekksummen av pakken fra uoffisiell plassering av den. For eksempel, SHA256 sjekksummen kan sjekkes med kommandoen:

[Note]

Note

Hvis kontrollsummen og pakken er lastet ned fra samme uklarerte plassering, vil du ikke oppnå sikkerhetsforbedring ved å bekrefte pakken med sjekksummen. Angriperen kan forfalske kontrollsummen i tillegg til å kompromittere selve pakken.

sha256sum -c fil.sha256sum

Hvis GnuPG-2.4.5 er installert, kan du også bekrefte ektheten til pakken med en GPG signatur. Importer oppstrøms GPG offentlig nøkkel med:

gpg --recv-key nøkkelID

nøkkelID bør erstattes med nøkkelID fra et sted du kan stole på (for eksempel, kopier den fra oppstrøms offisielle nettside ved å bruke https). Nå kan du verifisere signaturen med:

gpg --recv-key fil.sig fil

Fordelen med GnuPG signaturen er, at når du har importert en offentlig nøkkel som du kan stole på, kan du laste ned både pakken og dens signatur fra samme uoffisielle sted og verifiser dem med den offentlige nøkkelen. Så du trenger ikke å koble til offisielle oppstrømsnettsted for å hente en kontrollsum for hver nye utgivelse. Du trenger bare å oppdatere den offentlige nøkkelen hvis den er utløpt eller tilbakekalt.

Opprette Loggfiler Under Installasjonen

For større pakker er det praktisk å lage loggfiler i stedet for å stirre på skjermen i håp om å fange en bestemt feil eller advarsel. Loggfiler er også nyttige for feilsøking og journalføring. Følgende kommando lar deg lage en installasjonslogg. Erstatt <kommando> med kommandoen du har tenkt å utføre.

( <kommando> 2>&1 | tee compile.log && exit $PIPESTATUS )

2>&1 omdirigerer feilmeldinger til den samme plassering som standard utdata. tee kommandoen tillater visning av utdata mens du logger resultatene til en fil. Parentesene rundt kommandoen kjører hele kommandoen i et underskall og til slutt exit $PIPESTATUS kommando sikrer resultatet av <kommando> returneres som resultatet og ikke resultatet av tee kommandoen.

Bruk av Flere Prosessorer

For mange moderne systemer med flere prosessorer (eller kjerner) kan kompileringstiden for en pakke reduseres ved å utføre en "parallell make" ved enten å sette en miljøvariabel eller fortelle make programmet å utføre flere jobber samtidig.

For eksempel inneholder en Intel Core i9-13900K CPU 8 ytelse (P) kjerner og 16 effektivitet (E) kjerner, og P-kjernene støtter SMT (Simultaneous MultiThreading, også kjent som Hyper-Threading) slik at hver P-kjerne kan kjøre to tråder samtidig og Linux-kjernen vil behandle hver P-kjerne som to logiske kjerner. Som et resultat er det totalt 32 logiske kjerner. For å bruke alle disse logiske kjernene som kjører make, vi kan sette en miljøvariabel for å fortelle make til å kjøre 32 jobber samtidig:

export MAKEFLAGS='-j32'

eller bare bygge med:

make -j32

Hvis du har brukt den valgfrie sed når du bygget ninja i LFS, kan du bruke:

export NINJAJOBS=32

når en pakke bruker ninja, eller bare:

ninja -j32

Hvis du ikke er sikker på antall logiske kjerner, kjør nproc kommandoen.

For make, standard antall jobber er 1. Men for ninja, standard antall jobber er N + 2 hvis antallet logiske kjerner N er større enn 2; eller N + 1 hvis N er 1 eller 2. Grunnen til å bruke en rekke jobber litt større enn antallet logiske kjerner er å holde alle logiske prosessorer opptatt selv om noen jobber utfører I/O operasjoner.

Merk at -j brytere begrenser bare parallellen jobber startet av make eller ninja, men hver jobb kan fortsatt skape sine egne prosesser eller tråder. Til eksempel, ld.gold vil bruke flere tråder for kobling, og noen tester av pakker kan skape flere tråder for testing av trådsikkerhetsegenskaper. Det er ingen generisk måte for byggesystem for å kjenne antall prosesser eller tråder skapt av en jobb. Så generelt bør vi ikke vurdere verdien som er gått med -j en hard grense for antall logiske kjerner å bruke. Les the section called “Bruk Linux Control Group for å begrense ressursbruken” hvis du vil sette slikt en hard grense.

Generelt bør antallet prosesser ikke overstige antallet kjerner støttet av CPU. For å liste opp prosessorene på ditt system, utsted: grep processor /proc/cpuinfo.

I noen tilfeller kan bruk av flere prosesser resultere i en "løps" tilstand hvor suksessen til bygget avhenger av rekkefølgen til kommandoer som kjøres av make programmet. For eksempel, hvis en kjørbar trenger fil A og fil B, og prøver å koble programmet før en av de avhengige komponentene er tilgjengelig vil resultere i en feil. Denne tilstanden oppstår vanligvis fordi oppstrømsutvikleren ikke har angitt alle forutsetningene riktig som trengs for å oppnå et trinn i Makefile.

Hvis dette skjer, er den beste måten å fortsette på å gå tilbake til en enkelt prosessor bygg. Legg til -j1 til en make kommando vil overstyre den lignende innstillingen i MAKEFLAGS miljøvariabel.

[Important]

Important

Et annet problem kan oppstå med moderne CPUer, som har mange kjerner. Hver påbegynt jobb bruker minne, og hvis summen av det nødvendige minnet for hver jobb overskrider tilgjengelig minne, kan du støte på enten et OOM kjerneavbrudd (tom minne) eller intens bruk av vekselfilen som vil bremse byggingen utover rimelige grenser.

Noen kompilasjoner med g++ kan bruke opptil 2,5 GB minne, så for å være sikker bør du begrense antall jobber til (Totalt minne i GB)/2,5, i det minste for store pakker som LLVM, WebKitGtk, QtWebEngine eller libreoffice.

Bruk Linux Control Group for å begrense ressursbruken

Noen ganger ønsker vi å begrense ressursbruken når vi bygger en pakke. For eksempel, når vi har 8 logiske kjerner, vil vi kanskje bruke bare 6 kjerner for å bygge pakken og reservere 2 kjerner for å spille av en film. Linux-kjernen har en funksjon kalt kontrollgrupper (cgroup) for et slikt behov.

Aktiver control group i kjernekonfigurasjonen, og bygg deretter opp igjen kjernen og start om nødvendig:

General setup --->
  [*] Control Group support --->                                       [CGROUPS]
    [*] Memory controller                                                [MEMCG]
    [*] Cpuset controller                                              [CPUSETS]

Forsikre at Sudo-1.9.15p5 er installert. For å kjøre make -j5 med de første 4 logiske kjernene og 8 GB av systemminne, utsted:

bash -e << \EOF
  sudo mkdir /sys/fs/cgroup/$$
  sudo sh -c \
    "echo +memory +cpuset > /sys/fs/cgroup/cgroup.subtree_control"
  sudo sh -c \
    "echo 0-3 > /sys/fs/cgroup/$$/cpuset.cpus"
  sudo sh -c \
    "echo $(bc -e '8*2^30') > /sys/fs/cgroup/$$/memory.high"
  (
    sudo sh -c "echo $BASHPID > /sys/fs/cgroup/$$/cgroup.procs"
    exec make -j5
  )
  sudo rmdir /sys/fs/cgroup/$$
EOF

Med 8589934592 (utdataen av bc -e '8*2^30', 2^30 representerer 230, dvs. en Gigabyte) i memory.high oppføringen , en myk grense for minnebruk er satt. Hvis prosessene i cgroup (make og alle underprosesser av den) bruker mer enn 8 GB systemminne totalt, kjernen vil strupe ned prosessene og prøve å gjenvinne systemminne fra dem. Men de kan fortsatt bruke mer enn 8 GB systemminne. Hvis du vil sette en hard grense i stedet, erstatt memory.high med memory.max. Men å gjøre det vil føre til at prosessene drepes hvis 8 GB ikke er nok for dem.

0-3 i cpuset.cpus oppføringen gjør at kjernen bare kjører prosessene i cgroup på de logiske kjernene med tallene 0, 1, 2 eller 3. Det kan hende du må juster denne innstillingen basert på kartleggingen mellom de logiske kjernene og fysiske kjerner. For eksempel, med en Intel Core i9-13900K CPU, de logiske kjernene 0, 2, 4, ..., 14 er tilordnet de første trådene til de åtte fysiske P-kjernene, de logiske kjernene 1, 3, 5, ..., 15 er kartlagt til de andre trådene til de fysiske P-kjernene, og den logiske kjernene 16, 17, ..., 31 er kartlagt til de 16 fysiske E-kjernene. Så hvis vi ønsker å bruke fire tråder fra fire forskjellige P-kjerner, må vi spesifisere 0,2,4,6 i stedet for 0-3. Merk at de andre CPU modeller kan bruke et annet kartleggingsskjema. Hvis du ikke er sikker på kartleggingen mellom de logiske kjernene og de fysiske kjernene, kjør lscpu --extended kommandoen som vil gi ut logiske kjerne IDer i CPU kolonnen og fysisk kjerne IDer i CORE kolonnen.

Når nproc eller ninja kommandoer kjører i en cgroup, vil den bruke antallet logiske kjerner som er tildelt cgroup som system logical core count. For eksempel i en cgroup med logiske kjerner 0-3 tildelt, nproc vil skrive ut 4, og ninja vil kjøre 6 (4 + 2) jobber samtidig hvis ingen -j innstilling er eksplisitt gitt.

Les Documentation/admin-guide/cgroup-v2.rst filen i Linux kjernekildetreet for detaljert forklaring av cgroup2 pseudo-fil systemoppføringer referert til i kommandoen.

Automatiserte Byggeprosedyrer

Det er tider når automatisering av byggingen av en pakke kan være praktisk. Alle har sine egne grunner til å ønske å automatisere byggingen, og alle gjør det på sin egen måte. Å opprette Makefileer, Bash skripter, Perl skripter eller bare en liste over kommandoer som brukes til å klippe og lime er bare noen av metodene du kan bruke for å automatisere byggingen av BLFS pakker. Detaljert hvordan og eksempler på de mange måter du kan automatisere byggingen av pakker på er utenfor rammen av denne seksjonen. Denne delen vil vise deg bruk av filomdirigering og yes kommandoer for å gi ideer om hvordan du kan automatisere byggene dine.

Filomadressering for å Automatisere Inndata

Du vil finne tidspunkter gjennom hele BLFS reisen din at du kommer over en pakke som har en kommando som ber deg om informasjon. Denne informasjon kan være konfigurasjonsdetaljer, en mappebane eller et svar til en lisensavtale. Dette kan by på en utfordring for å automatisere byggingen av den pakken. Noen ganger vil du bli bedt om annen informasjon i en rekke spørsmål. En metode for å automatisere denne typen scenario krever å legge de ønskede svarene i en fil og bruke omdirigering slik at programmet bruker dataene i filen som svar på spørsmålene.

Dette gjør effektivt at testpakken bruker svarene i filen som innspill til spørsmålene. Av og til kan du ende opp med å gjøre litt prøving og feiling for å bestemme det nøyaktige formatet på inndatafilen for noen ting, men når du har funnet ut og dokumentert, kan du bruke dette til å automatisere byggingen av pakken.

Bruke yes for å Automatisere Inndata

Noen ganger trenger du bare å gi ett svar, eller gi samme svar på mange spørsmål. For disse tilfellene, yes kommandoen fungerer veldig bra. yes kommandoen kan brukes til å gi et svar (det samme ett) til ett eller flere forekomster av spørsmål. Den kan brukes til å simulere å trykke på Enter tasten, skrive inn Y tasten eller skrive inn en tekststreng. Kanskje den enkleste måten er å vise bruken på er i et eksempel.

Først lager du et kort Bash skript ved å skrive inn følgende kommandoer:

cat > blfs-yes-test1 << "EOF"
#!/bin/bash

echo -n -e "\n\nPlease type something (or nothing) and press Enter ---> "

read A_STRING

if test "$A_STRING" = ""; then A_STRING="Just the Enter key was pressed"
else A_STRING="You entered '$A_STRING'"
fi

echo -e "\n\n$A_STRING\n\n"
EOF
chmod 755 blfs-yes-test1

Kjør nå skriptet ved å utstede ./blfs-yes-test1 fra kommandolinjen. Den vil vente på et svar, som kan være hva som helst (eller ingenting) etterfulgt av Enter tasten. Etter å ha skrevet inn noe, vil resultatet bli ekkoet til skjermen. Bruk nå yes kommandoen for å automatisere inntasting av en respons:

yes | ./blfs-yes-test1

Legg merke til videreledingen av yes til skriptet resulterer i at y blir overført til skriptet. Prøv nå med en tekststreng:

yes 'This is some text' | ./blfs-yes-test1

Den nøyaktige strengen ble brukt som respons på skriptet. Endelig, prøv det med en tom (null) streng:

yes '' | ./blfs-yes-test1

Legg merke til at dette resulterer i at du bare videreleder pressingen av Enter tasten til skriptet. Dette er nyttig for når standardsvar på ledeteksten er tilstrekkelig. Denne syntaksen brukes i Net-tools instruksjoner for å godta alle standardsvarene til de mange ledetekstene under konfigurasjonstrinnet. Du kan nå fjerne testskriptet om ønskelig.

Filomadressering for å Automatisere Utdata

For å automatisere byggingen av noen pakker, spesielt de som krever at du leser en lisensavtale en side om gangen, krever å bruke en metode som unngår å måtte trykke på en tast for å vise hver side. Omdirigere utdataene til en fil kan brukes i disse tilfellene for å hjelpe med automatiseringen. Den forrige delen på denne siden berørte opprettelse av loggfiler for byggeutdataen. Omdirigeringsmetoden vist der brukte tee kommandoen for å omdirigere utdata til en fil men også vise utdataene på skjermen. Her vil utdataen kun sendes til en fil.

Igjen, den enkleste måten å demonstrere teknikken på er å vise et eksempel. Usted først kommandoen:

ls -l /usr/bin | less

Selvfølgelig må du se utdataene en side om gangen fordi less filteret ble brukt. Prøv nå den samme kommandoen, men denne gangen omdirigerer utdataene til en fil. Den spesielle filen /dev/null kan brukes i stedet for filnavnet som vises, men du vil ikke ha noen loggfil å undersøke:

ls -l /usr/bin | less > redirect_test.log 2>&1

Legg merke til at denne gangen kom kommandoen umiddelbart tilbake til skallets ledetekst uten å måtte bla gjennom utdataene. Du kan nå fjerne loggfilen.

Det siste eksemplet vil bruke yes kommandoen i kombinasjon med utdataomdirigering for å omgå å måtte bla gjennom utdataen og deretter gi en y til en spørring. Denne teknikken kan brukes i tilfeller der du ellers måtte bla gjennom utdata fra en fil (for eksempel en lisensavtale) og svare deretter på spørsmål om do you accept the above?. For dette eksempelet, et annen kort Bash skript kreves:

cat > blfs-yes-test2 << "EOF"
#!/bin/bash

ls -l /usr/bin | less

echo -n -e "\n\nDid you enjoy reading this? (y,n) "

read A_STRING

if test "$A_STRING" = "y"; then A_STRING="You entered the 'y' key"
else A_STRING="You did NOT enter the 'y' key"
fi

echo -e "\n\n$A_STRING\n\n"
EOF
chmod 755 blfs-yes-test2

Dette skriptet kan brukes til å simulere et program som krever at du leser en lisensavtale, og svarer deretter på riktig måte for å godta avtalen før programmet vil installere noe. Kjør først skriptet uten automatiseringsteknikker ved å utstede ./blfs-yes-test2.

Utfør nå følgende kommando som bruker to automatiseringsteknikker, gjøre det egnet for bruk i et automatisert byggeskript:

yes | ./blfs-yes-test2 > blfs-yes-test2.log 2>&1

Hvis ønskelig, utsted tail blfs-yes-test2.log for å se slutten av den sidesøkte utdataen, og bekreftelse på at y ble sendt videre til skriptet. Når du er overbevist om at den fungerer som den skal, kan du fjerne skriptet og loggfilen.

Til slutt, husk at det er mange måter å automatisere og/eller skripte byggekommandoene. Det er ikke en eneste riktig måte å gjøre det på. Det er bare fantasien din som setter grenser.

Avhengigheter

For hver pakke som er beskrevet, viser BLFS de kjente avhengighetene. Disse er oppført under flere overskrifter, hvis betydning er som følger:

  • Påkrevd betyr at målpakken ikke kan bygges riktig uten at avhengigheten først har blitt installert, bortsett fra hvis avhengigheten sies å være kjøretid som betyr at målpakken kan bygges men kan ikke fungere uten den.

    Merk at en målpakke kan begynne å fungere på mange subtile måter: en installert konfigurasjonsfil kan gjøre init systemet, cron nissen eller buss nissen for å kjøre et program automatisk; en annen pakke som bruker målpakken som en avhengighet kan kjøre et program fra målpakken i byggesystemet; og konfigurasjonsdelene i BLFS boken kan også kjøre et program fra en nettopp installert pakke. Så hvis du installerer målpakken uten en Påkrevd (kjøretid) avhengighet installert, Bør du installere avhengigheten så snart som mulig etter installasjonen av målpakken.

  • Anbefalt betyr at BLFS sterkt foreslår at denne pakken installeres først (bortsett fra hvis det sies å være kjøretid, se nedenfor) for et rent og problemfritt bygg, som ikke vil ha problemer verken under byggeprosessen eller ved kjøretid. Instruksjonene i boken forutsetter at disse pakkene er installert. Noen endringer eller løsninger kan være nødvendige hvis disse pakker ikke er installert. Hvis en anbefalt avhengighet er sagt å være kjøretid, betyr det at BLFS sterkt foreslår at denne avhengigheten er installert før du bruker pakken, for å få full funksjonalitet.

  • Valgfri betyr at denne pakken kan bli installert for ekstra funksjonalitet. Ofte vil BLFS beskrive avhengighet for å forklare den ekstra funksjonalitetenen som vil bli resultatet. Noen valgfrie avhengigheter kan automatisk plukkes opp av målpakken hvis avhengigheten er installert, mens andre trenger flere konfigurasjonsalternativer for å bli aktivert når målpakken er bygget. Slike tilleggsalternativer er ofte dokumentert i BLFS boken. Hvis en valgfri avhengighet er sagt å være kjøretid, betyr det at du kan installere avhengigheten etter installasjon av målpakken for å støtte noen valgfrie funksjoner i målpakken hvis du trenger disse egenskapene.

    En valgfri avhengighet kan være utenfor BLFS. Hvis du trenger en slik ekstern valgfri avhengighet for noen funksjoner du trenger, les Gå Utover BLFS for generelle hint om å installere en pakke utenfor BLFS.

Bruke de Nyeste Pakkekildene

Noen ganger kan du støte på en situasjon i boken når en pakke ikke vil bygge eller fungere skikkelig. Selv om redaktørene prøver å sikre at hver pakke i boken bygger og fungerer som den skal, noen ganger har pakken blitt oversett eller ble ikke testet med denne versjonen av BLFS.

Hvis du oppdager at en pakke ikke vil bygge eller fungere som den skal, bør du se om det finnes en mer oppdatert versjon av pakken. Typisk betyr dette at du går til vedlikeholderens nettsted og laster ned den nyeste tarballen og forsøke å bygge pakken. Hvis du ikke kan bestemme vedlikeholderens nettsted ved å se på nedlastingsadressene, bruk Google og spør etter pakkens navn. Skriv for eksempel i Google-søkefeltet: 'pakkenavn nedlasting' (utelat anførselstegn) eller noe lignende. Noen ganger å skrive: 'pakkenavn hjemmeside' vil resultere i at du finner vedlikeholderens nettsted.

Strippe En Gang Til

I LFS, stripping av feilsøkingssymboler og unødvendige symboltabell oppføringer ble diskutert et par ganger. Når du bygger BLFS pakker, er det generelt ingen spesielle instruksjoner som diskuterer stripping en gang til. Stripping kan gjøres mens du installerer en pakke, eller etterpå.

Stripping while Installing a Package

Det er flere måter å strippe kjørbare filer installert av en pakke. Det avhenger av byggesystemet som brukes (se nedenfor avsnittet om byggesystemer), så bare noen generelle forhold kan listes opp her:

[Note]

Note

Følgende metoder ved hjelp av funksjonen til et byggesystem (autoverktøy, meson eller cmake) vil ikke strippe statiske biblioteker hvis noen er installert. Heldigvis er det ikke for mange statiske biblioteker i BLFS, og et statisk bibliotek kan alltid strippes trygt med å kjøre strip --strip-unneeded på den manuelt.

  • Pakkene som bruker autoverktøy har vanligvis et install-strip mål i deres genererte Makefile filer. Så å installere strippede kjørbare er bare et spørsmål om å bruke make install-strip i stedet for make install.

  • Pakkene som bruker meson byggesystemet kan godta -D strip=true når du kjører meson. Hvis du har glemt å legge til dette alternativet ved kjøring av meson, kan du også kjøre meson install --strip i stedet for ninja install.

  • cmake genererer install/strip mål for både Unix Makefiles og Ninja generatorer (standard er Unix Makefiles på linux). Så bare kjør make install/strip eller ninja install/strip i stedet for install motparter.

  • Å strippe (eller ikke generere) feilsøkingssymboler kan også oppnås ved å strippe -g<noe> alternativer i C/C++ anrop. Hvordan du gjør det er veldig spesifikt for hver enkelt pakke. Og den stripper ikke unødvendige symboltabelloppføringer. Så det vil ikke bli forklart i detalj her. Se også nedenfor avsnittene om optimalisering.

Stripping av Installerte Kjørbare filer

strip verktøyet endrer filer på plass, noe som kan bryte noe ved å bruke det hvis det er lastet inn i minnet. Merk at hvis en fil er i bruk, men nettopp strippet fra disken (dvs. ikke overskrevet eller modifisert), er dette ikke et problem siden kjernen kan bruke slettede filer. Se på /proc/*/maps og det er sannsynlig at du vil se noen (slettede) oppføringer. mv fjerner bare målfilen fra mappen, men berører ikke innholdet, slik at den tilfredsstiller betingelsen for at kjernen skal bruke den gamle (slettede) filen. Men denne tilnærmingen kan løsne harde lenker til dupliserte kopier, forårsaker det en oppblåsthet som åpenbart er uønsket når vi stripper for å redusere systemstørrelsen. Hvis to filer i samme filsystem deler samme inodenummer, de er harde lenker til hverandre, og vi burde rekonstruere koblingen. Skriptet nedenfor er bare et eksempel. Det skal kjøres som root bruker:

cat > /usr/sbin/strip-all.sh << "EOF"
#!/usr/bin/bash

if [ $EUID -ne 0 ]; then
  echo "Need to be root"
  exit 1
fi

last_fs_inode=
last_file=

{ find /usr/lib -type f -name '*.so*' ! -name '*dbg'
  find /usr/lib -type f -name '*.a'
  find /usr/{bin,sbin,libexec} -type f
} | xargs stat -c '%m %i %n' | sort | while read fs inode file; do
       if ! readelf -h $file >/dev/null 2>&1; then continue; fi
       if file $file | grep --quiet --invert-match 'not stripped'; then continue; fi

       if [ "$fs $inode" = "$last_fs_inode" ]; then
         ln -f $last_file $file;
         continue;
       fi

       cp --preserve $file    ${file}.tmp
       strip --strip-unneeded ${file}.tmp
       mv ${file}.tmp $file

       last_fs_inode="$fs $inode"
       last_file=$file
done
EOF
chmod 744 /usr/sbin/strip-all.sh

Hvis du installerer programmer i andre mapper som f.eks /opt eller /usr/local, kan det være lurt å strippe filene der også. Bare legg til andre mapper for å skanne i den sammensatte find kommandoen mellom krøllparentesene i listen over.

For mer informasjon om stripping, se https://www.technovelty.org/linux/stripping-shared-libraries.html.

Arbeide med ulike byggesystemer

Det er nå tre forskjellige byggesystemer i vanlig bruk for å konvertere C eller C++ kildekode til kompilerte programmer eller biblioteker og deres detaljer (spesielt å finne ut om tilgjengelige alternativer og deres standardverdier) er forskjellige. Det er kanskje lettest å forstå problemene forårsaket av noen valg (vanligvis langsom utførelse eller uventet bruk av, eller utelatelse av, optimaliseringer) ved å starte med CFLAGS, CXXFLAGS, og LDFLAGS miljøvariabler. Det er også noen programmer som bruker Rust.

De fleste LFS og BLFS byggere er sannsynligvis klar over det grunnleggende om CFLAGS og CXXFLAGS for å endre hvordan et program er kompilert. Vanligvis brukes en eller annen form for optimalisering av oppstrøms utviklere (-O2 eller -O3), noen ganger med opprettelse av feilsøkingssymboler (-g), som standard.

Hvis det er motstridende flagg (f.eks. flere forskjellige -O verdier), den siste verdien vil bli brukt. Noen ganger betyr dette at flagg spesifisert i miljøvariabler vil bli plukket opp før verdier hardkodet i Makefilen, og derfor ignorert. For eksempel, der en bruker spesifiserer -O2 og det blir etterfulgt av -O3 vil byggingen bruke -O3.

Det er forskjellige andre ting som kan sendes i CFLAGS eller CXXFLAGS, for eksempel å tillate bruk av instruksjonssettet utvidelser tilgjengelig med en spesifikk mikroarkitektur (f.eks. -march=amdfam10 eller -march=native), stille inn den genererte koden for en spesifikk mikroarkitektur (f.eks. -mtune=tigerlake or -mtune=native, hvis -mtune= ikke brukes, mikroarkitekturen fra -march= innstillingen vil bli brukt), eller spesifisere en spesifikk standard for C eller C++ (-std=c++17 for eksempel). Men en ting som nå har kommet frem er at programmerere kan inkludere feilsøkingspåstander i koden sin, forventer de skal deaktiveres i utgivelser ved å bruke -D NDEBUG. Spesielt hvis Mesa-24.1.5 er bygget med disse påstander aktivert, noen aktiviteter som lasting av spill kan ta ekstremt lang tid, selv på skjermkort av høy klasse.

Autotools med Make

Denne kombinasjonen beskrives ofte som CMMI (configure, make, make install) og brukes her til også å dekke de få pakkene som har et konfigureringsskript som ikke er generert av autoverktøy.

Noen ganger å kjøre ./configure --help vil produsere nyttige alternativer om brytere som kan brukes. Andre ganger, etter å ha sett på utdataene fra configure må du kanskje se på detaljene i skriptet for å finne ut hva det faktisk søkte for.

Mange konfigureringsskript vil plukke opp alle CFLAGS eller CXXFLAGS fra miljøet, men CMMI pakker varierer med hvordan disse vil bli blandet med flagg som ellers ville blitt brukt (forskjellig: ignorert, brukt til å erstatte programmererens forslag, brukt før programmerers forslag, eller brukt etter programmererens forslag).

I de fleste CMMI pakkene vil kjøring av make liste hver kommando og kjøre det, ispedd eventuelle advarsler. Men noen pakker prøver å være stille og bare vise hvilken fil de kompilerer eller kobler i stedet for å vise kommandolinjen. Hvis du trenger å inspisere kommandoen, enten på grunn av en feil, eller bare for å se hvilke alternativer og flagg som brukes, legg til V=1 for å lage påkallelsen kan hjelpe.

CMake

CMake fungerer på en helt annen måte, og den har to bakstykker som kan brukes på BLFS: make og ninja. Standard bakstykke er make, men ninja kan være raskere på store pakker med flere prosessorer. For å bruke ninja, spesifiser -G Ninja i cmake kommandoen. Imidlertid er det noen pakker som skaper fatale feil i deres ninja filer, men bygd vellykket ved å bruke standard Unix Makefiler.

Den vanskeligste delen med å bruke CMake er å vite hvilke alternativer du måtte ønske å spesifisere. Den eneste måten å få en liste over hva pakken vet er å kjøre cmake -LAH og se på utdataen for standardkonfigurasjon.

Det kanskje viktigste med CMake er at den har en variasjon av CMAKE_BUILD_TYPE verdier, og disse påvirker flaggene. Standaren er at dette ikke er satt og ingen flagg blir generert. Eventuelle CFLAGS eller CXXFLAGS i miljøet vil bli brukt. Hvis programmereren har kodet noen feilsøkingspåstander, disse vil være aktivert med mindre -D NDEBUG brukes. Følgende CMAKE_BUILD_TYPE verdier vil generere flaggene som vises, og disse skal komme etter eventuelle flagg i miljøet og har derfor forrang.

Verdi Flagg
Debug -g
Release -O3 -D NDEBUG
RelWithDebInfo -O2 -g -D NDEBUG
MinSizeRel -Os -D NDEBUG

CMake prøver å produsere stille bygginger. For å se detaljene til kommandoene som kjøres, bruk make VERBOSE=1 eller ninja -v.

Som standard behandler CMake filinstallasjon annerledes enn andre byggesystemer: hvis en fil allerede eksisterer og ikke er nyere enn en fil som ville overskrive den, så blir ikke filen installert. Dette kan være et problem hvis en bruker ønsker å registrere hvilken fil som tilhører en pakke, enten ved hjelp av LD_PRELOAD, eller ved å liste nyere filer enn et tidsstempel. Standarden kan endres ved å angi variabelen CMAKE_INSTALL_ALWAYS til 1 i miljøet, for eksempel med å export det.

Meson

Meson har noen likheter med CMake, men mange forskjeller. Å få detaljer om definisjonene som du kanskje ønsker å endre kan du se på meson_options.txt som vanligvis er i mappen på øverste nivå.

Hvis du allerede har konfigurert pakken ved å kjøre meson og nå ønsker å endre en eller flere innstillinger, kan du enten fjerne byggemappen, gjenskape den og bruke de endrede alternativene, eller kjøre i byggemappen meson configure, f.eks. for å angi et alternativ:

meson configure -D <some_option>=true

Hvis du gjør det, filen meson-private/cmd_line.txt vil vise den siste kommandoen som ble brukt.

Meson gir følgende byggetype verdier, og flaggene de aktiverer kommer etter eventuelle flagg som leveres i miljøet og har derfor forrang.

  • plain: ingen flagg lagt til. Dette er for distributører for å levere sine egne CFLAGS, CXXFLAGS og LDFLAGS. Det er ingen åpenbar grunn til å bruke dette i BLFS.

  • debug: -g - dette er standard hvis ingenting er spesifisert i enten meson.build eller kommandolinjen. Men det resulterer i store og langsomme binærfiler, så vi bør overstyre det i BLFS.

  • debugoptimized: -O2 -g - dette er standard spesifisert i meson.build av noen pakker.

  • release: -O3 (noen ganger vil en pakke tvinge -O2 her) - dette er byggetypen vi bruker for de fleste pakker med Meson byggesystem i BLFS.

-D NDEBUG flagget antydes av utgivelsen byggetype for noen pakker (for eksempel Mesa-24.1.5). Det kan også gis eksplisitt ved å sende -D b_ndebug=true.

For å se detaljene for kommandoene som kjøres i en pakke ved hjelp av meson, bruk ninja -v.

Rustc og Cargo

De fleste utgitte rustc programmer leveres som crates (kilde tarballer) som vil spørre en server om å sjekke gjeldende versjoner av avhengigheter og last dem ned etter behov. Disse pakkene er bygget med cargo --release. I teorien kan du manipulere RUSTFLAGS for å endre optimaliseringsnivået (standard for --release er 3, dvs -Copt-level=3, er lik -O3) eller for å tvinge den til å bygge for maskinen den blir kompilert på, ved hjelp av -Ctarget-cpu=native men i praksis ser dette ut til å ikke gjøre noen vesentlig forskjell.

Hvis du kompilerer et frittstående Rust program (som et upakket .rs fil) ved å kjøre rustc direkte, bør du spesifisere -O (forkortelsen av -Copt-level=2) eller -Copt-level=3 ellers vil den gjøre en uoptimalisert kompilering og kjøre mye langsommere. Hvis du kompilerer programmet for å feilsøke det, bytt ut -O eller -Copt-level= alternativer med -g for å produsere et uoptimalisert program med feilsøkingsinformasjon.

Lik ninja, som standard cargo bruker alle logiske kjerner. Dette kan ofte omgås, enten ved å eksportere CARGO_BUILD_JOBS=<N> eller sende --jobs <N> til cargo. For å kompilere rustc selv, spesifisere --jobs <N> for påkallelser av x.py (sammen med CARGO_BUILD_JOBS miljøvariabel, som ser ut som en belte og seler tilnærming, men ser ut til å være nødvendig) fungerer for det meste. Unntaket er kjører testene når du bygger rustc, noen av dem vil bruk likevel alle tilgjengelige CPUer, i det minste fra og med rustc-1.42.0.

Optimalisering av bygget

Mange mennesker vil foretrekke å optimalisere kompileringer slik de finner passende, ved å tilby CFLAGS eller CXXFLAGS. For en introduksjon til alternativene tilgjengelig med gcc og g++ se https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Optimize-Options.html. Det samme innholdet finnes også i info gcc.

Noen pakker er som standard -O2 -g, andre -O3 -g, og hvis CFLAGS eller CXXFLAGS leveres, kan de legges til pakkens standardinnstillinger, erstatte pakkens standardinnstillinger, eller til og med bli ignorert. Det er detaljer om noen skrivebordspakker som var stort sett aktuelt i april 2019 på https://www.linuxfromscratch.org/~ken/tuning/ - i spesielt, README.txt, tuning-1-packages-and-notes.txt, og tuning-notes-2B.txt. Det spesielle å huske er at hvis du ønsker å prøve noen av de mer interessante flagg trenger du kanskje å tvinge detaljerte bygg for å bekrefte hva som blir brukt.

Klart, hvis du optimaliserer ditt eget program kan du bruke tid på det profilere det og kanskje omkode noe av det hvis det er for tregt. Men for å bygge et helt system er det upraktisk. Generelt, -O3 produserer vanligvis raskere programmer enn -O2. Spesifisere -march=native er også gunstig, men det betyr at du ikke kan flytte binærfilene til en inkompatibel maskin - dette gjelder også for nyere maskiner, ikke bare for eldre maskiner. For eksempelprogrammer kompilert for amdfam10 kjører på gamle Phenoms, Kaveris og Ryzens, men programmer kompilert for en Kaveri vil ikke kjøre på en Ryzen fordi visse op-koder ikke er tilstede. På samme måte, hvis du bygger for en Haswell, vil ikke alt kjøre på en SandyBridge.

[Note]

Note

Pass på at navnet på en -march innstilling samsvarer ikke alltid med basislinjen til mikroarkitekturen med samme navn. For eksempel Skylake baserte Intel Celeron prosessorer støtter ikke AVX i det hele tatt, men -march=skylake antar AVX og til og med AVX2.

Når et delt bibliotek bygges av GCC, en funksjon kalt semantic interposition er aktivert som standard. Når det delte biblioteket refererer til et symbolnavn med ekstern kobling og standard synlighet, hvis symbolet finnes i begge de delte biblioteket og de viktigste kjørbare, semantiske interposisjonsgarantiene symbolet i den kjørbare hovedfilen brukes alltid. Denne funksjonen ble oppfunnet i et forsøk på å gjøre oppførselen til å koble til en delt bibliotek og koble et statisk bibliotek så likt som mulig. I dag bare et lite antall pakker er fortsatt avhengig av semantikk interposisjon, men funksjonen er fortsatt på som standard for GCC, forårsaker mange optimaliseringer deaktivert for delte biblioteker fordi de er i konflikt med semantisk interposisjon. -fno-semantic-interposition alternativet kan bli sendt til gcc eller g++ for å deaktivere semantisk interposisjon og muliggjør flere optimaliseringer for delt biblioteker. Dette alternativet brukes som standard for enkelte pakker (for eksempel Python-3.12.5), og det er også standard for Clang.

Det er også forskjellige andre alternativer som noen hevder er gunstige. I verste fall får du rekompilere og teste, og så oppdage at i din bruk gir alternativene ikke en fordel.

Hvis du bygger Perl eller Python moduler, generelt CFLAGS og CXXFLAGS brukt er de som ble brukt av disse foreldre pakker.

For LDFLAGS, det er tre alternativer som kan brukes for optimalisering. De er ganske trygge å bruke og byggesystemet for noen pakker bruker noen av disse alternativene som standard.

Med -Wl,-O1, linkeren vil optimer hash tabellen for å øke hastigheten på den dynamiske koblingen. Merk at -Wl,-O1 er helt urelatert til kompilatoroptimaliseringsflagg -O1.

Med -Wl,--as-needed, linkeren vil se bort fra unødvendige -lfoo alternativer fra kommandolinjen, dvs. e. det delte biblioteket libfoo vil bare bli koblet hvis et symbol i libfoo er virkelig henvist fra det kjørbare eller delte biblioteket som kobles til. Dette kan noen ganger dempe overdreven avhengighet til delte biblioteker problemer forårsaket av libtool.

Med -Wl,-z,pack-relative-relocs, linkeren genererer en mer komprimert form av de relative flytteoppføringene for PIE-er og delte biblioteker. Det reduserer størrelsen på den tilknyttede PIE eller delt bibliotek, og fremskynder lasting av PIE eller delt bibliotek.

-Wl, prefiks er nødvendig fordi til tross for at variabelen er navngitt LDFLAGS, innholdet er faktisk sendt til gcc (eller g++, clang, etc.) under koblingsstadiet, ikke direkte sendt til ld.

Alternativer for å sikre bygget

Selv på stasjonære systemer er det fortsatt mye som kan utnytte sårbarheter. For mange av disse kommer angrepet via javascript i en nettleser. Ofte brukes en rekke sårbarheter for å få tilgang til data (eller noen ganger til pwn, dvs. eie, maskinen og installer rootkits). De fleste kommersielle distros vil bruke ulike sikringstiltak.

Tidligere var det Hardened LFS der gcc (en mye eldre versjon) ble tvunget til å bruke herding (med alternativer for å slå av noe av det på en per pakke-basis). De nåværende LFS- og BLFS-bøkene fører videre en del av sin ånd ved å aktivere PIE (-fPIE -pie) og SSP (-fstack-protector-strong) som standard for GCC og clang. Og, linkerene (ld.bfd og ld.gold) har også aktivert -Wl,-z,relro som gjør en del av Global Offset Table (GOT) uforanderlig, som standard siden Binutils 2.27. Det som blir dekket her er annerledes - først må du sørge for at pakken faktisk bruker flaggene du har lagt til, og ikke overstyrer dem.

For herdealternativer som er rimelig billige, finnes det noen diskusjon i "tuning" lenken ovenfor (noen ganger kan en eller flere av disse alternativene være upassende for en pakke). Disse alternativene er -D _FORTIFY_SOURCE=2 (eller -D _FORTIFY_SOURCE=3 som er sikrere men med større ytelsesoverhead) og (for C++) -D _GLIBCXX_ASSERTIONS. På moderne maskiner skal disse bare ha en liten innvirkning på hvor raskt ting kjører, og ofte vil de ikke merkes.

De største distroene bruker mye mer, som f.eks:

  • -Wl,-z,now: deaktiverer lazy binding for å forbedre -Wl,-z,relro, sånn at hele GOT kan gjøres uforanderlig.

  • -fstack-clash-protection: hindrer angriperen fra å bruke en offset som er stor nok og ikke tilstrekkelig kontrollert til å hoppe over stabel guard siden plassert av kjernen og stabel canary plassert ved -fstack-protector=strong, og endre stabelen fra en heapadresse, eller omvendt.

  • -ftrivial-auto-var-init=zero: initialiserer noen variabler ved å fylle null byte hvis de ikke er initialisert på andre måter.

  • -fcf-protection=full: bruker Intel og AMD CET teknologi for å begrense måladressene for control-flow overføringsinstruksjoner. For å gjøre det virkelig effektivt for en pakke, alle pakker som gir et delt bibliotek for pakken som skal brukes må bygges med dette alternativet, så vel som selve pakken, Glibc må konfigureres med --enable-cet alternativet aktivert, og systemet må kjøre på Intel Tiger Lake eller nyere, eller AMD Zen 3 eller nyere. Dersom kriteriene ikke er oppfylt, vil programmet satt sammen med dette alternativet fortsatt kjøre, men er egentlig ikke beskyttet av CET.

I GCC 14, alternativet -fhardened er en forkortelse for å aktivere alle herdealternativene nevnt ovenfor. Det setter -D _FORTIFY_SOURCE=3 istedenfor -D _FORTIFY_SOURCE=2.

Du kan også møte den såkalte userspace retpoline (-mindirect-branch=thunk etc.) hvilken tilsvarer spekter begrensninger som ble tatt i bruk i linuxkjernen sent i 2018. Kjernebegrensningene forårsaket mange klager om tapt ytelse, hvis du har en produksjonsserver ønsker du kanskje å vurdere å teste det, sammen med de andre tilgjengelige alternativene, å se om ytelsen fortsatt er tilstrekkelig.

Mens gcc har mange herdealternativer, ligger clang/LLVMs styrke andre steder. Noen alternativer som gcc tilbyr sies å være mindre effektive i clang/LLVM.