Zum Inhalt

Craft-Datei

Eine Craft-Datei definiert, wie die Ausgabedateien erzeugt werden. Die Craft-Datei beschreibt u.a. die Konfiguration des javac Befehls, der zum Kompilieren genutzt wird. Unter Auswahl der Craft-Datei ist beschrieben, wie angegeben werden kann, welche Craft-Datei verwendet werden soll.

Tipp

In der Regel sollte die Craft-Datei craft.txt genannt werden. Das ermöglicht ein automatisches Finden der Datei.

Aufbau

Eine Craft-Datei ist eine UTF-8 Textdatei. Sie besteht aus einer Aneinanderreihung von Befehlen, wobei jeder Befehl durch eine Zeile dargestellt wird. Leere Zeilen werden ignoriert.

Ein Befehl besteht aus einer Folge von Wörtern, die mit Leerzeichen getrennt sind. Das erste Wort eines Befehls ist der Befehlsname. Alle weiteren Wörter sind die Argumente des Befehls.

Anführungszeichen

Falls ein Wort Leerzeichen enthalten soll, so kann es in Anführungszeichen " geschrieben werden. Wird ein Wort in Anführungszeichen geschrieben, so können bestimmte Escape-Sequenzen verwendet werden.

Escape-Sequenz Zeichen im Wort
\" "
\\ \
\$ $
\n LF (U+000A)
\r CR (U+000D)
\t Horizontal Tab (U+0009)

Beispiel

Die Zeile A B "C D" "\"E\"" wird zu dem Befehl A mit den Argumenten B, C D und "E".

Variablen

Variablen haben einen Namen und repräsentieren einen Wert in Textform. Der Wert von Variablen ist dynamisch und wird erst zur Laufzeit von Crafter ermittelt. Innerhalb von Wörtern mit Anführungszeichen kann der Wert einer Variablen mit der Syntax ${NAME} eingefügt werden.

Variablen können von anderen Befehlen, wie z.B. temp-dir gesetzt werden. Wurde eine Variable von keinem anderen Befehl gesetzt, so wird nach einer Umgebungsvariablen mit dem angegebenen Namen gesucht. Falls eine Variable nicht gefunden werden kann, wird kein Befehl ausgeführt und der Craft-Prozess bricht ab.

Beispiel

class-path "${LIB}/example.jar"
Es wird die Datei example.jar aus dem LIB-Ordner zum Class-Path hinzugefügt. Dabei wird der Pfad zum LIB-Ordner aus der Umgebungsvariablen LIB gelesen. Der Pfad kann also für jedes System unterschiedlich sein.

Kommentare

Wird das Zeichen # in einer Zeile gefunden, so wird der Rest der Zeile ignoriert. Steht ein # am Anfang der Zeile, wird die gesamte Zeile ignoriert. Auf diese Weise können Kommentare geschrieben werden.

Befindet sich das # innerhalb von Anführungszeichen, so wird es als Teil des Wortes interpretiert und der Rest der Zeile wird nicht ignoriert.

Befehle

Eine Craft-Datei besteht aus einer Auflistung von Befehlen.

Übersicht

