Pengemasan Paket dalam Gradle

Dalam artikel saya, saya ingin berbicara tentang trik lain yang dapat dengan mudah diimplementasikan menggunakan paket perpustakaan pengemasan ulang Gradle. Setiap orang yang bahkan bekerja sedikit dengan sistem build ini tahu bahwa secara otomatis tahu cara menyelesaikan konflik dari berbagai versi perpustakaan, dan jika Anda mau, Anda dapat memengaruhi ini, misalnya, memperbaiki versi perpustakaan tertentu:


configurations.all { resolutionStrategy { force "org.ow2.asm:asm:7.2" } } 

Sayangnya, ini tidak selalu membantu menyelesaikan masalah konflik versi. Misalnya, ada masalah yang diketahui bahwa beberapa perangkat htc dalam firmware sudah memiliki pustaka gson, dan jika versi gson Anda berbeda dari yang terpasang, maka masalah dapat terjadi, karena ClassLoader akan memuat hanya satu kelas ke dalam memori, dan dalam hal ini akan menjadi satu sistem.


Masalah ini juga dapat terjadi ketika mengembangkan perpustakaan. Jika Anda menghubungkan 2 perpustakaan ke proyek Anda yang menggunakan perpustakaan pihak ketiga yang sama dari versi yang berbeda, misalnya 1 dan 2, maka Gradle akan menyelesaikan dan mengambil versi terbaru, yang kedua. Tetapi jika tidak ada kompatibilitas ke belakang di perpustakaan pihak ketiga ini dan versi kedua tidak bisa hanya digunakan bukan yang pertama, maka akan ada masalah yang pasti akan sangat sulit untuk dilacak dengan jejak. Perpustakaan yang menunggu versi pertama akan menerima kelas kedua dan hanya crash.


Saya mengalami konflik versi ketika menulis plugin grad , ia menggunakan pustaka asm , yang bertentangan. Setelah menulis plugin, saya memeriksa kinerjanya pada proyek uji: semuanya baik-baik saja, diperiksa pada proyek hewan peliharaan, semuanya baik-baik saja juga, tetapi ketika saya menghubungkannya ke proyek kerja nyata dengan sekelompok dependensi pihak ketiga, saya mengalami masalah.



Solusi untuk masalah di bawah luka.


Namun berhasil, apa yang salah?


Kami mendapatkan jejak kesalahan penuh:



Kita melihat bahwa kesalahan dalam konstruktor pustaka ClassVisitor asm ada di baris 79. Mari kita lihat di sana, tetapi ketika mencoba membuka ClassVisitor , studio menawarkan 2 opsi



Plugin saya menggunakan asm versi 7.2 , jadi kami pergi ke sana dan pada baris 79 kita melihat yang berikut:



Ini jelas bukan yang kita butuhkan. Sekarang, masuk ke ClassVisitor versi 6:



Hanya IllegalArgumentException kami tanpa pesan. Plugin saya menggunakan versi ASM api 7 dari Opcodes.ASM7 , dan dalam versi 6 perpustakaan api ini belum ada, oleh karena itu, IllegalArgumentException di lalat konstruktor. Kita dapat menyimpulkan bahwa plugin menerima versi pustaka yang salah.


Pertanyaan sampah, saya pikir, dan melakukan ini:


 configurations.all { resolutionStrategy { force "org.ow2.asm:asm:7.2" } } 

Saya menyesal, ini sama sekali tidak berpengaruh. Saya masih tidak dapat menemukan alasan yang tepat mengapa tidak mungkin untuk memperbaiki versi asm, meskipun perintah ./gradlew app:dependencies perintah ./gradlew app:dependencies menunjukkan bahwa versi tersebut telah diganti dengan 7.2. Jika seseorang memiliki pemikiran atau asumsi, saya akan senang mendengar pendapat.


Masalahnya harus dipecahkan entah bagaimana


