Zunächst ein kleiner Hintergrund. Anfang der 2010er Jahre habe ich ein kleines Konverter-Dienstprogramm für BIN-Dateien des BK-0010- Emulators in WAV-Dateien erstellt. Das Dienstprogramm wurde in Python mit dem Ziel maximaler Portabilität geschrieben, es funktionierte ohne Probleme und ich vergaß es für eine Weile. Aber im Jahr 2016 erschien der Benutzer, der keine Ahnung von Python und wie man es installiert. Er wollte einen einfachen ausführbaren Monolithen, der "einfach funktioniert". Seine Anfrage erschien mir logisch und ich beschloss, das Dienstprogramm als eine Reihe von ausführbaren Binärdateien für die Hauptplattformen zu überarbeiten.

Python und Java gaben keine solche Gelegenheit (es sei denn, es bestand natürlich der Wunsch, das Dienstprogramm um viele zehn Megabyte zu erhöhen). Möglicherweise könnte die Lösung in C / C ++ erfolgen, aber bei einer derart gezielten Abdeckung der Plattformen würden Schwierigkeiten bei der Cross-Kompilierung über die für die Aufgabe vorgesehene Zeit hinausgehen (und ich musste Cross-Assembly für Windows, Linux und MacOS in 64- und 32-Bit unterstützen Optionen). Also machte ich auf die Sprache Go aufmerksam, die immer beliebter wird, die zu diesem Zeitpunkt bereits ziemlich ausgereift war und die einzige, die ohne alle Tänze mit einem Tamburin die erforderliche Cross-Compilation sofort bereitstellt (!) .
Eine Unannehmlichkeit, die mich an Go sehr ärgerte (insbesondere als Java-Entwickler), war die schlechte Nachdenklichkeit bei der Organisation der Struktur von Go-Projekten und die Notwendigkeit, die Umgebung ständig anzupassen. Vielleicht hatten die Go-Entwickler ursprünglich eine bestimmte Verwendung geplant, oder es gab einen Schwerpunkt auf Containern, aber ich habe mich an den „leckeren“ gewöhnt, und da mein Hauptwerkzeug in Java Maven ist , habe ich beschlossen, ein Plug-In zu erstellen, das Dienstprogramme und GoSDK-Befehle mit der automatischen Generierung der erforderlichen aufruft Umgebungsvariablen.
Es war nicht interessant, ein einfaches Plugin zu erstellen, das das Dienstprogramm go aufruft, und ich entschied mich für den Schritt - Installation von GoSDK auf der Hostplattform. Unmittelbar nach dem Start wird das Vorhandensein von GoSDK in seinem Konfigurationsverzeichnis überprüft (ich habe den Standardpfad ~/.mvnGoLang
), und ~/.mvnGoLang
die erforderliche Version fehlt, wird das GoSDK-Archiv automatisch von der offiziellen Site heruntergeladen und entpackt. Auf diese Weise konnten wir tragbare Go-Projekte erstellen, ohne uns Gedanken darüber machen zu müssen, ob das Tool der erforderlichen Version vorinstalliert und konfiguriert ist. Natürlich habe ich bei vielen Einstellungen die Möglichkeit vorausgesehen, eine vorinstallierte Version zu verwenden, und Einstellungen für alle Schritte des Prozesses hinzugefügt, da für viele Probleme wie das Deaktivieren der Überprüfung von SSL-Zertifikaten oder das allgemeine Ausführen von HTTP-Anforderungen außerhalb (z. B. für das Keycloak- Projekt) von entscheidender Bedeutung sind.
Im nächsten Schritt habe ich alle zu diesem Zeitpunkt bereitgestellten go-Dienstprogrammbefehle in die Maven-Ziele (Ziele) eingewickelt. Da die Möglichkeit bestand, dass mit der neuen Version von GoSDK ein weiterer neuer Befehl angezeigt wurde, wurde eine custom
Aufgabe hinzugefügt, mit der der Benutzer den gewünschten Befehl selbst bestimmen kann. Standardmäßig werden Aufgaben im Rahmen von Maven-Phasen (Phasen) in der folgenden Reihenfolge ausgeführt:
- Als
default-clean
in Phase Clean reinigen - Fix als
default-fix
in der Validierungsphase - Get als
default-get
in der Initialisierungsphase - Generieren als
default-generate
in der Phase " Generieren von Quellen" - fmt als
default-fmt
in der Prozessquellenphase - Test als
default-test
in der Testphase - Build als
default-build
in der Paketphase - Als
default-install
interne Task mvninstall in der Installationsphase ausgeführt - Installation als
default-deploy
in der Bereitstellungsphase
Jeder der grundlegenden Schritte kann deaktiviert werden, indem die Aufgabe in eine nicht vorhandene Phase übersetzt wird:
<execution> <id>default-fix</id> <phase>none</phase> </execution>
In der internen Implementierung wurden die Aufgaben in "Arbeiten mit Abhängigkeiten" und "Keine Lösung von Abhängigkeiten erforderlich" unterteilt, nachdem die Unterstützung für den Modulmodus angezeigt wurde. Die meisten Aufgaben wurden auf "Arbeiten mit Abhängigkeiten" migriert.
Bei der Struktur des Go-maven-Projekts habe ich versucht, näher an die für Go akzeptierte Standardordnerstruktur heranzukommen (d. H. /src
und /bin
im Stammverzeichnis des Projekts). Da Maven jedoch für Java inhaftiert ist, war es nicht direkt möglich, seinen Ansatz zur Organisation der Projektstruktur zu „brechen“ und diesen Schritt für den Benutzer unsichtbar zu machen, sodass die Grundkonfiguration des Plugins selbst für viele mit Maven vertraute Personen etwas ungewöhnlich erscheint:
<build> ```${basedir}/src</sourceDirectory> <directory>${basedir}/bin</directory> <plugins> <plugin> <groupId>com.igormaznitsa</groupId> <artifactId>mvn-golang-wrapper</artifactId> <version>2.3.3</version> <extensions>true</extensions> <configuration> <goVersion>1.12.9</goVersion> </configuration> </plugin> </plugins> </build>
WARNUNG! Aus irgendeinem Grund zeigt der HabR beim Formatieren von XML <sourceDirectory>${basedir}/src</sourceDirectory>
Abschnitt <sourceDirectory>${basedir}/src</sourceDirectory>
Wie Sie sehen, müssen Sie den Quellordner /src
und den Ordner mit dem Ergebnis /bin
direkt bestimmen. Dies ist einerseits ein Minus, andererseits die Möglichkeit, ihren Standort zu ändern.
Die gesamte minimalistische pom.xml für ein Einzelmodulprojekt, a la Hello world, lautet wie folgt:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.igormaznitsa</groupId> <artifactId>mvn-golang-helloworld</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>mvn-golang</packaging> <build> ```${basedir}/src</sourceDirectory> <directory>${basedir}/bin</directory> <plugins> <plugin> <groupId>com.igormaznitsa</groupId> <artifactId>mvn-golang-wrapper</artifactId> <version>2.3.3</version> <extensions>true</extensions> <configuration> <goVersion>1.12.9</goVersion> </configuration> </plugin> </plugins> </build> </project>
Bitte beachten Sie, dass die Verpackung des Projekts als mvn-golang bezeichnet ist . Diese Konfiguration reicht aus, um die ausführbare Datei zu erstellen und sie auf der Grundlage der Quelltexte im Ordner src in den resultierenden bin-Ordner zu legen. Der Go-Build-Cache wird auch im /bin
(standardmäßig als /bin/.goBuildCache
) und mit diesem temporären Ordner mit clean gelöscht.
In der Installationsphase wird die interne mvninstall
Task mvninstall
, die einfach das gesamte Projekt in ein Zip-Archiv packt und es als generiertes Artefakt im Maven-Repository ablegt. Anfangs habe ich diese Artefakte nur gespeichert, aber ab Version 2.3.2 wurde ein Mechanismus hinzugefügt, der sie als Standard-Maven-Abhängigkeiten unterstützt, und es wurde möglich, Projekte mit "gemeinsamem" Code über das Maven-Repository zu entwickeln. Es ist klar, dass das Einfügen der generierten binären Ergebnisse als Artefakte in das Repository aufgrund plattformübergreifender Anforderungen eine schlechte Idee ist und daher der Inhalt des Ordners /bin
nicht in das Artefakt gepackt wird.
Das Verbinden eines anderen Projekts mit dem Packen von mvn-golang
als Maven-Abhängigkeit sieht ungefähr so aus:
<dependency> <groupId>com.igormaznitsa</groupId> <artifactId>mvn-go-test-mix-terminal</artifactId> <version>1.0.0-SNAPSHOT</version> <type>mvn-golang</type> </dependency>
In Version 2.3.3 wurde Unterstützung für die Arbeit mit dem Go- Mechanismus von Modulen hinzugefügt, diese ist jedoch standardmäßig nicht aktiviert (aus Gründen der Abwärtskompatibilität) und wird mithilfe des Konfigurationsparameters aktiviert:
<moduleMode>true</moduleMode>
Als sich der Mechanismus der Go-Module noch im experimentellen Stadium befand, fügte ich Unterstützung für die Arbeit mit Abhängigkeitsversionen durch direkte Aufrufe von CVS-Dienstprogrammen hinzu. Ein Testbeispiel wurde erstellt . Aber jetzt denke ich, dass ein solcher Mechanismus nicht mehr von großem Interesse ist und es rentabler ist, Standardabhängigkeiten durch Module zu verwenden. Darüber hinaus kann das Plugin zum Zeitpunkt der go.mod
des Projekts go.mod
Dateien vorverarbeiten und die Pfade zu lokalen Ordnern ersetzen, wenn im Rahmen eines Projekts mit mehreren Modulen gearbeitet wird.
Da Maven die Möglichkeit der Standardisierung mithilfe von Archetypen vorsieht, habe ich zwei Archetypen erstellt:
- com.igormaznitsa: mvn-golang-hello: 2.3.3 für einen einfachen Archetyp mit einem Modul
- com.igormaznitsa: mvn-golang-hello-multi: 2.3.3 für ein Projekt mit mehreren Modulen und gemeinsam genutztem Quellcode
Ein Beispiel für die Arbeit mit dem Archetyp eines Einzelmodulprojekts ist in der folgenden Animation zu sehen
.
Sie können auch einfach das Projekt "Hello World" klonen und herumspielen:
git clone https://github.com/raydac/mvn-golang-example.git

