1 Theorie |
Für Textzeichen wird der Datentyp "char" benutzt. Neuere Linux- und Unix-Systeme verwenden meist die UTF-8-Codierung, um nichtenglische Zeichen zu codieren.
Der Datentyp "wchar_t" wird hauptsächlich für die X11-Programmierung verwendet und von Toolkits für GUI-Programmierung wie z.B. wxWidgets.
Wiederverwendbare Module werden in Bibliotheken zusammengefasst. Eine Bibliothek ist eine Archivdatei, die verschiedene Module enthält. Um die Bibliothek beim Linken eines ausführbaren Programmes zu verwenden, muss nur ein Dateiname (der der Bibliothek) angegeben werden, anstatt alle Module einzeln aufzulisten.
Eine Bibliothek wird mit dem Programm "ar" erstellt.
Hier ein Makefile-Ausschnitt aus dem Verzeichnis hsmet, um die Bibliothek libhsmet.a zu erstellen:
LIBHSMETOBJ= he-error.o he-file.o he-geom.o he-long.o he-longfo.o \ he-longso.o he-read.o he-strch.o he-ulong.o he-ulongfo.o \ he-ulongso.o libhsmet.a: $(LIBHSMETOBJ) -[ ! -f libhsmet.a ] || rm -f libhsmet.a ar -r libhsmet.a $(LIBHSMETOBJ) -ranlib libhsmet.a || echo 'No need to worry.' chmod 644 libhsmet.a
Zunächst wird eine evtl. vorhandene Datei libhsmet.a
gelöscht.
Anschließend wird mit dem Kommando "ar" die Bibliothek erstellt.
Angegeben werden dabei der Bibliotheksname mit der Option "-r",
anschließend die zu verwendenden Objektmodule.
Das Programm "ranlib" wird auf älteren Linux/Unix-Vesionen
benötigt, um einen Index der Funktionen und Variablen zu erstellen
und zur Bibliothek hinzuzufügen. Auf aktuellen Linux- bzw.
Solaris-Systemen ist der Aufruf von ranlib nicht mehr erforderlich,
wird aber empfohlen, falls das Programm ranlib verfügbar ist.
Bibliotheksdateien werden meist in ein Verzeichnis installiert, das als letzte Komponente "lib" im Namen hat. Bibliotheken als Bestandteil des Betriebssystems werden meist nach /usr/lib installiert, selbst installierte Bibliotheken nach /usr/local/lib.
Die zugehörigen Header-Dateien werden meist in ein Verzeichnis installiert, das als letzte Komponente "include" im Namen hat. Header-Dateien des Betriebssystems werden meist nach /usr/include installiert, Header-Dateien von selbst installierter Software nach /usr/local/include.
Auf Unterverzeichnisse von /usr bzw. /usr/local hat nur der
root-Benutzer Zugriff.
Normale Nutzer können Bibliotheken nur in ihr Home-Verzeichnis
installieren.
Für den C-Compiler muss das Verzeichnis mit den Header-Dateien im Include-Suchpfad stehen. Mit der Option "-IVerzeichnis" kann ein Verzeichnis zum Suchpfad hinzugefügt werden.
Für den Linker muss das Verzeichnis mit der Bibliotheksdatei im Library-Suchpfad stehen. Mit der Option "-LVerzeichnis" kann ein Verzeichnis zum Suchpfad hinzugefügt werden.
Um die Bibliothek libhsmet.a mit zu verwenden, muss der Linker
mit der Option "-lhsmet" aufgerufen werden.
Die Option "-lname" veranlasst, dass im Library-Suchpfad
nach einer Datei libname.so (siehe nächster Abschnitt) oder
libname.a gesucht wird. Wird libname.a gefunden, so
werden die darin enthaltenen Objektmodule zur ausführbaren Datei
hinzugelinkt.
Aktuelle Programmierumgebungen verwenden intelligente Linker. Diese
fügen nur die Objektmodule der Bibliothek zur ausführbaren Datei
hinzu, die auch tatsächlich benötigt werden.
Dynamische Bibliotheken werden erst beim Programmstart mit dem ausführbaren Programm verlinkt. Sie haben die Endung .so (shared object).
Bei der Erstellung des ausführbaren Programmes fügt der Linker nicht die Bibliotheksmodule in das ausführbare Programm ein, sondern nur einen Hinweis, dass die entsprechende Bibliothek beim Programmstart dynamisch gelinkt werden muss. Dieser eingebaute Hinweis beinhaltet im Normalfall einen Dateinamen ohne Verzeichnisangabe, aber meist mit Angabe einer Versionsnummer (die Bibliotheksversion, siehe unten).
Welche Verzeichnisse nach der angegebenen Datei durchsucht
werden, ist systemabhängig. Meist werden - falls vorhanden -
zunächst die Umgebungsvariablen LD_LIBRARY_PATH bzw. LD_RUN_PATH
durchsucht. Diese enthalten eine Liste von Verzeichnissen, jeweils
durch Doppelpunkt getrennt.
Falls die Datei dort nicht gefunden wurde, werden unter Linux die
Verzeichnisse durchsucht, die in der Datei /etc/ld.so.cache
konfiguriert sind. Diese Datei wird mit dem Programm ldconfig aus
der Konfigurationsdatei /etc/ld.so.conf erzeugt.
Zuletzt werden Standardverzeichnisse wie /usr/lib durchsucht.
Wird ein Programm mit einer aktuellen Version einer dynamischen Bibliothek gelinkt und dann auf einen Computer übertragen, auf dem nur eine ältere Version der Bibliothek mit geringerem Funktionsumfang vorhanden ist, so ist das Programm nicht lauffähig.
Bei der Installation des Programmes muss also gleichzeitig sichergestellt werden, dass für alle vom Programm verwendeten dynamischen Bibliotheken die jeweils passende Version vorhanden ist.
Für Quelltexte wird meist eine zwei-, drei- oder vierstellige Versionsnummer im Dateinamen verwendet.
Für die dynamische Bibliothek wird meist eine ein- oder
zweistellige Versionsnummer verwendet, die mit den ersten Stellen
der Quelltext-Version einhergeht.
Alle API-Änderungen gehen mit einer neuen Bibliotheksversion
einher. Unter API-Änderungen werden Änderungen verstanden, die dazu
führen, dass
API-Änderungen beinhalten insbesondere
Wird eine dynamische Bibliothek installiert, so werden im lib-Verzeichnis normalerweise drei Dateien angelegt:
Die Header-Dateien werden wie bei statischen Bibliotheken auch im include-Verzeichnis gespeichert.
Alle Programme, die libname.so.Bibliotheksversion benutzen, verwenden nun ab dem nächsten Programmstart die aktualisierte Version.
Allen Programmen, die die alte Bibliotheksversion erfordern,
steht diese weiterhin zur Verfügung.
Die neue Bibliotheksversion ist für alle Programme verfügbar, die
diese erfordern.
Beim Erstellen von Programmen führt die Linker-Option "-labc" über die symbolischen Links dazu, dass die aktualisierte Version verwendet wird. Neu erstellte Programm verwenden also die aktuelle libname.so.Bibliotheksversion.
In den folgenden beiden Makefile-Auszügen wird eine fiktive Bibliothek libabc.so mit Quelltex-Version 2.0.0.13 und Bibliotheks-Version 2.0 erstellt.
Beim Compilieren der C-Quelltexte zu Objektmodulen muss die Option "-fPIC" verwendet werden. Der damit erzeugte Code ist im Hauptspeicher verschiebbar (PIC: position independent code).
Der nachfolgende Makefile-Auszug zeigt, wie nach der Erstellung der Objektmodule die dynamische Bibliothek erstellt wird.
SVERS=2.0.0.13 LVERS=2.0 OBJECTS= ... Objekt-Dateien ... libabc.so: $(OBJECTS) -[ ! -f libabc.so.$(LVERS) ] || rm libabc.so.$(LVERS) -[ ! -f libabc.so.$(SVERS) ] || rm libabc.so.$(SVERS) -[ ! -f libabc.so ] || rm libabc.so cc -shared -fPIC -D_REENTRANT -o libabc.so.$(SVERS) $(OBJECTS) -Wl,soname,libabc.so.$(LVERS) -Wl,-z,defs ln -s libabc.so.$(SVERS) libabc.so.$(LVERS) ln -s libabc.so.$(LVERS) libabc.so
Die Option -Wl,soname,libabc.so.$(LVERS) legt den SONAME-Eintrag auf libabc.so.2.0 fest. Wird die Bibliothek beim Linken eines Programmes verwendet, wird der SONAME mit im ausführbaren Programm gespeichert. Beim Start des Programmes wird dann die shared library libabc.so.2.0 gesucht und dynamisch gelinkt.
Der GNU C-Compiler kennt die Option "-rpath ...", hiermit kann eine Liste von Verzeichnissen vorgegeben werden, in denen dann nach der Bibliothek gesucht wird, wenn das Programm gestartet wird:
SVERS=2.0.0.13 LVERS=2.0 RPATH=/usr/local/lib:/usr/lib:/lib OBJECTS= ... Objekt-Dateien ... libabc.so: $(OBJECTS) -[ ! -f libabc.so.$(LVERS) ] || rm libabc.so.$(LVERS) -[ ! -f libabc.so.$(SVERS) ] || rm libabc.so.$(SVERS) -[ ! -f libabc.so ] || rm libabc.so cc -shared -rpath $(RPATH) -fPIC -D_REENTRANT -o libabc.so.$(SVERS) $(OBJECTS) -Wl,soname,libabc.so.$(LVERS) -Wl,-z,defs ln -s libabc.so.$(SVERS) libabc.so.$(LVERS) ln -s libabc.so.$(LVERS) libabc.so
Der Suchpfad, in dem bei Ausführung des fertigen Programmes nach
der dynamischen Bibliothek gesucht wird, wird hier bereits bei der
Erstellung der dynamischen Bibliothek angegeben und in dieser
gespeichert.
Wird die Bibliothek beim Linken eines Programmes verwendet, wird
diese Information in das ausführbare Programm übernommen.
Beim Compilieren der C-Quelltexte zu Objektmodulen muss die Option "-xcode=pic32" verwendet werden. Der damit erzeugte Code ist im Hauptspeicher verschiebbar (PIC: position independent code).
SVERS=2.0.0.13 LVERS=2.0 OBJECTS= ... Objekt-Dateien ... libabc.so: $(OBJECTS) -[ ! -f libabc.so.$(LVERS) ] || rm libabc.so.$(LVERS) -[ ! -f libabc.so.$(SVERS) ] || rm libabc.so.$(SVERS) -[ ! -f libabc.so ] || rm libabc.so cc -G -Bdynamic -dy -xcode=pic32 -D_REENTRANT -o libabc.so.$(SVERS) -h libabc.so.$(LVERS) ln -s libabc.so.$(SVERS) libabc.so.$(LVERS) ln -s libabc.so.$(LVERS) libabc.so
Hier sorgt die Option -h für den SONAME-Eintrag in der Bibliothek.
Beim Linken werden die Optionen "-L...Bibliothekssuchpfad..." und -labc verwendet.
Beim Linken werden die Optionen "-Bdynamic" und "-dy" verwendet.
Diese Optionen bewirken, dass die *.so-Datei verwendet wird, wenn
eine Bibliothek sowohl als *.so- als auch als *.a-Datei
vorliegt.
Optional kann "-xcode=pic32" auch beim Linken mit angegeben
werden.
Mit der Option "-R ..." kann hier die Doppelpunkt-getrennte
Liste von Verzeichnissen vorgegegen werden, in denen dann nach der
Bibliothek gesucht wird, wenn das Programm gestartet wird.
Der Suchpfad wird hier also erst beim Erstellen des ausführbaren
Programmes angegeben und in diesem gespeichert.
Die Installation von Paketen über eine Paketverwaltung ist
angenehmer als die Installation jeweils aus den Quelltexten
vorzunehmen.
Moderne Paketverwaltungs-Systeme beziehen die Pakete über das
Internet und installieren erforderliche weitere Pakete gleich
mit.
Das Erstellen von Paketen wird hier am Beispiel eine Projektes zur Dreieckflächenberechnung gezeigt, an diesem Projekt sind folgende Dateien beteiligt:
triangle.c | Bibliotheks-Modul mit einer Funktion zur Berechung der Dreieckfläche |
triangle.h | Header-Datei mit dem Prototypen der Funktion zur Berechnung der Dreieckfläche |
mtriangle.c | Modul mit dem Hauptprogramm |
configure.ac | Quelldatei für das configure-Script |
Makefile.in | Aus dieser Datei wird erstellt das configure-Script das Makefile |
Das Makefile muss die Verwendung der Variable DESTDIR unterstützen. Dazu wird am Beginn des Makefiles ein leerer Eintrag
DESTDIR=
erstellt, dieser kann durch ein Kommandozeilenargument überschrieben werden, z.B.:
make DESTDIR=/opt/irgendwo install
Die Kommandos für das Ziel "install" installieren Dateien nicht
direkt nach $(bindir), $(sysconfdir) ... sondern nach
$(DESTDIR)$(bindir), $(DESTDIR)$(sysconfdir) ...
Diese Verzeichnisse müssen bei Bedarf neu angelegt und mit
Berechtigungen versehen werden. Das oben dargestellte make-Kommando
installiert dann die Dateien nicht in die Verzeichnis-Hierarchie
des Systems, sondern legt alle zu installierenden Dateien in einer
Verzeichnis-Hierarchie unterhalb von /opt/irgendwo ab.
Diese Verzeichnis-Hierarchie wird für die Paket-Erstellung
benutzt.
Hier ein Auszug aus einem Makefile.in als Beispiel:
# Package prefix DESTDIR= prefix=@prefix@ datarootdir=@datarootdir@ exec_prefix=@exec_prefix@ bindir=@bindir@ sbindir=@sbindir@ libexecdir=@libexecdir@ datadir=${datarootdir} sysconfdir=@sysconfdir@ scd=$(sysconfdir) libdir=@libdir@ sharedlibdir=$(libdir)/shared mandir=@mandir@ includedir=@includedir@ localstatedir=@localstatedir@ srcdir=@srcdir@ top_srcdir=@top_srcdir@ VPATH=@srcdir@ myprog: ... # Abhängigkeiten von myprog ... # Kommandos, um myprog zu erstellen install: -[ -d $(DESTDIR)$(bindir) ] || mkdir -p $(DESTDIR)$(bindir) -[ -d $(DESTDIR)$(libdir) ] || mkdir -p $(DESTDIR)$(libdir) -[ -d $(DESTDIR)$(includedir) ] || mkdir -p $(DESTDIR)$(includedir) chmod 755 $(DESTDIR)$(bindir) chmod 755 $(DESTDIR)$(libdir) chmod 755 $(DESTDIR)$(includedir) cp myprog $(DESTDIR)$(bindir)/myprog chmod 755 $(DESTDIR)$(bindir)/myprog -chmod 644 *.h -chmod 755 *.so -tar cf - ./*.h | ( cd $(DESTDIR)$(includedir) ; tar xvf - ) -tar cf - ./*.so | ( cd $(DESTDIR)$(libdir) ; tar xvf - )
Zusätzlich zu den üblichen Entwicklungstools wird noch das Paket "rpmdevtools" benötigt.
Zur Installation der Entwicklungstools empfehle ich:
yum install yum-tools rpmdevtools yum-builddep kernel
Die Verzeichnisstruktur für die RPM-Tools kann entweder mit
rpmdev-setuptree
oder manuell mit
mkdir -p $HOME/rpmbuild/SOURCES mkdir -p $HOME/rpmbuild/SPECS mkdir -p $HOME/rpmbuild/RPMS mkdir -p $HOME/rpmbuild/SRPMS mkdir -p $HOME/rpmbuild/BUILD
erstellt werden.
Auf einigen Systemen erwarten die RPM-Tools die Verzeichnisse
SOURCES, SPECS... als Unterverzeichnisse von /usr/src/redhat.
Um als Nutzer RPMs im Homeverzeichnis bauen zu können, muss das
Makro "_topdir" entsprechend definiert werden.
Hierzu ist in der Datei $HOME/.rpmmacros folgende Zeile einzutragen
(Datei neu anlegen, falls sie noch nicht existiert):
%_topdir /home/joe/rpmbuild
Das Quelltext-Archiv muss im Verzeichnis $HOME/rpmbuild/SOURCES abgelegt werden.
Eine *.spec-Datei enthält die Informationen für den Bau eines
Paketes, diese Dateien werden im Verzeichnis $HOME/rpmbuild/SPECS
abgelegt.
Einige Editoren (z.B. vim) stellen beim Schreiben einer neuen
*.spec-Datei ein Template bereit.
Hier ein Beispiel für eine Datei "triangle.spec", die von dem
Template abgeleitet wurde:
Name: triangle
Version: 1.0.0
Release: 1%{?dist}
Summary: Triangle area calculation
Vendor: Alfred Ahnungslos
Packager: Dora Deppenheimer
Group: Applications/Tools
License: BSD
URL: http://www.triangle.org/
Source0: http://www.triangle.org/triangle-1.0.0.zip
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
# BuildRequires:
# Requires:
Prefix: /usr
%description
A program and a shared library to calculate a triangle area.
%prep
%setup -q
%post
ldconfig
%postun
ldconfig
%build
%configure
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
%doc README
/usr
%changelog
Folgende Einträge sind vorhanden:
rpm --prefix=/opt/software/joe -ihv triangle-1.0.1.rpm
cd $HOME/rpmbuild/SPECS rpmbuild -ba triangle.spec
Die *.rpm-Dateien landen in $HOME/rpmbuild/RPMS/Architektur.
yum install $HOME/rpmbuild/RPMS/Architektur/paket.rpm
oder
rpm -i $HOME/rpmbuild/RPMS/Architektur/Paket.rpm
yum remove Paket
oder
rpm -e Paket
SVR4 packages werden beispielsweise unter Solaris benutzt.
Auch für SVR4-Pakete ist es erforderlich, dass das Makefile den DESTDIR-Eintrag unterstützt, siehe RPM → DESTDIR-Unterstützung.
Die Software wird erstellt und in ein spezielles Verzeichnis installiert:
mkdir -p /home/dora/pkgs mkdir -p /home/dora/pkgs/Paket make DESTDIR=/home/dora/pkgs/Paket install
Im Verzeichnis /home/dora/pkgs/Paket wird eine Datei pkginfo angelegt, z.B.:
PKG="DODEtriangle"
NAME="triangle"
ARCH="sparc"
VERSION="1.0.0"
CATEGORY="application"
VENDOR="Alfred Ahnungslos"
PSTAMP="Dora Deppenheimer"
EMAIL="dora.deppenheimer@fh-schmalkalden.de"
CLASSES="none"
Die Datei enthält folgende Informationen:
PKG | Eindeutiger Paketname. Die Großbuchstaben-Folge am Anfang soll es erleichtern, Paketnamen nach Herausgeber zu sortieren. |
NAME | Paket-Name. |
ARCH | Unterstützte Hardware-Architektur. |
VERSION | Versionsnummer. |
CATEGORY | Paket-Kategorie, sollte für Anwendungsprogramme immer "application" sein. |
VENDOR | Autor der Original-Quelltexte. |
PSTAMP | Name desjenigen, der das Paket erzeugt. |
E-Mail-Adresse desjenigen, der das Paket erzeugt. | |
CLASSES | Sollte auf "none" belassen werden. |
Eine Web-Suche nach
Solaris package pkginfo file
führt zu Webseiten mit detaillierter Beschreibung des pkginfo-Dateiformates.
Im Verzeichnis /home/dora/pkgs/Paket wird eine Datei prototype angelegt, z.B.:
i pkginfo=/home/dora/pkgs/triangle/pkginfo
f none /usr/bin/triangle=/home/dora/pkgs/triangle/usr/bin/triangle 0755 bin bin
f none /usr/include/triangle.h=/home/dora/pkgs/triangle/usr/include/triangle.h 0644 bin bin
f none /usr/lib/libtriangle.so.1.0=/home/dora/pkgs/triangle/usr/lib/libtriangle.so.1.0 0644 bin bin
s none /usr/lib/libtriangle.so=libtriangle.so.1.0 0644 bin bin
Das Script dkmkproto.pl kann mit
cd /home/dora/pkgs/Paket perl dkmkproto.pl
benutzt werden, um ein Grundgerüst der prototype-Datei zu erstellen. Dieses muss allerdings vor Verwendung manuell überprüft und ggf. nachbearbeitet werden.
Eine Web-Suche nach
Solaris package prototype file
führt zu Webseiten mit detaillierter Beschreibung des prototype-Dateiformates.
Mit
cd /home/dora/pkgs/Paket pkgmk -o -d /home/dora/pkgs
wird im Verzeichnis /home/dora/pkgs ein Unterverzeichnis DODEtriangle angelegt, das jetzt alle Dateien für das Package enthält. Der Name wird dem PKG-Eintrag der pkginfo-Datei entnommen.
Mit
cd /home/dora/pkgs pkgtrans -s `pwd` /home/dora/pkgs/dode-triangle-1.0.0 DODEtriangle
wird die Package-Datei /home/dora/pkgs/dode-triangle-1.0.0 angelegt.
Als root wird
pkgadd -d /home/dora/pkgs/dode-triangle-1.0.0 DODEtriangle
ausgeführt, um das Package zu installieren.
Soll das Package deinstalliert werden, wird als root
pkgrm DODEtriangle
ausgeführt.
1 | http://apps.e-technik.fh-schmalkalden.de/krause/tipps/linux.html#swpackages |
2 | http://www.rpm.org/max-rpm/ |