2009-03-12 20 views
7

Son zamanlarda, make-based oluşturma işlemimizdeki bağımlılıklar için .d dosyalarını işleme biçimimiz hakkında bir tartışma başlatıyoruz. Sorun, bazen dosyalar oluşturulduğunda .d dosyalarının bozulabileceği konusunda ortaya çıkarıldı.Hata durumunda ek dosyaları silme işlemini gerçekleştirme

Bir derleme kesildiğinde veya hata verirse, oluşturma işleminde olduğu nesne dosyalarının silinmesini sağlamak için .DELETE_ON_ERROR hedefini kullanıyoruz. Ancak, derleme zamanında da silinmesi gereken .d dosyalarını oluşturmak için GCC kullanıyoruz. Bunu anlatabilmek için basit bir yol var gibi görünmüyor.

Soru şu ki, bir hata durumunda hem nesneyi hem de bağımlılık dosyalarımızı silmek için koaksiyel yapmamızın bir yolu var mı? Kuralları kurmamızın bir yolu var mı? Böylece hem .d hem de .o dosyalarının aynı anda üretildiğini ve bir hata varsa silinmesi gerektiğini biliyor mu?

Alternatif olarak, bozuk .d dosyaları sorununu çözmek için yapabileceğimiz başka bir şey var mı? Bu satırlar boyunca bir öneri, .d dosyalarını geçici bir adla üretmek ve dosya başına doğru adla kopyalayan ayrı bir derleme sonrası adımına sahip olmaktır.

cevap

6

Genel olarak, GNU make çoklu çıkışlı hedefleri desteklemiyor. Bununla birlikte, bu kuralın bir istisnası vardır: örüntü kuralları. Makefile'nizi nesne dosyalarını oluşturmak için desen kuralları kullanacak şekilde yapılandırabilirseniz, hedeflerinize ulaşmanız mümkün olabilir. Örneğin: "hata" kuralda tespit edildiğinde

.DELETE_ON_ERROR: 

all: foo.o 

%.o %.d: %.c 
    @touch $*.d 
    @touch $*.o 
    @exit 1 

Sen .d ve .o dosyası hem silinir, bu makefile ile göreceksiniz. Bu yaklaşımın avantajı, .d dosyasının nasıl oluşturulacağını ve hangi kuralı üreteceğini açıklayarak bağımlılık grafiğini daha doğru bir şekilde ifade etmesidir.

Alternatif olarak, bu durumda ortak bir paradigma önerdiğiniz gibi: GCC'nin .d dosyasını geçici bir dosya adına oluşturması ve yalnızca GCC komutunun başarıyla tamamlanmasından sonra yerine taşınması. Genellikle bu kabuğun bir hile ile gerçekleştirilir: Burada "sihirli" hile

all: foo.o 

%.o: %.c 
    gcc -o [email protected] -MMD -MF $(basename [email protected]).d.tmp -c $< \ 
     && mv $(basename [email protected]).d.tmp $(basename [email protected]).d 

, derleme bir yan etkisi olarak bağımlılık dosyası oluşturur GCC bayrakları -MMD kullanımı ve -MF hangi Bağımlılık dosyasının çıktı adını belirtmenize izin verir; ve cmd1 && cmd2 sözdiziminin kabuk kullanması,başarılı bir şekilde çıkarsa, kabuğun yalnızca cmd2'u çalıştırmasına neden olur.

+0

".DELETE_ON_ERROR:" makefile'nin en üstündeki tüm geçici dosyalarımızdan kurtulmama izin verin. Teşekkürler! –

+0

"% .o:% .c" desen kuralının tarifi için mv'yi ikinci satır olarak ayarlamanızı öneririm.Davranışta bir değişiklik görmüyorum ya da '&&' harfini ilk satıra koymak için kullanmanın yararı yok. –

+0

@RichardPerrin Eğer gmake '-i' (hataları göz ardı et) seçeneği ile çağrılırsa, teklifiniz yanlış davranış üretecektir. Bu durumda, sürümünüz 'mv' komutunu çalıştırır, orijinalim yüklenmezken' gcc'de bir hata olup olmadığına bakar. –

-1

Eric'in örneklerinin düzgün çalışması için elimden geleni yapıyorum. GCC (sürüm 4.4) -MM anahtarını geçtiğinizde hiçbir şey derlemez, böylece bir seferde .d derleyip yazabilirsiniz gibi görünmüyor. İşte ne yaptım:

%.o: %.c 
    @rm -f [email protected] $(patsubst %.o,%.d,[email protected]) 
    gcc -c $< -o [email protected] 
    @$(CXX) -MM -MG > $(patsubst %.o,%.d,[email protected]) 

Varolan .d dosyasını, ikinci komut, gerçek derleme adımı, başarılı olursa yenisi yalnızca yürütülür üretir üçüncü çizgiyi silerek başlar (Eric'in & & hüner gerekli değildir, bunu otomatik olarak yapar). Herhangi bir nedenle, derleme başarısız olursa varolan bir .o dosyası otomatik olarak silinmez, ancak [email protected] ilk rm ekleyerek kolayca çözüldü.

+0

Doğru, gcc, yalnızca '-MM' belirtirseniz aslında dosyayı derlemez. Orijinal cevabımda açıklandığı gibi '-MF'yi de kullanmalısınız. –

+0

@Eric -MF anahtarını da ekledim, ancak önişlemci gcc'nin derleyici bölümüne hiçbir çıkış göndermiyor gibi görünüyor, bu yüzden sıfır bayt nesne dosyasıyla sonlandırıyorum ... – Wim

+0

Üzgünüz, hata yaptım: -MMD'yi değil, -MM'yi istiyorum. Orijinal cevabı da düzelttim. –