Oft stellt sich die vernünftige Frage: Warum ist das alles notwendig und welche Boni bringt der Einsatz von Maven beim Aufbau eines Go-Projekts? Ich werde versuchen, es Punkt für Punkt zu beantworten:
- Maven ist eine sehr ausgereifte, plattformübergreifende Projektbildungsumgebung, die von fast allen CI-Plattformen unterstützt wird, z. B. Jenkins. Mit Go2XUnit können Sie Testergebnisse in das Format konvertieren, das von Berichts-Plugins angezeigt wird.
- Maven ist plattformübergreifend und wird von allen Betriebssystemen unterstützt, die in allen Repositorys enthalten sind. Das Vorhandensein flexibel aktivierter Profile erleichtert die Anpassung des Prozesses für verschiedene Plattformen.
- Maven verfügt über eine RIESIGE Anzahl von Plugins , die es einfach machen, einen synergistischen Effekt zu erzielen, indem beispielsweise Go und GWT kombiniert , ANTLR mit dem Projekt verbunden , Go basierend auf Protobuf-Deskriptoren generiert und sogar Vorverarbeitung hinzugefügt werden . All dies kann manuell über Batch-Dateien organisiert werden. Wenn es jedoch offiziell unterstützte Plugins gibt, ist es rentabler, diese zu verwenden.
- Das Projekt lässt sich leicht zwischen Maschinen und Plattformen portieren, und das Umschalten der GoSDK-Version erfolgt durch Ändern einer Zeile.
- Einfache Organisation von Projekten mit mehreren Modulen mit Trennung des Quellcodes durch das Maven-Repository.
- Das Tool ist Java-Entwicklern vertraut und vertraut, was ihre Anpassung beim Wechsel zur Entwicklung auf Golang oder bei der Entwicklung mehrsprachiger Go + Java-Lösungen erleichtert.
- In Umgebungen, die Maven unterstützen, besteht die Möglichkeit einer Pseudoentwicklung unter Go, auch wenn diese Plattform nicht unterstützt wird, z. B. in der NetBeans-IDE .
Der größte Nachteil der Lösung ist meiner Meinung nach einer hier - eine begrenzte Anzahl von Entwicklern, die mit Maven in der Golang-Community vertraut sind. Für diejenigen, die mit C / C ++ zu Golang gewechselt sind, ist es klar, dass es schwierig ist, etwas näheres und teureres zu finden, und niemand hat die "nativen" Go-Build-Systeme abgebrochen. Mir ist aufgefallen, dass viele Entwickler aus irgendeinem Grund Plattformen nicht gerne mischen.
Daher habe ich kurz eine Möglichkeit gezeigt, Maven bei der Entwicklung von Go-Projekten mit dem Plugin mvn-golang-wrapper zu verwenden. Das Plugin-Projekt ist als OSS-Projekt konzipiert und auf GitHub veröffentlicht . Wenn jemand interessiert ist und es in seinen Projekten verwenden wird, zögern Sie nicht, Fragen zu stellen und "Fehler zu melden". Ich habe versucht, eine Reihe von Beispielen für verschiedene Anlässe zu erstellen (bei denen das Plugin getestet wird), aber ich kann nicht alles abdecken.
Testbeispiele im Plugin-Projekt verwenden die Dev-Version. Wenn Sie sie also nach dem Klonen des Projekts lokal erstellen möchten, müssen Sie zuerst die Dev-Version des Plugins mit dem Befehl im Projektstammverzeichnis erstellen:
mvn install
mvn-golang-examples
können Sie in jedes Teilprojekt von mvn-golang-examples
und es mit erstellen
mvn clean install
Sie können auch mit dem Erstellen aller Beispiele aus dem Stammverzeichnis des Projekts beginnen
mvn clean install -Pexamples
Das Plugin unterstützt die Multithread-Assemblierung von Projekten und kann mithilfe des entsprechenden Arguments beschleunigt werden, z. B. in 6 Threads
mvn clean install -Pexamples -T6
Während der Entwicklung hat das Projekt eine anständige Menge an "Schnickschnack" angesammelt, die ich in diesem kurzen Artikel nicht behandelt habe. Informationen zu den Parametern mit kleinen Konfigurationsbeispielen finden Sie in der Mind Map dieses Plugins (die Quelldatei im SciaReto- Format finden Sie hier ):
