Maven-cara untuk membangun proyek Go

Pertama, sedikit latar belakang. Pada awal 2010-an, saya membuat utilitas konverter kecil untuk file BIN dari emulator BK-0010 ke file WAV. Utilitas ini ditulis dalam Python dengan tujuan portabilitas maksimum, ia bekerja tanpa masalah dan saya lupa sebentar. Tetapi pada tahun 2016, pengguna muncul, yang tidak tahu tentang Python dan cara menginstalnya. Dia menginginkan monolit yang dapat dieksekusi sederhana yang akan "hanya bekerja" Permintaannya tampak logis bagi saya, dan saya memutuskan untuk mengolah utilitas sebagai satu set file biner yang dapat dieksekusi untuk platform utama.


gambar


Python dan Java tidak memberikan kesempatan seperti itu (kecuali tentu saja ada keinginan untuk mengembang utilitas oleh puluhan megabyte). Secara potensial, solusinya dapat dibuat dalam C / C ++, tetapi dengan cakupan yang ditargetkan dari platform, kesulitan dengan kompilasi silang akan melampaui waktu yang diberikan untuk tugas (dan saya harus mendukung perakitan silang untuk Windows, Linux dan MacOS dalam 64 dan 32 bit opsi). Jadi saya menarik perhatian pada bahasa Go, yang mulai populer, yang pada saat itu sudah cukup matang dan satu-satunya yang, tanpa "menari dengan rebana," memberikan semua kompilasi silang yang diperlukan langsung dari kotak (!) .


Satu ketidaknyamanan yang sangat mengganggu saya tentang Go (terutama sebagai pengembang Java) adalah kurangnya perhatian dalam mengatur struktur proyek Go dan kebutuhan untuk terus-menerus menyesuaikan lingkungan. Mungkin para pengembang Go awalnya merencanakan untuk penggunaan tertentu atau ada fokus pada wadah, tetapi saya terbiasa dengan yang β€œenak” dan karena alat utama saya di Jawa adalah Maven , saya memutuskan untuk membuat plug-in yang membuat panggilan ke utilitas dan perintah GoSDK dengan generasi otomatis dari yang diperlukan. variabel lingkungan.


Itu tidak menarik untuk membuat plugin sederhana yang akan memanggil utilitas go, dan saya memutuskan untuk pergi dari langkah - menginstal GoSDK pada platform host. Segera setelah start, keberadaan GoSDK diperiksa di direktori konfigurasinya (saya memilih path default ~/.mvnGoLang ) dan, dengan tidak adanya versi yang diperlukan, arsip GoSDK secara otomatis diunduh dan dibuka dari situs resmi . Ini memungkinkan kami membuat proyek Go portabel tanpa khawatir tentang apakah alat versi yang diperlukan sudah diinstal sebelumnya dan dikonfigurasi. Tentu saja, dengan banyak pengaturan, saya melihat kemungkinan menggunakan versi pra-instal dan menambahkan pengaturan untuk semua langkah dalam proses, karena untuk banyak masalah seperti menonaktifkan verifikasi sertifikat SSL atau umumnya membuat permintaan HTTP di luar (seperti untuk proyek Keycloak ) sangat penting .


Langkah selanjutnya, saya membungkus Maven-tujuan (sasaran) semua perintah utilitas yang disediakan saat itu. Karena ada kemungkinan bahwa perintah baru lain akan muncul dengan versi baru GoSDK, tugas custom ditambahkan yang memungkinkan pengguna untuk menentukan perintah yang diinginkan sendiri. Secara default, dalam kerangka fase-maven (fase), tugas dijalankan dalam urutan berikut:


  • bersihkan sebagai default-clean dalam fase clean
  • fix as default-fix dalam fase validasi
  • dapatkan sebagai default-get dalam fase inisialisasi
  • menghasilkan sebagai default-generate dalam fase menghasilkan-sumber
  • fmt sebagai default-fmt dalam fase proses-sumber
  • uji sebagai uji default-test pada fase uji
  • build as default-build dalam fase paket
  • sebagai default-install tugas internal mvninstall dijalankan pada fase instalasi
  • instal sebagai default-deploy di fase deploy

Salah satu langkah dasar dapat dinonaktifkan dengan menerjemahkan tugas ke fase tidak ada:


 <execution> <id>default-fix</id> <phase>none</phase> </execution> 

