Soru Makefile'de .PHONY'nin amacı nedir?


Nedir .PHONY Makefile'de mi demek istiyorsun? Ben geçtim buama bu çok karmaşık.

Birisi bana basit terimlerle açıklayabilir mi?


1211
2018-01-27 09:08


Menşei




Cevaplar:


Varsayılan olarak, Makefile hedefleri "dosya hedefleri" dir - bunlar başka dosyalardan dosyalar oluşturmak için kullanılır. Hedefin bir dosya olduğunu varsayar ve bu da Makefiles yazısını göreceli olarak kolaylaştırır:

foo: bar
  create_one_from_the_other foo bar

Ancak, bazen Makefile'nizin dosya sisteminde fiziksel dosyaları temsil etmeyen komutları çalıştırmasını istersiniz. Bunun iyi örnekleri, "temiz" ve "tüm" ortak hedeflerdir. Durum böyle değil, ama sen Mayıs ayı potansiyel olarak adlandırılmış bir dosya var clean ana dizininizde. Böyle bir durumda Make varsayılan olarak çünkü şaşkın olacaktır clean hedef bu dosyayla ilişkilendirilir ve Make, yalnızca dosya bağımlılıklarına göre güncel görünmediğinde çalıştırılır.

Bu özel hedefler denir sahte ve açıkça, Dosyaları ile ilişkili olmadıklarını söyleyebilirsiniz.

.PHONY: clean
clean:
  rm -rf *.o

şimdi make clean adında bir dosya varsa bile beklendiği gibi çalışacak clean.

Make açısından, sahte bir hedef sadece her zaman güncel olmayan bir hedeftir, bu yüzden ne zaman istersen make <phony_target>, dosya sisteminin durumundan bağımsız olarak çalışır. Bazı ortak make genellikle sahte olan hedefler şunlardır: all, install, clean, distclean, TAGS, info, check.


1348
2018-01-27 09:11



@eSKay: 'neden' sahte 'deniyor?' - Çünkü gerçek bir hedef değil. Yani, hedef ad bu hedefin komutları tarafından üretilen bir dosya değildir. - Bernard
@Lazer: Yerli bir ingilizce konuşmacısı olup olmadığını bilmiyorum. Değilim. Sahte kelimesi, kulağa hoş geldiği anlamına gelmez. en.wiktionary.org/wiki/phony diyor ki: Sahte; sahte; yanıltıcı bir görünüme sahip. - Bahbar
Bu cevap tam olarak tamamlanmamıştır - bununla bağlantılı öğreticide ele alınabilir. .PHONY, hedefiniz ne olursa olsun topolojik çeşitliliğin bir parçasıysa, bir Makefile'de bir etiket / dosyaya zorlar. Diğer bir deyişle, sahte olan bir 'cleanup:' etiketiniz varsa ve yükleme etiketiniz bir önkoşul olarak temizleme ile tanımlanmışsa, yani 'install: cleanup', temizleme her zaman Makefile 'kur' oluşturmaya çalıştığında çalıştırılmalıdır. Bu, başarılı olup olmadıklarına bakılmaksızın her zaman atılmasını istediğiniz adımlar için yararlıdır - zaman damgalarını yok sayar ve zorlar. - synthesizerpatel
@synthesizerpatel Yani, eğer a: b, b: c, c: ph nerede ph olduğu .PHONYsen sor a, ve b güncel, yorumunuz şunu ima ediyor ph çalıştırılacak. Aslında, hiçbiri a, b, c Aslında hiç güncel olamaz. - Evgeni Sergeev
Görevle aynı ada sahip bir dosyanız olmadığı sürece .PHONY kullanmanıza gerek olmadığını unutmayın. Görev her zaman her zaman yürütülür ve Makefile daha okunabilir olacaktır. - Alkaline


Var olduğunu varsayalım install Makefile'de çok yaygın olan hedef. Yaparsan değil kullanım .PHONYve adında bir dosya install Makefile ile aynı dizinde bulunur, sonra make install yapacağım hiçbir şey değil. Bunun nedeni, kuralı, "adlandırılmış dosyayı oluşturmak için bu türden bir reçete yürütmek" anlamına gelir. install". Dosya zaten orada olduğundan ve bağımlılıkları değişmediğinden hiçbir şey yapılmayacak.

