Kitabı oku: «Praxishandbuch Open Source», sayfa 6
d) Executables
84
Eng mit dem Binärcode hängen die ausführbaren Dateien oder Executables zusammen. Dabei handelt es sich um Dateien, die als Computerprogramm ausgeführt werden können. Sie enthalten also den oben beschriebenen maschinenlesbaren Programmcode, der direkt oder durch eine Laufzeitumgebung – ein sog. runtime environment – ausgeführt werden kann. In einigen Fällen werden auch Dateien, die Bytecode oder Scripting Anweisungen enthalten, als ausführbare Dateien bezeichnet.4 Für dieses Buch sollen sich die Begriffe ausführbare Datei bzw. Executable einfach auf ausführbare Computerprogramme beziehen, die aufgrund ihrer Maschinenlesbarkeit keine für den menschlichen Betrachter verarbeitbaren Informationen zu FOSS Lizenzierung und Rechtsinhabern enthalten.
85
Backup: Erkennen von Code Formen anhand der Dateiendung
Anhand von Dateiendungen lässt sich bereits auf den ersten Blick erkennen, um welche Art von Code es sich bei einer Datei handelt. Mit dem Blick auf die Dateiendung kann man also direkt feststellen, ob es sich um Source Code oder um ausführbare Dateien handelt. Damit sehen Sie auch auf den ersten Blick, ob sich aus der jeweiligen Datei ggf. noch weitere Informationen für die FOSS Bewertung ziehen lassen (wie Angaben zu Copyrights und Lizenzierung in den Datei-Headern von Source Code Dateien) oder ob für die vorliegende Datei ggf. andere und/oder strengere Lizenzbedingungen gelten (für den Fall, dass die Lizenz unterschiedliche Vorgaben für die Weitergabe als ausführbare Datei macht).
Dateiendungen, die darauf hinweisen, dass es sich um Source Code handelt, sind beispielsweise .c, .h, .src oder .java. Hierbei handelt es sich jeweils um Textdateien, die Source Code oder Deklarationen zum Source Code enthalten. Auch bei Dateien, die auf .txt enden, handelt es sich um Textdateien. Solche im Code enthaltenen .txt Dateien enthalten häufig Informationen zur Lizenzierung, den Rechtsinhabern oder weitere hilfreiche Informationen zur Software (z.B. als LICENSE.txt, COPYING.txt oder README.txt).
Bei Dateiendungen wie .html oder .js handelt es sich zwar um Dateien, die von der Maschine direkt ausgeführt werden können, bei denen aber dennoch der Source Code direkt vorliegt und – z.B. mittels eines Texteditors – betrachtet werden kann. Da hier alle Informationen für den Betrachter lesbar vorhanden sind, können diese wie Source Code behandelt werden.
Hinsichtlich der ausführbaren Dateien und somit des Binärcodes dürfte die Dateiendung .exe wohl die bekannteste sein. Allerdings gibt es auch noch zahlreiche andere Dateiendungen, die auf Binärcode hindeuten, wie beispielsweise .dll oder .so, die auf Programmbibliotheken hindeuten, aber z.B. auch .msi, .bin oder .dat.
Bei der Endung .jar ist die Einordnung nicht immer auf den ersten Blick möglich. Denn hierbei kann es sich entweder um eine Java-Anwendungsdatei handeln, die durch Anklicken ausgeführt werden kann, oder aber um ein Java Archiv, das mehrere Java Dateien und auch andere Dateien enthalten kann. Diese Archive können dann mittels eines Packprogramm (wie WinZip, 7-Zip, o.ä.) geöffnet werden, um zu ermitteln, welche Art von Dateien sich darin befinden.
1 https://de.wikipedia.org/wiki/Quelltext. 2 https://en.wikipedia.org/wiki/Object_code. 3 https://de.wikipedia.org/wiki/Binärcode. 4 https://de.wikipedia.org/wiki/Ausführbare_Datei.
2. Von welchen Tools die Entwickler sprechen
86
– Entwicklung und Build sind unterschiedliche Bereiche; Entwicklung betrifft die Erstellung von Code, Build den Kompilierprozess, also die Erzeugung der Executables.
– Entwicklungsumgebungen, SDKs und Package Manager unterstützen bei der Verwaltung und Erzeugung von Code.
– Der Compiler erzeugt aus Source Code zusammen mit einem Linker ein ausführbares Programm, das nur noch in maschinenlesbarer Form vorliegt.
87
Zur Erstellung von Code bzw. Software werden unterschiedliche Werkzeuge – sogenannte Programmierwerkzeuge oder Entwicklungstools – benötigt. Dabei handelt es sich um Computerprogramme, die es ermöglichen, Code zu erzeugen und diesen anschließend weiter zu be- und verarbeiten. Um besser zu verstehen, wie Software entsteht und bei welchen Entwicklungsschritten z.B. welche Formen von Code entstehen, wollen wir hier einen kurzen Überblick über die gängigen Werkzeuge zur Erstellung und Bearbeitung von Code geben, insbesondere dort, wo diese auch im Zusammenhang mit der Bewertung von FOSS relevant sein können.
88
Es gibt grundsätzlich unterschiedliche Herangehensweisen bei der Erstellung und Bearbeitung von Code. So können entweder einzelne Programmiertools verwendet werden, die sich der Entwickler nach Bedarf selbst zusammenstellt, oder es wird auf sogenannte Entwicklungsumgebungen zurückgegriffen, die bereits alle notwendigen Hilfsprogramme mitbringen.
Abbildung 1: Software-Entwicklung/Build-Prozess© Jun Rechtsanwälte (CC BY-SA 4.0)
a) Entwicklungsumgebungen und Build-Tools
89
Bei dem Begriff „Entwicklungsumgebung“ handelt es sich um einen Oberbegriff für unterschiedliche Arten von Hilfsmitteln zur Erzeugung und Bearbeitung von Code. So fallen unter diesen Begriff beispielsweise IT-Plattformen bzw. Systemumgebungen, auf denen Software entwickelt wird, oder Sammlungen von Computerprogrammen zur Software-Entwicklung, z.B. die sogenannten integrierten Entwicklungsumgebungen oder Software Development Kits. Der Begriff „Build-Umgebung“ bezieht sich dagegen nicht auf die Erstellung von Code, sondern den darauf folgenden Schritt, nämlich das Erzeugen von Executables. Build-Tools sind also die Programme, die beim Kompilieren eingesetzt werden.
90
Bei der Systemumgebung handelt es sich einfach um eine Plattform, mit der ein informationstechnisches System betrieben wird. Ein solches System hat dabei häufig einen dreistufigen Aufbau, der aus einer Entwicklungsumgebung besteht, auf der der Entwickler neue Software entwickelt, einer Testumgebung, auf der die neu erstellte Software getestet werden kann, und einer Produktivumgebung, auf der die Software letztendlich betrieben und zu Geschäftszwecken genutzt wird. Die Entwicklungsumgebung der Systemumgebung beschreibt dabei kein eigentliches Entwicklungswerkzeug, sondern lediglich den Ort, an dem neue Software entwickelt wird.5
91
Eine integrierte Entwicklungsumgebung oder auch IDE (kurz für Integrated Development Environment), stellt eine Sammlung verschiedener aufeinander abgestimmter Computerprogramme dar, die der Entwicklung von Software dienen. Solche IDEs gibt es für nahezu alle Programmiersprachen und Plattformen, wobei eine IDE in der Regel jeweils nur eine Programmiersprache unterstützt. Statt eine IDE zu verwenden, kann ein Entwickler sich die zur Software-Entwicklung benötigten Einzelwerkzeuge wie Texteditor, Compiler, Linker, etc. (mehr dazu siehe Rn. 97ff.) auch einzeln besorgen und zusammenstellen. Der Vorteil der IDE besteht jedoch darin, dass die einzelnen Werkzeuge bereits gut aufeinander abgestimmt sind und Software-Entwicklung in der Regel ohne Medienbrüche stattfinden kann.6 Beispiele für solche IDEs sind u.a. Eclipse oder die NetBeans IDE.
92
Neben den IDEs gibt es auch noch die Software Development Kits (kurz: SDKs). Diese stellen ebenfalls eine Sammlung von verschiedenen Werkzeugen und Hilfsmitteln zur Erstellung von Software dar und beziehen sich meist auf ein konkretes Produkt, wie z.B. Android, oder eine Programmiersprache und stellen dafür dann neben den Entwicklungstools auch entsprechende Schnittstellen und Dokumentationen, diverse Bibliotheken und manchmal auch Testprojekte zur Verfügung. Viele SDKs beinhalten bereits eine entsprechende IDE, mit der die anderen vom SDK bereitgestellten Komponenten genutzt werden können. Jedoch ist es auch möglich, die durch ein SDK bereitgestellten Funktionen in einer selbstgewählten IDE zu nutzen.7 Beispiele für SDKs wären das Android SDK oder das Java Development Kit (JDK).
93
Weitere wichtige Werkzeuge sind die Build-Tools. Hierbei handelt es sich ebenfalls wieder um Computerprogramme. Diese dienen aber nicht der grundsätzlichen Erstellung von Code, sondern vielmehr dazu, den bereits geschriebenen Source Code in ausführbaren Code umzuwandeln. Zwar sind auch IDEs mit ihren integrierten Compilern in der Lage dazu, aus dem dort geschriebenen Source Code ein ausführbares Programm zu erzeugen. Allerdings muss dies hier händisch durch den Entwickler angestoßen werden. Die Build-Tools bieten die Möglichkeit, den Build-Prozess – also die Kompilierung des Source Code in ein ausführbares Programm (siehe ausführlich Rn. 97ff.) – zu automatisieren und so z.B. zu ermöglichen, den Build immer zu einem festgelegten Zeitpunkt mit dem bis dahin neu hinzugefügten Code automatisch durchzuführen.8 Bekannte Build-Tools sind z.B. Maven, Gradle oder Ant.
94
Gelegentlich stößt man auch auf den Begriff Toolchain. Auch diese bezeichnet eine systematische Sammlung von verschiedenen Werkzeugen zur Erstellung und Bearbeitung von Code und beschreibt damit im Grunde etwas Ähnliches wie die bereits oben erwähnten Entwicklungsumgebungen. Der Begriff der Toolchain stammt daher, dass die unterschiedlichen Werkzeuge nacheinander in Form einer Kette eingesetzt werden. Hier sind regelmäßig ebenfalls Texteditoren zur Erstellung des Code sowie Compiler und Linker zur Umwandlung in ein ausführbares Programm enthalten.9 Ein bekanntes Beispiel für eine Toolchain ist die GNU Toolchain, die alle vom GNU Projekt entwickelten Programmierwerkzeuge enthält.
95
Ein ebenfalls wesentlicher Teil bei der Erstellung und Verwaltung von Code sind die sog. Paketverwaltungen oder Package Manager. Diese stellen ebenfalls eine Sammlung von Werkzeugen dar, die diesmal aber nicht zur Erstellung, sondern lediglich zur Verwaltung von Code dienen. Die Hauptfunktionen der Package Manager sind die Installation, Aktualisierung und Deinstallation von Software. Wichtigster Bestandteil ist die Paketdatenbank, die alle Informationen über installierte bzw. zur Verfügung stehende Software-Pakete beinhaltet. Grundsätzlich stammt diese Art der Software-Verwaltung aus dem Umfeld von Betriebssystemen und ermöglicht die einfache Verwaltung der auf und mit dem Betriebssystem betriebenen Software.10
96
Der Begriff des Package Manager wird aber auch für Plattformen verwendet, auf denen Entwickler Software-Pakete zur Lösung diverser Problemstellungen finden und die zudem die Möglichkeit bieten, die entsprechenden Pakete zu verwalten oder diese direkt in eigene Software oder eigene Software-Paketen zu integrieren. Ein Beispiel für eine solche Plattform ist der Node Package Manager oder kurz npm. npm ist ein Package Manager für node.js, die Laufzeitumgebung von JavaScript. Er bietet eine große Datenbank an bereits fertigen Paketen, die Möglichkeit, diese Pakete zu bearbeiten und an eigene Bedürfnisse anzupassen sowie die Pakete zu verwalten und mit anderen zu teilen.11 Auch wenn die Package Manager eher als Werkzeuge zur Verwaltung gedacht sind, kann damit, durch Einbeziehung diverser bereitgestellter Pakete in die eigene Software, natürlich auch Software bearbeitet werden.
b) Werkzeugkoffer zum Coden – Compiler, Parser, Linker und Interpreter
97
Wie bereits erwähnt, bedarf es spezieller Programme und Zwischenschritte, um zwischen den unterschiedlichen Formen des Code zu wechseln. Code, der in einer der gängigen Programmiersprachen geschrieben wurde, liegt zunächst im menschenlesbaren Source Code vor. Soll dieser Code dann zu einer ausführbaren Datei werden, muss er in eine maschinenlesbare Form übersetzt werden. Dazu werden spezielle Programme verwendet, die Compiler genannt werden. Compiler wandeln also Source Code in Maschinensprache um und übersetzen dabei das gesamte Programm und erzeugen dadurch zusammen mit einem Linker ein Executable, das auch separat – also ohne den Source Code – weitergegeben werden kann.
98
Backup: Kurze Übersicht zu gängigen Compilern
Es existieren zahlreiche Compiler und Linker für jede Programmiersprache. Nicht jeder Compiler und/oder Linker ist dabei gleich gut für jedes Vorhaben geeignet, da die unterschiedlichen Programme unterschiedliche Stärken und Schwächen aufweisen. Allerdings haben sich einige gängige Programme durchgesetzt, zu denen wir hier einen kurzen Überblick geben wollen.
Compiler für C und C++:
GNU GCC Compiler, Clang, Intel C++ Compiler, Microsoft Visual C++, Oracle C Compiler, Wind River (Diab) Compiler
Compiler für Java:
GNU Compiler for Java, javac, Eclipse Compiler for Java (JDT Core), Iodine
Compiler für Python:
Psyco, Cython, PyPy, Shed Skin
Viele der gängigen und oben genannten Compiler stehen unter FOSS Lizenzen und können daher in der Praxis Probleme mit sich bringen. Während einige Compiler, wie z.B. PyPy, unter liberalen Lizenzen stehen, stehen viele der gängigen Compiler, wie z.B. der GCC Compiler, der Java Compiler von Eclipse oder auch Shed Skin, unter strengen FOSS Lizenzen mit Copyleft. Gerade der GCC Compiler unter der GPL ist ein gutes Beispiel für Probleme, die mit FOSS Compilern auftreten können. Denn der GCC Compiler fügt während des Kompilierprozesses Teile seines eigenen (unter der GPL lizenzierten) Code – insbesondere einige GCC Header Dateien oder Runtime Libraries – in das kompilierte Programm ein.12 Diese GPL lizenzierten Code Bestandteile können dann ein Copyleft auslösen und so die kompilierte Software infizieren. Da die FSF dieses Problem aber erkannt hat und nicht grundsätzlich verhindern will, dass auch kommerzielle Programme mit dem GCC Compiler erstellt werden können, wurde hier eine Ausnahme, die sog. GCC Runtime Library Exception, geschaffen. Diese besagt, dass das Ergebnis eines Kompilierprozesses mit dem GCC Compiler nicht zwingend unter der GPL lizenziert werden muss, auch wenn in dem Ergebnis Code Bestandteile unter der GPL enthalten sind.
Bei dem Einsatz von FOSS Compilern sollte also immer darauf geachtet werden, ob der Compiler FOSS lizenzierten Code in das kompilierte Programm einfügt und ob bei Copyleft Lizenzen ggf. entsprechende Ausnahmen existieren, die in solchen Fällen von einem Copyleft befreien. Um diese Probleme zu umgehen, können ansonsten auch einfach kommerzielle Compiler wie beispielsweise die von Microsoft oder Wind River Systems verwendet werden.
99
Häufig gibt es bei dieser Übersetzung einen Zwischenschritt, bei dem der Source Code zunächst in eine Art Zwischencode – den oben erwähnten Object Code (siehe Rn. 82) – umgewandelt wird. Dieser Zwischencode hat den Vorteil, dass er häufig auf verschiedenen Plattformen läuft und auch von Interpretern verwendet werden kann. Diesen so entstandenen Object Code übersetzt der Compiler dann weiter in den Maschinencode, der vom jeweiligen Zielsystem verstanden werden kann. Der Linker – ebenfalls ein gesondertes Computerprogramm – setzt dann die kompilierten Programmbestandteile und -module, die mittels des Compilers erzeugt wurden, zu einer ausführbaren Datei zusammen, um auf diese Weise das fertige Programm zu erhalten. Bei dieser Zusammensetzung der Programmteile gibt es unterschiedliche Arten, die als statische und dynamische Verlinkung bezeichnet werden (siehe Rn. 106f.).
100
Neben den Compilern, die direkt Binärcode erzeugen, gibt es auch noch sog. Interpreter. Dabei handelt es sich um Programme, die Source Code direkt zur Laufzeit verarbeiten. Die Anweisung im Source Code wird dabei eingelesen, analysiert und dann ausgeführt. Anders als beim Compiler wird dadurch keine Datei erzeugt, die mehrmals ausgeführt werden kann, und es entsteht auch keine dauerhafte Übersetzung des Source Code. Der Interpreter stellt eher eine Zwischenschicht zwischen Programmiersprache und Maschine dar, die die Anweisungen des Source Code analysiert und dann die gewünschte Aktion im Zielsystem aufruft und ausführt. Man erhält durch den Einsatz eines Interpreters also kein unabhängiges Executable, sondern benötigt weiterhin den Source Code des auszuführenden Programms.13
101
Eine weitere Form von Hilfsprogrammen, mit denen man bei der Umwandlung von Code häufig zu tun hat, sind Parser. Mit einem Parser kann der Quelltext entsprechend aufbereitet werden, indem dieses Programm die Zeichenketten analysiert und in eine Repräsentation umwandelt, mit der ein anderes Programm arbeiten kann. Die meisten Programmiersprachen sind so gestaltet, dass sie für den Entwickler übersichtlich und komfortabel sind. Die oben bereits erwähnten Compiler können aber mit zusätzlich im Source Code enthaltenen Informationen, wie z.B. Kommentaren der Entwickler, nichts anfangen und diese nicht sinnvoll in Maschinensprache übersetzen. Hier hilft der Parser dabei, den Quelltext zu analysieren und zu bereinigen, so dass der Compiler im Anschluss den überarbeiteten Code verwenden und umwandeln kann.14 Ein weiteres Beispiel für ein solches Programm wäre der in einem Webbrowser enthaltene Parser, der den rein als Text vorliegenden HTML Code so aufbereitet, dass damit die entsprechende Webseite angezeigt werden kann.
102
Backup: Gängige FOSS Parser
Auch bei den Parsern gibt es zahlreiche Programme unter FOSS Lizenzen. Einige gängige FOSS Parser sind z.B. GNU Bison15, ANTLR16, JavaCC17, OpenL18, runcc19 oder SJPT20.
Wie bei den Compilern sollte auch bei den Parsern auf die Lizenzierung geachtet werden. Zwar stehen einige der Programme unter liberalen Lizenzen, für viele sind aber ebenfalls strenge Copyleft Lizenzen einschlägig. Parser dienen zwar eher zur Analyse und Aufbereitung des Code als zu dessen eigentlicher Erstellung; es ist jedoch trotzdem möglich, dass Teile des Parsers in den damit analysierten und bearbeiteten Programmcode eingefügt werden. Auch hier ist das Programm der FSF, der GNU Bison Parser, wieder ein gutes Beispiel. Um es Entwickler zu ermöglichen, auch mit einem unter der GPL lizenzierten Parser kommerzielle Programme zu erstellen, hat die FSF hier wiederum eine Ausnahme zur GPL speziell für ihren Bison Parser geschaffen. Diese sog. Bison Exception ermöglicht es, das Ergebnis aus dem Parser trotz ggf. enthaltenem GPL Code unter eine eigene Lizenz zu stellen.21
5 https://de.wikipedia.org/wiki/Systemumgebung. 6 https://de.wikipedia.org/wiki/Integrierte_Entwicklungsumgebung. 7 Augsten, https://www.dev-insider.de/was-ist-ein-sdk-a-730921/. 8 https://www.it-talents.de/blog/it-talents/alles-ueber-den-build-prozess#-ides-und-build-tools. 9 https://de.wikipedia.org/wiki/Toolchain. 10 Augsten, https://www.dev-insider.de/was-ist-eine-software-paketverwaltung-a-847919/. 11 https://www.onlinesolutionsgroup.de/blog/glossar/n/npm-node-package-manager/. 12 FSF, Using the GNU Compiler Collection (GCC), Ziff. 6.59, https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc.pdf. 13 Augsten, https://www.dev-insider.de/der-unterschied-von-compiler-und-interpreter-a-742282/. 14 Augsten, https://www.dev-insider.de/was-ist-ein-parser-a-756662/. 15 https://www.gnu.org/software/bison/manual/. 16 https://www.antlr.org/. 17 https://cs.lmu.edu/~ray/notes/javacc/. 18 http://openl.org/. 19 https://java-source.net/open-source/parser-generators/runcc. 20 http://sjpt.sourceforge.net/. 21 https://www.gnu.org/software/bison/.
3. Juristen müssen diese Verlinkung verstehen
103
– Für das Auslösen eines Copyleft kommt es auf die Verbindungen des FOSS Code mit eigenen Programmbestandteilen an.
– Daher sollte die konkrete Art der Verlinkung (statisch, dynamisch oder andere Formen der Interaktion von Code) ermittelt und korrekt anhand der Lizenzvorgaben eingeordnet werden.
– Die Art der Verlinkung von FOSS mit eigenen Programmbestandteilen ist abhängig von der verwendeten Programmiersprache, da nicht alle Programmiersprachen alle Arten der Verlinkung zulassen.
104
Zahlreiche FOSS Lizenzen – insbesondere solche mit einem beschränkten Copyleft – knüpfen unterschiedliche Anforderungen und Konsequenzen an den Einsatz der jeweiligen FOSS Komponente, je nachdem wie diese mit dem übrigen, meist proprietären Code der Software interagiert. Es kommt dabei in der Regel darauf an, wie stark die FOSS Komponente in die eigene Software eingebunden wird. Wir sprechen hier von statischer oder dynamischer Verlinkung, um zu beschreiben, wie eng die FOSS Komponente mit proprietärem Code verbunden ist. Um diese Differenzierung besser nachvollziehen zu können, möchten wir an dieser Stelle zum einen erklären, wie wir die Begriffe der statischen und dynamischen Verlinkung grundsätzlich verstehen und in diesem Buch Bezug darauf nehmen. Zum anderen soll kurz dargestellt werden, wie sich die unterschiedlichen Arten der Verlinkung in diversen Programmiersprachen manifestieren können. Denn je nachdem, in welcher Programmiersprache die jeweilige Software geschrieben wurde, kommen bereits nur bestimmte Arten der Verlinkung überhaupt in Frage bzw. wird der Begriff der Verlinkung möglicherweise anders genutzt und kann so zu Missverständnissen führen.