Dalam implementasi internal, tugas dibagi menjadi "bekerja dengan dependensi" dan "tidak memerlukan resolusi dependensi", setelah munculnya dukungan untuk mode modul, sebagian besar bermigrasi ke "bekerja dengan dependensi".


Struktur proyek Go-maven, saya mencoba untuk lebih dekat dengan struktur folder standar yang diterima untuk Go (mis. /src dan /bin di root proyek). Tetapi karena Maven dipenjara untuk Java, itu tidak mungkin secara langsung untuk "mematahkan" pendekatannya untuk mengatur struktur proyek dan membuat langkah ini tidak terlihat oleh pengguna, sehingga konfigurasi dasar dari plugin terlihat sedikit tidak biasa bahkan bagi banyak yang akrab dengan pakar:


 <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> 

PERINGATAN! Untuk beberapa alasan, HabR dapat menampilkan bagian <sourceDirectory>${basedir}/src</sourceDirectory> ketika memformat XML

Seperti yang Anda lihat, Anda harus langsung menentukan folder sumber /src dan folder dengan hasil /bin . Di satu sisi, ini adalah minus, di sisi lain, kemungkinan mengubah lokasi mereka.


Seluruh pom.xml minimalis untuk proyek modul-tunggal, ala Hello world, adalah sebagai berikut:


 <?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> 

Harap dicatat bahwa pengemasan proyek ini disebut sebagai mvn-golang . Konfigurasi ini cukup untuk membangun file yang dapat dieksekusi dan meletakkannya di folder bin yang dihasilkan berdasarkan teks sumber dalam folder src. Go build cache juga akan dibuat di /bin (sebagai /bin/.goBuildCache secara default) dan akan dihapus dengan bersih dengan folder sementara ini.


Pada fase instal , tugas mvninstall internal mvninstall , yang hanya mengemas seluruh proyek dalam arsip zip dan menempatkannya dalam repositori maven sebagai artefak yang dihasilkan. Awalnya, saya baru saja menyimpan artefak ini, tetapi dari versi 2.3.2, sebuah mekanisme ditambahkan untuk mendukung mereka sebagai dependensi pakar standar dan menjadi mungkin untuk mengembangkan proyek dengan "berbagi" kode umum melalui repositori pakar. Jelas bahwa menempatkan hasil biner yang dihasilkan ke dalam repositori sebagai artefak adalah ide yang buruk karena persyaratan lintas-platform dan oleh karena itu isi folder /bin tidak dikemas dalam artefak.


Menghubungkan proyek lain dengan pengemasan mvn-golang sebagai ketergantungan maven terlihat seperti ini:


 <dependency> <groupId>com.igormaznitsa</groupId> <artifactId>mvn-go-test-mix-terminal</artifactId> <version>1.0.0-SNAPSHOT</version> <type>mvn-golang</type> </dependency> 

Dengan versi 2.3.3, dukungan ditambahkan untuk bekerja dengan mekanisme modul Go , tetapi secara default tidak diaktifkan (untuk kompatibilitas mundur) dan diaktifkan menggunakan parameter konfigurasi:


 <moduleMode>true</moduleMode> 

Ketika mekanisme modul Go masih pada tahap percobaan, saya menambahkan dukungan untuk bekerja dengan versi ketergantungan melalui panggilan langsung ke utilitas CVS, contoh uji dibuat . Tapi sekarang saya berpikir bahwa mekanisme seperti itu tidak lagi menarik dan lebih menguntungkan untuk menggunakan dependensi standar melalui modul. Selain itu, plugin ini dapat go.mod file go.mod pada saat membangun proyek, menggantikan jalur ke folder lokal jika pekerjaan sedang berlangsung dalam kerangka proyek multi-modul.


Karena Maven menyediakan kemungkinan standardisasi menggunakan arketipe, saya membuat dua arketipe:


  • com.igormaznitsa: mvn-golang-hello: 2.3.3 untuk arketipe modul tunggal sederhana
  • com.igormaznitsa: mvn-golang-hello-multi: 2.3.3 untuk proyek multi-modul dengan kode sumber bersama

Contoh bekerja dengan pola dasar proyek modul tunggal dapat dilihat pada animasi di bawah ini
gambar .


