Kapitel 5. Vorgaben und Richtlinien für das Quelltextverzeichnis

This translation may be out of date. To help with the translations please access the FreeBSD translations instance.

Dieses Kapitel dokumentiert verschiedene Vorgaben und Richtlinien für das FreeBSD-Quelltextverzeichnis.

5.1. Stil-Richtlinien

Ein konsistenter Code-Stil ist extrem wichtig, besonders in einem so grossen Projekt wie FreeBSD. Der Code sollte dem FreeBSD Code-Stil entsprechen, welcher in style(9) und style.Makefile(5) genauer beschrieben ist.

5.2. MAINTAINER eines Makefiles

Wenn ein bestimmter Bereich der FreeBSD src/-Distribution von einer Person oder Gruppe gepflegt wird, kann dies durch einen Eintrag in die Datei src/MAINTAINERS der Öffentlichkeit mitgeteilt werden. Maintainer eines Ports in der Ports-Sammlung können ihre Verantwortung über den Port durch einen Eintrag in die MAINTAINER-Zeile im Makefile des Ports der Welt mitteilen.

MAINTAINER= email-addresses

Für andere Teile des Repositories oder andere Abschnitte, die noch keinen Maintainer aufweisen, oder falls Sie sich nicht sicher sind, wer der Maintainer ist, sehen Sie sich die Commit-Historie des betreffenden Ports an. Es ist recht häufig der Fall, dass ein Maintainer nicht explizit aufgeführt ist, aber trotzdem diejenigen Personen, die den Port seit den letzten paar Jahren aktiv betreuen, daran interessiert sind, Änderungen zu begutachten. Selbst wenn dies nicht explizit in der Dokumentation oder im Quellcode erwähnt ist, wird es trotzdem als höfliche Geste angesehen, wenn man nach einer Überprüfung der eigenen Änderungen fragt.

Die Rolle eines Maintainers ist die folgende:

  • Der Maintainer ist verantwortlich für diesen Code. Er oder sie muss einerseits für die Behebung von Fehlern und das Beantworten von Problemberichten für diesen Code die Verantwortung tragen und andererseits, falls es sich um beigesteuerte Software handelt, neue Versionen verfolgen und bereitstellen.

  • Änderungen an Verzeichnissen, die ein Maintainer definiert hat, sollten an den Maintainer für eine Überprüfung gesendet werden, bevor diese committet werden. Nur wenn der Maintainer in einer inakzeptablen Zeitspanne auf mehrere E-Mails nicht antwortet, können die Änderungen, die mit dem Commit in Kraft treten, auch ohne Überprüfung durch den Maintainer vollzogen werden. Dennoch wird empfohlen, dass die Änderungen, falls möglich, von jemand anderem überprüft werden.

  • Es ist natürlich nicht akzeptabel, einer Person oder Gruppe den Status eines Maintainers zu geben, so lange sie nicht zustimmt, diese Pflicht auf sich zu nehmen. Andererseits muss es kein einzelner Mensch sein. Eine Gruppe von Menschen ist genauso in Ordnung.

5.3. Beigesteuerte Software

Einige Teile der FreeBSD-Distribution enthalten Software, die aktiv außerhalb des FreeBSD-Projektes gepflegt wird. Aus historischen Gründen nennen wir dies contributed Software. Beispiele dafür sind sendmail, gcc und patch.

Über die Jahre wurden verschiedene Methoden genutzt, um solche Software zu verwalten, und jede hat Vor- wie auch Nachteile. So hat sich kein eindeutiger Gewinner herauskristallisiert.

Es wurde viel über diesen Umstand diskutiert und eine Methode als die "offizielle" vorgestellt, um in Zukunft diese Art der Software zu importieren. Ferner wird dringend geraten, dass sich existierende, beigesteuerte Software diesem Modell annähert, da es signifikante Vorteile gegenüber der alten Methode gibt. Dazu gehört auch, dass jeder einfach Diffs bezüglich der "offiziellen" Quelltext-Versionen erzeugen kann (auch ohne direkten Repository-Zugang). Dies wird es deutlich vereinfachen, Änderungen an die Hauptentwickler zurückfließen zu lassen.

Letztendlich kommt es jedoch auf die Menschen an, welche die Arbeit leisten. Wenn die Durchführung dieses Modells bei einem Paket mal nicht möglich ist, können Ausnahmen dieser Regeln nur mit Genehmigung des Core-Teams und der Übereinstimmung der anderen Entwickler gewährt werden. Die Fähigkeit, dieses Paket auch in Zukunft pflegen zu können, ist eine der Schlüsselfragen bei dieser Entscheidung.

Durch einige bedauernswerte Einschränkungen des RCS-Dateiformats und die Handhabung von Herstellerzweigen ist von unwesentlichen, trivialen und/oder kosmetischen Änderungen an Dateien dringend abzuraten, die dem Herstellerzweig folgen. "Grammatikalische oder sprachliche Fehlerbehebungen" sind explizit unter der "Kosmetik"-Kategorie einzuordnen und sollten vermieden werden. Das Repository kann sich durch Änderungen einzelner Zeichen dramatisch aufblähen.

5.3.1. Herstellerimports mit CVS

Das file-Werkzeug soll als Beispiel dienen, wie dieses Modell funktioniert:

src/contrib/file enthält den Quelltext so, wie vom Maintainer dieses Pakets bereitgestellt. Teile, die unter FreeBSD gänzlich unnutzbar sind, können entfernt werden. Im Fall von file(1) wurde u.a. das Unterverzeichnis python und Dateien mit dem Präfix lt vor dem Import entfernt.

src/lib/libmagic enthält ein Makefile im bmake-Stil, das die Regeln des Standard-Makefiles bsd.lib.mk nutzt, um die Bibliothek zu erstellen und die Dokumentation zu installieren.

src/usr.bin/file enthält ein Makefile im bmake-Stil, welches das file-Programm erstellt und installiert, ebenso die dazugehörigen Manualpages, welche die Regeln von bsd.prog.mk nutzen.

Das Entscheidende ist hier das src/contrib/file-Verzeichnis, welches nach den folgenden Regeln erstellt wird: Es muss den Quelltext aus dem Original enthalten (ohne RCS-Schlüsselworte und im korrekten Herstellerzweig) mit so wenig FreeBSD-spezifischen Änderungen wie möglich. Sollte es Zweifel geben, wie hier zu verfahren ist, unbedingt zuerst nachfragen und nicht auf gut Glück etwas probieren in der vagen Hoffnung, dass es "irgendwie funktioniert".

Aufgrund der eingangs schon erwähnten Einschränkungen bei Herstellerzweigen ist es erforderlich, dass "offizielle" Fehlerbehebungen vom Hersteller in die Originalquellen der Distribution einfließen und als Resultat wieder in den Herstellerzweig importiert werden. Offizielle Fehlerbehebungen sollten nie direkt in FreeBSD eingepflegt und "committet" werden, da dies den Herstellerzweig zerstören würde und der Import von zukünftigen Versionen wäre um ein Vielfaches schwerer, da es zu Konflikten kommen würde.

Da einige Pakete Dateien enthalten, die zur Kompatibilität mit anderen Architekturen und Umgebungen als FreeBSD gedacht sind, ist es zulässig, diese Teile zu löschen, wenn sie für FreeBSD nicht von Interesse sind, und so Speicherplatz zu sparen. Dateien, die ein Copyright und Release-artige Informationen zu den vorhandenen Dateien enthalten, sollten nicht gelöscht werden.

Falls es einfacher erscheint, können die bmake-Makefiles vom Verzeichnisbaum durch einige Dienstprogramme automatisch erstellt werden, was es hoffentlich sogar noch einfacher macht, eine Version zu aktualisieren. Ist dies geschehen, so stellen Sie bitte sicher, diese Werkzeuge in das Verzeichnis src/tools gleich mit dem Port an sich einzuchecken, sodass es für zukünftige Maintainer verfügbar ist.

Im Verzeichnis src/contrib/file sollte eine Datei mit dem Namen FREEBSD-upgrade hinzugefügt werden und sie sollte den Stand wie folgt anzeigen:

  • Welche Dateien ausgelassen wurden.

  • Von wo die Original-Distribution stammt und/oder wo die offizielle Hauptseite zu finden ist.

  • Wohin Fehlerbehebungen an den Originalautor gesendet werden können.

  • Möglicherweise eine Übersicht, welche FreeBSD-spezifischen Änderungen vorgenommen wurden.

Ein Beispielinhalt von src/contrib/groff/FREEBSD-upgrade ist hier aufgelistet:

$FreeBSD: src/contrib/groff/FREEBSD-upgrade,v 1.5.12.1 2005/11/15 22:06:18 ru Exp $

This directory contains virgin sources of the original distribution files
on a "vendor" branch.  Do not, under any circumstances, attempt to upgrade
the files in this directory via patches and a cvs commit.

To upgrade to a newer version of groff, when it is available:
        1. Unpack the new version into an empty directory.
           [Do not make ANY changes to the files.]

        2. Use the command:
                cvs import -m 'Virgin import of FSF groff v<version>' \
                        src/contrib/groff FSF v<version>

           For example, to do the import of version 1.19.2, I typed:
                cvs import -m 'Virgin import of FSF groff v1.19.2' \
                        src/contrib/groff FSF v1_19_2

        3. Follow the instructions printed out in step 2 to resolve any
           conflicts between local FreeBSD changes and the newer version.

Do not, under any circumstances, deviate from this procedure.

To make local changes to groff, simply patch and commit to the main
branch (aka HEAD).  Never make local changes on the FSF branch.

All local changes should be submitted to Werner Lemberg <wl@gnu.org> or
Ted Harding <ted.harding@nessie.mcc.ac.uk> for inclusion in the next
vendor release.

ru@FreeBSD.org - 20 October 2005

Eine weitere Möglichkeit ist es, eine Liste von Dateien, die nicht enthalten sein sollen zu pflegen, was besonders dann sehr hilfreich sein kann, wenn die Liste ziemlich gross oder kompliziert ist bzw. Imports sehr häufig stattfinden. Durch erstellen einer Datei namens FREEBSD-Xlist im gleichen Verzeichnis, in welches das Herstellerverzeichnis importiert werden soll, die eine Liste von auszuschliessenden Dateinamen-Mustern pro Zeile enthält, können zukünftige Imports folgendermassen durchgeführt werden:

% tar -X FREEBSD-Xlist -xzf vendor-source.tgz

Als Beispiel einer FREEBSD-Xlist-Datei wird hier diejenige von src/contrib/tcsh gezeigt:

*/BUGS
*/config/a*
*/config/bs2000
*/config/bsd
*/config/bsdreno
*/config/[c-z]*
*/tests
*/win32

Bitte importieren Sie weder FREEBSD-upgrade noch FREEBSD-Xlist mit den beigesteuerten Quellen. Stattdessen sollten Sie diese Dateien nach dem initialen Import hinzufügen.

5.3.2. Herstellerimports mit SVN

