$ @ Ve $ <makefile sembolleri ne anlama geliyor?


416
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o:
    $(CC) $(CFLAGS) $< -o $@

Ne $@ve $<tam olarak yapmak?


5
Yukarıdaki bağlantı koptu, işte bir tane daha: gnu.org/software/make/manual/html_node/Automatic-Variables.html
asciz

1
Merhaba bu ".cpp.o:" hedef olarak ne anlama geliyor? (son satırdan önce?).
pseudonym_127

3
".Cpp.o:", ".cpp" den (
.fpp

1
Ben Mohit onun postfile makef inanıyorum aşağıdaki bağlantıda bir yapmak öğretici olduğunu belirtmek gerekir hissediyorum. mrbook.org/blog/tutorials/make
DeepDeadpool

Microsoft , Otomatik Değişkenlerden (MAKE için) daha net olan Dosya Adı Makroları (NMAKE için) olarak adlandırır. Her iki tarafı eğitim amaçlı görmek yararlıdır.
Ivanzinho

Yanıtlar:


502

$@oluşturulan dosyanın adı ve $<ilk önkoşuldur (genellikle kaynak dosyadır). Tüm bu özel değişkenlerin bir listesini GNU Marka kılavuzunda bulabilirsiniz .

Örneğin, aşağıdaki beyanı göz önünde bulundurun:

all: library.cpp main.cpp

Bu durumda:

  • $@ için değerlendirir all
  • $< için değerlendirir library.cpp
  • $^ için değerlendirir library.cpp main.cpp

16
Belirterek It yetmeyecek $@mutlaka bir dosya olma sonunda zorunda değildir, aynı zamanda bir adı olabilir .PHONYhedefe.
Ephemera

Komut satırı seçeneklerine şunu ekleyebilir miyim: $@sname.os gibi birleştirme çıktısı oluşturmak için?
huseyin tugrul buyukisik

4
İlk bağımlılık listeyi temsil eden bir değişken olduğunda dikkatli olun, $ <genişletildikten sonra değerlendirilir. Dolayısıyla, LIST = lib1.cpp lib2.cpp ve tümü: $ {LIST} main.cpp olduğunda, $ <sadece lib1.cpp olarak değerlendirilir. Birkaç yıl önce, bu davranıştan kaynaklanan sonuçta neler olduğunu anlamak için biraz zaman harcadım.
Chan Kim

Genel olarak $ @, hedefin sol tarafına atıfta bulunur:
Deepak Kiran

78

$@Ve $<denir otomatik değişkenler . Değişken $@, oluşturulan dosyanın adını (yani hedef) ve $<çıktı dosyasını oluşturmak için gereken ilk önkoşulu temsil eder.
Örneğin:

hello.o: hello.c hello.h
         gcc -c $< -o $@

İşte hello.oçıktı dosyası. $@Genişleyen budur . İlk bağımlılık hello.c. $<Genişleyen budur .

-cBayrağı üretir .odosyası; man gccdaha ayrıntılı bir açıklama için bakınız . Oluşturulacak -oçıktı dosyasını belirtir.

Daha fazla bilgi için Linux Makefiles hakkındaki bu makaleyi okuyabilirsiniz .

Ayrıca, GNU makekılavuzlarını da kontrol edebilirsiniz . Makefiles yapmayı ve hata ayıklamayı kolaylaştırır.

Bu komutu çalıştırırsanız, makefile veritabanının çıktısını alır:

make -p 

1
Cevabınız kulağa $<genişleyecek hello.c hello.h(her ikisi). Lütfen açıkla.
Dr Beco

Evet, hello.c ve hello.h içerecektir
becerikli

19
$<sadece ilk öğedir. Tümünü dahil etmek için kullanın $^.
Dr Beco

1
Dr Beco haklı. Yazar cevabını değiştirmelidir.
PT Huynh

67

Gönderen GNU Make, 3. Baskı, s ile Projeleri yönetme. 16 ( GNU Ücretsiz Dokümantasyon Lisansı altındadır ):

Otomatik değişkenlermake bir kural eşleştikten sonra tarafından ayarlanır . Hedef ve önkoşul listelerindeki öğelere erişim sağlar, böylece dosya adlarını açıkça belirtmeniz gerekmez. Kod çoğaltmasından kaçınmak için çok yararlıdırlar, ancak daha genel kalıp kuralları tanımlarken kritiktirler.

Yedi “çekirdek” otomatik değişken vardır:

  • $@: Hedefi temsil eden dosya adı.

  • $%: Bir arşiv üyesi belirtiminin dosya adı öğesi.

  • $<: İlk önkoşulun dosya adı.

  • $?: Boşluklarla ayrılmış, hedeften daha yeni olan tüm ön koşulların adları.

  • $^: Boşluklarla ayrılmış tüm ön koşulların dosya adları. Bu listede yinelenen dosya adları vardır, çünkü derleme, kopyalama vb. Gibi birçok kullanım için çoğaltmalar istenmez.

  • $+: Benzer şekilde $^, bu $+yinelenenleri içermesi dışında boşluklarla ayrılmış tüm önkoşulların adlarıdır . Bu değişken, yinelenen değerlerin anlamı olan bağlayıcılara argümanlar gibi belirli durumlar için oluşturuldu.

  • $*: Hedef dosya adının gövdesi. Bir kök tipik olarak soneki olmayan bir dosya adıdır. Desen kurallarının dışında kullanılması önerilmez.

Ayrıca, yukarıdaki değişkenlerin her birinin diğer markalarla uyumluluk için iki çeşidi vardır. Bir değişken, değerin yalnızca dizin bölümünü döndürür. Bu, sembolün bir “D” ekleme ile gösterilir $(@D), $(<D)vb varyantının getiri değerin sadece dosya bölümü. Bu, sembole “F” ekleyerek belirtilir $(@F), $(<F)bu varyant isimleri parantez içine alınmalıdır birden fazla karakter uzunluğunda ve böylece olduklarını vs. Not. GNU make, dir ve notdir fonksiyonları ile daha okunabilir bir alternatif sunar.


37

$@Ve $<özel makrolardır.

Nerede:

$@ hedefin dosya adıdır.

$< ilk bağımlılığın adıdır.


19

Makefil'ı helloherhangi biri halinde yürütülebilir main.cpp, hello.cpp, factorial.cppdeğişti. Bu spesifikasyonu elde etmek için mümkün olan en küçük Makefile olabilir:

hello: main.cpp hello.cpp factorial.cpp
    g++ -o hello main.cpp hello.cpp factorial.cpp
  • pro: okunması çok kolay
  • con: bakım kabusu, C ++ bağımlılıklarının çoğaltılması
  • con: verimlilik sorunu, biz sadece bir değiştirilse bile tüm C ++ yeniden derlemek

Yukarıdakileri iyileştirmek için yalnızca düzenlenen C ++ dosyalarını derliyoruz. Ardından, ortaya çıkan nesne dosyalarını birbirine bağlarız.

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

main.o: main.cpp
    g++ -c main.cpp

hello.o: hello.cpp
    g++ -c hello.cpp

factorial.o: factorial.cpp
    g++ -c factorial.cpp
  • pro: verimlilik sorununu düzeltir
  • con: yeni bakım kabusu, nesne dosyaları kurallarında potansiyel yazım hatası

Bunu geliştirmek için tüm nesne dosyası kurallarını tek bir .cpp.okuralla değiştirebiliriz:

OBJECTS=main.o hello.o factorial.o

hello: $(OBJECTS)
    g++ -o hello $(OBJECTS)

.cpp.o:
    g++ -c $< -o $@
  • pro: kısa bir makefile sahip olmak, okumak biraz kolay

İşte .cpp.okural oluşturmak için nasıl tanımlar anyfile.odan anyfile.cpp.

  • $< ilk bağımlılıkla eşleşir, bu durumda, anyfile.cpp
  • $@bu durumda hedefle eşleşir anyfile.o.

Makefile'de bulunan diğer değişiklikler şunlardır:

  • Derleyicileri g ++ 'dan herhangi bir C ++ derleyicisine değiştirmeyi kolaylaştırır.
  • Derleyici seçeneklerini değiştirmeyi kolaylaştırır.
  • Bağlayıcı seçeneklerini değiştirmeyi kolaylaştırır.
  • C ++ kaynak dosyalarını ve çıktısını değiştirmeyi kolaylaştırır.
  • Uygulamanızı oluşturmaya çalışmadan önce tüm kaynak dosyalarınızın var olduğundan emin olmak için hızlı bir denetim görevi gören varsayılan bir 'all' kuralı eklendi.

1

kaynakları derlemek, ancak farklı bir dizinde nesneleri kullanmak istiyorsanız:

Yapman lazım :

gcc -c -o <obj/1.o> <srcs/1.c> <obj/2.o> <srcs/2.c> ...

ancak makroların çoğunda sonuç tüm nesneler ve ardından tüm kaynaklar tarafından takip edilir:

gcc -c -o <all OBJ path> <all SRC path>

böylece bu hiçbir şeyi derlemeyecek ^^ ve nesne dosyalarınızı farklı bir dizine koyamayacaksınız :(

çözüm bu özel makroları kullanmaktır

$@ $<

bu, SRC'deki (src / file.c) her .c dosyası için bir .o dosyası (obj / file.o) oluşturur.

$(OBJ):$(SRC)
   gcc -c -o $@ $< $(HEADERS) $(FLAGS)

anlamı :

    $@ = $(OBJ)
    $< = $(SRC)

ancak tüm OBJ hatlarının INSTEAD ve ardından tüm SRC hatlarının satır satır satırları


Acaba, "siz" yerine "u" yazarak kazandığınız bu kadar zamanla ne yapıyorsunuz?
Ivanzinho
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.