Serangkaian googling dan pendalaman ke dalam pekerjaan hujan es dimulai. Akibatnya, saya pergi ke situs web asm, mungkin mereka tahu sesuatu tentang ini. Ternyata mereka benar-benar tahu, jawaban pertanyaan saya ada di bagian FAQ. Mereka mengatakan untuk mengganti paket asm dengan yang lain, mereka bahkan menawarkan utilitas untuk ini. Ok, ayo coba. Anda hanya perlu menghubungkan plug-in dan melakukan sedikit pengaturan:


 apply plugin: 'org.anarres.jarjar' ... dependencies { implementation fileTree(dir: 'build/jarjar', include: ['*.jar']) implementation jarjar.repackage('asm') { from 'org.ow2.asm:asm:7.2' classRename "org.objectweb.asm.**", "stater.org.objectweb.asm.@1" } } 

build/jarjar dalam hal ini, direktori di mana file jar asm library dengan paket-paket yang di-bungkus akan dihasilkan, jadi Anda perlu membuka akses ketergantungan ke direktori ini melalui fileTree . Perpustakaan sekarang akan tersedia dengan import stater.org.objectweb.asm.* Alih-alih org.objectweb.asm.* . Plugin ini memiliki berbagai pengaturan, tetapi dalam contoh saya, hanya mengubah paket sudah cukup.


Selanjutnya, periksa seluruh proyek dan ubah impor di mana-mana dari org.objectweb.asm ke
stater.org.objectweb.asm . Menurut pendapat saya, utilitas yang sangat nyaman, berkali-kali lebih mudah daripada melakukannya dengan tangan, terutama ketika memperbarui perpustakaan, kami hanya mengubah from 'org.ow2.asm:asm:7.2' ke versi baru dan nama panggilan jar yang dikemas dengan versi baru akan dihasilkan di mesin otomatis.


Jika Anda hanya memiliki proyek (bukan perpustakaan), maka ini sudah cukup bagi Anda untuk menyelesaikan konflik yang tidak terpecahkan, seperti gson yang disebutkan di awal artikel. Tetapi jika Anda, seperti saya, menulis perpustakaan, maka itu belum semuanya.


Kami memecahkan masalah pengemasan ulang, tetapi sekarang asm terhubung ke proyek bukan melalui ketergantungan pada repositori maven jarak jauh, tetapi melalui file jar lokal, yang akan hilang begitu saja ketika perpustakaan Anda digunakan dan akan ada kesalahan NoClassDefFoundError . Tetapi masalah ini cukup sederhana untuk dipecahkan:


  1. Di file gradle kami, buat konfigurasi baru:


     configurations { extraLibs implementation.extendsFrom(extraLibs) } 

  2. Selanjutnya kita berubah


     implementation fileTree(dir: 'build/jarjar', include: ['*.jar']) 

    pada


     extraLibs fileTree(dir: 'build/jarjar', include: ['*.jar']) 

  3. Tetapkan ulang tugas yang bertanggung jawab untuk mengumpulkan file jar terakhir Anda dan tulis semua perpustakaan dengan konfigurasi baru kami di nama panggilan jar terakhir:


     jar { from { configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) } } } 


Itu saja, gunakan plugin kami seperti sebelumnya, terhubung ke proyek di mana ada konflik yang tidak dapat diselesaikan dan semuanya berfungsi dengan baik.
Pengemasan ulang seperti itu membuat perpustakaan kami lebih toleran terhadap kesalahan ketika terhubung ke berbagai jenis proyek dengan perpustakaan lain.


Dan jika Anda hanya menghubungkan file jar perpustakaan yang bertentangan ke plugin tanpa mengemas ulang?


Gagasan buruk, itu tidak akan mengarah pada sesuatu yang baik. Dalam proses membangun proyek, ada check...DuplicateClasses tugas yang menarik check...DuplicateClasses , yang hanya memotong file dengan paket yang sama. Yaitu, file yang diperoleh dari file jar perpustakaan yang terhubung dan file dari perpustakaan yang sama yang terhubung melalui repositori jarak jauh. Hasilnya adalah kesalahan ini:



Itu saja. Terima kasih untuk semua orang yang membaca!


Tulsa untuk dikemas ulang
Plugin contoh

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


All Articles