Dieser Abschnitt beschreibt die Prozedur für Herstellerimports mit Subversion im Detail.

  1. Vorbereiten des Quellbaums

    Wenn dies Ihr erster Import nach dem Wechsel zu SVN ist, sollen Sie den Herstellerbaum aufräumen, verflachen und die Merge-Historie in den Hauptzweig vorbereiten. Falls das nicht Ihr erster Import ist, können Sie diesen Schritt ohne Probleme überspringen.

    Während der Konvertierung von CVS zu SVN wurden Herstellerzweige mit der gleichen Struktur wie der Hauptzweig importiert. Beispielsweise wurden die foo Herstellerquellen in vendor/foo/dist/contrib/foo abgelegt, jedoch ist dies unpraktisch und zwecklos. Was wir wirklich wollen, ist dass die Herstellerquellen direkt in vendor/foo/dist liegen, beispielsweise so:

    % cd vendor/foo/dist/contrib/foo
    % svn move $(svn list) ../..
    % cd ../..
    % svn remove contrib
    % svn propdel -R svn:mergeinfo
    % svn commit

    Beachten Sie, dass das propdel-Bit notwendig ist, da mit Subversion 1.5 automatisch svn:mergeinfo zu jedem Verzeichnis hinzugefügt wird, das Sie kopieren oder verschieben. In diesem Fall brauchen Sie diese Informationen nicht, da Sie nichts in den Zweig mergen werden, den Sie gelöscht haben.

    Sie werden wahrscheinlich die Tags genauso verflachen wollen. Die Prozedur dafür ist die selbe. Wenn Sie dies tun, sollten Sie den Commit bis zum Schluss aufschieben.

    Prüfen Sie den dist-Baum und führen Sie alle nötigen Aufräumarbeiten durch, die Sie für sinnvoll erachten. Sie werden möglicherweise die Erweiterung von Schlüsselwörtern deaktivieren wollen, da dies auf unmodifizierten Quellen keinen Sinn ergibt. In machen Fällen kann dies sogar schädlich sein.

    % svn propdel svn:keywords -R .
    % svn commit

    Bootstrappen der svn:mergeinfo auf dem Zielverzeichnis (des Hauptzweiges) auf die Revision die mit der letzten Änderung, die im Herstellerzweig vor dem Import der neuen Quellen durchgeführt wurde, korrespondiert, wird ebenso benötigt:

    % cd head/contrib/foo
    % svn merge --record-only svn_base/vendor/foo/dist@12345678 .
    % svn commit

    Dabei entspricht svn_base dem Basisverzeichnis Ihres SVN-Repositories, z.B. svn+ssh://svn.FreeBSD.org/base.

  2. Neue Quellen importieren

    Bereiten Sie einen kompletten, sauberen Baum mit Herstellerquellen vor. Mit SVN können wir eine komplette Distribution in dem Herstellerzweig aufbewahren, ohne den Hauptzweig aufzublähen. Importieren Sie alles, aber mergen Sie nur das, was wirklich benötigt wird.

    Beachten Sie, dass Sie alle Dateien, die seit dem letzten Herstellerimport hinzugefügt wurden, auch einbeziehen und diejenigen, welche entfernt wurden, auch löschen müssen. Um dies zu bewerkstelligen, sollten Sie sortierte Listen der Bestandteile des Herstellerbaums und von den Quellen, Sie die vorhaben zu importieren, vorbereiten:

    % cd vendor/foo/dist
    % svn list -R | grep -v '/$' | sort > ../old
    % cd ../foo-9.9
    % find . -type f | cut -c 3- | sort > ../new

    Mit diesen beiden Dateien, wird Ihnen das folgende Kommando alle Dateien auflisten, die entfernt wurden (nur die Dateien in old):

    % comm -23 ../old ../new

    Der folgende Befehl wird die hinzugefügten Dateien auflisten (nur diejenigen Dateien in new):

    % comm -13 ../old ../new

    Wir führen dies nun zusammen:

    % cd vendor/foo/foo-9.9
    % tar cf - . | tar xf - -C ../dist
    % cd ../dist
    % comm -23 ../old ../new | xargs svn remove
    % comm -13 ../old ../new | xargs svn add

    Wenn in der neuen Version neue Verzeichnisse hinzugekommen sind, wird dieser letzte Befehl fehlschlagen. Sie müssen diese Verzeichnisse hinzufügen und anschliessend den Befehl erneut ausführen. Genauso müssen Sie Verzeichnisse, die entfernt wurden, händisch löschen.

    Prüfen Sie die Eigenschaften jeder neuen Datei:

    • Alle Textdateien sollten svn:eol-style auf den Wert native gesetzt haben.

    • Alle Binärdateien sollten svn:mime-type auf application/octet-stream gesetzt haben, ausser es existiert ein passenderer Medientyp.

    • Ausführbare Dateien sollten svn:executable auf * gesetzt haben.

    • Es sollten keine anderen Eigenschaften auf den Dateien im Baum gesetzt sein.

      Sie sind bereit, zu committen, jedoch sollten Sie zuerst die Ausgabe von svn stat und svn diff überprüfen, um sicher zu gehen, dass alles in Ordnung ist.

      Sobald Sie den die neue Release-Version des Herstellers committed haben, sollten Sie Ihn für zukünftige Referenzen taggen. Die beste und schnellste Methode ist, dies direkt im Repository zu tun:

      % svn copy svn_base/vendor/foo/dist svn_base/vendor/foo/9.9

      Um den neuen Tag zu bekommen, brauchen Sie nur ihre Arbeitskopie von vendor/foo zu aktualisieren.

      Wenn Sie lieber die Kopie in der ausgecheckten Kopie durchführen wollen, vergessen Sie nicht, die generierte svn:mergeinfo wie oben beschrieben zu entfernen.

  3. Mit -HEAD mergen

    Nachdem Sie Ihren Import vorbereitet haben, wird es Zeit zu mergen. Die Option --accept=postpone weist SVN an, noch keine merge-Konflikte aufzulösen, weil wir uns um diese manuell kümmern werden:

    % cd head/contrib/foo
    % svn update
    % svn merge --accept=postpone svn_base/vendor/foo/dist

    Lösen Sie die Konflikte und stellen Sie sicher, dass alle Dateien, die im Herstellerzweig hinzugefügt oder entfernt wurden, auch sauber im Hauptzweig hinzugefügt bzw. gelöscht wurden. Es ist immer ratsam, diese Unterschiede gegen den Herstellerbaum zu prüfen:

    % svn diff --no-diff-deleted --old=svn_base/vendor/foo/dist --new=.

    Die Option --no-diff-deleted weist SVN an, keine Dateien zu prüfen, die sich zwar im Herstellerbaum, aber nicht im Hauptzweig befinden.

    Bei SVN gibt es das Konzept von innerhalb und ausserhalb des Herstellerbaums nicht. Wenn eine Datei, die zuvor eine lokale Änderung hatte, aber nun keine mehr besitzt, entfernen Sie einfach das was übrig ist, wie FreeBSD Versionstags, damit diese nicht länger in den diffs gegen den Herstellerbaum erscheinen.

    Wenn irgendwelche Änderungen notwendig sind, um die Welt mit den neuen Quellen zu bauen, machen Sie diese jetzt und testen Sie diese bis Sie sicher sind, dass alles korrekt gebaut wird und richtig funktionert.

  4. Commit

    Nun sind Sie bereit für den Commit. Stellen Sie sicher, dass Sie alles in einem einzigen Schritt durchführen. Idealerweise sollten Sie alle diese Schritte in einem sauberen Baum durchgeführt haben. Falls dies der Fall ist, können Sie einfach aus dem obersten Verzeichnis dieses Baums committen. Dies ist der beste Weg, um Überraschungen zu vermeiden. Wenn Sie dies korrekt durchführen, wird der Baum atomar von einem konsistenten Zustand mit dem alten Code in einen neuen konsistenten Zustand mit dem neuen Code überführt.

