Katakanlah saya memiliki makefile dengan aturan tersebut
%.o: %.c
gcc -Wall -Iinclude ...
Saya ingin * .o dibangun kembali setiap kali file header berubah. Daripada mengerjakan daftar dependensi, setiap kali file header /include
berubah, maka semua objek di dir harus dibangun kembali.
Saya tidak bisa memikirkan cara yang baik untuk mengubah aturan untuk mengakomodasi ini, saya terbuka untuk saran. Poin bonus jika daftar tajuk tidak harus menggunakan hardcode
Jawaban:
Jika Anda menggunakan kompiler GNU, kompilator dapat menyusun daftar dependensi untuk Anda. Fragmen makefile:
atau
di mana
SRCS
variabel menunjuk ke seluruh daftar file sumber Anda.Ada juga alatnya
makedepend
, tapi saya tidak pernah menyukainyagcc -MM
sumber
depend
menjalankan hanya ketika file sumber telah berubah? Tampaknya berjalan setiap saat ...build/file.o
?Kebanyakan jawaban ternyata rumit atau salah. Namun contoh sederhana dan kuat telah diposting di tempat lain [ codereview ]. Memang opsi yang disediakan oleh preprocessor gnu agak membingungkan. Namun, penghapusan semua direktori dari target build dengan
-MM
didokumentasikan dan bukan bug [ gpp ]:Opsi (agak lebih baru)
-MMD
mungkin yang Anda inginkan. Untuk kelengkapan, contoh makefile yang mendukung beberapa dir src dan direktori build dengan beberapa komentar. Untuk versi sederhana tanpa build dirs lihat [ codereview ].Metode ini berfungsi karena jika ada beberapa baris dependensi untuk satu target, dependensi hanya digabungkan, misalnya:
setara dengan:
seperti yang disebutkan di: Makefile multiple dependency lines untuk satu target?
sumber
CPP
should readCPPS
a.cpp
,b.cpp
) di./src/
, bukankah substitusi itu akan berhasil$(OBJ)=./build/src/a.o ./build/src/b.o
?Seperti yang saya posting di sini, gcc dapat membuat dependensi dan mengkompilasi pada saat yang bersamaan:
Parameter '-MF' menentukan file untuk menyimpan dependensi.
Tanda hubung di awal '-include' memberitahu Make untuk melanjutkan jika file .d tidak ada (misalnya pada kompilasi pertama).
Perhatikan bahwa tampaknya ada bug di gcc terkait opsi -o. Jika Anda mengeset nama file objek menjadi obj / _file__c.o maka file .d yang dihasilkan akan tetap berisi file .o, bukan obj / _file__c.o.
sumber
man gcc
kata-MM
menyiratkan-E
, yang "berhenti setelah preprocessing".-MMD
Sebagai gantinya, Anda membutuhkan : stackoverflow.com/a/30142139/895245Bagaimana dengan sesuatu seperti:
Anda juga dapat menggunakan wildcard secara langsung, tetapi saya cenderung merasa bahwa saya membutuhkannya di lebih dari satu tempat.
Perhatikan bahwa ini hanya berfungsi dengan baik pada proyek kecil, karena mengasumsikan bahwa setiap file objek bergantung pada setiap file header.
sumber
make clean all
setiap saat.gcc
garis tidak dijalankan sama sekali, tapi built-in aturan (yang%o: %.c
aturan) dijalankan sebagai gantinya.Solusi Martin di atas berfungsi dengan baik, tetapi tidak menangani file .o yang berada di subdirektori. Godric menunjukkan bahwa flag -MT menangani masalah itu, tetapi secara bersamaan mencegah file .o ditulis dengan benar. Berikut ini akan menangani kedua masalah tersebut:
sumber
Ini akan melakukan pekerjaan dengan baik, dan bahkan menangani subdir yang ditentukan:
mengujinya dengan gcc 4.8.3
sumber
Ini dua baris:
Ini berfungsi dengan resep make default, selama Anda memiliki daftar semua file objek Anda
OBJS
.sumber
Saya lebih suka solusi ini, daripada jawaban yang diterima oleh Michael Williamson, ini menangkap perubahan pada sumber + file sebaris, lalu sumber + tajuk, dan akhirnya hanya sumber. Keuntungan di sini adalah bahwa seluruh pustaka tidak dikompilasi ulang jika hanya dilakukan sedikit perubahan. Bukan pertimbangan besar untuk proyek dengan beberapa file, tetapi jika Anda memiliki 10 atau 100 sumber, Anda akan melihat perbedaannya.
sumber
Pekerjaan berikut untuk saya:
sumber
Versi jawaban Sophie yang sedikit dimodifikasi yang memungkinkan untuk mengeluarkan file * .d ke folder berbeda (saya hanya akan menempelkan bagian menarik yang menghasilkan file dependensi):
Perhatikan bahwa parameternya
digunakan untuk memastikan bahwa target (yaitu nama file objek) dalam file * .d yang dihasilkan berisi jalur lengkap ke file * .o dan bukan hanya nama file.
Saya tidak tahu mengapa parameter ini TIDAK diperlukan saat menggunakan -MMD dalam kombinasi dengan -c (seperti dalam versi Sophie ). Dalam kombinasi ini tampaknya menulis jalur lengkap dari file * .o ke dalam file * .d. Tanpa kombinasi ini, -MMD juga menulis hanya nama file murni tanpa komponen direktori ke dalam file * .d. Mungkin ada yang tahu mengapa -MMD menulis jalur lengkap jika digabungkan dengan -c. Saya belum menemukan petunjuk apa pun di halaman manual g ++.
sumber