Xcode 11 mengkompilasi ulang terlalu banyak

12

Xcode 11 mengkompilasi ulang (hampir?) Seluruh proyek saya, bahkan jika saya hanya mengubah variabel pribadi lokal, atau mengubah nilai konstanta dalam lingkup lokal, kadang-kadang bahkan dalam lingkup fungsi pribadi lokal. Saya kadang-kadang bisa mendapatkan 2 atau 3 perubahan dengan build cepat seperti yang diharapkan, tetapi segera memutuskan untuk mengkompilasi ulang semuanya lagi (yang terlalu lama).

Ada ide apa yang mungkin terjadi? Apakah Xcode tidak dapat menentukan apa yang berubah, mengapa ia mengkompilasi ulang banyak hal lain (bahkan modul lain).

Setiap saran sangat dihargai, terima kasih!

Nikolay Suvandzhiev
sumber
2
Saya akan menyarankan: Pastikan Anda melakukan debug membangun dengan bangunan tambahan, bukan optimasi seluruh modul. Keluar dan bersihkan DerivedData. Dan perbarui ke Xcode 11.4, kadang-kadang kompilasi begitu cepat sehingga saya bahkan tidak melihat itu terjadi.
matt
1
Utas ini mungkin menjawab pertanyaan Anda: stackoverflow.com/questions/25537614/…
Endanke
Ini sangat tergantung pada proyek, perlu menganalisis build log tentang apa yang terjadi. Saya tidak mengamati perilaku seperti itu dengan Xcode 11.2+, sementara memiliki proyek yang sangat besar. Apakah Anda akan memberikan akses ke sumber proyek Anda, jika tidak, semua saran tidak masuk akal?
Asperi
Periksa properti Legacy Build System, seharusnya tidak dicentang jika Anda tidak mengubah submodul
BrunoLoops

Jawaban:

8

Kami memiliki masalah yang sama dan kami memperbaikinya. Dua kali.

Bangun tambahan (mesin bangun yang sama):

sebelum: ~ 10m setelah: ~ 35s

BAGAIMANA?

Mari kita mulai dengan pengalaman kita terlebih dahulu. Kami memiliki proyek Swift / Obj-C yang besar dan itulah yang menjadi perhatian utama: waktu pembangunan lambat dan Anda harus membuat proyek baru untuk mengimplementasikan fitur baru (secara harfiah). Poin bonus untuk penyorotan sintaks yang tidak berfungsi.

Teori

Untuk benar-benar memperbaiki ini, Anda harus benar - benar memahami cara kerja sistem build. Misalnya, mari coba cuplikan kode ini:

import FacebookSDK
import RxSwift
import PinLayout

dan bayangkan Anda menggunakan semua impor ini dalam file Anda. Dan juga file ini tergantung pada file lain, yang tergantung pada perpustakaan lain, yang pada gilirannya menggunakan perpustakaan lain dll.

Jadi untuk mengkompilasi file Anda Xcode harus mengkompilasi setiap perpustakaan yang Anda sebutkan dan setiap file tergantung, jadi jika Anda mengubah salah satu dari file "inti" Xcode harus membangun kembali seluruh proyek secara harfiah.

Pohon ketergantungan

Build Xcode multi-threaded , tetapi terdiri dari banyak pohon single-threaded .

Jadi pada langkah pertama setiap build tambahan Xcode menentukan file mana yang harus dikompilasi ulang dan membangun pohon AST . Jika Anda mengubah file yang bertindak sebagai " dapat diandalkan " pada file lain, maka setiap file lain yang bertindak sebagai " tergantung " harus dikompilasi ulang.

Kopel

Jadi saran pertama adalah untuk menurunkan kopling . Bagian-bagian proyek Anda harus independen satu sama lain.

Obj-C / Swift bridge

Masalah dengan pohon-pohon itu jika Anda menggunakan jembatan Obj-C / Swift, Xcode harus melalui fase lebih dari biasanya:

Dunia yang sempurna:

  1. Membangun kode Obj-C
  2. Buat kode Swift

Jembatan Swift / Obj-C

Obj-C / Swift bridge:

  1. [REPEATABLE STEP] Buat kode Swift, yang diperlukan untuk mengkompilasi kode Obj-C
  2. [REPEATABLE STEP] Buat kode Obj-C, yang diperlukan untuk mengkompilasi kode Swift
  3. Ulangi 1 & 2 hingga Anda hanya memiliki kode Swift & Obj-C yang tersisa
  4. Buat kode Obj-C
  5. Buat kode Swift

Obj-C / Swift bridge

Jadi, jika Anda mengubah sesuatu dari langkah 1 atau 2, pada dasarnya Anda dalam masalah. Solusi terbaik adalah meminimalkan Obj-C / Swift Bridge (dan menghapusnya dari proyek Anda).

Jika Anda tidak memiliki Obj-C / Swift Bridge, itu luar biasa dan Anda bisa melanjutkan ke langkah berikutnya:

Manajer Paket Swift

Saatnya pindah ke SwiftPM (atau setidaknya mengkonfigurasi Cocoapod Anda lebih baik).

Masalahnya, sebagian besar kerangka kerja dengan konfigurasi Cocoapods standar menyeret banyak hal yang tidak Anda butuhkan.

Untuk menguji ini buat proyek kosong dengan hanya satu ketergantungan seperti PinLayout, misalnya dan coba tulis kode ini dengan Cocoapods (konfigurasi default) dan SwiftPM.

import PinLayout

final class TestViewController: UIViewController {

}

Spoiler: Cocoapods akan mengkompilasi kode ini, karena Cocoapods akan mengimpor SETIAP IMPOR PinLayout (termasuk UIKit) dan SwiftPM tidak akan melakukannya karena SwiftPM mengimpor kerangka kerja secara atom.

Retas kotor

Apakah Anda ingat Xcode build multi-threaded?

Nah, Anda dapat menyalahgunakannya, jika Anda dapat membagi proyek Anda menjadi banyak bagian independen dan mengimpor semuanya sebagai kerangka kerja independen ke proyek Anda. Itu memang menurunkan kopling dan itu sebenarnya solusi pertama yang kami gunakan, tapi itu sebenarnya tidak terlalu efektif, karena kami hanya bisa mengurangi waktu build tambahan menjadi ~ 4-5m yang TIDAK ADA dibandingkan dengan metode pertama.

x0 z1
sumber
Semoga beruntung kawan. Bagikan pengalaman Anda bagaimana Anda menurunkan sambungan dalam proyek Anda. Sampai jumpa!
x0 z1
3

Tidak ada peluru emas di sini, tetapi banyak hal yang perlu diperiksa:

  • Pastikan Anda benar-benar menggunakan konfigurasi Debug dalam skema AndaEditor Skema Xcode menggunakan konfigurasi Debug

  • Lihat di bawah untuk cara memastikan Anda menggunakan build tambahan versus seluruh modul per saran. Pastikan juga Tingkat Pengoptimalan untuk Debug Anda tidak ada. Pengaturan Xcode Build menunjukkan penambahan Build

  • Jika Anda menggunakan kerangka berat tipe-inferensi seperti RxSwift, menambahkan anotasi tipe eksplisit dapat mempercepat waktu pembuatan.

  • Jika proyek ini sangat besar, Anda dapat mempertimbangkan refactoring keluar grup logis file sumber ke dalam kerangka kerja, tetapi itu mungkin terlalu drastis dari perubahan daripada yang Anda inginkan

Mungkin membantu jika Anda memberikan beberapa lebih spesifik tentang proyek: apakah Anda secara statis menghubungkan perpustakaan apa pun? Apakah itu kerangka kerja atau target aplikasi? Seberapa besar dan versi cepat apa yang Anda gunakan? Apakah Anda memiliki Fase Bangun kustom seperti linter atau pembuatan kode yang kadang-kadang dapat dilewati?

nteissler
sumber