Anda juga dapat mengkloning proyek "Hello World" dan bermain-main:


 git clone https://github.com/raydac/mvn-golang-example.git 

gambar


Seringkali muncul pertanyaan yang masuk akal - mengapa semua ini diperlukan dan bonus apa yang diberikan oleh penggunaan Maven dalam proses membangun Proyek-Go? Saya akan mencoba menjawabnya poin demi poin:


  1. Maven adalah lingkungan proyek-bangunan lintas-platform yang sangat matang, didukung oleh hampir semua platform CI, misalnya Jenkins, menggunakan Go2XUnit Anda dapat mengonversi hasil tes ke format yang ditampilkan dengan melaporkan plugin.
  2. Maven adalah lintas-platform dan didukung oleh semua sistem operasi, yang termasuk dalam semua repositori. Kehadiran profil yang diaktifkan secara fleksibel memudahkan untuk menyesuaikan proses untuk berbagai platform.
  3. Maven memiliki sejumlah besar plugin , yang membuatnya mudah untuk mendapatkan efek sinergis, misalnya dengan menggabungkan Go dan GWT , menghubungkan ANTLR ke proyek , menghasilkan Go berdasarkan deskriptor Protobuf dan bahkan menambahkan preprocessing . Semua ini dapat diatur secara manual melalui file batch, tetapi jika ada plugin resmi yang didukung, maka lebih menguntungkan untuk menggunakannya.
  4. Proyek ini menjadi portabel antara mesin dan platform, dan beralih versi GoSDK dilakukan dengan mengubah satu baris.
  5. Kemudahan mengatur proyek multi-modul, dengan pemisahan kode sumber melalui repositori Maven.
  6. Alat ini akrab dan akrab bagi pengembang Java, yang memfasilitasi adaptasi mereka ketika beralih ke pengembangan di Golang atau ketika mengembangkan solusi Go + Java multibahasa.
  7. Ada kemungkinan pseudo-development on Go di lingkungan yang mendukung Maven, bahkan jika mereka tidak memiliki dukungan untuk platform ini, misalnya, di NetBeans IDE .

Kelemahan terbesar dari solusi, menurut saya, adalah satu di sini - sejumlah pengembang yang akrab dengan Maven di antara komunitas Golang. Bagi mereka yang beralih ke Golang dengan C / C ++, jelas bahwa sulit untuk menemukan sesuatu yang lebih dekat dan lebih mahal untuk dibuat, serta tidak ada yang membatalkan sistem Go-build "asli". Saya perhatikan bahwa untuk beberapa alasan, banyak pengembang tidak suka mencampur platform.


Jadi, saya secara singkat menunjukkan salah satu cara untuk menggunakan Maven ketika mengembangkan proyek Go menggunakan plugin mvn-golang-wrapper. Proyek plugin dirancang sebagai proyek OSS dan diposting di GitHub . Jika seseorang tertarik dan akan menggunakan proyek mereka, maka jangan ragu untuk bertanya dan "melaporkan bug." Saya mencoba membuat serangkaian contoh untuk berbagai kesempatan (di mana plugin sedang diuji), tetapi saya tidak bisa membahas semuanya.


Uji kasus dalam proyek plugin menggunakan versi dev, jadi jika Anda ingin membangunnya secara lokal setelah mengkloning proyek, Anda harus terlebih dahulu membangun versi dev plugin menggunakan perintah di direktori root proyek:


 mvn install 

setelah itu, Anda dapat masuk ke mvn-golang-examples proyek mvn-golang-examples dan membangunnya bersama


 mvn clean install 

Anda juga dapat mulai membangun semua contoh dari akar proyek, menggunakan


 mvn clean install -Pexamples 

Plugin ini mendukung perakitan multi-threaded proyek dan dapat dipercepat menggunakan argumen yang sesuai, memecah misalnya menjadi 6 utas


 mvn clean install -Pexamples -T6 

Selama pengembangan, proyek ini telah mengakumulasikan sejumlah "lonceng dan peluit" yang layak, yang saya putuskan untuk tidak dibahas dalam artikel singkat ini. Informasi tentang parameter dengan contoh konfigurasi kecil dapat ditemukan di mind map plugin ini (file sumber dalam format SciaReto ada di sini ):


gambar

Source: https://habr.com/ru/post/id465803/


All Articles