Ancak eğer install PHONY'yi hedefle, make aracının hedefin kurgusal olduğunu ve yapmanın gerçek dosyayı oluşturmasını beklememesi gerektiğini söyler. Bu yüzden bu olup olmadığını kontrol etmez install dosya var, yani: a) dosya mevcutsa ve b) eklenmesi durumunda davranışı değiştirilmez stat() çağrılmayacak.

Genellikle Makefile'deki hedef isimle aynı ada sahip bir çıktı dosyası üretmeyen tüm hedefler PHONY olmalıdır. Bu genellikle şunları içerir: all, install, clean, distclean, ve bunun gibi.


636
2017-08-26 10:54



@PineappleUndertheSea Kabul edilen cevap başlangıçtaki değersizlik seviyesinden önemli ölçüde geliştirildi ve şimdi bu kadar iyi. Yorumunuzu anlamak için gözden geçirme geçmişini incelemek zorunda kaldım. - Mark Amery
Bu benim kod tabanımdaki 'install' veya benzeri adlara sahip bir dosyaya sahip olmayacağından, biraz anlamsız görünüyor. Çoğu dosya bir dosya uzantısına sahip olacak ve dosya uzantısı olmayan dosyalar genellikle "README" gibi tüm büyük harflerde. Daha sonra, 'install.sh' yerine 'install' adında bir bash betiğiniz varsa, kötü bir zaman geçireceksiniz. - Jason Tu
@JasonTu Bu mutlaka doğru değildir. Bash komut dosyası kuralları, .sh veya .bash Ana programa sahip oldukları gibi çalışan "programlar" uzantısı ve dahil ettiğiniz kitaplıklar için bir uzantı ekleme (source mylib.sh). Aslında bu SO sorusuna girdim çünkü Makefile'im ile aynı dizinde bir senaryo vardı install - Kyle
@Kyle Evet, kendimin ne demek istediğinden emin değilim. Kullanıyorum bu günlerde .PHONY her zaman... - Jason Tu
@JasonTu Buradaki çözüm basit: bir zaman makinesi inşa et ve geçmiş benliğinizi "değiştir". Yanınızda bir kürek almanızı öneriyorum, böylece kimse sizin .PHONY sürümü. - Mateen Ulhaq


NOT: Make aracı makefile okur ve bir kuralda ':' sembolünün her iki tarafındaki dosyaların zaman damgalarını kontrol eder.

Örnek

Bir 'test' dizininde aşağıdaki dosyalar bulunur:

prerit@vvdn105:~/test$ ls
hello  hello.c  makefile

Makefile'de bir kural şöyle tanımlanır:

hello:hello.c
    cc hello.c -o hello

Şimdi 'merhaba' dosyasının 'merhaba.c' dosyasından sonra oluşturulan bazı verileri içeren bir metin dosyası olduğunu varsayalım. Bu nedenle 'merhaba' ('merhaba') 'in zamanlama (veya yaratma) zaman damgası' merhaba.c'ninkinden daha yeni olacaktır. Bu yüzden komut satırından 'merhaba' yapalım, şöyle yazdırılır:

make: `hello' is up to date.

Şimdi 'hello.c' dosyasına erişin ve içine kod sözdizimini veya mantığını etkilemeyen ve daha sonra kaydedip çıkılan beyaz boşluklar ekleyin. Şimdi, merhaba.c'nin değişiklik zaman damgası, 'merhaba'dan daha yenidir. Şimdi 'merhaba yap' diye çağırırsanız, komutları şu şekilde çalıştırır:

cc hello.c -o hello

Ve 'merhaba' dosyası (metin dosyası) yeni bir ikili dosya 'merhaba' ile (yukarıdaki derleme komutunun sonucu) üzerine yazılacaktır.

Makefile'de .PHONY'yi kullanırsak

.PHONY:hello

hello:hello.c
    cc hello.c -o hello

ve sonra 'merhaba yap', 'merhaba' isimli pwd'de herhangi bir dosya mevcutsa ve her seferinde komutu yürütürse göz ardı eder.

Şimdi makefile'de hiçbir hedef bağımlılığın bulunmadığını varsayalım:

hello:
    cc hello.c -o hello

ve 'merhaba' dosyası pwd 'testinde zaten mevcut, daha sonra' merhaba yap 'her zaman şöyle görünür:

make: `hello' is up to date.

64
2017-09-30 14:51



Bu sadece yaptığım komutları mantıklı hale getirmekle kalmıyor, aynı zamanda neden oluyor makeBir bütün olarak mantıklı olmak gerekirse, hepsi dosyalarla ilgili! Bu cevap için teşekkür ederim. - Kzqai


