Saya perlu mengoptimalkan ukuran executable saya ( ARM
pengembangan) dan saya perhatikan bahwa dalam skema build saya saat ini ( gcc
+ ld
) simbol yang tidak digunakan tidak dilucuti.
Penggunaan arm-strip --strip-unneeded
untuk executable / perpustakaan yang dihasilkan tidak mengubah ukuran keluaran dari executable (saya tidak tahu mengapa, mungkin itu tidak bisa) .
Bagaimana cara (jika ada) untuk memodifikasi pipeline bangunan saya, sehingga simbol yang tidak digunakan dihilangkan dari file yang dihasilkan?
Aku bahkan tidak akan berpikir tentang ini, tapi lingkungan tertanam saya saat ini sangat tidak "kuat" dan menyimpan bahkan 500K
dari 2M
hasil dalam meningkatkan kinerja pemuatan sangat bagus.
Memperbarui:
Sayangnya gcc
versi saat ini yang saya gunakan tidak memiliki -dead-strip
opsi dan -ffunction-sections... + --gc-sections
untuk ld
tidak memberikan perbedaan yang signifikan untuk keluaran yang dihasilkan.
Saya terkejut bahwa ini bahkan menjadi masalah, karena saya yakin itu gcc + ld
harus secara otomatis menghapus simbol yang tidak digunakan (mengapa mereka bahkan harus menyimpannya?).
boost
perpustakaan,.exe
file yang dihasilkan berisi banyak file objek yang tidak terpakai dan karena spesifikasi runtime yang saya sematkan saat ini , memulai10mb
aplikasi membutuhkan waktu lebih lama daripada, misalnya, memulai500k
aplikasi.Jawaban:
Untuk GCC, ini dilakukan dalam dua tahap:
Pertama-tama kompilasi data tetapi beri tahu kompilator untuk memisahkan kode menjadi beberapa bagian terpisah dalam unit terjemahan. Ini akan dilakukan untuk fungsi, kelas, dan variabel eksternal dengan menggunakan dua tanda compiler berikut:
Tautkan unit terjemahan bersama-sama menggunakan tanda pengoptimalan linker (ini menyebabkan linker membuang bagian yang tidak direferensikan):
Jadi jika Anda memiliki satu file bernama test.cpp yang memiliki dua fungsi yang dideklarasikan di dalamnya, tetapi salah satunya tidak digunakan, Anda dapat menghilangkan yang tidak digunakan dengan perintah berikut ke gcc (g ++):
(Perhatikan bahwa -Os adalah tanda compiler tambahan yang memberi tahu GCC untuk mengoptimalkan ukuran)
sumber
mingw
ini tidak berfungsi saat menautkan libstdc ++ dan libgcc secara statis dengan flag-static
. Opsi penaut-strip-all
sedikit membantu, tetapi masih dapat dieksekusi (atau dll) yang dihasilkan sekitar 4 cara lebih besar dari apa yang akan dihasilkan Visual Studio. Intinya adalah, saya tidak memiliki kendali atas bagaimanalibstdc++
dikompilasi. Harus ada satu-ld
satunya pilihan.Jika utas ini dipercaya, Anda perlu menyediakan
-ffunction-sections
dan-fdata-sections
ke gcc, yang akan menempatkan setiap fungsi dan objek data di bagiannya masing-masing. Kemudian Anda memberikan dan--gc-sections
ke GNU ld untuk menghapus bagian yang tidak digunakan.sumber
Anda sebaiknya memeriksa dokumen Anda untuk versi gcc & ld:
Namun bagi saya (OS X gcc 4.0.1) saya menemukan ini untuk ld
Dan opsi bermanfaat ini
Ada juga catatan di gcc / g ++ man bahwa penghapusan kode mati jenis tertentu hanya dilakukan jika pengoptimalan diaktifkan saat kompilasi.
Meskipun opsi / ketentuan ini mungkin tidak berlaku untuk kompiler Anda, saya sarankan Anda mencari sesuatu yang serupa di dokumen Anda.
sumber
mingw
.-dead_strip
bukanlahgcc
pilihan.Kebiasaan pemrograman juga bisa membantu; misalnya menambah
static
fungsi yang tidak diakses di luar file tertentu; gunakan nama yang lebih pendek untuk simbol (bisa membantu sedikit, kemungkinan tidak terlalu banyak); gunakanconst char x[]
jika memungkinkan; ... makalah ini , meskipun membahas tentang objek bersama yang dinamis, dapat berisi saran yang, jika diikuti, dapat membantu memperkecil ukuran keluaran biner akhir Anda (jika target Anda adalah ELF).sumber
.so
di Linux), jadi nama simbol harus dipertahankan sehingga API sepertictypes
modul FFI Python dapat menggunakannya untuk mencari simbol berdasarkan nama pada waktu proses.Jawabannya adalah
-flto
. Anda harus meneruskannya ke langkah kompilasi dan tautan Anda, jika tidak maka tidak akan melakukan apa-apa.Ini sebenarnya bekerja dengan sangat baik - mengurangi ukuran program mikrokontroler yang saya tulis menjadi kurang dari 50% dari ukuran sebelumnya!
Sayangnya itu memang tampak agak buggy - saya punya contoh hal-hal tidak dibangun dengan benar. Mungkin karena sistem build yang saya gunakan (QBS; ini sangat baru), tetapi dalam hal apa pun, saya sarankan Anda hanya mengaktifkannya untuk build akhir Anda jika memungkinkan, dan menguji build itu secara menyeluruh.
sumber
-flto
saya tidak mengerti apa yang dilakukannya di belakang layar.-flto
itu tidak mengkompilasi setiap file untuk dirakit, itu mengkompilasinya ke LLVM IR, dan kemudian tautan terakhir mengkompilasi mereka seolah-olah semuanya berada dalam satu unit kompilasi. Itu berarti dapat menghilangkan fungsi yang tidak terpakai dan inline non-static
one, dan mungkin hal-hal lain juga. Lihat llvm.org/docs/LinkTimeOptimization.htmlMeskipun tidak hanya tentang simbol, jika mencari ukuran - selalu kompilasi dengan flag
-Os
dan-s
.-Os
mengoptimalkan kode yang dihasilkan untuk ukuran minimum yang dapat dieksekusi dan-s
menghapus tabel simbol dan informasi relokasi dari yang dapat dieksekusi.Terkadang - jika ukuran kecil diinginkan - bermain-main dengan flag pengoptimalan yang berbeda mungkin - atau mungkin tidak - memiliki makna. Misalnya toggling
-ffast-math
dan / atau-fomit-frame-pointer
mungkin terkadang menghemat puluhan byte.sumber
-ffast-math
membuat malapetaka dalam kode C ++ yang sepenuhnya sesuai standar, jadi saya tidak akan merekomendasikannya.Menurut saya jawaban yang diberikan oleh Nemo adalah yang benar. Jika instruksi itu tidak berhasil, masalahnya mungkin terkait dengan versi gcc / ld yang Anda gunakan, sebagai latihan saya menyusun program contoh menggunakan instruksi yang dirinci di sini
Kemudian saya menyusun kode menggunakan sakelar penghapusan kode mati yang semakin agresif:
Parameter kompilasi dan penautan ini menghasilkan file executable dengan ukuran 8457, 8164 dan 6160 byte, masing-masing, kontribusi paling substansial berasal dari deklarasi 'strip-all'. Jika Anda tidak dapat menghasilkan pengurangan serupa di platform Anda, mungkin versi gcc Anda tidak mendukung fungsi ini. Saya menggunakan gcc (4.5.2-8ubuntu4), ld (2.21.0.20110327) di Linux Mint 2.6.38-8-generic x86_64
sumber
strip --strip-unneeded
hanya beroperasi pada tabel simbol yang dapat dieksekusi Anda. Itu tidak benar-benar menghapus kode yang dapat dieksekusi.Pustaka standar mencapai hasil yang Anda cari dengan memisahkan semua fungsinya menjadi file objek terpisah, yang digabungkan menggunakan
ar
. Jika Anda kemudian menautkan arsip yang dihasilkan sebagai pustaka (mis. Memberikan opsi-l your_library
ke ld) maka ld hanya akan menyertakan file objek, dan oleh karena itu simbol, yang sebenarnya digunakan.Anda mungkin juga menemukan beberapa jawaban untuk pertanyaan penggunaan yang serupa ini .
sumber
Saya tidak tahu apakah ini akan membantu kesulitan Anda saat ini karena ini adalah fitur terbaru, tetapi Anda dapat menentukan visibilitas simbol secara global. Meneruskan
-fvisibility=hidden -fvisibility-inlines-hidden
kompilasi dapat membantu penaut untuk menghilangkan simbol yang tidak diperlukan nanti. Jika Anda membuat file yang dapat dieksekusi (sebagai lawan dari pustaka bersama), tidak ada lagi yang bisa dilakukan.Informasi lebih lanjut (dan pendekatan yang lebih baik untuk misalnya perpustakaan) tersedia di wiki GCC .
sumber
Dari manual GCC 4.2.1, bagian
-fwhole-program
:sumber
-flto
.Anda dapat menggunakan biner strip pada file objek (mis. Dapat dieksekusi) untuk menghapus semua simbol darinya.
Catatan: itu mengubah file itu sendiri dan tidak membuat salinan.
sumber