Bir makefile'ı bir hedefi yeniden oluşturmaya nasıl zorlarsınız?


184

Oluşturup sonra başka bir makefile çağıran bir makefile var. Bu makefile, işi yapan daha fazla makefile çağırdığından, gerçekten değişmez. Böylece projenin inşa edildiğini ve güncel olduğunu düşünüyor.

dnetdev11 ~ # make
make: `release' is up to date.

Makefile'ı hedefi yeniden oluşturmaya nasıl zorlarım?

clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean


build = svn up ~/xxx                                                       \
        $(clean)                                                                \
        ~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace        \
        $(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1)                    \


release:
        $(build )

debug:
        $(build DEBUG=1)

clean:
        $(clean)

install:
        cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
        cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib

Not: Masumları korumak için isimler kaldırıldı

Düzenleme: Son Sabit sürüm:

clean = $(MAKE) -f xxx_compile.workspace.mak clean;


build = svn up;                                         \
        $(clean)                                        \
        ./cbp2mak/cbp2mak -C . xxx_compile.workspace;   \
        $(MAKE) -f xxx_compile.workspace.mak    $(1);   \


.PHONY: release debug clean install

release:
        $(call build,)

debug:
        $(call build,DEBUG=1)

clean:
        $(clean)

install:
        cp ./source/xxx_utillity/release/xxx_util /usr/bin
        cp ./dlls/Release/xxxcore.so /usr/lib

Lodle, bu sık ziyaret edilen bir soru olduğundan, soruyu daha modern olacak şekilde düzenlemek ister misiniz? (Görünüşe göre .PHONYtek probleminiz değildi ve çözümü soruya gerçekten düzenlememeniz gerekiyor, ya da en azından artık değil.)
Keith M

Yanıtlar:


23

Bir veya daha fazla hedefinizin sahte olduğunu beyan edebilirsiniz .

Sahte hedef, gerçekte bir dosyanın adı olmayan hedeftir; bunun yerine, açık bir istekte bulunduğunuzda bir tarifin yürütülmesi sadece bir addır. Sahte bir hedef kullanmanın iki nedeni vardır: aynı ada sahip bir dosyayla çakışmadan kaçınmak ve performansı artırmak için.

...

Sahte bir hedef, gerçek bir hedef dosyanın önkoşulu olmamalıdır; öyleyse, tarifi bu dosyayı her güncellemeye gittiğinde çalıştırılacaktır. Sahte bir hedef hiçbir zaman gerçek bir hedefin önkoşulu olmadığı sürece, sahte hedef tarifi yalnızca sahte hedef belirtilen bir hedef olduğunda yürütülecektir


68
Bu cevap, "kabul edilmiş" ve yüksek oranda "kaldırılmış" olmakla birlikte, gerçekten sınır dışıdır. Birincisi, "hedefleri sahte olarak ilan et" diyor, sonra "sahte hedef gerçekten bir dosyanın adı değil" diyor. Hedefiniz bir dosyaysa, bu cevaptaki bir çelişkidir. İkincisi, "sahte hedef gerçek bir ön koşul olmamalı" diyor - peki, ya öyleyse? Orijinal soru, olup olmadığını belirtmedi. Doğru cevap, olduğunu değil ilan etmek için sahte olma hedefleri, daha ziyade, ilave bir düzmece hedefini beyan ve sonra, bu konuda, sen yeniden istediğiniz hedeflere bağlıdır.
Mark Galeck

2
@MarkGaleck. Yanıt, "Sahte hedef, gerçekte bir dosyanın adı olmayan bir hedeftir" ifadesini verdiğinde, doğrudan gcc make manual'dan alıntı yapar. Kesinlikle doğru.
drlolly

"Hedef", :yalnızca oluşturmak istediğiniz sonucu değil (örneğin ikili dosyanız) iki nokta üst üste işaretinin solundaki metni ifade eden bir Marka terimidir . Soruda, release, debug, clean, ve installyap hedefler değildir xxx_utilya xxxcore.soveya başka bir şey.
Keith M

728

-BÜlkenin uzun şeklidir marka geçin --always-make, söyler makegöz ardı damgaları ve öngörülen hedefler haline. Bu, make'i kullanma amacını yenebilir, ancak ihtiyacınız olan şey olabilir.


4
@MarkKCowan Tamamen katılıyorum! Bu seçenekler tam olarak aradığım şey, Dave'in önerdiği gibi bazı geçici çözüm kesmek değil.
Maarten Bamelis

8
Bu yaklaşımdaki uyarı, çok fazla şey inşa etmesidir. Özellikle autotools ile ben yapılandırmak rerunning gördüm .. LD_PRELOAD tabanlı bir çözüm inşa edilebilir diliyorum !!
vrdhn

evet, hatta istemediğiniz dosyaları yeniden yazabilir! bağımlılıklarda görünen ve yeniden inşa ve üzerine yazılan küresel sistem kütüphaneleri gibi ...
Julio Guerra

18

Bir Sun el kitabında belgelenmiş olan bir püf noktası make(var olmayan) bir hedef '.FORCE' kullanmaktır. Şunları içeren bir dosya, force.mk oluşturarak bunu yapabilirsiniz:

.FORCE:
$(FORCE_DEPS): .FORCE

Ardından, mevcut makefile'ınızın çağrıldığını varsayarak makefileşunları çalıştırabilirsiniz:

make FORCE_DEPS=release -f force.mk -f makefile release

Dan beri .FORCE mevcut değil, buna bağlı şey tarih ve yeniden inşa çıkacak.

Bütün bunlar herhangi bir sürümü ile çalışacaktır make; Linux'ta GNU Make'a sahipsiniz ve bu nedenle .PHONY hedefini tartışıldığı gibi kullanabilirsiniz.

Ayrıca, makesürümün neden güncel olduğunu düşündüğü de dikkate alınmalıdır. Bunun nedeni touch release, yürütülen komutlar arasında bir komut olması olabilir ; bunun nedeni, varolan ve bağımlılığı olmayan ve bu nedenle güncel olan 'release' adlı bir dosya veya dizin olması olabilir. O zaman asıl sebep var ...


14

Başka biri önerdi .PHONY kesinlikle doğru. .PHONY, giriş ve çıkış arasındaki tarih karşılaştırmasının geçersiz olduğu herhangi bir kural için kullanılmalıdır. Formun herhangi bir hedefi olmadığından, output: inputTÜMÜ için .PHONY kullanmalısınız!

Bütün bunlar, muhtemelen çeşitli dosya adları için makefile üst kısmında bazı değişkenler tanımlamak ve hem giriş hem de çıkış bölümleri olan gerçek make kuralları tanımlamak gerekir, böylece make avantajlarını kullanabilirsiniz, yani sadece gerçekten derlemek copmile için gerekli olan şeyler!

Düzenle: örnek eklendi. Test edilmedi, ama böyle yapıyorsun.

.PHONY: clean    
clean:
    $(clean)

1
Bana bir örnek gösterebilirsen iyi olur. Atm im sadece iş baraj şey almaya çalışırken kesmek hack: P
Lodle

1
.PHONYHedefin yeri önemli değil. İçinde herhangi bir yerde olabilir Makefile.
Adrian W

5

Doğru hatırlıyorsam, 'make' bir hedefin güncel olup olmadığını belirlemek için zaman damgalarını (dosya değiştirme zamanı) kullanır. Yeniden oluşturmayı zorlamanın yaygın bir yolu, 'dokunma' komutunu kullanarak bu zaman damgasını güncellemektir. Hedefinizi birinin (belki de bu alt markalardan birinin) zaman damgasını güncellemek için makefile'ınızda 'dokunma'yı çağırmayı deneyebilirsiniz, bu da Make'ı bu komutu yürütmeye zorlayabilir.


5

Bu basit teknik, zorlama istenmediğinde marka dosyasının normal çalışmasına izin verecektir. Dosyanızın sonunda kuvvet adı verilen yeni bir hedef oluşturun . Kuvvet hedef varsayılan hedef bağlı olduğu bir dosya dokunacaktır. Aşağıdaki örnekte touch myprogram.cpp dosyasını ekledim . Ayrıca için yinelemeli çağrı ilave yapmak . Bu, her kuvvet uyguladığınızda varsayılan hedefin oluşturulmasına neden olur .

yourProgram: yourProgram.cpp
       g++ -o yourProgram yourProgram.cpp 

force:
       touch yourProgram.cpp
       make

Asla makebir Makefile içinde kullanmamalısınız . $(MAKE)Bunun yerine kullanın .
Benjamin Crawford Ctrl-Alt-Tut

3

Bunu denedim ve benim için çalıştı

bu hatları Makefile'a ekle

clean:
    rm *.o output

new: clean
    $(MAKE)     #use variable $(MAKE) instead of make to get recursive make calls

kaydet ve şimdi ara

make new 

ve her şeyi tekrar derleyecek

Ne oldu?

1) 'yeni' çağrılar temiz. '.o' uzantılı tüm nesne dosyalarını silen 'clean' do 'rm'.

2) 'yeni' çağrılar 'yapmak'. 'make', '.o' dosyası olmadığını görerek tüm '.o' dosyalarını yeniden oluşturur. bağlayıcı tüm .o dosyası int bir yürütülebilir çıktı bağlar

İyi şanslar


1
İçin tarifi de newiyi kullanım $(MAKE)dahamake
Basile Starynkevitch

1

Miller'ın Özyinelemeli Zarar Görmesini Sağlamak için aramaktan kaçınmalısınız$(MAKE) ! Gösterirseniz, zararsızdır, çünkü bu gerçekten bir makefile değil, sadece bir paket betiği değildir, Shell'de de yazılmış olabilir. Ancak daha derin özyineleme seviyelerinde böyle devam ettiğinizi söylüyorsunuz, bu yüzden muhtemelen bu göz açıcı denemede gösterilen sorunlarla karşılaştınız.

Tabii ki GNU ile kaçınmak zorlaşıyor. Ve bu sorunun farkında olsalar da, bu işleri yapmanın belgelenmiş yoludur.

OTOH, makepp bu soruna bir çözüm olarak oluşturuldu. Dosyalarınızı her bir dizin düzeyinde yazabilirsiniz, ancak hepsi projenizin tam görünümünde bir araya getirilir.

Ancak eski makyaj dosyaları tekrar tekrar yazılır. Bu nedenle $(MAKE), alt istekleri ana makepp işlemine geri döndürmekten başka bir şey yapmayan bir çözüm var . Sadece alt yapımlarınız arasında gereksiz veya daha kötü, çelişkili şeyler yaparsanız, talep etmelisiniz --traditional-recursive-make(elbette makepp'in bu avantajını bozar). Diğer markalarınızı bilmiyorum, ancak temiz yazılmışlarsa, makepp ile, burada başkaları tarafından önerilen herhangi bir saldırıya gerek kalmadan gerekli yeniden yapılandırmalar otomatik olarak gerçekleşmelidir.


Soruya cevap vermedi: ana noktaya teğet ve bir cevap değil bir yorum olmalı.
flungo

Belki yeterince açık değildim. İle makepp bütün bu sarıcı makefile gerekli değildir. Kesin bağımlılıkları bilerek (hepsi, sadece bundan sonra listelenenler değil :), gerektiğinde her zaman yeniden inşa edilecektir.
Daniel

1

Zaten başarıyla derlediğiniz çıktılardan herhangi birini korumanıza gerek yoksa

nmake /A 

hepsini yeniden inşa eder


0

Aslında hedefin ne olduğuna bağlıdır. Sahte bir hedefse (yani, hedef bir dosyayla ilişkili DEĞİLSE) .PHONY olarak bildirmeniz gerekir.

Ancak hedef sahte bir hedef değilse, ancak bir nedenden ötürü yeniden oluşturmak istiyorsanız (bir örnek, __TIME__ önişleme makrosunu kullandığınız durumdur), burada yanıtlarda açıklanan FORCE şemasını kullanmalısınız.



0

Zaten bahsedildi, ancak kullanmaya ekleyebileceğimi düşündüm touch

touchDerlenecek tüm kaynak dosyalarınız varsa , touchkomut dosyanın zaman damgalarını sistem saatine değiştirir.touch komut idam edildi.

Kaynak dosya timstamp makebir dosyanın değiştiğini "bilmek" için kullanılan ve yeniden derlenmesi gereken

Örneğin: Proje bir c ++ projesiyse, yapın touch *.cpp, sonra maketekrar çalıştırın ve make tüm projeyi yeniden derlemelidir.


0

Abernier'in işaret ettiği gibi, GNU marka kılavuzunda bir hedefin yeniden inşasını zorlamak için 'sahte' bir hedef kullanan önerilen bir çözüm var:

clean: FORCE
        rm $(objects)
FORCE: ; 

Bu, diğer bağımlılıklardan bağımsız olarak temiz çalışır.

Noktalı virgülü kılavuza ekledim, aksi takdirde boş bir satır gerekli.


-1

Linux sistemimde (Centos 6.2), kural aslında hedefle eşleşen bir dosya oluşturduğunda, hedef .PHONY bildirimi ile FORCE üzerinde sahte bir bağımlılık oluşturma arasında önemli bir fark vardır. Dosyanın her seferinde yeniden oluşturulması gerektiğinde, hem dosyadaki sahte bağımlılık FORCE hem de sahte bağımlılık için .PHONY gerekir.

yanlış:

date > $@

sağ:

FORCE
    date > $@
FORCE:
    .PHONY: FORCE

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.