.PHONY: install
  • "install" kelimesinin bu dosyada bir dosya adı göstermediği anlamına gelir Makefile;
  • Makefile'nin "yükleme" adlı bir dosyayla ilgisi olmadığı anlamına gelir aynı dizinde.

63
2017-08-25 22:39





Bir dosya adı olmayan bir yapı hedefidir.


34
2018-01-27 16:48





En iyi açıklama GNU kullanım kılavuzunun kendisidir: 4.6 Sahte Hedefler bölümü.

.PHONY make'den biri Özel Yerleşik Hedef İsimleri. İlgilendiğiniz başka hedefler var, bu yüzden bu referansları gözden geçirmeye değer.

Bir .PHONY hedefini göz önünde bulundurmanın zamanı geldiğinde, tarifi kendi tarifini yürütecek   Bu ada sahip bir dosya bulunup bulunmadığına bakılmaksızın koşulsuz olarak    son değişiklik zamanı.

Ayrıca ilginizi çekebilir Standart hedefler gibi all ve clean.


21
2018-04-03 23:49





Fiziksel bir hedef başka bir fiziksel hedefe bağlı olan sahte hedefe bağlı olduğunda, ".PHONY" ifadesinin önemli bir zorlu muamelesi de vardır:

TARGET1 -> PHONY_FORWARDER1 -> PHONY_FORWARDER2 -> TARGET2

TARGET2'yi güncellediyseniz TARGET1'in TARGET1'e göre bayat sayılması gerektiğini, böylece TARGET1'in yeniden oluşturulmasını beklersiniz. Ve gerçekten bu şekilde çalışıyor.

Zor olan bölüm TARGET2 değil TARGET1'e karşı bayat - bu durumda TARGET1'in yeniden oluşturulmasını beklememelisiniz.

Bu şaşırtıcı bir şekilde işe yaramaz çünkü: sahte hedef zaten çalıştı (sahte hedefler normalde yaptığı gibi), bu demektir ki sahte hedef güncellendi. Ve bu yuzden TARGET1, sahte hedefe karşı bayat olarak kabul edilir.

Düşünmek:

all: fileall

fileall: file2 filefwd
    echo file2 file1 >fileall


file2: file2.src
    echo file2.src >file2

file1: file1.src
    echo file1.src >file1
    echo file1.src >>file1

.PHONY: filefwd
.PHONY: filefwd2

filefwd: filefwd2

filefwd2: file1
    @echo "Produced target file1"


prepare:
    echo "Some text 1" >> file1.src
    echo "Some text 2" >> file2.src

Bununla oynayabilirsiniz:

  • önce "kaynak dosyaları" hazırlamak için 'hazırla'
  • bunları güncellemek için belirli dosyalara dokunarak bununla oynayın

Bu fileallun, sahte bir hedef yoluyla dolaylı olarak dosya1'e bağlı olduğunu görebilirsiniz. her zaman Bu bağımlılık nedeniyle yeniden inşa edilir. Bağımlılığı değiştirirseniz fileall itibaren filefwd için fileşimdi fileall her seferinde yeniden inşa edilmez, ancak sadece bağımlı hedeflerden herhangi biri bir dosya olarak ona karşı batarsa.


8
2018-02-11 10:11





Sık sık varsayılan hedefin ateş etmemesini söylemek için kullanırım.

superclean: clean andsomethingelse

blah: superclean

clean:
   @echo clean

%:
   @echo catcher $@

.PHONY: superclean

PHONY olmadan make superclean ateş clean, andsomethingelse, ve catcher superclean; ama PHONY ile, make superclean ateş etmeyecek catcher superclean.

Anlatmak için endişelenmenize gerek yok clean Hedef PHONY, çünkü tamamen sahte değil. Temiz dosyayı asla üretmese de, ateş etme emirleri vardır, bu yüzden nihai bir hedef olduğunu düşünün.

Ancak superclean Hedef gerçekten sahte, bu yüzden yapmak için depsler sağlayan başka bir şey ile onu yığmaya çalışacağız superclean hedef - bu diğer içerir superclean hedefler ve % hedef.

Hiç bir şey söylemediğimizi unutmayın. andsomethingelse veya blahBöylece açıkça yakalayıcıya giderler.

Çıktı şuna benzer:

$ make clean
clean

$ make superclean
clean
catcher andsomethingelse

$ make blah 
clean
catcher andsomethingelse
catcher blah

0
2017-07-08 13:22