5.4. Belastende Dateien

Es kann gelegentlich notwendig sein, belastende Dateien in den FreeBSD-Quelltextbaum zu integrieren. Braucht ein Gerät zum Beispiel ein Stück binären Code, der zuerst geladen werden muss, bevor das Gerät funktioniert, und wir haben keine Quellen zu diesem Code, dann wird die binäre Datei als belastend bezeichnet. Die folgenden Richtlinien sind beim Aufnehmen von belastenden Dateien in den FreeBSD-Quelltextbaum zu beachten.

  1. Jede Datei, die durch die System-CPU(s) ausgeführt wird und nicht als Quelltext vorliegt, ist belastend.

  2. Jede Datei, deren Lizenz restriktiver ist als die BSD- oder GNU-Lizenz, ist belastend.

  3. Eine Datei, die herunterladbare Binär-Daten enthält, ist nur belastend, wenn (1) oder (2) zutreffen. Sie muss in einem ASCII-Format gespeichert werden, das Architektur-neutral ist (file2c oder uuencoding wird empfohlen).

  4. Jede belastende Datei braucht eine spezielle Genehmigung vom Core-Team, bevor diese in das Repository aufgenommen werden darf.

  5. Belastende Dateien liegen unter src/contrib oder src/sys/contrib.

  6. Das komplette Modul sollte auch am Stück aufbewahrt werden. Es gibt keinen Grund, dieses zu teilen, außer es gibt einen Code-Austausch mit Quelltext, der nicht belastend ist.

  7. Objekt-Dateien werden wie folgt benannt: arch/filename.o.uu>.

  8. Kernel-Dateien:

    1. Sollten immer nach conf/files.* verweisen (um den Bau einfach zu halten).

    2. Sollten sich immer in LINT befinden, jedoch entscheidet das Core-Team je nach Fall, ob es auskommentiert wird oder nicht. Das Core-Team kann sich zu einem späteren Zeitpunkt immer noch anders entscheiden.

    3. Der Release-Engineer entscheidet, ob es in ein Release aufgenommen wird oder nicht.

  9. Userland-Dateien:

    1. Das Core-Team entscheidet, ob der Code von make world gebaut wird oder nicht.

    2. Der Release-Engineer entscheidet, ob es in das Release aufgenommen wird oder nicht.

