Jawaban:
Secara default, target Makefile adalah "target file" - target tersebut digunakan untuk membuat file dari file lain. Anggap targetnya adalah file, dan ini membuat penulisan Makefiles relatif mudah:
foo: bar
create_one_from_the_other foo bar
Namun, kadang-kadang Anda ingin Makefile Anda menjalankan perintah yang tidak mewakili file fisik dalam sistem file. Contoh yang baik untuk ini adalah target umum "bersih" dan "semua". Kemungkinannya bukan ini masalahnya, tetapi Anda mungkin berpotensi memiliki nama file clean
di direktori utama Anda. Dalam kasus seperti itu, Make akan menjadi bingung karena secara default clean
target akan dikaitkan dengan file ini dan Make hanya akan menjalankannya ketika file tersebut tampaknya tidak mutakhir sehubungan dengan dependensinya.
Target khusus ini disebut palsu dan Anda dapat secara eksplisit memberi tahu Make mereka tidak terkait dengan file, misalnya:
.PHONY: clean
clean:
rm -rf *.o
Sekarang make clean
akan berjalan seperti yang diharapkan bahkan jika Anda memiliki file bernama clean
.
Dalam hal Make, target palsu hanyalah target yang selalu kedaluwarsa, jadi setiap kali Anda bertanya make <phony_target>
, itu akan berjalan, terlepas dari keadaan sistem file. Beberapa umum make
target yang sering palsu adalah: all
, install
, clean
, distclean
, TAGS
, info
, check
.
Mari kita asumsikan Anda memiliki install
target, yang sangat umum di makefile. Jika Anda tidak menggunakan .PHONY
, dan file bernama install
ada di direktori yang sama dengan Makefile, maka make install
tidak akan melakukan apa pun . Ini karena Make menafsirkan aturan berarti "menjalankan resep ini-dan-itu untuk membuat file bernama install
". Karena file sudah ada di sana, dan dependensinya tidak berubah, tidak ada yang akan dilakukan.
Namun jika Anda membuat install
target PHONY, itu akan memberi tahu alat make bahwa target tersebut fiktif, dan yang membuat tidak boleh mengharapkannya untuk membuat file yang sebenarnya. Karenanya ia tidak akan memeriksa apakah install
file itu ada, artinya: a) perilakunya tidak akan diubah jika file itu ada dan b) ekstra stat()
tidak akan dipanggil.
Secara umum semua target di Makefile Anda yang tidak menghasilkan file output dengan nama yang sama dengan nama target harus PHONY. Hal ini biasanya meliputi all
, install
, clean
, distclean
, dan sebagainya.
.sh
atau .bash
ekstensi untuk "program" yang berjalan seperti mereka memiliki fungsi utama dan cadangan menambahkan ekstensi untuk perpustakaan yang Anda sertakan ( source mylib.sh
). Bahkan, saya sampai pada pertanyaan SO ini karena saya punya skrip di direktori yang sama dengan Makefile saya dipanggilinstall
.PHONY
semua waktu ...
.PHONY
versinya.
CATATAN : Alat make membaca makefile dan memeriksa stempel waktu modifikasi file di kedua sisi simbol ':' dalam aturan.
Dalam direktori 'test' file berikut ada:
prerit@vvdn105:~/test$ ls
hello hello.c makefile
Dalam makefile aturan didefinisikan sebagai berikut:
hello:hello.c
cc hello.c -o hello
Sekarang asumsikan file 'halo' adalah file teks yang berisi beberapa data, yang dibuat setelah file 'hello.c'. Jadi cap waktu modifikasi (atau kreasi) 'halo' akan lebih baru daripada 'hello.c'. Jadi ketika kita akan memanggil 'make hello' dari baris perintah, itu akan dicetak sebagai:
make: `hello' is up to date.
Sekarang akses file 'hello.c' dan letakkan beberapa spasi putih di dalamnya, yang tidak memengaruhi sintaksis atau logika kode lalu simpan dan keluar. Sekarang cap waktu modifikasi hello.c lebih baru daripada 'hello'. Sekarang jika Anda memanggil 'make hello', itu akan menjalankan perintah sebagai:
cc hello.c -o hello
Dan file 'halo' (file teks) akan ditimpa dengan file biner baru 'halo' (hasil dari perintah kompilasi di atas).
Jika kita menggunakan .PHONY di makefile sebagai berikut:
.PHONY:hello
hello:hello.c
cc hello.c -o hello
dan kemudian memanggil 'make hello', itu akan mengabaikan semua file yang ada di pwd 'test' dan menjalankan perintah setiap waktu.
Sekarang anggaplah, bahwa target 'halo' tidak memiliki ketergantungan menyatakan:
hello:
cc hello.c -o hello
dan file 'halo' sudah ada di pwd 'test', maka 'make hello' akan selalu ditampilkan sebagai:
make: `hello' is up to date.
make
secara keseluruhan masuk akal, ini semua tentang file! Terima kasih atas jawaban ini.
.PHONY: install
Penjelasan terbaik adalah GNU make manual sendiri: 4,6 bagian Target Phony .
.PHONY
adalah salah satu dari Nama Target Built-in Khusus make . Ada target lain yang mungkin Anda minati, jadi ada baiknya membaca sekilas referensi ini.
Ketika tiba saatnya untuk mempertimbangkan target .PHONY, make akan menjalankan resepnya tanpa syarat, terlepas dari apakah file dengan nama itu ada atau berapa waktu modifikasi terakhirnya.
Anda mungkin juga tertarik dengan Target Standar make seperti all
dan clean
.
Ada juga satu trik rumit yang penting dari ".PHONY" - ketika target fisik bergantung pada target palsu yang tergantung pada target fisik lain:
TARGET1 -> PHONY_FORWARDER1 -> PHONY_FORWARDER2 -> TARGET2
Anda hanya berharap bahwa jika Anda memperbarui TARGET2, maka TARGET1 harus dianggap basi terhadap TARGET1, sehingga TARGET1 harus dibangun kembali. Dan itu benar-benar bekerja seperti ini .
Bagian yang sulit adalah ketika TARGET2 tidak basi terhadap TARGET1 - dalam hal ini Anda harus mengharapkan bahwa TARGET1 tidak boleh dibangun kembali.
Ini mengejutkan tidak berfungsi karena: target palsu dijalankan pula (seperti yang biasanya dilakukan target palsu) , yang berarti bahwa target palsu dianggap diperbarui . Dan karena itu TARGET1 dianggap basi terhadap target palsu .
Mempertimbangkan:
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
Anda dapat bermain-main dengan ini:
Anda dapat melihat bahwa file semua tergantung pada file1 secara tidak langsung melalui target palsu - tetapi selalu dibangun kembali karena ketergantungan ini. Jika Anda mengubah ketergantungan dalam fileall
dari filefwd
menjadi file
, sekarang fileall
tidak bisa dibangun kembali setiap kali, tetapi hanya ketika salah satu dari target bergantung basi terhadap itu sebagai file.
Target khusus .PHONY:
memungkinkan untuk mendeklarasikan target palsu, sehinggamake
tidak akan memeriksanya sebagai nama file yang sebenarnya: itu akan berfungsi sepanjang waktu walaupun file tersebut masih ada.
Anda dapat menempatkan beberapa .PHONY:
di Makefile
:
.PHONY: all
all : prog1 prog2
...
.PHONY: clean distclean
clean :
...
distclean :
...
Ada cara lain untuk mendeklarasikan target palsu: sederhananya '::'
all :: prog1 prog2
...
clean ::
...
distclean ::
...
'::' memiliki arti khusus: target palsu ditambah mereka dapat muncul beberapa kali:
clean ::
rm file1
...
clean ::
rm file2
Blok perintah akan dipanggil satu demi satu.
Saya sering menggunakannya untuk memberi tahu target default untuk tidak menembak.
superclean: clean andsomethingelse
blah: superclean
clean:
@echo clean
%:
@echo catcher $@
.PHONY: superclean
Tanpa palsu, make superclean
akan memecat clean
, andsomethingelse
dan catcher superclean
; tetapi dengan PHONY, make superclean
tidak akan memecat catcher superclean
.
Kita tidak perlu khawatir untuk mengatakan bahwa clean
targetnya adalah PHONY, karena itu tidak sepenuhnya palsu. Meskipun tidak pernah menghasilkan file bersih, ia memiliki perintah untuk diaktifkan sehingga membuat akan berpikir itu adalah target akhir.
Namun, superclean
target tersebut benar-benar palsu, jadi make akan mencoba menumpuknya dengan hal lain yang menyediakan deps untuk superclean
target - ini termasuk superclean
target lain dan%
target.
Perhatikan bahwa kami tidak mengatakan apa-apa tentang andsomethingelse
atau blah
, jadi mereka jelas pergi ke penangkap.
Outputnya terlihat seperti ini:
$ make clean
clean
$ make superclean
clean
catcher andsomethingelse
$ make blah
clean
catcher andsomethingelse
catcher blah