Befehl Beschreibung
java-version <number> Setzt die Java-Version, für die die Source-Dateien kompiliert werden.
+ <path> Fügt den Ordner (oder die Datei) zum Root des aktuellen File-Trees hinzu.
+ <path> -> <target-path> Fügt den Ordner (oder die Datei) unter dem Ziel-Pfad zum aktuellen File-Tree hinzu.
- <path> Entfernt den Pfad aus dem aktuellen File-Tree.
class-path <path> Fügt den Pfad beim Kompilieren zum Class-Path hinzu.
module-path <path> Fügt den Pfad beim Kompilieren zum Module-Path hinzu.
add-modules <modules> Fügt die angegeben Module, welche mit , getrennt wurden, mit --add-modules zum javac Befehl hinzu.
depend <path> Das Projekt unter dem angegeben Pfad wird von diesem Projekt verwendet.
include <path> Das Projekt unter dem angegeben Pfad wird von diesem Projekt verwendet. Der gesamte Build des angegeben Projektes wird zu diesem Build hinzugefügt.
name <name> Setzt den Projektnamen für diese Craft-Datei.
license <path> Die angegebene Lizenzdatei wird unter einem besonderen Pfad zum aktuellen File-Tree hinzugefügt.
zip <name> Beginn eines ZIP-Blocks. Von nun an werden + und - Befehle auf den File-Tree der ZIP-Datei angewendet. Der Craft-Prozess wird eine ZIP-Datei mit dem angegebenen Namen erstellen.
end-zip Beendet den ZIP-Block.
exec <command>* Führt den angegebenen Systembefehl aus.
temp-dir <var-name> Erstellt einen neuen temporären Ordner und speichert den Pfad unter dem angegebenen Variablennamen.
manifest-file <file> Verwendet die angegebene Datei als Manifest.
manifest <key> <value> Setzt ein Main-Attribut des Manifests auf den angegebenen Wert.
output-dir <dir> Setzt das Ausgabeverzeichnis.
if-standalone <command>* Führt den angegebenen Craft-Datei Befehl nur aus, falls ein Standalone-Build erzeugt werden soll.
if-not-standalone <command>* Führt den angegebenen Craft-Datei Befehl nur aus, falls kein Standalone-Build erzeugt werden soll.

Java-Version

Mit java-version <number> wird die Java-Version ausgewählt, für die der Source-Code kompiliert werden soll. Anhand der Java-Version und den installierten JDKs wird ausgewählt, welches javac zum Kompilieren verwendet wird. Jede Craft-Datei muss genau einmal den java-version Befehl enthalten.

Dateien hinzufügen

Der + <path> Befehl fügt eine Datei oder einen Ordner zum Root des File-Trees hinzu. Zeigt der Pfad auf einen Ordner, so wird dieser rekursiv hinzugefügt. Der angegebene Pfad kann ein Multi-Path sein.

Standardmäßig wird die Datei bzw. der Ordner in den File-Tree der JAR-Datei eingefügt. Falls zuvor ein noch nicht geschlossener zip Befehl ausgeführt wurde, so wird die Datei bzw. der Ordner stattdessen zum File-Tree der ZIP-Datei hinzugefügt.

Mit der Syntax + <path> -> <target-path> kann die Datei bzw. der Ordner zu einem bestimmten Sub-Tree (bzw. Unterordner) hinzugefügt werden. Komponenten des Zielpfads werden mit / getrennt. Für Komponenten, welche noch nicht existieren, werden neue Ordner-Knoten erstellt. Zeigt der Pfad auf eine Datei und endet der Zielpfad mit /, so behält die Datei ihren Namen und der Zielpfad beschreibt nur den Zielordner.

Dateien entfernen

Der - <path> Befehl entfernt den angegebenen Pfad aus dem File-Tree. Zeigt der Pfad auf einen Ordner-Knoten, so werden zusätzlich deren Inhalte entfernt.

Info

Der Pfad beschreibt einen Knoten im File-Tree und keinen Ort im Dateisystem. Es werden keine Dateien gelöscht.

Dependencies

Projekte können andere Projekte benötigen oder verwenden. Eine einfache Möglichkeit dazu bieten die class-path <path>, module-path <path> und add-modules <modules> Befehle. Diese ermöglichen es beim Kompilieren Einträge zum Class-Path bzw. zum Module-Path von javac hinzuzufügen. Die angegebenen Pfade können jeweils Multi-Paths sein.