5.5. Shared-Libraries

Sollten Sie die Unterstützung für Shared-Libraries bei einem Port oder einem Stück Software, das dies nicht hat, hinzufügen, sollten die Versionsnummern dessen Regeln folgen. Im Allgemeinen hat die sich daraus resultierende Nummer nichts mit der Release-Version der Software zu tun.

Die drei Grundsätze zum Erstellen von Shared-Libraries sind:

  • Sie beginnen mit 1.0.

  • Gibt es eine Änderung, die abwärtskompatibel ist, so springen Sie zur nächsten Minor-Version (beachten Sie, dass ELF-Systeme die Minor-Version ignorieren).

  • Gibt es eine inkompatible Änderung, so springen Sie bitte zur nächsten Major-Version.

Zum Beispiel wird beim Hinzufügen von Funktionen und oder Fehlerbehebungen zur nächsten Minor-Version gesprungen, beim Löschen einer Funktion, Ändern von Funktionsaufrufen usw. ändert sich die Major-Version.

Bleiben Sie bei Versionsnummern in der Form major.minor (x.y). Unser dynamischer Linker a.out kann mit Versionsnummern in der Form x.y.z nicht gut umgehen. Jede Versionsnummer nach dem y (die dritte Zahl) wird völlig ignoriert, wenn Versionsnummern der Shared-Libraries verglichen werden, um zu bestimmen, mit welcher Bibliothek eine Anwendung verlinkt wird. Sind zwei Shared-Libraries vorhanden, die sich nur in der "micro"-Revision unterscheiden, so wird ld.so zu der höheren verlinken. Dies bedeutet, dass wenn Sie mit libfoo.so.3.3.3 verlinken, der Linker nur 3.3 in den Header aufnimmt und alles linkt, was mit libfoo.so.3 .(irgendetwas >= 3).(höchste verfügbare Nummer) beginnt.

ld.so wird immer die höchste "Minor"-Revision benutzen. Beispielsweise wird es die libc.so.2.2 bevorzugen gegenüber der libc.so.2.0, auch dann, wenn das Programm ursprünglich mit libc.so.2.0 verlinkt war.

Unser dynamischer ELF-Linker kann keine Minor-Versionen handhaben. Dennoch sollten die Major- und Minor-Versionen genutzt werden, da unsere Makefiles "das Richtige machen" bezogen auf den Systemtyp.

Für nicht-Port-Bibliotheken lautet die Richtlinie, die Shared-Library-Versionsnummer nur einmal zwischen den Releases zu ändern. Weiterhin ist es vorgeschrieben, die Major-Version der Shared-Libraries nur bei Major-OS-Releases zu ändern (beispielsweise von 6.0 auf 7.0). Wenn Sie also eine Änderung an einer Systembibliothek vornehmen, die eine neue Versionsnummer benötigt, überprüfen Sie die Commit-Logs des Makefiles. Es liegt in der Verantwortung des Committers, dass sich eine erste solche Änderung seit dem letzten Release in der aktualisierten Versionsnummer der Shared-Library im Makefile äußert, folgende Änderungen werden nicht berücksichtigt.


Last modified on: 9. März 2024 by Danilo G. Baio