OpenBSD Ports: Special Porting Topics : (v1.85 ; 25/02/2021)
— [ FAQ Index ] | [ Index Ports ] ~ Traduction française de la page OpenBSD Ports : Sujets spécifiques —
Les bibliothèques partagées sont un peu délicates pour diverses raisons. Vous devez comprendre le schéma de noms des bibliothèques : libfoo.so.major.minor
.
Quand vous liez un programme, le linker ld insère l'information dans la bibliothèque créée. Vous pouvez le voir avec ldd(1). Plus tard, lors de l'exécution du programme, le linker dynamique ld.so(1) utilise cette information pour trouver la bonne bibliothèque dynamique :
Ainsi, cela signifie que toutes les bibliothèques avec le même numéro majeur et un numéro mineur supérieur ou égal doivent satisfaire l'API binaire que le programme attend. Si ce n'est pas le cas, alors votre port est cassé. Spécifiquement, il sera cassé quand les utilisateurs essaieront de mettre à jour leur système.
Les règles pour les bibliothèques partagées sont très simples.
$ nm -g oldlib.so.X.Y | cut -c10- | grep -e^T
et de
$ nm -g newlib.so.X.Y | cut -c10- | grep -e^T
Cela ne montre pas si les types des arguments des fonctions ont changés, mais au moins vous verrez rapidement si certaines fonctions ont été ajoutées et/ou supprimées.
Parfois, cela arrive qu'une bibliothèque est écrite en plusieurs fichiers, et que les fonctions internes soient visibles pour communiquer entres ces fichiers. Traditionnellement ces noms de fonctions commencent par un underscore, et n'ont pas part à l'API elle-même.
Quelques ports ont besoin d'être modifiés, de toute façon, pour compiler les bibliothèques partagées correctement. Rappelez-vous que la compilation des bibliothèques partagées devraient être faites par :
cc -shared -fpic|-fPIC -o libfoo.so.4.5 obj1 obj2
Essayer de renommer la bibliothèque après cette action pour ajuster le numéro de version ne fonctionnera pas : les bibliothèques ELF utilisent un peu plus de magie pour paramétrer le nom interne de la bibliothèque, ainsi vous devez la lier avec la version correcte dès la première fois.
D'un autre côté, souvenez-vous que vous pouvez surcharger les variables de Makefile
depuis la ligne de commande, par l'usage de MAKE_FLAGS
dans le Makefile
du port. Dans certains cas, le programme que vous portez aura une simple variable qui vous permet de surcharger en paramétrant la version de la bibliothèque dans MAKE_FLAGS
, par exemple MAKE_FLAGS= SO_VERSION=${LIBfoo_VERSION}
. Dans d'autres, le port aura besoin d'être corrigé pour utiliser de telle variable.
L'infrastructure du port gère déjà ces détails dans les ports basés sur libtool et ceux sur CMake. Pour libtool, par défaut la version de la base du système est utilisée, mais dans d'autres cas, cela est insuffisant et USE_LIBTOOL=gnu
peut être paramétrée. CMake est géré par l'usage du module cmake.port.mk
: MODULES += devel/cmake
. Dans ces cas, plus de détails sont gérés automatiquement :
SHARED_LIBS
est examinée et les numéros de versions sont automatiquement remplacés. ${WRKBUILD}/shared_libs.log
, qui peut être directement incluse dans le Makefile
du port.
Quelques ports utilisent le drapeau -soname
de ld(1) pour surcharger la spécification de la bibliothèque dans le champ DT_SONAME. Paramétrez
DT_SONAME n'est pas un bogue en lui-même mais il n'est pas habituellement désirable dans OpenBSD là où ld.so(1) est intelligent, et que l'arborescence des ports prend soin de changer les versions des bibliothèques. Toutefois, d'un mauvais soname peut résulter des binaires inutilisables qui dépendent de cette bibliothèque : soit toujours ou après certaines mises à jour du port contenant la bibliothèque. Pour vérifier si le champ DT_SONAME est paramétré, exécutez la commande suivante :
$ objdump -x /path/to/libfoo.so.0.0 | fgrep SONAME SONAME libfoo.so.0.0
En règle générale, le paramétrage de soname devrait être explicitement corrigé. La seule exception est la situation où le bon soname est enregistré et qu'il est difficile de corriger le code relatif à soname et qu'un tel correctif ne sera pas accepté. Dans ce cas, soname devrait pleinement correspondre au nom de fichier (voir l'exemple ci-dessus).
Demander à l'utilisateur d'ajouter des répertoires à son chemin ldconfig(8) est une très mauvaise idée : toutes les bibliothèques partagées qui sont liées directement aux programmes devraient apparaître dans /usr/local/lib
. Toutefois, il est possible d'utiliser un lien symbolique vers l'actuelle bibliothèque. Vous devriez comprendre les règles de consultation des bibliothèques :
-L
pour paramétrer les chemins à consulter pour les bibliothèques. Cela stoppe la consultation aussi tôt que possible s'il trouve qu'une bibliothèque correspond à ces requis.
Ainsi, supposons que vous avez deux port qui fournissent deux versions majeures d'une bibliothèque donnée, telles que qt.1.45
et qt.2.31
. Puisque les deux ports peuvent être installés simultanément, pour s'assurer qu'un programme donné sera lié à qt.1
, la bibliothèque est fournie en tant que /usr/local/lib/qt/libqt.so.1.45
, et les programmes seront liés en utilisant :
$ ld -o program program.o -L/usr/local/lib/qt -lqt
De la même manière, un programme qui est lié avec qt.2
utilisera le fichier /usr/local/lib/qt2/libqt.so.2.31
avec :
$ ld -o program program.o -L/usr/local/lib/qt2 -lqt
Pour résoudre ces bibliothèques à l'exécution, un lien appelé /usr/local/lib/libqt.so.1.45
et un lien appelé /usr/local/lib/libqt.so.2.31
ont été fournis. C'est suffisant pour satisfaire ld.so(1).
C'est une erreur de lier un programme en utilisant qt1
avec :
$ ld -o program program.o -L/usr/local/lib -lqt
Ce code suppose que qt.2.31
n'est pas installé, ce qui est une mauvaise supposition.
De telles astuces sont seulement nécessaires dans de rares cas de bibliothèques très répandues où une période de transition entre les versions majeures doit être fournie. En général, c'est suffisant de s'assurer que les bibliothèques apparaissent dans /usr/local/lib
.
Le code des nouvelles dépendances a besoin des dépendances complètes de bibliothèques. Vous devez utiliser make lib-depends-check
ou make port-lib-depends-check
pour vérifier qu'un port mentionne toutes les bibliothèques requises. Vous les écrivez simplement dans LIB_DEPENDS/WANTLIB
, tel que :
LIB_DEPENDS += x11/gtk+ WANTLIB += gtk>=1.2 gdk>=1.2
Ce n'est pas une erreur de spécifier les bibliothèques statiques sur une ligne WANTLIB
. WANTLIBS
sont pleinement évaluées au moment de la compilation des packages : le package résultant aura l'information de dépendance de la bibliothèque intégrée en tant que lignes pour ld.so qui capture le numéro actuel major.minor qui est utilisé pour la compilation, et rien pour les bibliothèques statiques.
Dans les faits, fournir des lignes LIB_DEPENDS
même pour les bibliothèques statiques est une bonne idée. Cela simplifiera la mise à jour du port si une dépendance donnée bascule d'une bibliothèque statique à une bibliothèque partagée.
Les lignes WANTLIB
doivent spécifier certains chemins utilisés par ld. Avec le même exemple que ci-dessus, un standard qt2 dépend de fragment qui dirait WANTLIB += lib/qt2/qt.=2
. Ceci permet à la dépendance de vérifier que le code fasse les bonnes choses lorsque de multiples versions d'une même bibliothèque sont rencontrées.
Ainsi, quand vous mettez à jour ou ajoutez un port qui invoque des bibliothèques partagées, certains détails doivent être faits correctement.
WANTLIB
et LIB_DEPENDS
. Si vous introduisez de nouvelles bibliothèques partagées, surveillez les BUILD_DEPENDS
qui ont besoin d'être transformées en LIB_DEPENDS
. Aucoconf est un outil GNU supposé aider à écrire des programmes portables. Il est souvent utilisé avec automake (des makefiles portables) et libtool (des bibliothèques partagées portables).
Ces outils ne fonctionnent pas aussi bien que prévu, et créer souvent des challenges spécifiques dans le port de logiciel vers OpenBSD.
Un certain nombre de projets logiciels ont des scripts de configuration, et dans la plupart des cas, ces scripts ont été générés par autoconf. De tels scripts ont une ligne en début qui dit :
# Generated automatically using autoconf version 2.13
ou quelque chose de similaire. La procédure de génération est couverte dans la section suivante. Le plus souvent, les ports autoconf arrivent avec les scripts générés, et avec les scripts source qui les génèrent. La nouvelle section couvre le simple cas où vous désirez simplement exécuter le script généré, sans le modifier. Assurez-vous de lire la section à-propos des chevaux de Troie.
Ce script est normalement exécuté pendant la phase de configuration lors de la compilation des ports. Pour invoquer le script configure, il suffit de paramétrer CONFIGURE_STYLE=gnu
qui invoquera automatiquement ${WRKSRC}/configure
.
Si votre script configure est ailleurs, paramétrez juste CONFIGURE_SCRIPT
en lui donnant la bonne valeur.
Les scripts configure prennent souvent beaucoup d'arguments. Le processus par défaut de l'arborescence des ports sera seulement de leur passer –prefix
et –sysconfdir
. De très anciens scripts configure ne comprennent pas –sysconfdir
; vous pouvez paramétrez le vieux CONFIGURE_STYLE=gnu
dans de tels cas.
De même, certains ports ne font pas attention à DESTDIR
. Ces ports accepteront souvent le paramétrage de prefix=${DESTDIR}/usr/local
sans aucun problème, ce qui peut être fait avec CONFIGURE_STYLE=gnu dest
.
Les ports utilisant autoconf et automake auront les Makefiles
avec un format spécifique qui commence par quelques emplacements standards.
bindir
: emplacement pour les binairessysconfdir
: lieu pour la configurationincludedir
: endroit où inclure les répertoires
Si le script configure ne vous permet pas de les surcharger, vous serez toujours capable de le faire plus tard lors des phases de compilations ou fake
. Cela suppose, bien sûr, que la seule référence d'un tel répertoire soit dans le Makefile
généré.
Par exemple, une astuce pratique consiste à basculer sysconfdir
vers ${PREFIX}/share/example/pkgname
durant la phase fake
pour obtenir les fichiers de config par défaut du package (puisque les packages ne stockent pas normalement leurs fichiers sous /etc
).
Les ports utilisant pleinement autoconf et automake peuvent supporter la compilation dans un répertoire différent : essayez de paramétrer SEPARATE_BUILD=flavored
et regardez si cela fonctionne. Cela vous permettra de supprimer l'arborescence de compilation sans supprimer l'arborescence source, en vous donnant des endroits séparés pour ${WRKSRC}
et ${WRKBUILD}
. Dans quelques cas, des compilations séparées peuvent avoir besoin d'utiliser gmake, là où le reste du port se contente de bsd-make, ce qui dans ce cas ne vaut pas la peine.
Automake générera quelques règles pour recompiler tous les scripts générés s'il y a des changements. C'est ce qui est souvent obtenu dans le cas des correctifs spécifiques à OpenBSD. Pour cette raison, tant que CONFIGURE_STYLE
correspond à l'utilisation d'autoconf, la post-correction touchera à de nombreux fichiers dans un ordre spécifique, de sorte qu'aucune dépendance automatique ne soit déclenchée plus tard. La liste des dépendances est donnée dans l'ordre tsort(1) dans un fichier mentionné dans REORDER_DEPENDENCIES
(qui par défaut est ${PORTSDIR}/infrastructure/mk/automake.dep
).
Le script configure exécute en premier un script fixe appelé config.guess
, ce qui déterminera quel système configure est exécuté. config.guess
ne varie pas d'un port à l'autre et est un script fixe, ainsi l'arborescence des ports d'OpenBSD le remplace avec une version fixée qui connaît certaines des architectures spécifiques d'OpenBSD. Depuis que la plupart des packages logiciels sont livrés avec config.guess
, et puisque certains sont très anciens, c'est une étape nécessaire. Si un package logiciel contient plus d'un config.guess
, vous pouvez les surcharger tous en paramétrant MODGNU_CONFIG_GUESS_DIRS
par une pleine liste des répertoires à traiter.
Le script configure généré par autoconf vérifie alors simplement toutes les fonctionnalités sur le système existant, en recherchant le compilateur, et en exécutant de simples programmes de test. Puisque certains de ces tests sont longs, l'arborescence des ports est en premier configurer avec le fichier CONFIG_SITE=config.site
. La configuration recherchera les contenus du fichier en premier avant d'exécuter les tests. Certains scripts configure peuvent avoir des bogues qui les empêchent de s'exécuter correctement en la présence de config.site
. Paramétrer CONFIG_SITE
vide éliminera ce genre de problèmes.
La plupart des configure détecteront automatiquement certaines conditions. Il est très important de chercher les options de configure, les sorties de configure, et le fichier généré config.log
: ceci vous indiquera quelles options sont trouvées, et lesquelles ne le sont pas. Cela vous permet de trouver où configure ne trouve pas un package installé.
Cela vous dit aussi quels packages optionnels configure trouvent. Dans l'arborescence des ports, ceux-ci sont appelés des dépendances cachées. C'est une mauvaise chose : une dépendance cachée est un package supplémentaire que configure récupérera s'il est installé. Cela créera alors un paquet mutant. Dans certains cas, la compilation échouera à cause de particularités d'OpenBSD. Dans certains cas, la création du package échouera, car certains fichiers auront des noms différents. Dans certains cas, le package résultant sera incorrect, car il n'enregistrera aucune dépendance sur le package optionnel. La recherche des sorties de configure est l'une des tâches les plus importantes d'un responsable de port. Attention aux tests en cascade : détecter une fonctionnalité donnée peut conduire un script configure à essayer à trouver une fonctionnalité dépendante, vous ne verrez donc pas la deuxième fonctionnalité dans la sortie de configuration à moins que la première fonctionnalité ne soit déclenchée.
Dans les cas où certaines dépendances cachées sont trouvées, certaines actions devraient être prises. L'action la plus simple est d'installer le package optionnel, et de voir ce que fait configure. S'il détecte le package, on peut soit désactiver la détection (par l'usage des options de configure, ou les variables d'environnement, ou la correction du script configure), soit vérifier que la compilation s'effectue bien et par l'ajout de la dépendance dans la liste des packages dépendants. Un meilleur choix est de trouver un ensemble raisonnable de dépendances par défaut, et d'ajouter alors certaines saveurs pour couvrir certaines fonctionnalités communes.
Les scripts configure sont normalement générés depuis un fichier configure.in
(les versions récentes d'autoconf utilisent à la place un fichier configure.ac
). Une bibliothèque standard de définitions est souvent disponible dans un aclocal.m4
.
Dans la plupart des cas, corriger directement configure est une mauvaise idée. Il est mieux de corriger le fichier configure.in
et d'obtenir que l'arborescence des ports appelle autoconf. Les bons porteurs s'efforceront d'écrire les changements de configure.in
qu'ils peuvent transmettre aux auteurs de logiciel.
Différentes versions d'autoconf produiront des scripts distincts de configure. autoconf-2.13
est spécial : il a été utilisé sur une période assez longue, et il y a eu de versions mutantes d' autoconf-2.13
(en fait, des versions beta d'un autoconf récent) largement utilisées.
Puisque plusieurs versions d'autoconf sont utilisables en même temps, le script d'autoconf actuellement disponible dans l'arborescence des ports fait partie d'un port appelé metaauto.
Tel script autoconf est appelé et contrôlé par la variable d'environnement AUTOCONF_VERSION
. L'appel d'autoconf se fait si vous paramétrez CONFIGURE_STYLE=autoconf
, avec le paramétre AUTOCONF_VERSION
. Dans la plupart, identifiez la version d'autoconf qui est utilisée pour générer le script configure distribué (habituellement évident lors de la lecture du script) et utilisez vous-même la même version.
Autoconf s'appuie sur le préprocesseur unix standard m4(1). Normalement, autoconf s'appuie sur certaines fonctionnalités de la version GNU de m4, gm4. Heureusement, le m4 d'OpenBSD a assez de fonctionnalités pour exécuter autoconf aussi bien, il a juste besoin d'être invoqué avec -g
pour capturer autoconf. Très rarement, l'exécution d'autoconf avec le m4 d'OpenBSD produira des scripts configure bogués. Les développeurs d'OpenBSD doivent corriger une telle issue.
Les scripts configure sont de gros fichiers générés. C'est la place idéal pour cacher des chevaux de troie, ce qui est déjà arrivé dans le passé. C'est la principale raison pour laquelle plusieurs versions d'autoconf sont dans l'arborescence : un bon porteur est censé vérifier qu'un script configure généré correspond à ce que le fichier autoconf de l'arborescence des ports construit.
Autoheader est un autre programme relié à autoconf qui normalement est exécuté pour créer un fichier config.h.in
. Paramétrer CONFIGURE_STYLE=autoconf
exécutera aussi autoheader. Certains ports n'utilisent pas autoheader. Paramétrer CONFIGURE_STYLE=autoconf no-autoheader
corrigera ce problème.
libtool a quelques crochets spécifiques dans configure.in
. Il y a souvent un script libtool.m4
fourni avec. Obtenir de libtool qu'il fasse bien les choses va au-delà de cette documentation.
Les packages devraient seulement installer les fichiers sous ${PREFIX}
, qui est /usr/local
par défaut. D'un autre côté, la politique d'OpenBSD est d'installer la plupart des fichiers de configuration sous ${SYSCONFDIR}
, qui est /etc
par défaut.
Notez qu'il est parfaitement acceptable pour un package binaire d'avoir les deux ${PREFIX}
et ${SYSCONFDIR}
codés en dur : PREFIX
et SYSCONFDIR
sont principalement des paramètres utilisateur qui influencent la compilation du package.
Les listes d'empaquetage contiennent un mécanisme spécifique pour gérer les fichiers de configuration.
${PREFIX}/share/examples/PKGNAME/foo.rc
.@sample ${SYSCONFDIR}/foo.rc
juste sous le fichier de configuration type.
Contrairement à d'autres fichiers dans la liste d'empaquetage, les entrées @sample
peuvent avoir un nom de chemin absolu.
Certains gros packages peuvent aussi avoir besoin de leur propre répertoire de configuration, @sample ${SYSCONFDIR}/directory/
s'en occupera.
Utiliser @sample directory/
pour créer des répertoires spécifiques au port qui ne capturent aucun fichier de configuration est assurément un bon style. @sample
interprète correctement les annotations correctes de @mode
, @owner
, @group
. Cela peut être un peu compliqué, parce que vous avez souvent besoin de basculer entre le mode par défaut et le mode spécifique d'un fichier de configuration.
make update-plist
sait comment copier les annotations @sample
, mais il ne sait pas comment les créer, elles doivent être écrites en premier.
Notez la distinction entre les fichiers de configuration et les fichiers de configuration type : le port doit être configuré pour trouver ses fichiers sous ${SYSCONFDIR}
. C'est seulement durant l'étape de la simulation d'installation qu'il doit mettre ses affaires sous ${PREFIX}/share/examples
. Une manière simple de gérer cela est de copier les fichiers dans un post-install
.
Une astuce pratique qui fonctionne souvent est de regarder le Makefile
d'un programme, et de surcharger le répertoire de configuration durant la phase de simulation d'installation par l'usage spécifique de FAKE_FLAGS
, par exemple :
FAKE_FLAGS= DESTDIR=${WRKINST} \ sysconfdir=${WRKINST}${TRUEPREFIX}/share/examples/PKGNAME
Vous avez juste besoin de surveiller les programmes qui écrivent le répertoire de configuration dans des fichiers spécifiques durant la phase d'installation.
security/integrit
utilise un répertoire de configuration avec certains fichiers. Sa liste d'empaquetage peut ressembler à ceci : @comment $OpenBSD$ @bin bin/i-ls @info info/integrit.info @man man/man1/i-ls.1 @man man/man1/i-viewdb.1 @man man/man1/integrit.1 @bin sbin/i-viewdb @bin sbin/integrit share/doc/integrit/ share/doc/integrit/README share/doc/integrit/crontab share/doc/integrit/install_db share/doc/integrit/integrit_check share/doc/integrit/viewreport share/examples/integrit/ @sample ${SYSCONFDIR}/integrit/ share/examples/integrit/root.conf @sample ${SYSCONFDIR}/integrit/root.conf share/examples/integrit/src.conf @sample ${SYSCONFDIR}/integrit/src.conf share/examples/integrit/usr.conf @sample ${SYSCONFDIR}/integrit/usr.conf
mail/dovecot
utilise @sample dir/
pour créer des répertoires privés.... @extraunexec rm -rf /var/dovecot/* @sample ${SYSCONFDIR}/dovecot/ @sample ${SYSCONFDIR}/dovecot/conf.d/ @mode 755 @sample /var/dovecot/ @mode 750 @group _dovenull @sample /var/dovecot/login/
sysutils/nut
utilise un propriétaire spécifique pour ses fichiers de configuration.@comment $OpenBSD$ @conflict upsd-* @newuser ${NUT_USER}:${NUT_ID}:daemon:UPS User:/var/empty:/sbin/nologin ... share/examples/nut/ @sample ${SYSCONFDIR}/nut/ @owner ${NUT_USER} share/examples/nut/ups.conf @sample ${SYSCONFDIR}/nut/ups.conf share/examples/nut/upsd.conf @mode 600 @sample ${SYSCONFDIR}/nut/upsd.conf @mode share/examples/nut/upsd.users @mode 600 @sample ${SYSCONFDIR}/nut/upsd.users @mode share/examples/nut/upsmon.conf @mode 600 @sample ${SYSCONFDIR}/nut/upsmon.conf @mode share/examples/nut/upssched.conf @sample ${SYSCONFDIR}/nut/upssched.conf @mode 700 @sample /var/db/nut/ @mode @owner share/ups/ share/ups/cmdvartab share/ups/driver.list
Ce document traite actuellement des soucis d’échantillonnage de sons seulement. Les contributions traitant des synthétiseurs et des tables waveform sont les bienvenues.
Les applications audio ont tendance à être difficiles à porter, car il s'agit d'un domaine où les interfaces ne sont pas du tout normalisées, bien que les approches ne varient pas beaucoup d'un système d'exploitation à l'autre.
OpenBSD a sa propre couche audio fournie par la bibliothèque sndio, documentée dans sio_open(3). Jusqu'à ce que cela soit fusionné dans cette page, vous pouvez trouver d'autres informations à-propos de programmer cette API dans ce guide, des conseils sur l'écriture et le port du code audio. sndio permet aux processus utilisateur d'accéder au matériel audio(4) et au serveur audio sndiod(8) d'une manière uniforme. Il supporte l'opération full-duplex, et quand il est utilisé avec le serveur sndiod(8), il supporte le ré-échantillonnage et les conversions de format à la volée.
VOUS NE DEVRIEZ RIEN SUPPOSER DU MATÉRIEL AUDIO UTILISÉ.
Le mauvais code est un code qui vérifie seulement le champ a_info.play.precision
par rapport à 8 ou 16 bits, et suppose des échantillons non signés ou signés basés sur le comportement soundblaster. Vous devriez vérifier le type d'échantillon explicitement, et accorder le code en rapport. Un simple exemple :
AUDIO_INIT_INFO(&a_info); a_info.play.encoding = AUDIO_ENCODING_SLINEAR; a_info.play.precision = 16; a_info.play.sample_rate = 22050; error = ioctl(audio, AUDIO_SETINFO, &a_info); if (error) /* deal with it */ error = ioctl(audio, AUDIO_GETINFO, &a_info); switch(a_info.play.encoding) { case AUDIO_ENCODING_ULINEAR_LE: case AUDIO_ENCODING_ULINEAR_BE: if (a_info.play.precision == 8) /* ... */ else /* ... */ break; case ... default: /* don't forget to deal with what you don't know !!! For instance, */ fprintf(stderr, "Unsupported audio format (%d), ask ports@ about that\n", a_info.play.encoding); } /* now don't forget to check what sampling frequency you actually got */
Il s'agit du plus petit fragment de code qui traitera la plupart des problèmes.
En usage normal, vous demandez juste le type d'encodage (ex, AUDIO_ENCODING_SLINEAR
), et vous recevez l'encodage avec endianness (ex, AUDIO_ENCODING_SLINEAR_LE
). En considérant qu'une carte son n'a pas à utiliser le même endianness que votre plate-forme, vous devriez être préparé à traiter cela. La manière la plus facile est de préparer un tampon audio plein, et d'utiliser swab(3) si un changement d'endianness est requis. Le traitement des échantillons externes se résume généralement à :
Évidemment, vous pouvez supprimer les étapes 3 et 5 si vous jouez simplement un extrait sonore qui se trouve dans votre format natif de la carte son.
Le matériel peut avoir certaines limitations bizarres, telles que ne pas être capable de dépasser 22 050 Hz en stéréo, mais être capable de monter à 44 100 Hz en mono. Dans de tels cas, vous devriez donner à l'utilisateur la possibilité d'indiquer ses préférences, essayez ensuite de faire du mieux que possible pour lui donner les meilleures performances possibles. Par exemple, il est stupide de limiter la fréquence à 22 050 Hz à cause de votre sortie stéréo. Que se passe-t-il si l'utilisateur ne dispose pas d'une chaîne stéréo connectée à sa sortie de carte audio ?
Il est aussi stupide de coder en dur des limitations telles que soundblaster dans vos programmes. Vous devriez faire attention à cela, mais essayez de dépasser la barrière des 22 050 Hz stéréo et vérifiez le résultat.
Vous devriez définitivement vérifier la fréquence d'échantillonnage que votre carte vous renvoie.
Une différence de 5 % équivaut déjà à un demi-ton, et certaines personnes ont une audition beaucoup plus précise que cela, même si la plupart d'entre nous ne remarquons rien. Votre application devrait pouvoir effectuer un ré-échantillonnage à la volée, peut-être naïvement, ou par des applications sournoises de la formule de ré-échantillonnage de Shannon si vous le pouvez.
Les échantillons n'utilisent pas toujours la pleine plage de valeurs possibles. Premièrement, les échantillons enregistrés avec un gain bas ne fonctionneront pas très forts sur la machine, forçant l'utilisateur à monter le volume. Deuxièmement, sur les machines ayant un son mal isolé, la sortie de son faible signifie que vous entendez surtout le cœur de votre machine, et non pas le son attendu. Finalement, la conversion stupide de 16 bits à 8 bits peut vous laisser avec seulement 4 bits audio utilisables, ce qui rend la qualité terriblement mauvaise.
Si possible, la meilleure solution est probablement d'analyser à l'avance le flux entier que vous allez jouer, et de le mettre à l'échelle pour qu'il fonctionne sur la plage dynamique complète. Si vous ne pouvez pas vous le permettre, mais que vous pouvez avoir a bit of look-ahead sur ce que vous allez jouer, que vous pouvez ajuster le volume à la volée, vous avez juste à vous assurer que le facteur d'amplification reste sur la fréquence basse par rapport au son que vous voulez jouer, et que vous n'obtenez absolument pas de débordements – cela sonnera toujours bien pire que l'amélioration que vous essayez d'obtenir.
Comme la perception du volume sonore est logarithmique, l'utilisation de décalages arithmétiques est généralement suffisante. Si votre donnée est signée, vous devriez explicitement coder le décalage en tant que division, car l'opérateur C »
n'est pas portable sur une donnée signée.
Si tout échoue, vous devriez au moins essayer de fournir à l'utilisateur une option d'échelle de volume.
Les applications bas de gamme n'ont habituellement rien à faire de cela. Gardez à l'esprit que certains d'entre nous utilise OpenBSD sur 68030 bas de gamme, et que si une application sonore peut fonctionner dessus, elle le fera.
N'oubliez pas d'exécuter des évaluations. Les optimisations théoriques sont juste cela : théoriques. Certaines hard figures devraient être collectées pour vérifier quelle taille d'améliorations est possible de celles qui ne le sont pas.
Pour des applications audio de haute performance, telle que mpegI-layer3, certains points devraient être pris en compte :
write
, en tant que système d'appel, entraîne un coût élevé comparé au procédé interne audio. AUDIO_GETENC ioctl
devrait être utilisé pour récupérer tous les formats que le dispositif audio fournit. Faites spécifiquement attention au drapeau AUDIO_ENCODINGFLAG_EMULATED
. Si votre application est toujours capable de sortir toutes sortes de formats bizarres, et raisonnablement optimisée pour cela, essayez d'utiliser un format natif à tout prix. D'un autre côté, le code d'émulation présent dans le dispositif audio peut être considéré comme raisonnablement optimal, ainsi ne le remplacez pas par du code modifié rapidement. Un modèle que vous pouvez avoir à suivre pour obtenir des résultats optimaux est d'abord de compiler un petit programme de test qui s'informe du matériel audio spécifique disponible, puis de procéder à la configuration de votre programme afin qu'il traite de façon optimale ce matériel. Vous pouvez vous attendre raisonnablement à ce que les personnes qui veulent avoir de bonne performance audio recompilent votre port lorsqu'ils changent de matériel, à condition que cela fasse une différence.
En considérant qu'OpenBSD n'est pas temps réel, vous pouvez toujours souhaiter écrire des applications audio qui le soient, par exemple des jeux. Dans de tel cas, vous devez baisser la taille du bloc afin que les sons ne se désynchronisent pas avec le jeu courant. Le problème avec cela est que si le dispositif audio peut être starved, cela peut donner des résultats horribles.
Dans le cas où vous voulez simplement que l'audio soit synchronisé avec certaines sorties graphiques, mais que le comportement de votre programme est prévisible, la synchronisation est plus facile à réaliser. Vous jouez juste vos échantillons audio, et demandez au dispositif audio sur lequel vous jouez actuellement avec AUDIO_GETOOFFS
, d'utiliser alors l'information pour synchroniser après les graphiques. Si vous demandez suffisamment souvent (disons, toutes les dixièmes de seconde) et aussi longtemps que vous avez assez de puissance pour exécuter votre application, vous pouvez obtenir une très bonne synchronisation de cette manière. Il se peut que vous deviez ajuster les figures par un constant offset, car il y a un certain décalage entre ce que l'audio rapporte, ce qui est en cours de lecture, et le temps qu'il faut pour que XWindow affiche quelque chose.
Dans le cas des applications audio, travailler avec l'auteur original du programme est très important. Si, par exemple, leur code ne fonctionne seulement qu'avec des cartes soundblaster, il y a une bonne chance qu'ils doivent bientôt faire face à d'autres technologies.
Si vous n'envoyez pas vos commentaires à l'auteur, votre travail sera inutile.
Il se peut aussi que l'auteur ait déjà remarqué les problèmes que vous rencontrez et qu'il les aborde dans son arborescence de développement actuel. Si les correctifs que vous écrivez représentent plus qu'une poignée de lignes, la coopération est certainement une très bonne idée.
Cette section fournit les guides d'instructions sur comment traiter les problèmes avec groff versus mandoc(1) dans les ports, et quoi faire avec les pages de manuel non anglaises.
Lors de la création d'un nouveau port ou la mise à jour d'un port existant, veuillez vérifier que le port puisse utiliser mandoc pour formater ses manuels. Les deux vérifications automatiques et manuelles décrites ci-dessous sont requises. Cela peut permettre que les manuels soient plus utiles pour les utilisateurs du port, et réduira le temps de construction du port.
Si un nouveau port ou un port existant, qui n'est pas marqué avec USE_GROFF
, ne fonctionne pas avec mandoc, veuillez le rapporter à schwarze@, qui corrigera probablement mandoc.
Aucun outil n'est requis excepté l'utilitaire mandoc(1) inclus dans le système de base. Dans le cas très inhabituel où vous suspectez de récents changements de mandoc importants pour le port, vous pouvez facilement mettre à jour mandoc, même sans mettre à jour le reste du système :
$ cd /usr/src/usr.bin/mandoc/ $ cvs -q up -Pd $ make cleandir $ make obj $ make $ doas make install
En option, vous pouvez aussi obtenir une copie de l'utilitaire gmdiff qui aide à comparer les sorties de groff et mandoc. Le script gmdiff n'est pas strictement requis, faire les vérifications à la main est parfaitement acceptable.
Les paragraphes suivants demandent d'envoyer les rapports aux responsables de mandoc dans quelques situations particulières. Avant d'envoyer de tels rapports, veuillez toujours cocher la liste de vérification suivante :
mandoc -Tlint
(ou mandoc -Tlint -Werror
quand les messages importants ne sont pas pertinents) dans le corps de votre courriel. Habituellement, cela est facile à reproduire, mais il peut arriver que ce ne soit pas le cas, causant une confusion inutile. Pour faire la partie automatique de la vérification, veuillez exécuter la commande suivante sur tous les fichiers sources des manuels de mdoc(7) et man(7) contenus dans le port :
$ mandoc -Tlint -Werror *
Si vous obtenez des messages UNSUPPORTED
, examinez attentivement les emplacements respectifs de la page du manuel. Il est probable que la page soit mal formée avec mandoc et que le port requiert USE_GROFF
. Si vous êtes sûr que toutes les erreurs de formatage liées aux fonctionnalités non prises en charge sont mineures et ne gênent pas le lecteur, vous pouvez supprimer USE_GROFF
; mais en cas de doute, laissez en place USE_GROFF
quand il y a des messages UNSUPPORTED
.
S'il y a des messages ERROR
, ils devraient être brièvement examinés. Dans le cas inhabituel où ils sont relatifs à des erreurs de formatage avec mandoc qui n'arrivent pas avec groff, ils devraient être rapportés ; le responsable de mandoc peut choisir de laisser mandoc émettre des messages UNSUPPORTED
dans des cas supplémentaires ou de corriger le formatage.
Si les pages de manuel sont bonnes avec groff, ne les corrigez jamais pour éliminer les erreurs de mandoc. Ce serait simplement un projet make-work qui n'aiderait personne : cela n'aidera pas à améliorer les manuels ni mandoc.
S'il n'y a pas d'erreurs ou que les erreurs ne sont pas relatives à des problèmes de formatage avec mandoc, passez à la partie manuelle de la vérification. Regardez comment les manuels sont formatés par mandoc. Ont-ils l'air bien ? Si oui, vous n'avez pas besoin de USE_GROFF
, et il n'y a rien à rapporter.
S'il n'y a pas d'erreurs, mais que la sortie de mandoc a des problèmes sérieux, tels que, une information pertinente est manquante ou une partie de la sortie est déformée, veuillez toujours rapporter vos résultats, même si vous savez que cela est dû à un problème connu avec mandoc. Nous voulons savoir quelles issues posent de sérieux problèmes en pratique, de manière à ce que nous puissions traiter en premier lieu les problèmes les plus pressants.
Si le sortie de mandoc a de sérieux problèmes et que la sortie de groff fait de mauvaises choses, alors les manuels sont probablement tout simplement cassés en amont. Dans ce cas, vous avez les options habituelles lorsqu'un port de logiciel est cassé : abandonner le port, ignorer le problème, rapporter en amont, et/ou corriger les bogues. Si vous avez besoin d'aide avec ce dernier, parlez-en à schwarze@.
S'il n'y a pas d'erreurs, mais que la sortie de mandoc a de petits problèmes qui ne gênent pas réellement l'utilisateur lors de la lecture du manuel, il est bienvenue que vous rapportiez ces problèmes aussi. Dans ce cas, vous êtes cordialement invités à vérifier en première la liste TODO de mandoc, pour éviter de rapporter encore et encore les mêmes petits problèmes - mais en cas de doute, il est toujours préférable de rapporter les doublons plutôt que de laisser les problèmes passer inaperçus.
S'il y a seulement très peu d'erreurs, en particulier si vous avez l'impression que la sortie de mandoc est tout de même correcte, vous n'avez généralement pas besoin de USE_GROFF=Yes
. En cas de doute, demandez un avis. De telles questions contribuent souvent à améliorer le signalement des erreurs mandoc, en particulier à identifier et à supprimer les messages d'erreurs mandoc factices.
Pour accélérer les vérifications des manuels, en particulier si vous faites souvent les vérifications mandoc sur les ports OpenBSD, et afin de réduire les risques de problèmes overlooking, considérez l'usage de l'utilitaire gmdiff. Il prend les noms de fichier d'un nombre arbitraire de fichiers sources des manuels comme arguments, exécute groff et mandoc sur tous les fichiers à tour de rôle, et compare les sorties des deux programmes. Toutefois, gardez à l'esprit que vous faites toujours des vérifications manuelles avec le but ultime de juger de la qualité des sorties de mandoc : tous les points ci-dessus s'appliquent toujours même si vous utilisez le script gmdiff pour vous aider dans votre travail. Notez aussi que gmdiff trouvera habituellement de petites différences de formatage entre les deux programmes, en particulier à-propos du respect des espaces blancs. Si la sortie de mandoc semble bonne, même s'il y a de légères différences avec la sortie de groff, USE_GROFF
n'est pas nécessaire.
Pour faciliter l'usage, il est possible d'utiliser gmdiff depuis une cible personnalisée de mk.conf :
gmdiff: @make fake; cd ${WRKINST}${TRUEPREFIX}; find man -type f -path 'man/man*' -print0 | xargs -0r gmdiff | less
Vous pourriez vous poser des questions sur les messages d'avertissement de mandoc, par opposition aux erreurs mandoc. En résumé, la distinction est que les erreurs peuvent avoir un impact sérieux sur l'utilité de la sortie, alors que les avertissements peuvent au pire causer des problèmes mineurs de formatage, si cela est. Si un message d'avertissement de mandoc apparaît être relatif à des sorties sérieusement déformées, cela est probablement un bogue dans mandoc et doit toujours être rapporté. Cela dit, il est évident que les messages d'avertissements ne sont pas pertinents pour la décision d'utiliser ou non mandoc pour un port donné. Ils existent pour les auteurs de manuels, pour aider à améliorer la qualité des manuels, mais pas pour les porteurs.
Dans le cas où vous êtes un des développeurs en amont du port, ou si vous savez qu'ils se soucient de la bonne qualité de leurs manuels et acceptent volontiers les correctifs, il peut être judicieux d'utiliser mandoc -Tlint
pour identifier les problèmes potentiels de formatage et de produire des correctifs à soumettre. Habituellement, il n'y a pas besoin de mettre de tels correctifs dans l'arborescence des ports.
Comme pour tout esprit de linting, avant de changer le code source de votre mdoc(7) ou man(7) ou d'envoyer vos correctifs, assurez-vous en premier d'avoir trouvé de réels problèmes dans les manuels. L'utilitaire mandoc n'est pas parfait. Il peut produire de faux messages d'avertissements. Nous essayons de corriger cela, mais il y a toujours de la place pour l'améliorer. En cas de doute, rapportez l'issue et demandez un avis.
Voici des règles empiriques, non forgées dans la pierre. Si vous trouvez que votre port a des besoins spéciaux, vous pouvez les mettre de côté ; le but est rendre le port pratique pour les utilisateurs. Envisagez d'en discuter avec schwarze@ à ce propos si vous le faites, peut-être nous apprendrons quelque chose de votre port.
BUILD_DEPENDS = converters/libiconv
et utilisez iconv(1) pour la cible post-build
. man/language/manN/*.N
et ne faites pas USE_GROFF
. man/language/manN
, sans aucun caractère “_” ou “@”. Ne jamais inclure l'encodage dans le nom du chemin, et assurez-vous que la partie /language/
ne contienne pas de “.” (un point). zh_CN
et zh_TW
plutôt que juste zh
. De même, conservez pt
et pt_BR
tels qu'ils sont, et installez les deux s'ils sont disponibles. Si vous suivez ce qui précède, les personnes peuvent effectuer les opérations suivantes sans modifier la configuration par défaut :
$ doas pkg_add mc $ export LC_CTYPE=en_US.UTF-8 $ alias ruman="man -m /usr/local/man/ru" $ ruman mc
Cette section essaye de fournir certaines informations sur l'écriture et l'installation de scripts rc.d(8).
Les ports qui installent un service bénéficient grandement de scripts rc.d(8). Ils permettent à l'utilisateur de vérifier facilement si le service est fonctionnel, aussi bien que de fournir une manière facile et cohérente de démarrer et de l'arrêter.
Écrire un script rc.d(8) est simple et facile dû au fait d'une conception simple et propre du système rc.subr(8). Pensez qu'il y a plusieurs choses à prendre en compte.
${PKGDIR}
avec une extension .rc
, tel que mpd.rc
. Cela permettra aux outils package de le prendre. ${TRUEPREFIX}
lors de l'écriture du chemin du service. Voici, ci-dessous, un exemple typique de script :
#!/bin/ksh # # $OpenBSD: specialtopics.html,v 1.81 2018/09/18 08:04:03 bentley Exp $ daemon="${TRUEPREFIX}/sbin/munin-node" . /etc/rc.d/rc.subr pexp="/usr/bin/perl -wT ${daemon}${daemon_flags:+ ${daemon_flags}}" rc_pre() { install -d -o _munin /var/run/munin } rc_cmd $1
Un modèle de script peut aussi être trouvé dans le répertoire des modèles de l'arborescence des ports.
Cette page est la traduction officieuse de la page “Ports - Special Porting Topics” de la FAQ officielle d'OpenBSD.
En cas de doute, merci de vous y référer !
Si vous voulez participer à l'effort de traduction, merci de lire ce topic.
Contribut(rice|eur)s :