Projekte, die in Source-Code vorliegen, sollten besser mit depend <path> oder include <path> eingebunden werden. Dabei wird die Craft-Datei des angegebenen Projektes ausgeführt. Bei depend werden die Java-Klassen des Projektes zum Source-Path bzw. Class-Path dieses Projektes hinzugefügt. Wird include verwendet, so werden alle Exporte des Projektes zu diesem Projekt hinzugefügt. Entsprechend wird die JAR-Datei dieses Projektes auch die Java-Klassen und Resource-Dateien des anderen Projektes enthalten. Falls ein Standalone-Build erzeugt werden soll, verhalten sich alle depend Befehle wie include.

Der angegebene Pfad ist relativ zur Craft-Datei und kann entweder direkt auf die Craft-Datei verweisen, oder auf den Ordner in dem sich die Craft-Datei befindet. Wird nur der Ordner angegeben, wird nach einer craft.txt Datei in diesem Ordner gesucht.

Die Java-Version sowie das Manifest von Dependencies wird ignoriert. Entsprechend muss jedes Projekt ein eigenes Manifest definieren, falls eines benötigt wird.

depend oder include?

In den meisten Fällen sollte depend bevorzugt werden. Auf diese Weise hat der Nutzer beim Kompilieren die Auswahl, ob ein Standalone-Build erzeugt werden soll oder ein möglichst kleiner Build.

Die class-path und module-path Befehle sollten nur dazu verwendet werden, um bereits vorkompilierte JAR-Dateien nutzen zu können.

Projektname

Mit dem Befehl name <name> kann der Projektname der Craft-Datei angepasst werden. In jeder Craft-Datei sollte nur maximal ein name Befehl vorkommen. Wurde kein Projektname explizit angegeben, wird der Name des Ordners, in dem sich die Craft-Datei befindet, als Projektname verwendet.

Lizenzdateien

Der license <file> [name] Befehl ermöglicht es auf einfache Weise eine Lizenzdatei zum Export hinzuzufügen. Die angegebene Lizenzdatei wird an den Pfad META-INF/LICENSE/<name> eingefügt. Wird der optionale Parameter name nicht angegeben, wird der Projektname als Name verwendet.

Dieser Befehl ermöglicht es, dass ein Standalone-Build ohne weitere Konfiguration die Lizenzdateien von allen Projekten enthält.

license <file> ist im Allgemeinen äquivalent zu

+ <file> -> "META-INF/LICENSE/<name>"

ZIP

Neben der JAR-Datei können beliebig viele ZIP-Dateien generiert werden. Der Befehl zip <name> initiiert eine neue ZIP-Datei, welche den angegebenen Namen im Dateinamen enthalten wird. Nach dem zip Befehl können nur noch einige ausgewählte Befehle verwendet werden. Beispielsweise wirken + und - nun auf die ZIP-Datei anstatt auf die JAR-Datei.

Am Ende muss die ZIP-Datei mit dem end-zip Befehl abgeschlossen werden. Nach end-zip können wieder alle Befehle verwendet werden und + und - wirken wieder auf die JAR-Datei. Entsprechend kann auch von einem ZIP-Block gesprochen werden.

Die ZIP-Dateien werden erst erstellt, nachdem die gesamte Craft-Datei und insbesondere alle Systembefehle ausgeführt wurden.

Beispiel

+ src
zip extra
    + extra
    license LICENSE
end-zip
Die JAR-Datei enthält den src Ordner. Zusätzlich wird eine ZIP-Datei extra.zip erstellt, welche den extra Ordner sowie eine Lizenzdatei enthält.

Systembefehle

Manchmal sind nicht alle Dateien so vorhanden, dass sie direkt im Export vorhanden sein können. Für solche Fälle kann der exec <cmd> Befehl genutzt werden, der einen Systembefehl oder ein Skript ausführt.

Die ersten Argumente des exec Befehls können dazu verwendet werden, um Umgebungsvariablen an das zu startende Programm weiterzugeben. Dazu muss das Argument mit env: beginnen, worauf die Syntax <name>=<value> folgen muss. Dabei ist name der Name der Umgebungsvariablen und value der Wert, auf den sie gesetzt werden soll.

