อะไร.PHONY
หมายถึงใน Makefile? ฉันผ่านเรื่องนี้ไปแล้ว แต่มันซับซ้อนเกินไป
ใครสามารถอธิบายให้ฉันในแง่ง่าย?
อะไร.PHONY
หมายถึงใน Makefile? ฉันผ่านเรื่องนี้ไปแล้ว แต่มันซับซ้อนเกินไป
ใครสามารถอธิบายให้ฉันในแง่ง่าย?
คำตอบ:
โดยค่าเริ่มต้นเป้าหมาย Makefile คือ "เป้าหมายไฟล์" - พวกเขาจะใช้ในการสร้างไฟล์จากไฟล์อื่น ๆ Make ถือว่าเป้าหมายเป็นไฟล์และสิ่งนี้ทำให้การเขียน Makefiles ค่อนข้างง่าย:
foo: bar
create_one_from_the_other foo bar
อย่างไรก็ตามบางครั้งคุณต้องการให้ Makefile ของคุณเรียกใช้คำสั่งที่ไม่ได้แสดงถึงฟิสิคัลไฟล์ในระบบไฟล์ ตัวอย่างที่ดีสำหรับสิ่งนี้คือเป้าหมายทั่วไป "สะอาด" และ "ทั้งหมด" โอกาสนี้ไม่ใช่กรณี แต่คุณอาจมีชื่อไฟล์clean
ในไดเรกทอรีหลักของคุณ ในกรณีดังกล่าว Make จะสับสนเพราะโดยค่าเริ่มต้นclean
เป้าหมายจะเชื่อมโยงกับไฟล์นี้และ Make จะรันเฉพาะเมื่อไฟล์ไม่ปรากฏว่าเป็นข้อมูลล่าสุดเกี่ยวกับการขึ้นต่อกันของมัน
เป้าหมายพิเศษเหล่านี้เรียกว่าของปลอมและคุณสามารถบอกได้อย่างชัดเจนว่าพวกเขาไม่เกี่ยวข้องกับไฟล์เช่น:
.PHONY: clean
clean:
rm -rf *.o
ตอนนี้make clean
จะทำงานตามที่คาดไว้แม้ว่าคุณจะมีชื่อไฟล์clean
ก็ตาม
ในแง่ของการสร้างเป้าหมายปลอมเป็นเพียงเป้าหมายที่ล้าสมัยเสมอดังนั้นเมื่อใดก็ตามที่คุณถามmake <phony_target>
มันจะทำงานโดยไม่ขึ้นกับสถานะของระบบไฟล์ บางคนทั่วไปmake
เป้าหมายที่มักจะปลอมเป็น: all
, install
, clean
, distclean
, TAGS
, ,info
check
สมมติว่าคุณมีinstall
เป้าหมายซึ่งเป็นเรื่องธรรมดาใน makefiles หากคุณไม่ได้ใช้งาน.PHONY
และมีไฟล์ชื่อinstall
อยู่ในไดเรกทอรีเดียวกับ Makefile แล้วmake install
จะไม่ทำอะไรเลย นี่เป็นเพราะทำให้ตีความกฎเพื่อหมายถึง "ดำเนินการสูตรดังกล่าวและเช่นเพื่อสร้างไฟล์ชื่อinstall
" เนื่องจากไฟล์มีอยู่แล้วและการอ้างอิงของมันก็ไม่เปลี่ยนแปลงดังนั้นจะไม่มีการดำเนินการใด ๆ
อย่างไรก็ตามถ้าคุณสร้างinstall
PHONY เป้าหมายมันจะบอกเครื่องมือสร้างว่าเป้าหมายเป็นตัวละครและสิ่งนั้นไม่ควรคาดหวังว่ามันจะสร้างไฟล์จริง ดังนั้นมันจะไม่ตรวจสอบว่าinstall
ไฟล์นั้นมีอยู่หรือไม่ความหมาย: a) พฤติกรรมของมันจะไม่เปลี่ยนแปลงหากไฟล์นั้นมีอยู่และ b) stat()
จะไม่ถูกเรียกใช้เป็นพิเศษ
โดยทั่วไปเป้าหมายทั้งหมดใน Makefile ของคุณซึ่งไม่ได้สร้างไฟล์เอาต์พุตที่มีชื่อเดียวกันกับชื่อเป้าหมายควรเป็น PHONY นี้มักจะมีall
, install
, clean
, distclean
และอื่น ๆ
.sh
หรือ.bash
ส่วนขยายสำหรับ "โปรแกรม" ที่ทำงานเหมือนพวกเขามีฟังก์ชั่นหลักและสำรองเพิ่มส่วนขยายสำหรับห้องสมุดที่คุณรวม ( source mylib.sh
) ในความเป็นจริงฉันได้รับคำถาม SO นี้เพราะฉันมีสคริปต์ในไดเรกทอรีเดียวกันกับ Makefile ของฉันที่เรียกว่าinstall
.PHONY
ตลอดเวลา ...
.PHONY
รุ่น
หมายเหตุ : เครื่องมือ make จะอ่าน makefile และตรวจสอบการประทับเวลาการแก้ไขของไฟล์ที่ด้านข้างของสัญลักษณ์ ':' ในกฎ
ในไดเรกทอรี 'ทดสอบ' มีไฟล์ต่อไปนี้:
prerit@vvdn105:~/test$ ls
hello hello.c makefile
ใน makefile กฎถูกกำหนดดังนี้:
hello:hello.c
cc hello.c -o hello
ตอนนี้สมมติว่าไฟล์ 'hello' เป็นไฟล์ข้อความที่มีข้อมูลบางส่วนซึ่งสร้างขึ้นหลังจากไฟล์ 'hello.c' ดังนั้นการปรับเปลี่ยน (หรือสร้าง) ประทับเวลาของ 'สวัสดี' จะใหม่กว่า 'hello.c' ดังนั้นเมื่อเราจะเรียก 'make hello' จากบรรทัดคำสั่งมันจะพิมพ์เป็น:
make: `hello' is up to date.
ตอนนี้เข้าถึงไฟล์ 'hello.c' และใส่ช่องว่างสีขาวไว้ในนั้นซึ่งไม่ส่งผลกระทบต่อไวยากรณ์ของรหัสหรือตรรกะจากนั้นบันทึกและออก ตอนนี้การประทับเวลาการแก้ไขของ hello.c นั้นใหม่กว่าของ 'hello' ตอนนี้ถ้าคุณเรียกใช้ 'make hello' มันจะดำเนินการตามคำสั่งดังนี้
cc hello.c -o hello
และไฟล์ 'hello' (ไฟล์ข้อความ) จะถูกเขียนทับด้วยไฟล์ไบนารีใหม่ 'hello' (ผลลัพธ์ของคำสั่งการคอมไพล์ด้านบน)
ถ้าเราใช้. PHYY ใน makefile ดังต่อไปนี้:
.PHONY:hello
hello:hello.c
cc hello.c -o hello
จากนั้นเรียกใช้ 'make hello' มันจะไม่สนใจไฟล์ใด ๆ ที่มีอยู่ใน pwd 'test' และดำเนินการคำสั่งทุกครั้ง
ทีนี้สมมติว่าเป้าหมาย 'hello' นั้นไม่มีการขึ้นต่อกัน:
hello:
cc hello.c -o hello
และไฟล์ 'hello' มีอยู่ใน pwd 'test' แล้ว 'make hello' จะแสดงเป็น:
make: `hello' is up to date.
make
ความรู้สึกโดยรวมมันคือทั้งหมดที่เกี่ยวกับไฟล์! ขอบคุณสำหรับคำตอบนี้
.PHONY: install
มันเป็นเป้าหมายการสร้างที่ไม่ใช่ชื่อไฟล์
คำอธิบายที่ดีที่สุดคือการทำให้ GNU คู่มือตัวเอง: 4.6 ปลอมเป้าหมายส่วน
.PHONY
เป็นหนึ่งในการแต่งหน้าของพิเศษ Built-in ชื่อเป้าหมาย มีเป้าหมายอื่น ๆ ที่คุณอาจสนใจดังนั้นจึงควรอ่านข้อมูลอ้างอิงเหล่านี้
เมื่อถึงเวลาที่จะต้องพิจารณาเป้าหมาย. PHONY make จะเรียกใช้สูตรของมันโดยไม่มีเงื่อนไขโดยไม่คำนึงว่าไฟล์ที่มีชื่อนั้นมีอยู่หรือเวลาแก้ไขล่าสุด
นอกจากนี้คุณยังอาจจะสนใจในการแต่งหน้าของเป้าหมายมาตรฐานเช่นและall
clean
นอกจากนี้ยังมีการรักษา ".PHONY" ที่สำคัญอย่างหนึ่ง - เมื่อเป้าหมายทางกายภาพขึ้นอยู่กับเป้าหมายปลอมที่ขึ้นอยู่กับเป้าหมายทางกายภาพอื่น:
TARGET1 -> PHONY_FORWARDER1 -> PHONY_FORWARDER2 -> TARGET2
คุณเพียงแค่คาดหวังว่าหากคุณอัปเดต TARGET2 ดังนั้น TARGET1 ควรได้รับการพิจารณาว่าเก่ากับ TARGET1 ดังนั้น TARGET1 จึงควรสร้างใหม่ และมันใช้งานได้จริงด้วยวิธีนี้
ส่วนที่ยุ่งยากคือเมื่อ TARGET2 ไม่ได้ค้างกับ TARGET1 ซึ่งในกรณีนี้คุณควรคาดหวังว่า TARGET1 ไม่ควรสร้างใหม่
นี้น่าแปลกใจไม่ได้เพราะ: เป้าหมายปลอมที่กำลังวิ่งอยู่แล้ว (เป็นเป้าหมายของปลอมทำตามปกติ)ซึ่งหมายความว่าเป้าหมายของปลอมได้รับการพิจารณาการปรับปรุง และเนื่องจากการที่target1 ถือว่าเก่ากับเป้าหมายปลอม
พิจารณา:
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
คุณสามารถเล่นกับสิ่งนี้:
ท่านสามารถเข้าดู fileall ที่ขึ้นอยู่กับ file1 ทางอ้อมผ่านเป้าหมายปลอม - แต่ก็มักจะได้รับการสร้างขึ้นมาใหม่เนื่องจากการพึ่งพานี้ หากคุณเปลี่ยนการพึ่งพาในfileall
จากfilefwd
เป็นfile
ตอนนี้fileall
จะไม่ได้รับการสร้างขึ้นมาใหม่ทุกครั้ง แต่เฉพาะเมื่อเป้าหมายที่พึ่งพาใด ๆ นั้นค้างอยู่กับไฟล์นั้นเป็นไฟล์
เป้าหมายพิเศษ.PHONY:
ช่วยให้สามารถประกาศเป้าหมายปลอมได้ซึ่งmake
จะไม่ตรวจสอบว่าเป็นชื่อไฟล์จริง: มันจะทำงานตลอดเวลาแม้ว่าไฟล์ดังกล่าวจะยังคงอยู่
คุณสามารถใส่หลายอย่าง.PHONY:
ในMakefile
:
.PHONY: all
all : prog1 prog2
...
.PHONY: clean distclean
clean :
...
distclean :
...
มีวิธีอื่นในการประกาศเป้าหมายปลอม: เพียงใส่ '::'
all :: prog1 prog2
...
clean ::
...
distclean ::
...
'::' มีความหมายพิเศษ: เป้าหมายเป็นของปลอมและสามารถปรากฏได้หลายครั้ง:
clean ::
rm file1
...
clean ::
rm file2
บล็อกคำสั่งจะถูกเรียกหนึ่งบล็อกอื่น ๆ
ฉันมักจะใช้พวกเขาเพื่อบอกเป้าหมายเริ่มต้นที่จะไม่ยิง
superclean: clean andsomethingelse
blah: superclean
clean:
@echo clean
%:
@echo catcher $@
.PHONY: superclean
โดยไม่ต้องปลอมmake superclean
จะยิงclean
, andsomethingelse
และcatcher superclean
; แต่มีการปลอมจะไม่ยิงmake superclean
catcher superclean
เราไม่ต้องกังวลกับการบอกว่าclean
เป้าหมายคือ PHONY เพราะมันไม่ใช่ของปลอมอย่างสมบูรณ์ แม้ว่ามันจะไม่สร้างไฟล์ที่สะอาด แต่ก็มีคำสั่งให้ใช้ดังนั้น make จะคิดว่ามันเป็นเป้าหมายสุดท้าย
อย่างไรก็ตามsuperclean
เป้าหมายนั้นเป็นของปลอมจริงๆดังนั้น make จะพยายามที่จะรวมกับสิ่งอื่น ๆ ที่ให้การสนับสนุนสำหรับsuperclean
เป้าหมาย - ซึ่งรวมถึงsuperclean
เป้าหมายอื่น ๆและ%
เป้าหมาย
โปรดทราบว่าเราไม่พูดอะไรเลยเกี่ยวกับandsomethingelse
หรือblah
ดังนั้นพวกเขาจึงไปที่ตัวจับอย่างชัดเจน
ผลลัพธ์มีลักษณะดังนี้:
$ make clean
clean
$ make superclean
clean
catcher andsomethingelse
$ make blah
clean
catcher andsomethingelse
catcher blah