Celles et ceux qui ont construit un système LFS connaissent sans doute les principes généraux du téléchargement et de l'extraction de logiciel. Certaines de ces informations sont répétées ici pour les nouveaux qui construisent leurs propres logiciels.
Chaque ensemble d'instructions d'installation contient une URL sur laquelle laquelle vous pouvez télécharger le paquet. Cependant, les correctifs sont enregistrés sur les serveurs LFS et disponibles via HTTP. Ces derniers sont référencés, si besoin, dans les instructions d'installation.
Même si vous pouvez placer les fichiers sources où vous voulez, nous supposons que vous avez extrait le paquet et êtes allé dans le répertoire créé par le processus de décompression (le répertoire des sources). Nous supposons aussi que vous avez décompressé les correctifs requis et qu'ils sont dans le répertoire directement au-dessus du répertoire des sources.
Nous ne saurions que trop vous recommander de démarrer à partir d'une
arborescence de sources propre
à chaque fois. Cela veut dire que si vous avez eu une erreur lors de
la configuration ou de la compilation, il est généralement préférable
de supprimer l'arborescence des sources et de l'extraire de nouveau
avant de réessayer. Cela ne
s'applique évidemment pas si vous êtes un utilisateur avancé habitué
à modifier les Makefile
s et le code C.
Si vous avez un doute cependant, commencez à partir d'une
arborescence propre.
La règle d'or de l'administration d'un système Unix est de
n'utiliser vos super-pouvoirs que si nécessaire. D'où la
recommandation de BLFS de construire les logiciels en tant
qu'utilisateur non privilégié et de ne devenir l'utilisateur
root
que lors de l'installation du
logiciel. On suit cette philosophie dans tous les paquets de ce
livre. Sauf spécifications contraires, toutes les instructions
devraient être exécutées en tant qu'utilisateur non privilégié. Le
livre vous conseillera sur les instructions qui ont besoin des
privilèges root
.
S'il y a un fichier compressé au format .tar
, on le décompresse en utilisant une des
commandes suivantes :
tar -xvf filename.tar.gz tar -xvf filename.tgz tar -xvf filename.tar.Z tar -xvf filename.tar.bz2
Vous pouvez ne pas utiliser le paramètre v
dans les commandes décrites ci-dessus et
ci-dessous si vous souhaitez supprimer le listage verbeux de tous
les fichiers de l'archive au fur et à mesure qu'ils sont
extraits. Cela peut aider à accélérer l'extraction mais aussi
rendre plus évidentes les erreurs produites durant le processus.
Vous pouvez aussi utiliser une méthode légèrement différente :
bzcat filename.tar.bz2 | tar -xv
Enfin, nous avons parfois un fichier de correctif compressé au
format .patch.gz
ou .patch.bz2
. La meilleure manière d'applique le
correctif est de passer la sortie du décompresseur à l'utilitaire
patch via un pipe.
Par exemple :
gzip -cd ../patchname.patch.gz | patch -p1
Ou pour un correctif compressé avec bzip2 :
bzcat ../patchname.patch.bz2 | patch -p1
En général, pour vérifier que le fichier téléchargé est complet, de
nombreux mainteneurs de paquets distribuent aussi les sommes md5
des fichiers. Pour vérifier la somme md5 des fichiers téléchargés,
téléchargez à la fois le fichier et le fichier md5sum correspondant
dans le même répertoire (de préférence à partir d'emplacements
différents en ligne) et (en supposant que file.md5sum
est le fichier md5sum téléchargé),
lancez la commande suivante :
md5sum -c file.md5sum
S'il y a une erreur, elle sera signalée. Remarquez que le livre
BLFS contient aussi les sommes md5 de tous les fichiers sources.
Pour utiliser les sommes md5 fournies par BLFS, vous pouvez créer
un file.md5sum
(mettez les données
md5sum et le nom exact du fichier téléchargé sur la même ligne d'un
fichier, séparés par un espace blanc), et lancez la commande
montrée ci-dessus. Sinon, lancez simplement la commande décrite
ci-dessus et comparez la sortie avec les données de somme md5
inscrites dans le livre BLFS.
md5sum <name_of_downloaded_file>
Le MD5 n'est pas cryptographiquement sûr, donc les sommes md5 ne sont fournies que pour détecter des changements non intentionnels au contenu du fichier. Par exemple, une erreur ou troncation introduite pendant le transfert réseau, ou une mise à jour « furtive » du paquet en amont (mise à jour du contenu d'une archive publiée au lieu de créer directement une nouvelle version).
Il n'y a pas de manière sure à « 100 % » pour s'assurer de l'authenticité des fichiers sources. En supposant que les développeurs en amont gèrent leur site correctement (la clé privée n'est pas communiquée et le domaine n'est pas usurpé), et que les ancres de confiance ont été correctement configurées avec make-ca-1.12 sur le système BLFS, on peut raisonnablement faire confiance aux URL des site web officiels avec le protocole https. Remarquez que le livre BLFS lui-même est publié sur un site avec https, donc vous devez déjà avoir un peu confiance en le protocole https ou vous ne pourriez pas faire confiance au contenu de ce livre.
Si le paquet est téléchargé à partir d'un emplacement non officiel (par exemple un miroir local), vous pouvez utiliser des sommes de contrôles générées par un algorithme cryptographiquement sûr (par exemple SHA256) pour vérifier l'authenticité du paquet. Téléchargez le fichier de somme de contrôle depuis le site officiel des développeurs en amont (ou depuis un endroit auquel vous faites confiance) et comparez la somme de contrôle du paquet de l'emplacement non officiel. Par exemple, vous pouvez vérifier une somme de contrôle SHA256 avec la commande :
Si la somme de contrôle et le paquet sont téléchargés à partir de la même source non fiable, vous ne gagnerez rien à vérifier le paquet avec la somme de contrôle. L'attaquant peut présenter une fausse somme de contrôle en plus de compromettre le paquet en lui-même.
sha256sum -c file
.sha256sum
Si GnuPG-2.4.3 est installé, vous pouvez aussi vérifier l'authenticité du paquet avec une signature GPG. Importez la clé publique GPG amont avec :
gpg --recv-key keyID
keyID
devrait être
remplacée par l'identifiant de la clé fournie par un site
fiable (par exemple,
copiez-la depuis le site officiel en utilisant https). Maintenant
vous pouvez vérifier la signature avec :
gpg --recv-keyfile
.sigfile
L'avantage de la signature GnuPG est que, une fois une clé publique de confiance importée, vous pouvez télécharger à la fois le paquet et sa signature à partir du même emplacement non officiel et les vérifier avec la clé publique. Donc vous n'avez pas besoin de vous connecter au site officiel en amont pour récupérer une somme de contrôle pour chaque nouvelle version. Vous n'aurez besoin de mettre à jour la clé publique que si elle est révoquée ou expirée.
Pour les gros paquets, il est commode de créer des fichiers
journaux plutôt que de fixer indéfiniment l'écran en espérant
trouver une erreur ou un avertissement particulier. Les fichiers
journaux sont aussi utiles pour déboguer et garder des
enregistrements. La commande suivante vous permet de créer un
journal d'installation. Remplacez <commande>
par la commande
que vous cherchez à exécuter.
( <command>
2>&1 | tee compile.log && exit $PIPESTATUS )
2>&1
redirige les messages
d'erreur vers le même endroit que la sortie standard. La commande
tee vous permet de
voir la sortie en journalisant les résultats dans un fichier. Les
parenthèses autour de la commande exécutent toute la commande dans
un sous-shell. Enfin, la commande exit $PIPESTATUS s'assure que
c'est bien le résultat de <commande>
qui est retourné
et pas le résultat de la commande tee.
Pour la plupart des systèmes modernes avec des processeurs multiples (ou cœurs) le temps de compilation pour un paquet peut être réduit en effectuant une « construction parallèle » soit en initialisant une variable d'environnement, soit en disant au programme make combien de processeurs sont disponibles. Par exemple, un Core2Duo peut supporter deux processus simultanés avec :
export MAKEFLAGS='-j2'
ou en compilant simplement avec :
make -j2
Si vous avez appliqué le sed facultatif pendant la construction de ninja dans LFS, vous pouvez utiliser :
export NINJAJOBS=2
quand un paquet utilise ninja, ou simplement :
ninja -j2
mais pour ninja, le nombre de travaux par défaut est N + 2, si le nombre de processeurs N est plus grand que 2. Sinon, N + 1 si N est 1 ou 2. La raison pour laquelle cet outil utilise un nombre de tâches plus grand que le nombre de processeurs logiques est de faire travailler tous les processeurs logiques même si certaines tâches effectuent des opérations mémoires.
Généralement le nombre de processus ne doit pas trop dépasser le
nombre de cœurs supportés par le CPU. Pour lister les processeurs
de votre système, tapez : grep
processor /proc/cpuinfo
.
Dans certains cas, l'utilisation de processeurs multiples peut amener dans une situation de compétition où le succès de la construction dépend de l'ordre des commandes lancées par le programme make. Par exemple, si un exécutable demande un fichier A et un fichier B, essayer de lier le programme avant qu'un des composants dépendants ne soit disponible aboutira à un échec. Cela arrive en général quand les développeurs n'ont pas correctement désigné tous les prérequis utiles pour accomplir une étape du Makefile.
Si cela arrive, la meilleure chose à faire est de recommencer la
construction avec un seul processeur. En ajoutant -j1
à une commande make, cela écrasera
l'initialisation similaire dans une variable d'environnement
MAKEFLAGS
.
Un autre problème peut survenir avec les CPU modernes avec beaucoup de cœurs. Chaque tâche démarrée consomme de la mémoire, et si la somme de la mémoire requise par chaque tâche dépasse la quantité de mémoire disponible, vous aurez soit une interruption noyau OOM (plus de mémoire) ou une utilisation de l'espace d'échange qui ralentira excessivement la construction.
Comme certaines compilation avec g++ peuvent consommer jusqu'à 2,5 Go de mémoire, pour être sûr, vous devriez restreindre le nombre de tâches à (mémoire totale en Go)/2,5, au moins pour les gros paquets comme LLVM, WebKitGtk, QtWebEngine ou libreoffice.
Automatiser la construction d'un paquet peut parfois s'avérer
utile. On a tous des raisons différentes pour automatiser la
construction, et on le fait par nos propres moyens. Soit en créant
des Makefile
s, des scripts
Bash, des scripts Perl ou simplement une liste de commandes
utilisées à copier-coller. Ce sont toutes des méthodes que vous
pouvez utiliser pour automatiser la construction de paquets BLFS.
Détailler et donner des exemples sur les nombreuses manières
d'automatiser la construction de paquets va au-delà des objectifs
de cette section. Cette section vous présentera l'utilisation de la
redirection de fichiers et de la commande yes pour vous donner des idées
sur la façon d'automatiser vos constructions.
Il y aura des moments, tout au long de votre aventure BLFS, où vous tomberez sur un paquet ayant une invite de commande vous demandant des informations. Ces informations peuvent être des détails de configuration, un chemin de répertoire ou une réponse à un accord de licence. Cela peut être un challenge pour automatiser la construction de ce paquet. On vous demandera occasionnellement différentes informations via une série de questions. Une méthode pour automatiser ce type de scénario est de mettre les réponses désirées dans un fichier et d'utiliser la redirection pour que le programme utilise les données du fichier comme réponses aux questions.
Cela fait logiquement utilise les réponses du fichier comme entrée pour les questions de la suite de tests. Vous aurez parfois à faire des séries d'essais et erreurs pour déterminer le format exact de votre fichier d'entrée pour certaines choses, mais une fois expérimenté et documenté, vous pouvez utiliser cela pour automatiser la construction du paquet.
Vous n'aurez parfois besoin de ne fournir qu'une réponse ou alors la même réponse à de nombreuses invites. Dans ces cas-là, la commande yes fonctionne vraiment bien. On peut utiliser la commande yes pour fournir une réponse (la même) à une ou plusieurs questions. On peut l'utiliser pour simuler un simple appui sur la touche Entrée, l'entrée de la touche Y ou l'entrée d'une chaîne de texte. La manière la plus facile de montrer son utilisation est peut-être de prendre un exemple.
Créez tout d'abord un petit script Bash en entrant les commandes suivantes :
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
Maintenant, lancez le script en exécutant ./blfs-yes-test1 depuis la ligne de commande. Il attendra une réponse, qui peut être n'importe quoi (ou rien) suivi de la touche Entrée. Après avoir entré quelque chose, le résultat sera affiché à l'écran. Utilisez maintenant la commande yes pour automatiser l'entrée d'une réponse :
yes | ./blfs-yes-test1
Remarquez que la redirection (le piping) de yes en lui-même vers le script aboutit à ce que y est passé au script. Essayez-la maintenant avec une chaîne de texte :
yes 'This is some text' | ./blfs-yes-test1
La chaîne exacte était utilisée comme réponse au script. Enfin, essayez-la en utilisant une chaîne vide (null) :
yes '' | ./blfs-yes-test1
Remarquez que cela aboutit à ne passer au script que l'appui sur la touche Entrée. C'est utile parfois quand la réponse par défaut à l'invite est suffisante. Cette syntaxe est utilisée dans les instructions de Net-tools pour accepter tous les réglages par défaut à toutes les invites lors de l'étape de configuration. Vous pouvez maintenant supprimer le script de test si vous le désirez.
Pour automatiser la construction de certains paquets, surtout ceux qui vous demandent de lire un accord de licence page après page, il faut utiliser une méthode qui évite de devoir appuyer sur une touche pour afficher chaque page. On peut utiliser la redirection de sortie vers un fichier dans ce cas-là pour vous aider à automatiser. La section précédente de cette page a visé à créer des fichiers journaux de la sortie de la construction. La méthode de redirection qui y est décrite utilisait la commande tee pour rediriger la sortie tout en affichant aussi la sortie à l'écran. Ici on ne verra la sortie que dans un fichier.
De nouveau, la manière la plus facile de montrer la technique est de présenter un exemple. Lancez d'abord la commande :
ls -l /usr/bin | less
Bien entendu, vous devrez voir la sortie page par page car on a
utilisé le filtre less. Essayez maintenant la même
commande, mais en redirigeant cette fois la sortie vers un fichier.
Le fichier spécial /dev/null
peut
être utilisé à la place du fichier indiqué, mais vous n'aurez pas
de fichier journal à examiner :
ls -l /usr/bin | less > redirect_test.log 2>&1
Vous remarquerez que cette fois, la commande est immédiatement revenue à l'invite du shell sans devoir parcourir la sortie page par page. Vous pouvez maintenant supprimer le fichier journal.
Le dernier exemple utilisera la commande yes associée à la redirection de sortie pour éviter de naviguer page par page dans la sortie, puis de fournir un y à l'invite. Cette technique peut être utilisée dans les cas où vous devriez, sans elle, naviguer page par page dans la sortie d'un fichier (tel qu'un accord de licence), puis répondre à la question « Acceptez-vous ce qui précède ? ». Pour cet exemple, on a besoin d'un autre petit script Bash :
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
On peut utiliser ce script pour simuler un programme qui demande que vous lisiez un accord de licence et que vous acceptiez le contrat avant que le programme n'installe quoique ce soit. Lancez d'abord le script sans techniques d'automatisation en exécutant ./blfs-yes-test2.
Maintenant lancez la commande suivante qui utilise deux techniques d'automatisation, rendant l'utilisation convenable dans un script de construction automatisé :
yes | ./blfs-yes-test2 > blfs-yes-test2.log 2>&1
Si vous le désirez, lancez tail blfs-yes-test2.log pour voir la fin de la sortie paginée et la confirmation que y a été passé au script. Une fois que cela marche comme cela devrait, vous pouvez supprimer le script et le fichier journal.
Enfin, gardez à l'esprit qu'il y a de nombreux moyens d'automatiser ou de scripter les commandes de construction. Il n'y a pas « une seule » manière de procéder. Votre imagination est la seule limite.
Pour chaque paquet décrit, BLFS liste les dépendances connues. Elles sont listées sous plusieurs en-têtes, dont la signification est la suivante :
Requis signifie que le paquet cible ne peut pas se construire correctement sans avoir d'abord installé la dépendance, sauf si la dépendance est dite « à l'exécution », ce qui signifie que le paquet cible peut être construit mais ne peut pas fonctionner sans elle.
Remarquez qu'un paquet cible peut commencer à « fonctionner » de plusieurs manières subtiles : un fichier de configuration installé peut le faire exécuter au système d'initialisation, au démon cron ou au démon de bus automatiquement. Ou bien un autre paquet qui utilise le paquet cible en dépendance peut exécuter le programme du paquet cible dans son système de construction. Ou encore, les sections de configuration du livre BLFS peuvent également exécuter un problème du paquet tout juste installé. Si vous installez le paquet cible sans un dépendance Requise (à l'exécution), vous devriez installer la dépendance aussi vite que possible après l'installation du paquet cible.
Recommandées signifie que BLFS suggère fortement d'installer préalablement ce paquet (sauf si elle est dite « à l'exécution », voir plus bas) pour une construction propre et sans problème, ni pendant le processus de construction ni au moment de l'exécution. Les instructions dans le livre considèrent que ces paquets sont installés. Des modifications ou contournements peuvent être requis si ces paquets ne sont pas installés. Si une dépendance recommandée est dite « à l'exécution », cela signifie que BLFS suggère fortement d'installer cette dépendance avant d'utiliser le paquet, pour avoir toutes les fonctionnalités.
Facultatives signifie que ce paquet peut être installé pour ajouter une fonctionnalité. Souvent BLFS décrira la dépendance pour expliquer la fonctionnalité ajoutée. Une dépendance facultative peut être automatiquement trouvée par le paquet cible si la dépendance est installée, mais d'autres dépendances facultatives peuvent également nécessiter des options de configuration supplémentaires pour les activer à la construction du paquet cible. Ces options seront documentées dans le livre BLFS. Si un dépendance facultative est dite « à l'exécution », cela signifie que vous pouvez installer la dépendance après l'installation du paquet cible pour prendre en charge des fonctionnalités facultatives du paquet cible si vous en avez besoin.
Une dépendance facultative peut se trouver en dehors de BLFS. Si vous avez besoin d'une dépendance facultative externe pour des fonctionnalités, consultez Aller au-delà de BLFS pour trouver l'aide générique sur l'installation des paquets en dehors de BLFS.
Il peut arriver occasionnellement qu'un paquet ne se construise pas ou ne fonctionne pas correctement dans le livre. Bien que les éditeurs tentent de faire en sorte que chaque paquet dans le livre se construise et fonctionne correctement, il arrive parfois qu'un paquet ait été oublié ou n'ait pas été testé avec cette version particulière de BLFS.
Si vous découvrez un paquet qui ne se construit pas ou ne fonctionne pas correctement, vous pouvez regarder s'il s'agit de la version la plus récente du paquet. En général, cela signifie que vous devez vous rendre sur le site web du responsable, télécharger l'archive la plus récente et tenter de construire le paquet. Si vous ne pouvez pas déterminer le site web du responsable en regardant l'URL de chargement, utilisez Google et cherchez le nom du paquet. Par exemple, dans la barre de recherche de Google tapez : « nom_du_paquet download » (sans les guillemets) ou quelque chose de similaire. Parfois en tapant : « nom_du_paquet home page » vous trouverez le site web du responsable.
Dans LFS, le nettoyage des symboles de débogage et des entrées de la table des symboles inutiles a été abordé plusieurs fois. Pour la construction des paquets BLFS, il n'y a généralement pas d'instructions qui abordent de nouveau le nettoyage. Le nettoyage peut avoir lieu après l'installation d'un paquet, ou plus tard.
Il y a plusieurs manières de nettoyer les exécutables installés par un paquet. Elles dépendent du système de construction utilisé (voir plus bas la section sur les systèmes de construction), c'est pourquoi nous ne listons que quelques généralités ici :
Les méthodes suivantes qui utilisent la fonctionnalité d'un système de construction (autotools, meson ou cmake) ne nettoieront pas les bibliothèques statiques si elles sont installées. Heureusement il n'y a pas tant de bibliothèques statiques dans BLFS et une bibliothèque statique peut toujours être nettoyée sans problème en exécutant strip --strip-unneeded dessus manuellement.
Les paquets qui utilisent les autotools ont habituellement
une cible install-strip
dans leur fichier
Makefile
généré. Donc installer
des exécutables nettoyer est aussi simple qu'utiliser
make
install-strip au lieu de make install.
Les paquets qui utilisent le système de construction meson
acceptent -Dstrip=true
au lancement de
meson. Si vous
avez oublié d'ajouter cette option en lançant meson, vous pouvez aussi
lancer meson install
--strip au lieu de ninja install.
cmake génère
des cibles install/strip
aussi bien pour
le générateur de Makefiles
Unix
que pour le générateur Ninja
(par défaut c'est le
générateur de Makefiles
Unix
qui sera utilisé sur linux). Lancez
simplement make
install/strip ou ninja install/strip au lieu
de l'équivalent avec install.
Supprimer (ou éviter de générer) les symboles de débogage
peut aussi se faire en supprimant les options -g<quelque chose>
dans
les appels au compilateur C/C++. La manière de procéder est
spécifique à chaque paquet. En plus, cela ne supprime pas les
entrées inutiles de la table des symboles. Nous ne
l'expliquons donc pas ici. Voir plus bas les paragraphes sur
l'optimisation.
L'utilitaire strip
modifie les fichiers en place, ce qui peut casser tout ce qui
l'utilise s'il est chargé en mémoire. Remarquez que si un fichier
est utilisé mais simplement supprimé du disque (c.-à-d. pas écrasé
ou modifié), ce n'est pas un problème car le noyau peut utiliser
des fichiers « supprimés ». Regardez dans /proc/*/maps
, et il est probable que vous verrez
des entrées (deleted). La
commande mv supprime
seulement le fichier de destination du répertoire mais ne change
pas son contenu, donc elle satisfait aux conditions pour que le
noyau utilise l'ancien fichier supprimé. Mais cette approche peut
détacher des liens en dur et créer des copies dupliquées, causant
une plus forte utilisation du disque, ce qui n'est évidemment pas
souhaitable quand nous nettoyons pour réduire la taille du système.
Si deux fichiers du même système de fichiers partage le même numéro
d'inœud, ils sont liés en dur et nous devrions reconstruire le
lien. Le script ci-dessous est juste un exemple. Il devrait être
lancé en root
:
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
Si vous installez des programmes dans d'autres répertoires tels que
/opt
ou /usr/local
, vous pouvez vouloir nettoyer les
fichiers ici aussi. Ajoutez simplement d'autres répertoires à
scanner dans la liste des commandes find entre accolades.
Pour plus d'information sur le nettoyage, regardez https://www.technovelty.org/linux/stripping-shared-libraries.html.
Il y a maintenant trois systèmes de construction différents
utilisés régulièrement pour convertir du code source C ou C++ en un
programme compilé ou en une bibliothèque et leur fonctionnement (en
particulier, comment trouver les options disponibles et leurs
valeurs par défaut) est différent. Il peut être plus facile de
comprendre les problèmes causés par certains choix (typiquement une
exécution lente ou l'utilisation inattendue, ou l'omission, des
optimisations en commençant par les variables d'environnement
CFLAGS
, CXXFLAGS
et LDFLAGS
.
Certains programmes utilisent aussi Rust.
La plupart des lecteurs de LFS et de BLFS connaissent probablement
déjà les bases de l'utilisation de CFLAGS
et CXXFLAGS
pour
altérer la compilation d'un programme. En général, certaines formes
d'optimisations sont utilisées par les développeurs en amont
(-O2
ou -O3
), parfois avec la création de symboles de
débogage (-g
) par défaut.
S'il y a des drapeaux contradictoires (p. ex. plusieurs valeurs
différentes de -O
), la dernière valeur sera utilisée. Parfois
les drapeaux spécifiés dans les variables d'environnement sont
insérés avant les valeurs en dur dans le Makefile, ce qui signifie
qu'ils sont ignorés. Par exemple, si un utilisateur spécifie
-O2
et qu'il est suivi de -O3
, la construction utilisera -O3
.
On peut passer divers autres drapeaux dans CFLAGS et CXXFLAGS,
comme permettre d'utiliser les extensions des jeux d'instruction
disponibles pour une microarchitecture spécifique (p. ex.
-march=amdfam10
ou -march=native
), optimiser le code généré pour une
microarchitecture donnée (p. ex. -mtune=tigerlake
ou -mtune=native
, si -mtune=
n'est pas utilisé, la microarchitecture du
paramètre -march=
sera utilisé) ou pour
spécifier un standard C ou C++ particulier (-std=c++17
par exemple). Mais ce qui commence à
apparaître, c'est l'inclusion par les développeurs d'assertions de
débogage dans leur code qui sont généralement désactivés dans les
versions publiées avec -DNDEBUG
. Plus
spécifiquement, si Mesa-23.1.6 est construit avec ces assertions,
certaines activités comme le chargement de niveaux dans les jeux
peuvent prendre très longtemps, même sur des cartes vidéo haut de
gamme.
Cette combinaison est souvent décrite comme « CMMI » (configure, make, make install) et est utilisée ici pour couvrir aussi certains paquets dont le script configure n'a pas été généré par les autotools.
Parfois lancer ./configure --help affichera les options utiles des paramètres qui peuvent être utilisés. D'autres fois, après avoir regardé la sortie de configure vous pourriez avoir besoin de regarder les détails du script pour comprendre ce qu'il cherchait vraiment.
De nombreux scripts configure récupéreront les CFLAGS et CXXFLAGS de l'environnement, mais les paquets CMMI varient dans la manière dont ils seront insérés avec les drapeaux qui sinon seraient utilisés (au choix : ignorés, utilisés à la place de la suggestion des programmeurs, utilisés avant la suggestion des programmeurs ou utilisés après la suggestion des programmeurs).
Dans la plupart des paquets CMMI, make listera les commandes
lancées, séparées par des avertissements éventuels. Mais certains
paquets essayent d'être « silencieux » et ne montrent que les
fichiers qu'ils compilent ou dont ils éditent les liens au lieu de
montrer la ligne de commande. Si vous devez inspecter la commande,
soit à cause d'une erreur, ou juste pour voir les options et les
drapeaux utilisés, ajouterV=1
à
l'invocation make peut aider.
CMake fonctionne de manière différente et il a deux moteurs qui
peuvent être utilisés sur BLFS : make et ninja. Le moteur par défaut est
make, mais ninja est plus rapide sur les paquets plus gros avec
plusieurs processeurs. Pour utiliser ninja, spécifiez -G Ninja
dans la commande cmake. Cependant,
certains paquets peuvent avoir des erreurs fatales dans leurs
fichiers ninja tout en pouvant être construits sans problème avec
les Makefile Unix par défaut.
La partie la plus dure de l'utilisation de CMake est de connaître les options que vous voudrez spécifier. La seule manière de récupérer une liste de ce que le paquet connaît est de lancer cmake -LAH et de regarder la sortie pour cette configuration par défaut.
Peut-être que la chose la plus importante à propos de CMake est
qu'il a plusieurs valeurs de CMAKE_BUILD_TYPE et qu'elles affectent
les drapeaux. La valeur par défaut est vide et aucun drapeau n'est
généré. Les CFLAGS
et CXXFLAGS
dans l'environnement seront utilisés. Si le
programmeur a codé des assertions de débogage, elles seront
activées à moins que vous n'utilisiez -DNDEBUG. Les valeurs
CMAKE_BUILD_TYPE suivantes généreront les drapeaux associés et ils
seront ajoutés après les
drapeaux dans l'environnement et prennent donc le pas dessus.
Value | Flags |
---|---|
Debug |
-g
|
Release |
-O3 -DNDEBUG
|
RelWithDebInfo |
-O2 -g -DNDEBUG
|
MinSizeRel |
-Os -DNDEBUG
|
CMake essaye de produire des constructions silencieuses. Pour voir les détails des commandes lancées, utilisez make VERBOSE=1 ou ninja -v.
Par défaut, CMake traite l'installation des fichiers différemment
des autres systèmes de construction : si un fichier existe
déjà et n'est pas plus récent qu'un fichier qui le remplacerait,
alors le fichier n'est pas installé. cela peut être un problème si
vous voulez enregistrer quels fichiers appartiennent à quel paquet,
soit avec LD_PRELOAD
, soit en listant
les fichiers plus récents qu'un certain horodatage. Ce comportement
par défaut peut être modifié en paramétrant la variable
CMAKE_INSTALL_ALWAYS
à 1 dans
l'environnement, par exemple
en l'exportant.
Meson ressemble un peu à CMake, mais avec beaucoup de différences.
Pour trouver les détails des définitions que vous pourriez avoir
besoin de modifier, vous pouvez regarder dans meson_options.txt
qui est généralement dans le
répertoire de plus haut niveau.
Si vous avez déjà configuré le paquet en lançant meson et que vous souhaitez maintenant changer un ou plusieurs paramètres, vous pouvez soit supprimer le répertoire de construction, le recréer et utiliser les options modifiées, soit lancer meson configure dans le répertoire de construction, p. ex. pour ajouter une option :
meson configure -D<some_option>=true
Si vous faites cela, le fichier meson-private/cmd_line.txt
contiendra les
dernières commandes qui ont
été utilisées.
Meson fournit les valeurs buildtype suivantes, et les drapeaux qu'elles activent viennent après les drapeaux fournis dans l'environnement et prennent donc le pas.
plain : pas de drapeau supplémentaire. Cela est utilisé
pour spécifier ses propres CFLAGS
,
CXXFLAGS
et LDFLAGS
. Il n'y a pas de raison évidente pour
utiliser cela dans BLFS.
debug : -g
— c'est la valeur
par défaut si rien n'est spécifié dans meson.build
ni sur la ligne de commande.
Cependant, cela crée des binaires gros et lents, donc vous
devez le remplacer dans BLFS.
debugoptimized : -O2
-g
: c'est la valeur par défaut spécifiée dans
meson.build
pour certains
paquets.
release : -O3
(parfois un
paquet forcera -O2
) — c'est le
type de construction utilisé pour la plupart des paquets avec
le système de construction Meson dans BLFS.
Le drapeau -DNDEBUG
est sous-entendu
par le type de construction release pour certains paquets (par
exemple Mesa-23.1.6). Il peut également être fournit en
passant -Db_ndebug=true
.
Pour voir les détails des commandes qui sont lancées dans un paquet qui utilise meson, utilisez ninja -v.
La plupart des programmes rustc publiés sont fournis dans des
archives (ou « crates ») qui demanderont à un serveur de
vérifier les versions actuelles des dépendances et les téléchargera
au besoin. Ces paquets sont construits avec cargo --release. En théorie, on
peut manipuler les RUSTFLAGS pour changer le niveau d'optimisation
(la valeur par défaut pour --release
est 3, c.-à-d. -Copt-level=3
, comme
-O3
) ou pour forcer la construction
pour la machine sur laquelle il est compilé, avec -Ctarget-cpu=native
mais en pratique cela ne
semble pas faire de réelle différence.
Si vous compilez un programme Rust autonome (en tant que fichier
.rs
sans paquet) en exécutant
directement rustc,
vous devriez spécifier -O
(abbreviation
de -Copt-level=2
) ou -Copt-level=3
sinon il effectuera une compilation
non optimisée et s'exécutera bien
plus lentement. Si vous compilez un programme pour le
déboguer, remplacez les options -O
ou
-Copt-level=
par -g
pour produire un programme non optimisé avec des
informations de débogage.
Comme pour ninja, par
défaut cargo utilise
tous les processeurs logiques. Cela peut souvent être changé, soit
en exportant CARGO_BUILD_JOBS=
ou en passant
<N>
--jobs
à cargo. Pour compiler rustc
lui-même, spécifiez <N>
--jobs
lors de
l'invocation de x.py
(avec la variable d'environnement <N>
CARGO_BUILD_JOBS
, ce qui ressemble à une approche
« ceinture et
bretelle » mais a l'air nécessaire). L'exception
est le lancement des tests à la construction de rustc, où certains
d'entre eux utiliseront tout de même tous les CPU en ligne, au
moins à partir de rustc-1.42.0.
De nombreuses personnes préfèrent optimiser la compilation à leur
goût, en fournissant CFLAGS
ou
CXXFLAGS
. Vous trouverez une
introduction aux options disponibles avec gcc et g++ sur
https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Optimize-Options.html.
Ce contenu est également disponible dans info gcc.
Certains paquets utilisent par défaut-O2
-g
, d'autres -O3 -g
et si les
CFLAGS
ou CXXFLAGS
sont fournis ils peuvent être ajoutés aux
valeurs par défaut du paquet, remplacer les valeurs par défaut ou
même être ignorés. Il y a des détails sur les dernières versions
(en avril 2019) de certains paquets graphiques sur https://www.linuxfromscratch.org/~ken/tuning/
— en particulier, README.txt
,
tuning-1-packages-and-notes.txt
et
tuning-notes-2B.txt
. Ce dont il faut
se souvenir, c'est que si vous voulez essayer certains des drapeaux
les plus intéressants vous devez forcer les constructions à être
plus verbeuses pour confirmer qu'elles sont utilisées.
Clairement, si vous optimisez votre propre programme vous pouvez
passer du temps à effectuer des mesures et peut-être recoder
certaines parties plutôt lentes. Mais pour construire un système
complet cette approche est impossible. En général, -O3
produit des programmes plus rapides que
-O2
. Spécifier -march=native
est aussi bénéfique, mais cela
signifie que vous ne pouvez pas utiliser les binaires sur une
machine incompatible — cela s'applique aussi à des machines plus
récentes, pas seulement à des machines plus vieilles. Par exemple
les programmes compilés pour amdfam10
peuvent tourner sur les vieux Phenoms, Kaveris et Ryzens ;
mais les programmes compilés pour un Kaveri ne tourneront pas sur
un Ryzen parce que certains opcodes ne sont pas présents. De même,
si vous construisez pour un Haswell tout ne tournera pas sur un
SandyBridge.
Soyez conscient que le nom d'un paramètre -march
ne correspond pas toujours à la
microarchitecture de base du même nom. Par exemple, les
processeurs Celeron d'Intel basés sur Skylake ne prennent pas en
charge AVX du tout, mais -march=skylake
suppose AVX et même AVX2.
Lorsqu'une bibliothèque partagée est construite par GCC, une
fonctionnalité nommée « interposition sémantique » est activée
par défaut. Lorsque la bibliothèque partagée se réfère à un nom de
symbole avec un lien externe et la visibilité par défaut, si le
symbole existe à la fois dans la bibliothèque partagée et
l'exécutable principal, l'interposition sémantique garanti que le
symbole de l'exécutable principal sera toujours utilisé. Cette
fonctionnalité a été inventée pour essayer de rendre la liaison
d'une bibliothèque partagée et d'une bibliothèque statique aussi
proches que possible. Aujourd'hui seul un petit nombre de paquets
dépendent toujours de l'interposition sémantique, mais la
fonctionnalité est toujours proposée par défaut par GCC, ce qui
désactive plusieurs optimisations pour les bibliothèques partagées
car elles entrent en conflit avec l'interposition sémantique.
L'option -fno-semantic-interposition
peut être passée à gcc ou g++ pour désactiver
l'interposition sémantique et activer plus d'optimisations pour les
bibliothèques partagées. Cette option est utilisée par défaut dans
certains paquets (par exemple Python-3.11.4)
et elle est activée par défaut dans Clang.
Il y a aussi diverses autres options que certains pensent bénéfiques. Au pire, vous devez recompiler et tester, pour découvrir que pour votre utilisation ces options ne font rien de spécial.
Si vous construisez des modules Perl ou Python, en général les
CFLAGS
et CXXFLAGS
utilisés sont ceux utilisés pour construire
ces paquets « parents ».
Pour LDFLAGS
, il y a trois options pour
l'optimisation. Elles sont relativement sures à utiliser et le
système de construction de certains paquets utilisent certaines de
ces options par défaut.
Avec -Wl,-O1
, l'éditeur des liens
optimisera la table de hash pour accélérer la liaison dynamique.
Remarquez que -Zl,-O1
est complètement
décorrélée du drapeau d'optimisation du compilateur -O1
.
Avec -Wl,--as-needed
, l'éditeur des
liens ignorera les options -l
inutiles de la ligne de
commande, c.-à-d. que la bibliothèque partagée toto
lib
ne sera liée que si un
symbole de toto
lib
est vraiment demandé
par l'exécutable ou la bibliothèque dynamique en train d'être liée.
Cela peut parfois éviter des problèmes de « dépendances excessives à des
bibliothèques partagées » causés par
libtool.
toto
Avec -Wl,-z,-pack-relative-relocs
,
l'éditeur des liens générera une forme plus compacte des entrées de
relocations relatives pour les exécutables repositionnables et les
bibliothèques partagées. Cela réduit la taille des exécutables ou
des bibliothèques partagées et accélère leur chargement.
Le préfixe -Wl,
est nécessaire car
malgré le nom de la variable LDFLAGS
,
son contenu est en fait passé à gcc (ou g++, clang, etc) pendant l'édition des
liens, pas directement à ld.
Même sur un système de bureau, il y a des vulnérabilités exploitables. Pour beaucoup, l'attaque vient de javascript dans un navigateur. Souvent, une série de vulnérabilités sont utilisées pour récupérer un accès aux données (ou parfois pour powner, c.-à-d. cracker la machine et installer des rootkits). La plupart des distributions commerciales appliqueront diverses mesures de durcissement.
Par le passé, il existait un Hardened LFS (LFS durci) où gcc (une
version beaucoup plus vieille) était forcé à utiliser le
durcissement (avec des options pour les désactiver au cas par cas).
Les livres LFS et BLFS actuels portent encore une partie de cet
esprit en activant PIE (-fPIE -pie
) et
SSP (-fstack-protector-strong
) dans les
options par défaut de GCC et de clang. Ce dont on parle ici est
différent — vous devrez déjà vous assurer que le paquet utilise
bien vos options supplémentaires et qu'il ne les écrase pas.
Pour les options de durcissement qui sont raisonnablement peu
coûteuses, on en parle un peu dans le lien sur les expériences de
peaufinage précédent (parfois une ou plus de ces options peuvent
être inappropriées pour un paquet). Ces options sont -D_FORTIFY_SOURCE=2
et (pour C++) -D_GLIBCXX_ASSERTIONS
. Sur les machines modernes
elles ne devraient avoir qu'un très faible impact sur la vitesse
des programmes et souvent ne seront même pas perceptibles.
Les distros principales utilisent bien plus, comme RELRO
(Relocation Read Only) et parfois -fstack-clash-protection
. Vous pouvez aussi
rencontrer les « retpolines en espace utilisateur »
(-mindirect-branch=thunk
etc) qui sont
équivalents aux atténuations de spectre appliquées au noyau Linux
fin 2018. Les atténuations du noyau ont causé de nombreuses
plaintes à propos d'une perte de performance, donc si vous avez un
serveur en production vous devriez peut-être tester ça ainsi que
d'autres options disponibles, pour voir si les performances sont
toujours satisfaisantes.
Tandis que gcc a de nombreuses options de durcissement, la force de clang/LLVM se trouve ailleurs. Certaines options fournies par gcc sont dites moins efficaces dans clang/LLVM.