Das erste Argument des exec Befehls, das nicht mit env: beginnt, gibt den Systembefehl an, der ausgeführt werden soll. Alle darauf folgenden Argumente werden zu Argumenten des Systembefehls.

Das Working-Directory des Systembefehls ist der Ordner, in dem sich die Craft-Datei befindet.

Warnung

Systembefehle und Skripte können das System beschädigen.

Betriebssystemunabhängigkeit

Falls Betriebssystemunabhängigkeit wichtig ist, sollten nur Systembefehle verwendet werden, die auf allen Betriebssystemen verfügbar sind.

Beispiel

exec env:OUTPUT_DIR=out textscript run
+ out
Es wird textscript run ausgeführt. Dabei wird die Umgebungsvariable OUTPUT_DIR für den textscript Prozess auf out gesetzt. Je nach Konfiguration könnte TextScript nun Dateien im out Ordner schreiben. Daraufhin wird der out Ordner zum File-Tree der JAR-Datei hinzugefügt, sodass die Dateien, die TextScript generiert hat, in die JAR-Datei geschrieben werden.

Temporäre Ordner

Beim Erstellen von ZIP-Dateien und beim Ausführen von Systembefehlen kann ein temporärer Ordner sinnvoll sein. Mit dem Befehl temp-dir <VAR_NAME> wird ein neuer, leerer temporärer Ordner erstellt. Der absolute Pfad des Ordners wird in die angegebene Variable geschrieben.

Am Ende des Craft-Prozesses werden alle temporären Ordner gelöscht.

Manifest

Das Manifest einer JAR-Datei enthält Metadaten zu dieser JAR-Datei. Der Befehl manifest-file <file> ermöglicht es, eine beliebige Textdatei als Manifest einzulesen, welche als Manifest der JAR-Datei verwendet werden soll.

Mit dem Befehl manifest <key> <value> kann ein beliebiges Main-Attribut des Manifests gesetzt werden.

Standardmäßig enthält das Manifest nur das Manifest-Version Attribut. Entsprechend wird ein minimales Manifest exportiert, falls weder manifest-file noch manifest in der Craft-Datei genutzt wird.

If-Standalone

Mit if-standalone <cmd>* bzw. if-not-standalone <cmd>* wird abgeprüft, ob die Option --standalone angegeben bzw. nicht angegeben wurde. Falls das Kriterium erfüllt ist, wird der in den Argumenten angegebene Befehl angeführt.

Der if-not-standalone Befehl kann u.a. dafür verwendet werden, um bei Standalone-Builds ein anderes Manifest zu exportieren.

Beispiel

manifest Main-Class "de.tomatengames.tool.crafter.Crafter"
if-not-standalone manifest Class-Path "CompilerLib.jar TomatenUtil.jar"

Ausgabeverzeichnis

Mit dem Befehl output-dir <dir> kann der Pfad des Ausgabeverzeichnisses gesetzt werden. In dieses Verzeichnis werden die Ausgabedateien geschrieben.

Falls --output-dir im CLI angegeben wurde, so hat der output-dir Befehl der Craft-Datei keine Wirkung.

Falls kein Ausgabeverzeichnis angegeben wurde, werden die Ausgabedateien in den Ordner output/ relativ zur Craft-Datei geschrieben.

Multi-Path

Einige Befehle bieten die Möglichkeit einen Multi-Path als Argument verwenden zu können. In den meisten Fällen ist ein Multi-Path ein einfacher Pfad, der eindeutig auf eine Datei oder einen Ordner zeigt. Manchmal ist für Dateinamen aber nur ein Schema bekannt, oder es sollen mehrere Dateien berücksichtigt werden. Ein Multi-Path kann im Dateinamen des Pfades ein * enthalten. Der Multi-Path repräsentiert dann alle Dateien im angegeben Ordner, die dem Schema für den Dateinamen entsprechen. Dabei ist das * Zeichen ein Platzhalter für beliebig viele Zeichen. Die Komponenten in einem Multi-Path werden durch / getrennt.

