====== Le système de configuration ====== ===== Introduction ===== Cette petite bibliothèque permet de gérer depuis le shell des fichiers (ou chaînes) de configuration dans un format créé à cet effet, et ressemblant fortement au format //properties// de java. ===== Le format de fichier ===== ==== La syntaxe de base ==== <file> # un commentaire clé = valeur clé2 = valeur # reste de la ligne en commentaire </file> Lors de la lecture, les espaces autour du signe égal et à la fin de la valeur sont ignorées. De plus, toute ligne vide ou caractères après un ''#'' l'est aussi. Le nom des clés est libre, seuls les espaces, tabulations, caractères ''#'', '' ' '', ''"'' et ''='' sont proscrits. Cela permet une certaine liberté dans le nommage, et facilite le découpage hiérarchique des clés, par exemple : <file> # features part features.output = true features.output.verbose = true features.log = true features.log.file = mylogfile.log </file> ==== Valeurs booléennes ==== La lecture peut se faire directement sur des booléens. Ansi des valeurs telles que ''true'' ou ''yes'' ou ''N'' donneront des variables de valeur ''0'' ou ''1''. La liste suivante donne les valeurs possibles : * **t** ou **true** ou toute combinaison de majuscules/minuscules (par exemple ''True'') donne **1** * **y** ou **yes** ou toute combinaison de majuscules/minuscules (par exemple ''yEs'') donne **1** * **f** ou **false** ou toute combinaison de majuscules/minuscules (par exemple ''FaLsE'') donne **0** * **n** ou **no** ou toute combinaison de majuscules/minuscules (par exemple ''nO'') donne **0** * **0** et **1** donne bien entendu respectivement **0** et **1** ==== Valeurs multi-lignes ==== Une valeur peut s'étendre sur plusieurs lignes, sans avoir à modifier le contenu (pas de backslash à rajouter en fin de ligne), à l'instar des HEREDOC de Python, PHP ou autre Perl. Dans ce cas, la clé doit être suivie de la suite <nowiki>{{{</nowiki>, et la valeur doit se terminer par la suite <nowiki>}}}</nowiki> en début de ligne, et éventuellement suivie d'espaces. Par exemple : <file> ma.liste.de.commandes = {{{ ls touch toto # ls encore une fois :-) ls rm -f toto }}} </file> Dans ce cas, la valeur est reprise telle quelle de la source (les commentaires, lignes vides et espaces faisant partie de la valeur, ne sont pas ignorés, sauf si demandé) - après lecture, la valeur contiendra exactement : <file> ls touch toto # ls encore une fois :-) ls rm -f toto </file> Noter que les valeurs multi-lignes peuvent elles-mêmes contenir des valeurs mutli-lignes (imbriquées), de fait qu'il est possible de lire à partir de la propriété : <file> valeur = {{{ imbriqué = {{{ toto }}} # imbriqué }}} # valeur </file> le contenu : <file> imbriqué = {{{ toto }}} # imbriqué </file> Les commentaires en fin de valeur sont purement informatifs, et non nécessaires. ==== Substitutions de variables ==== Si demandé expréssement, certaines variables d'environnement peuvent être substituées. On peut alors remplacer la valeur d'une variable par son contenu dans l'ensemble de la valeur de la propriété, lors de la lecture ou de l'écriture de celle-ci. Dans le fichier source, les variables peuvent être référencées par un préfixe ''$'' ou encadrées par des ''@'', au choix (le style avec les ''@'' doit être spécifié lors de la lecture ou l'écriture). **Les variables d'environnement doivent être exportées pour être utilisables par la substitution.** Par exemple, nous avons deux variables d'environnement : <code bash> export version=5.4 export nom="properties" </code> Et un fichier de configuration contenant la propriété suivante : <file> ma.description = {{{ Version = $version Nom = $nom }}} </file> Lors de la lecture, en passant "''-u version,nom''", le résultat sera : <file> Version = 5.4 Nom = properties </file> On peut également indiquer un préfixe de substitution, afin d'éviter les conflits dans l'environnement : <code bash> export soft_version=5.4 export soft_nom="properties" </code> Le fichier de configuration n'a pas changé, et contient toujours les noms de variables plus simples : <file> ma.description = {{{ Version = $version Nom = $nom }}} </file> Lors de la lecture, en passant "''-u soft_:version,nom''", donc avec la liste des variables préfixée du nom de préfixe plus le signe "'':''", le résultat sera : <file> Version = 5.4 Nom = properties </file> Avec le style ''@'' cela donne : <file> ma.description = {{{ Version = @version@ Nom = @nom@ }}} </file> Avec le paramètre suivant "''-u @soft_:version,nom''" (notez le ''@'' juste avant le préfixe). ===== Activation ===== Vous trouverez le module sur subversion, dans le sous-projet **nlib** : <file> nprop.sh nprop.d/create.awk nprop.d/delete.awk nprop.d/find.awk nprop.d/read.awk nprop.d/shared.awk nprop.d/update.awk </file> Copiez ces fichiers là où bon vous semble (en gardant le répertoire **nprop.d** au même niveau que le script **nprop.sh**). Intégrer ce module à des scripts est alors aussi simple que de le //sourcer// et d'appeler ses fonctions : <code bash> source chemin/vers/lib/nprop.sh || { echo "problème pour sourcer nprop.sh" exit 1 } nprop_read -i my.conf -p my.property -v ma_variable echo "dans my.conf, 'my.property' vaut: $ma_variable" </code> Si vous désirez placer le répertoire **nprop.d** ailleurs, ou le renommer, il suffit de renseigner une variable juste avant d'utiliser les fonctions (avant ou après avoir sourcé **nprop.sh**) : <code bash> # les scripts awk se trouvent dans le répertoire conf_properties NPROPVAR_INTERNAL_DIR=/chemin/vers/les/libs/conf_properties source chemin/vers/lib/nprop.sh || exit $? # appel des fonctions </code> <code bash> source chemin/vers/lib/nprop.sh || exit $? # les scripts awk se trouvent dans le répertoire conf_properties NPROPVAR_INTERNAL_DIR=/chemin/vers/les/libs/conf_properties # appel des fonctions </code> ===== Les fonctions publiques ===== ==== nprop_read() ==== Lit la valeur d'une propriété. === synopsys === <code bash> nprop_read -p property [-i input] [-v var] [-s strip-option] [-u substitutes] [-a noprop|empty] </code> * **-p** nom de la propriété à lire * **-i** indique le fichier à lire (flux d'entrée standard si omis) * **-v** indique la variable dans laquelle placer la valeur (flux de sortie standard si omis) * **-s** options de suppression sur les valeurs multi-lignes (rendu telles quelles normalement) : * **c** supprime les commentaires * **e** supprime les lignes vides ou seulement constituées d'espaces ou tabulations * **b** supprime les commentaires et les lignes vides * **-u** substitution de variable d'environnement (voir le paragraphe [[nlib_nprop#substitutions_de_variables|Substitutions de variables]]) * **-a** permet de ne pas émettre d'erreur si la propriété n'existe pas (**noprop**) ou si la valeur est vide (**noprop** ou **empty**) === valeurs de retour === * **0** - ok * **1** - propriété inexistante (sauf si **-a noprop**) * **2** - la propriété multi-ligne n'est pas correctement terminée * **3** - la valeur de la propriété est vide (sauf si **-a noprop** ou **-a empty**) * **127** - mauvais appel (vérifier les paramètres) === utilisation === Deux façons de l'utiliser. Avec ou sans la variable de destination (paramètre **-v**) : <code bash> nprop_read -i fichier.conf -p ma.valeur.a.lire -v la_variable || { ret=$? echo "erreur de lecture de 'ma.valeur.a.lire' : $ret" exit $ret } echo "la valeur est : $la_variable" </code> <code bash> la_variable=`nprop_read -i fichier.conf -p ma.valeur.a.lire` || { ret=$? echo "erreur de lecture de 'ma.valeur.a.lire' : $ret" exit $ret } echo "la valeur est : $la_variable" </code> Cette deuxième approche est à préférer lorsque la valeur peut contenir des caractères interprétables par le shell, car dans ce cas, il ne seront pas interprété (sauf pour les variables substituées explicitement). ==== nprop_readbool() ==== Lit la valeur d'une propriété et la convertit en booléen (valeur **0** ou **1**), voir le paragraphe [[nlib_nprop#valeurs_booleennes|Valeurs booléennes]]. Le fonctionnement est identique à **nprop_read()**. === valeurs de retour === * **0** - ok * **1** - propriété inexistante (sauf si **-a noprop**) * **2** - la propriété multi-ligne n'est pas correctement terminée * **3** - la valeur de la propriété est vide (sauf si **-a noprop** ou **-a empty**) * **4** - la valeut ne peut être converti un booléen * **127** - mauvais appel (vérifier les paramètres) === utilisation === <code bash> nprop_readbool -i fichier.conf -p ma.valeur.booleenne -v la_variable || { ret=$? echo "erreur de lecture de ma.valeur.booleenne : $ret" exit $ret } if [ $la_variable -eq 1 ]; then echo "la valeur est vraie" else echo "la valeur est fausse" fi </code> ==== nprop_find() ==== Trouve les propriétés dont le nom correspond au pattern spécifié. === synopsys === <code bash> nprop_find -p pattern [-i input] [-v var] </code> * **-p** pattern pour lequel trouver les propriétés * **-i** indique le fichier à lire (flux d'entrée standard si omis) * **-v** indique la variable dans laquelle placer la valeur (flux de sortie standard si omis) === valeurs de retour === * **0** - ok * **1** - pas de propriété correspondant au patron * **127** - mauvais appel (vérifier les paramètres) === utilisation === Deux façons de l'utiliser, comme **nprop_read()**, avec ou sans variable de destination. Dans les exemples suivants, nous utiliserons ce **fichier.conf** : <file> one = 1 one.two = 2 one.two.three = 3a one.two.dub.three = 3b dyb.one.two.three = 3c </file> Le patron sera utilisé dans une expression régulière, la syntaxe est donc simple, tout en permettant des recherches avancées : <code bash> nprop_find -i fichier.conf -p 'one.two' </code> donnera :<file> one.two </file> Notez que la recherche se fait sur toute la longueur du nom de propriété, donc l'équivalent du **^** (début de ligne) et du **$** (fin de ligne) des expressions régulières est implicite. Pour rechercher des parties, ajoutez **.* ** aux endroits voulus : recherche de tout ce qui commence par **one.two** : <code bash> nprop_find -i fichier.conf -p 'one.two.*' </code> <file> one.two one.two.three one.two.dub.three </file> recherche de tout ce qui contient **one.two** (notez l'absence du point avant **one**) : <code bash> nprop_find -i fichier.conf -p '.*one.two.*' </code> <file> one.two one.two.three one.two.dub.three dub.one.two.three </file> cette fois-ci nécessite le point devant **.one.two** : <code bash> nprop_find -i fichier.conf -p '.*.one.two.*' </code> <file> dub.one.two.three </file> recherche de ce qui commence par **one.** et se termine par **.three** : <code bash> nprop_find -i fichier.conf -p 'one..*.three' </code> <file> one.two.three one.two.dub.three </file> ==== nprop_create() ==== Crée une nouvelle propriété. === synopsys === <code bash> nprop_create -p property -v value [-i input] [-o output] [-n nextto] [-b prefix] [-u substitutes] </code> * **-p** nom de la propriété à créer * **-v** la valeur de la propriété * **-i** indique le fichier à lire (flux d'entrée standard si omis) * **-o** fichier de destination (si omis, le même que le fichier d'entrée ou la sortie standard si la lecture se fait sur l'entrée standard) * **-n** placer la nouvelle propriété juste après celle-ci au lieu de la fin de fichier * **-b** ajouter cette chaîne avant la nouvelle propriété (pratique pour les commentaires) * **-u** substitution de variable d'environnement (voir le paragraphe [[nlib_nprop#substitutions_de_variables|Substitutions de variables]]) === valeurs de retour === * **0** - ok * **1** - la propriété existe déjà * **127** - mauvais appel (vérifier les paramètres) === utilisation === <code bash> nprop_create -i fichier.conf -p ma.valeur.a.creer -v la_valeur || { ret=$? echo "erreur de création de 'ma.valeur.a.creer' : $ret" exit $ret } </code> ==== nprop_update() ==== Met à jour une propriété existante. === synopsys === <code bash> nprop_update -p property -v value [-i input] [-o output] [-u substitutes] </code> * **-p** nom de la propriété à modifier * **-v** la nouvelle valeur * **-i** indique le fichier à lire (flux d'entrée standard si omis) * **-o** fichier de destination (si omis, le même que le fichier d'entrée ou la sortie standard si la lecture se fait sur l'entrée standard) * **-u** substitution de variable d'environnement (voir le paragraphe [[nlib_nprop#substitutions_de_variables|Substitutions de variables]]) === valeurs de retour === * **0** - ok * **1** - la propriété n'existe pas * **2** - la valeur existante multi-ligne ne se termine pas correctement * **127** - mauvais appel (vérifier les paramètres) === utilisation === <code bash> nprop_update -i fichier.conf -p ma.valeur.a.modifier -v la_valeur || { ret=$? echo "erreur de mise à jour de 'ma.valeur.a.modifier' : $ret" exit $ret } </code> ==== nprop_write() ==== Crée ou met à jour une propriété, en appellant **nprop_create()** puis **nprop_update()** si la première échoue. Cela permet de placer une valeur dans une propriété sans se soucier du fait qu'elle existe ou pas auparavant. L'appel est identique à **nprop_create()**. === synopsys === <code bash> nprop_write -p property -v value [-i input] [-o output] [-n nextto] [-b prefix] [-u substitutes] </code> === valeurs de retour === * **0** - ok * **2** - la valeur existante multi-ligne ne se termine pas correctement * **127** - mauvais appel (vérifier les paramètres) === utilisation === <code bash> nprop_write -i fichier.conf -p ma.valeur.a.ecrire -v la_valeur || { ret=$? echo "erreur de création de 'ma.valeur.a.ecrire' : $ret" exit $ret } </code> ==== nprop_delete() ==== Supprime une propriété === synopsys === <code bash> nprop_delete -p property [-i input] [-o output] [-a noprop] </code> * **-p** nom de la propriété à supprimer * **-i** indique le fichier à lire (flux d'entrée standard si omis) * **-o** fichier de destination (si omis, le même que le fichier d'entrée ou la sortie standard si la lecture se fait sur l'entrée standard) * **-a noprop** permet de ne pas émettre d'erreur si la propriété n'existe pas === valeurs de retour === * **0** - ok * **1** - la propriété n'existe pas (sauf si **-a noprop**) * **2** - la valeur existante multi-ligne ne se termine pas correctement * **127** - mauvais appel (vérifier les paramètres) === utilisation === <code bash> nprop_delete -i fichier.conf -p ma.valeur.a.supprimer || { ret=$? echo "erreur de suppression de 'ma.valeur.a.supprimer' : $ret" exit $ret } </code> ===== Un exemple concret: Ngadkm ===== En fait, il ne s'agit pas de Ngadkm, mais d'un exemple similaire, qui va permettre de découvrir les différentes utilisations de fonctions. De même, certaines valeurs dans la configuration sont purement fictives, et ne servent que pour le propos de ce tutoriel. Dans les commandes enregistrées dans la config, on retrouve des appels à **dkm_* **, il s'agit de fonctions internes à Ngadkm, ne vous en souciez pas. Pour info, **dkm_exec** permet de gérer à la fois si la sortie des commandes doit être affichée ou non à l'écran, selon un paramétrage, et de mettre fin au script si la commande échoue (renvoie une valeur différente de 0). Imaginons donc que nous faisions un script qui va lire des informations sur un package (ici **gcc-pass1**) dans un fichier de configuration **package.conf**, et les afficher à l'écran. Un vrai script pourra construire ledit package, selon les instructions trouvées dans le livre **LFS**. ==== Le fichier de configuration ==== <file> # ----------------------------------------------------------------------------- # gcc-pass1 gcc-pass1.name = gcc gcc-pass1.version = 4.1.1 gcc-pass1.chroot = true # it's a fake :-) gcc-pass1.srctree = @name@-@version@ gcc-pass1.archive.1 = @mirror.gnu@/@name@/@srctree@/@name@-core-@version@.tar.bz2 gcc-pass1.archive.2 = @mirror.gnu@/@name@/@srctree@/@name@-g++-@version@.tar.bz2 gcc-pass1.patch.1 = @mirror.lfs@/@srctree@-fictive.patch gcc-pass1.commands = {{{ dkm_unpack @archive1@ dkm_unpack @archive2@ dkm_patch @patch1@ dkm_mkdir @name@-build dkm_cd @name@-build dkm_exec ../@srctree@/configure \ --prefix=/tmpsys \ --with-local-prefix=/tmpsys \ --disable-nls \ --enable-shared \ --enable-languages=c dkm_exec make bootstrap dkm_exec make install dkm_exec ln -vs gcc /tmpsys/bin/cc dkm_cd dkm_exec rm -Rf @name@-* }}} # vi:set ts=2 sw=2 noet syn=sh: </file> Remarquez que chaque ligne débute par **gcc-pass1**, qui est le nom du package. On définit alors plusieurs propriétés à ce package : * **name** le vrai nom du logiciel, si le package a un nom spécial (ce qui est le cas ici, car on a rajouté **-pass1**) * **version** la version du logiciel * **chroot** le package doit être construit dans un chroot ou non ? * **srctree** le nom du répertoire dans lequel la ou les archives seront décompressées. Si cette propriété n'existe pas, le script déduira automatiquement qu'il s'agit de **nom**-**version** * **archive.* **une liste de tarballs à aller chercher. Commence à 1 et doit être une suite simple (1,2,3,..) * **patch.* **une liste de patchs à aller chercher. Même principe que pour les archives * **commands** les commandes à exécuter pour construire le package. On voit ici la syntaxe d'une propriété multi-lignes Vous avez sûrement remarqué les notations **@letruc@**. Il s'agit de [[ngadkm_core_conf#substitutions_de_variables|substitutions de variables]]. Ces variables correspondent toutes à des propriétés, à quelques exceptions près : * **@name@** -> **gcc-pass1.name** * **@version@** -> **gcc-pass1.version** * **@srctree@** -> **gcc-pass1.srctree** * **@archive1@** et **archive2** -> **gcc-pass1.archive.1** et **gcc-pass1.archive.2** * **@patch1@** -> **gcc-pass1.patch.1** * **@mirror.*@** sont les exceptions. Ces valeurs ne seront pas substituées, mais analysées par une autre partie du programme pour tenter de télécharger les fichiers sur différents mirroirs paramétrés (un exemple sera donné à la fin du tutoriel) Par exemple, la ligne : <file> gcc-pass1.srctree = @name@-@version@ </file> Donnera comme résultat "''__gcc__-__4.1.1__''" après les substitutions, et : <file> gcc-pass1.archive.1 = @mirror.gnu@/@name@/@srctree@/@name@-core-@version@.tar.bz2 </file> Donnera "''@mirror.gnu@/__gcc__/__gcc-4.1.1__/__gcc__-core-__4.1.1__.tar.bz2''" (car comme dit précédemment, les variables **@mirror.*@** ne sont pas substituées). ==== Le script de lecture ==== Créons maintenant un script shell **gccinfo.sh**, qui va lire toute cette configuration. === Initialisations === La première chose à faire est de sourcer **nprop.sh** comme expliqué plus haut. <code bash> #!/bin/bash source where/prop/is/nprop.sh || { ret=$? echo Error while sourcing the property module exit $ret } </code> Ensuite, on va nommer deux variables pour faciliter notre notation : <code bash> # le chemin du fichier de configuration conf=package.conf # le nom du package à construire - notez que cela correspond au début de la ligne de configuration. # Lorsqu'on voudra en faire un autre, on n'aura qu'à changer cette ligne. pkg=gcc-pass1 </code> Enfin, on va réinitialiser les variables qui seront lues. Pour cela, on utilise une fonctionnalité des shell Bourne : l'initialisation de la valeur d'une variable peut se faire après son export (exporter ne signifie pas "je délcare que la variable vaut ça pour tout le monde à partir de maintenant"). <code bash> unset pkg_name pkg_version pkg_chroot pkg_srctree pkg_archives pkg_patches export pkg_name pkg_version pkg_chroot pkg_srctree pkg_archives pkg_patches </code> On va en profiter pour se faire un petit raccourci pour le paramètre de substitution de variables : <code bash> substs='@pkg_:name,version,chroot,srctree' </code> === Lectures === On va maintenant lire les valeurs. Etant donné que l'on a exporté toutes les variables dès le début, la substitution fonctionnera sur les différentes variables au fur et à mesure qu'elles seront lues : <code bash> # lit le nom réel, et s'il n'est pas défini, prend le nom du package par défaut nprop_read -i $conf -p $pkg.name -v pkg_name || pkg_name=$pkg # à ce point précis, la substitution @name@ fonctionne # lit la version. La syntaxe sans nom de variable permet d'initialiser $pkg_version, # même si la fonction ne retourne rien. On se fout également de savoir si la fonction # a échoué ou non pkg_version=`nprop_read -i $conf -p $pkg.version` # on regarde si on a besoin d'entrer dans un chroot pour construire le package # Le fichier de configuration contient 'true', mais comme on utilise nprop_readbool(), # la fonction retournera 1. # Si la fonction échoue, on initialise la variable avec 0 nprop_readbool -i $conf -p $pkg.chroot -v pkg_chroot || pkg_chroot=0 # On lit le nom du répertoire créé par l'extraction de l'archive (on utilise ici les # substitutions pkg_srctree=`nprop_read -i $conf -p $pkg.srctree -u $substs` || { # Si c'est pas bon (la propriété n'existe pas ou la valeur est vide # on met par défaut "$pkg_name-$pkg_version" ou juste # "$pkg_name" si $pkg_version est vide srctree_version=${pkg_version:+'-'$pkg_version} pkg_srctree=$pkg_name$srctree_version } </code> On va maintenant lire les archives. Puisqu'il peut y en avoir plusieurs, on va rentrer dans une boucle pour lire les propriétés **gcc-pass1.archives.* ** à partir de 1 et séquentiellement, jusqu'à ce que ça plante : <code bash> # on commence à 1 num=1 # nprop_read() renvoie un nombre différent de 0 en cas d'échec, ce qui rend le test # de while faux while nprop_read -i $conf -p $pkg.archive.$num -v archive -u $substs; do # on veut générer des variables pkg_archive<num> pour les substituer aux # @archive<num>@. Comme on ne sait pas à l'avance le nom de la variable, # on utilise eval qui va transformer notre chaîne en instructions du shell eval " # crée la variable pkg_archive<num> avec le nom du fichier archive (sans le chemin) pkg_archive$num=`basename $archive` # on exporte, sinon ce ne sera pas substitué export pkg_archive$num # la variable $archsubst sera utilisé en complément de $substs, pour y ajouter nos # @archive<num>@ archsubst=$archsubst,archive$num " # on ajoute la nouvelle archive à la liste (séparé par un espace) $pkg_archives if [ -n "$pkg_archives" ]; then # si pas vide, liste="<ancienne liste><espace><nouvelle archive>" pkg_archives="$pkg_archives $archive" else # sinon, liste=<archive> pkg_archives=$archive fi # test suivant num=`expr $num + 1` done </code> On fait pareil pour les patchs : <code bash> num=1 while nprop_read -i $conf -p $pkg.patch.$num -v patch -u $substs; do eval "pkg_patch$num=`basename $patch`;export pkg_patch$num;patchsubst=$patchsubst,patch$num" if [ -n "$pkg_patches" ]; then pkg_patches="$pkg_patches $patch" else pkg_patches=$patch fi num=`expr $num + 1` done </code> Notez comme le code est concis quand on se passe de commentaires :-) Enfin, on lit les commandes, en faisant toutes les substitutions possibles : <code bash> pkg_commands=`nprop_read -i $conf -p $pkg.commands -u $substs$archsubst$patchsubst` </code> === Affichage === On va afficher les infos que l'on a eu : <code bash> echo package: $pkg echo ' name:' $pkg_name echo ' version:' $pkg_version echo ' chroot?:' $pkg_chroot echo ' srctree:' $pkg_srctree echo ' archives:' $pkg_archives echo ' patches:' $pkg_patches echo " commands: >>>$pkg_commands<<< " </code> ==== Résultat à l'écran ==== <file> package: gcc-pass1 name: gcc version: 4.1.1 chroot?: 1 srctree: gcc-4.1.1 archives: @mirror.gnu@/gcc/gcc-4.1.1/gcc-core-4.1.1.tar.bz2 @mirror.gnu@/gcc/gcc-4.1.1/gcc-g++-4.1.1.tar.bz2 patches: @mirror.lfs@/gcc-4.1.1-fictive.patch commands: >>> dkm_unpack gcc-core-4.1.1.tar.bz2 dkm_unpack gcc-g++-4.1.1.tar.bz2 dkm_patch gcc-4.1.1-fictive.patch dkm_mkdir gcc-build dkm_cd gcc-build dkm_exec ../gcc-4.1.1/configure \ --prefix=/tmpsys \ --with-local-prefix=/tmpsys \ --disable-nls \ --enable-shared \ --enable-languages=c dkm_exec make bootstrap dkm_exec make install dkm_exec ln -vs gcc /tmpsys/bin/cc dkm_cd dkm_exec rm -Rf gcc-*<<< </file> ==== Conclusion ==== Ce tutoriel est terminé. Nous n'avons vu que les fonctions de lecture, mais l'écriture est similaire (aka simple :-) ). Peut-être qu'un jour de continuerai avec ces dernières (en fonction des demandes). vous trouverez les sources complets [[prop_tuto_sources|ici]]. Pour tout commentaire, critique, demandes, [[mailto:richard-NOSPAM@houbathecatinfo-NOSPAM.info|contactez-moi]]. **riri**

 
nlib_nprop.txt · Dernière modification: 07/10/2007 12:39 par riri
 
Recent changes RSS feed Creative Commons License Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki