Saya sedang mengerjakan proyek C ++ besar di Visual Studio 2008, dan ada banyak file dengan #include
arahan yang tidak perlu . Kadang-kadang #include
s hanyalah artefak dan semuanya akan dikompilasi dengan baik dengan mereka dihapus, dan dalam kasus lain kelas dapat dideklarasikan dan #include dapat dipindahkan ke .cpp
file. Apakah ada alat yang bagus untuk mendeteksi kedua kasus ini?
96
PC Lint bekerja cukup baik untuk ini, dan menemukan semua jenis masalah konyol lainnya untuk Anda juga. Ini memiliki opsi baris perintah yang dapat digunakan untuk membuat Alat Eksternal di Visual Studio, tetapi saya telah menemukan bahwa addin Visual Lint lebih mudah untuk digunakan. Bahkan versi gratis Visual Lint membantu. Tapi coba PC-Lint. Mengkonfigurasinya agar tidak memberi Anda terlalu banyak peringatan membutuhkan sedikit waktu, tetapi Anda akan kagum dengan hasilnya.
sumber
Ada alat berbasis Clang baru, termasuk-apa-yang-Anda-gunakan , yang bertujuan untuk melakukan ini.
sumber
!!PENOLAKAN!! Saya bekerja pada alat analisis statis komersial (bukan PC Lint). !!PENOLAKAN!!
Ada beberapa masalah dengan pendekatan non parsing sederhana:
1) Set Kelebihan Beban:
Ada kemungkinan bahwa fungsi yang kelebihan beban memiliki deklarasi yang berasal dari file berbeda. Mungkin menghapus satu file header menghasilkan kelebihan muatan yang berbeda yang dipilih daripada kesalahan kompilasi! Hasilnya adalah perubahan diam-diam dalam semantik yang mungkin sangat sulit dilacak setelahnya.
2) Spesialisasi template:
Mirip dengan contoh overload, jika Anda memiliki spesialisasi parsial atau eksplisit untuk template, Anda ingin semuanya terlihat saat template digunakan. Mungkin spesialisasi untuk template utama ada di file header yang berbeda. Menghapus header dengan spesialisasi tidak akan menyebabkan kesalahan kompilasi, tetapi dapat mengakibatkan perilaku tidak terdefinisi jika spesialisasi tersebut telah dipilih. (Lihat: Visibilitas spesialisasi template dari fungsi C ++ )
Seperti yang ditunjukkan oleh 'msalters', melakukan analisis lengkap kode juga memungkinkan analisis penggunaan kelas. Dengan memeriksa bagaimana sebuah kelas digunakan melalui jalur file tertentu, dimungkinkan bahwa definisi kelas (dan oleh karena itu semua dependneciesnya) dapat dihapus seluruhnya atau setidaknya dipindahkan ke level yang lebih dekat ke sumber utama di include pohon.
sumber
Saya tidak tahu alat semacam itu, dan saya pernah berpikir untuk menulisnya di masa lalu, tetapi ternyata ini adalah masalah yang sulit dipecahkan.
Katakanlah file sumber Anda menyertakan ah dan bh; ah berisi
#define USE_FEATURE_X
dan penggunaan bh#ifdef USE_FEATURE_X
. Jika#include "a.h"
diberi komentar, file Anda mungkin masih dikompilasi, tetapi mungkin tidak melakukan apa yang Anda harapkan. Mendeteksi ini secara terprogram bukanlah hal yang sepele.Alat apa pun yang melakukan ini perlu mengetahui lingkungan build Anda juga. Jika ah terlihat seperti:
Kemudian
USE_FEATURE_X
hanya ditentukan jikaWINNT
ditentukan, jadi alat tersebut perlu mengetahui arahan apa yang dihasilkan oleh kompilator itu sendiri serta yang mana yang ditentukan dalam perintah kompilasi daripada di file header.sumber
Seperti Timmermans, saya tidak terbiasa dengan alat apa pun untuk ini. Tetapi saya telah mengenal programmer yang menulis skrip Perl (atau Python) untuk mencoba mengomentari setiap baris yang disertakan satu per satu dan kemudian mengkompilasi setiap file.
Tampaknya sekarang Eric Raymond memiliki alat untuk ini .
Google cpplint.py memiliki "termasuk apa yang Anda gunakan" aturan (di antara banyak lainnya), tetapi sejauh yang saya tahu, tidak ada "termasuk hanya apa yang Anda gunakan." Meski begitu, bisa bermanfaat.
sumber
Jika Anda tertarik dengan topik ini secara umum, Anda mungkin ingin melihat Desain Perangkat Lunak C ++ Skala Besar Lakos . Agak ketinggalan jaman, tetapi mengalami banyak masalah "desain fisik" seperti menemukan header minimum absolut yang perlu disertakan. Saya belum pernah melihat hal semacam ini didiskusikan di tempat lain.
sumber
Berikan Sertakan Manajer mencoba. Ini terintegrasi dengan mudah dalam Visual Studio dan memvisualisasikan jalur penyertaan Anda yang membantu Anda menemukan hal-hal yang tidak perlu. Secara internal menggunakan Graphviz tetapi ada banyak fitur keren lainnya. Dan meskipun itu adalah produk komersial, harganya sangat rendah.
sumber
Anda dapat membuat grafik penyertaan menggunakan C / C ++ Include File Dependencies Watcher , dan menemukan penyertaan yang tidak diperlukan secara visual.
sumber
Jika file header Anda biasanya dimulai dengan
(sebagai lawan menggunakan #pragma sekali) Anda dapat mengubahnya menjadi:
Dan karena compiler mengeluarkan nama file cpp yang sedang dikompilasi, itu akan memberi tahu Anda setidaknya file cpp mana yang menyebabkan header dibawa beberapa kali.
sumber
A.h
danB.h
keduanya bergantungC.h
dan Anda memasukkanA.h
danB.h
, karena Anda membutuhkan keduanya, Anda akan memasukkanC.h
dua kali, tapi tidak apa-apa, karena kompilator akan melewatkannya untuk kedua kalinya dan jika tidak, Anda harus ingat untuk selalu menyertakanC.h
sebelumA.h
atauB.h
berakhir di inklusi yang jauh lebih tidak berguna.PC-Lint memang bisa melakukan ini. Salah satu cara mudah untuk melakukan ini adalah dengan mengkonfigurasinya untuk mendeteksi file include yang tidak digunakan dan mengabaikan semua masalah lainnya. Ini cukup mudah - untuk mengaktifkan hanya message 766 ("File header tidak digunakan dalam modul"), cukup sertakan opsi -w0 + e766 pada baris perintah.
Pendekatan yang sama juga dapat digunakan dengan pesan terkait seperti 964 ("File header tidak langsung digunakan dalam modul") dan 966 ("File header yang disertakan tidak langsung tidak digunakan dalam modul").
FWIW Saya menulis tentang ini secara lebih rinci dalam posting blog minggu lalu di http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614976318 .
sumber
Jika Anda ingin menghapus
#include
file yang tidak perlu untuk mengurangi waktu build, waktu dan uang Anda mungkin lebih baik dihabiskan untuk memparalelkan proses build Anda menggunakan cl.exe / MP , make -j , Xoreax IncrediBuild , distcc / icecream , dll.Tentu saja, jika Anda sudah memiliki proses build paralel dan Anda masih mencoba untuk mempercepatnya, bersihkan
#include
arahan Anda dan hapus dependensi yang tidak perlu tersebut.sumber
Mulailah dengan setiap file include, dan pastikan bahwa setiap file include hanya menyertakan apa yang diperlukan untuk mengkompilasi sendiri. Semua file yang disertakan yang kemudian hilang untuk file C ++, dapat ditambahkan ke file C ++ itu sendiri.
Untuk setiap penyertaan dan file sumber, beri komentar setiap file penyertaan satu per satu dan lihat apakah itu terkompilasi.
Ini juga merupakan ide yang baik untuk mengurutkan file yang disertakan menurut abjad, dan jika tidak memungkinkan, tambahkan komentar.
sumber
Menambahkan salah satu atau kedua #defines berikut akan sering mengecualikan file header yang tidak diperlukan dan dapat meningkatkan waktu kompilasi secara substansial terutama jika kode yang tidak menggunakan fungsi Windows API.
Lihat http://support.microsoft.com/kb/166474
sumber
Jika Anda belum melakukannya, menggunakan tajuk yang telah dikompilasi untuk menyertakan semua yang tidak akan Anda ubah (tajuk platform, tajuk SDK eksternal, atau bagian proyek Anda yang sudah selesai statis) akan membuat perbedaan besar dalam waktu pembuatan.
http://msdn.microsoft.com/en-us/library/szfdksca(VS.71).aspx
Juga, meskipun mungkin sudah terlambat untuk proyek Anda, mengatur proyek Anda menjadi beberapa bagian dan tidak menggabungkan semua tajuk lokal ke satu tajuk utama yang besar adalah praktik yang baik, meskipun membutuhkan sedikit kerja ekstra.
sumber
Jika Anda akan bekerja dengan Eclipse CDT Anda dapat mencoba http://includator.com untuk mengoptimalkan struktur penyertaan Anda. Namun, Includator mungkin tidak cukup tahu tentang penyertaan VC ++ yang telah ditentukan sebelumnya dan menyiapkan CDT untuk menggunakan VC ++ dengan penyertaan yang benar belum dibangun ke dalam CDT.
sumber
Jetbrains IDE terbaru, CLion, secara otomatis menampilkan (dalam warna abu-abu) termasuk yang tidak digunakan dalam file saat ini.
Dimungkinkan juga untuk memiliki daftar semua include yang tidak digunakan (dan juga fungsi, metode, dll ...) dari IDE.
sumber
Beberapa jawaban yang ada menyatakan itu sulit. Itu memang benar, karena Anda memerlukan kompiler lengkap untuk mendeteksi kasus-kasus di mana deklarasi penerusan akan sesuai. Anda tidak dapat mengurai C ++ tanpa mengetahui arti simbol; tata bahasanya terlalu ambigu untuk itu. Anda harus tahu apakah nama tertentu menamai kelas (bisa dideklarasikan ke depan) atau variabel (tidak bisa). Selain itu, Anda harus peka namespace.
sumber
Mungkin agak terlambat, tetapi saya pernah menemukan skrip perl WebKit yang melakukan apa yang Anda inginkan. Saya yakin itu perlu beberapa adaptasi (saya tidak mahir dalam perl), tetapi itu harus melakukan trik:
http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes
(ini adalah cabang lama karena trunk tidak lagi memiliki file)
sumber
Jika ada header tertentu yang menurut Anda tidak diperlukan lagi (katakanlah string.h), Anda dapat mengomentari include tersebut lalu meletakkan ini di bawah semua include:
Tentu saja header antarmuka Anda mungkin menggunakan konvensi #define yang berbeda untuk mencatat penyertaannya dalam memori CPP. Atau tanpa konvensi, dalam hal ini pendekatan ini tidak akan berhasil.
Kemudian bangun kembali. Ada tiga kemungkinan:
Itu dibangun dengan baik. string.h tidak bersifat compile-critical, dan sertakannya dapat dihapus.
Perjalanan #error. string.g dimasukkan secara tidak langsung entah bagaimana Anda masih tidak tahu apakah string.h diperlukan. Jika diperlukan, Anda harus langsung #memasukkannya (lihat di bawah).
Anda mendapatkan kesalahan kompilasi lainnya. string.h diperlukan dan tidak disertakan secara tidak langsung, jadi penyertaan itu benar untuk memulai.
Perhatikan bahwa bergantung pada penyertaan tidak langsung ketika .h atau .c Anda secara langsung menggunakan .h lain hampir pasti merupakan bug: Anda sebenarnya menjanjikan bahwa kode Anda hanya akan memerlukan header itu selama beberapa header lain yang Anda gunakan memerlukannya, yang mungkin bukan yang Anda maksud.
Peringatan yang disebutkan dalam jawaban lain tentang header yang mengubah perilaku, bukan yang menyatakan hal-hal yang menyebabkan kegagalan build, juga berlaku di sini.
sumber