Info

Ein Multi-Path darf maximal ein * im Dateinamen enthalten. Befindet sich das * nicht im Dateinamen, sondern im Ordnerpfad, so wird es als gewöhnliches Zeichen interpretiert.

Beispiele

  • "${JAVAFX}/lib/javafx*.jar" wählt alle JavaFX JAR-Dateien aus.
  • lib/*.jar wählt alle JAR-Dateien im lib Ordner aus.

Vollständige Beispiele

Hier finden sich vollständige Beispiele für Craft-Dateien.

Einfaches Java-Projekt ohne Dependencies

Dieses Beispiel ist an die Craft-Datei des CompilerLib Projektes angelehnt.

java-version 8 # (1)!

+ src
- de/tomatengames/lib/compiler/test # (2)!

license "LICENSE" # (3)!

  1. Das Projekt soll für Java 8 kompiliert werden.
  2. Alle Java-Dateien und Resource-Dateien aus dem src Ordner sollen in der JAR-Datei vorhanden sein, außer das Test Package.
  3. Fügt die LICENSE Datei zur JAR-Datei hinzu.

Mit Dependencies und Manifest

Dieses Beispiel ist an die Craft-Datei des Crafter Projektes angelehnt.

java-version 21 # (1)!

depend "../CompilerLib/" # (2)!
depend "../TomatenUtil/"

+ src
- de/tomatengames/tool/crafter/test # (3)!

license "LICENSE" # (4)!

manifest Main-Class "de.tomatengames.tool.crafter.Crafter" # (5)!
if-not-standalone manifest Class-Path "CompilerLib.jar TomatenUtil.jar"

  1. Das Projekt soll für Java 21 kompiliert werden.
  2. Das Projekt hat 2 Dependencies: CompilerLib und TomatenUtil. Die Pfade zu den Projekten sind relativ zum Ordner in dem sich die Craft-Datei befindet. Die Projekte müssen eine craft.txt Datei enthalten.
  3. Alle Java-Dateien und Resource-Dateien aus dem src Ordner sollen in der JAR-Datei vorhanden sein, außer das Test Package.
  4. Fügt die LICENSE Datei zur JAR hinzu.
  5. Definiert das Manifest der JAR-Datei.

Spigot-Plugin mit Dependencies

java-version 8 # (1)!

class-path "../lib/spigot-1.8.8.jar" # (2)!

depend "../TomatenUtil/" # (3)!
depend "../ExamplePlugin/"

+ src
+ plugin.yml # (4)!
+ config.yml

license "LICENSE" # (5)!
  1. Das Plugin soll für Java 8 kompiliert werden.
  2. Fügt die Spigot-API beim Kompilieren zum Class-Path hinzu. Diese wird von Spigot-Plugins benötigt.
  3. Das Plugin hat eine normale Library (TomatenUtil) und ein anderes Spigot-Plugin (ExamplePlugin) als Dependencies. Die Pfade zu den Projekten sind relativ zum Ordner in dem sich die Craft-Datei befindet. Die Projekte müssen eine craft.txt Datei enthalten.
  4. Neben den Java-Dateien aus dem src Ordner muss ein Spigot-Plugin auch eine plugin.yml mit Metadaten zu dem Plugin enthalten. Optional kann auch eine config.yml enthalten sein.
  5. Fügt die LICENSE Datei zur JAR-Datei des Plugins hinzu.

Standalone-Build

Es ist nicht möglich ein Standalone-Build eines Spigot-Plugins zu erzeugen, das ein anderes Spigot-Plugin als Dependency hat. Beide Plugins enthalten eine plugin.yml, welche für die Funktionalität des Plugins notwendig ist. Die JAR-Datei kann aber nur eine plugin.yml enthalten.