makepp_cookbook - ອອນລາຍໃນຄລາວ

ນີ້ແມ່ນຄໍາສັ່ງ makepp_cookbook ທີ່ສາມາດດໍາເນີນການໄດ້ໃນ OnWorks ຜູ້ໃຫ້ບໍລິການໂຮດຕິ້ງຟຣີໂດຍໃຊ້ຫນຶ່ງໃນຫຼາຍໆບ່ອນເຮັດວຽກອອນໄລນ໌ຂອງພວກເຮົາເຊັ່ນ Ubuntu Online, Fedora Online, Windows online emulator ຫຼື MAC OS online emulator

ໂຄງການ:

NAME


makepp_cookbook -- ວິທີທີ່ດີທີ່ສຸດໃນການຕັ້ງຄ່າ makefiles ສໍາລັບສະຖານະການຕ່າງໆ

ລາຍລະອຽດ


ຂ້າພະເຈົ້າໄດ້ຄົ້ນພົບວ່າການປະຕິບັດບໍ່ມີໃຜເຄີຍອ່ານຄູ່ມືສໍາລັບເຄື່ອງມືຜະລິດ, ເພາະວ່າເວົ້າກົງໄປກົງມາ
ບໍ່ມີໃຜສົນໃຈແທ້ໆໃນຂະບວນການສ້າງຕົວມັນເອງ - ພວກເຮົາສົນໃຈພຽງແຕ່ຜົນໄດ້ຮັບ.
ສະນັ້ນ ປຶ້ມສູດອາຫານນີ້ຈຶ່ງຖືກນຳມາລວມກັນເພື່ອຫວັງວ່າຄົນເຮົາຈະສາມາດໄດ້ສິ່ງທີ່ເຂົາເຈົ້າຕ້ອງການ
ຢ່າງວ່ອງໄວຈາກຕົວຢ່າງໂດຍບໍ່ມີການ wading ຜ່ານຄູ່ມື. ນີ້ສະແດງໃຫ້ເຫັນວິທີການພິມ
ຄໍາຖາມ, ໃນຂະນະທີ່ຄໍາແນະນໍາການຕິດຕັ້ງແລະຕັນ stumbling ຈະພົບເຫັນຢູ່ໃນ
ຄໍາ​ຖາມ​ທີ່​ຖືກ​ຖາມ​ເລື້ອຍໆ.

ການກໍ່ສ້າງ ຫ້ອງສະຫມຸດ
Do ທ່ານ ກໍ່ ຕ້ອງການ a ຫ້ອງສະຫມຸດ?

ຂ້າພະເຈົ້າໄດ້ເຫັນໂຄງການຂະຫນາດໃຫຍ່ຈໍານວນຫນຶ່ງທີ່ປະກອບດ້ວຍຈໍານວນໂມດູນຈໍານວນຫລາຍ, ແຕ່ລະ
ເຊິ່ງອາໃສຢູ່ໃນໄດເລກະທໍລີຂອງຕົນເອງ. ໂດຍທົ່ວໄປແລ້ວ, ແຕ່ລະໄດເລກະທໍລີແມ່ນຖືກຈັດໃສ່ໃນຫ້ອງສະຫມຸດຂອງຕົນເອງ,
ແລະຫຼັງຈາກນັ້ນໂຄງການສຸດທ້າຍເຊື່ອມຕໍ່ກັບຫ້ອງສະຫມຸດທັງຫມົດ.

ໃນຫຼາຍໆກໍລະນີ, ຂ້າພະເຈົ້າຄິດວ່າແທນທີ່ຈະໃຊ້ຫ້ອງສະຫມຸດ, ມີວິທີການທີ່ດີກວ່າ. ຫ້ອງສະໝຸດ
ບໍ່ແມ່ນການແກ້ໄຂທີ່ຖືກຕ້ອງແທ້ໆຖ້າແຕ່ລະໂມດູນບໍ່ສາມາດຫຼືຈະບໍ່ຖືກນໍາໃຊ້ຄືນໃນອັນອື່ນ
ໂຄງການ, ເພາະວ່າຫຼັງຈາກນັ້ນທ່ານໄດ້ຮັບຂໍ້ບົກຜ່ອງທັງຫມົດຂອງຫ້ອງສະຫມຸດແລະບໍ່ມີ
ຂໍ້ດີ. ຫ້ອງສະຫມຸດມີປະໂຫຍດໃນກໍລະນີຕໍ່ໄປນີ້:

1. ໃນເວລາທີ່ທ່ານມີຊໍ່ຂອງ subroutines ທີ່ຕ້ອງໄດ້ຮັບການເຊື່ອມຕໍ່ກັບທີ່ແຕກຕ່າງກັນຫຼາຍ
ໂປລແກລມ, ແລະບໍ່ມີໂປລແກລມໃດໃຊ້ 100% ຂອງໂຄງສ້າງຍ່ອຍ - ແຕ່ລະໂຄງການໃຊ້ a
ຊຸດ​ຍ່ອຍ​ທີ່​ແຕກ​ຕ່າງ​ກັນ​. ໃນກໍລະນີນີ້, ມັນອາດຈະເປັນຄວາມຄິດທີ່ດີທີ່ຈະໃຊ້ຫ້ອງສະຫມຸດຄົງທີ່ (a
.a ໄຟລ໌, ຫຼືໄຟລ໌ທີ່ເກັບໄວ້).

2. ໃນເວລາທີ່ທ່ານມີໂມດູນທີ່ຄວນຈະໄດ້ຮັບການເຊື່ອມຕໍ່ກັບໂຄງການທີ່ແຕກຕ່າງກັນຫຼາຍ, ແລະທ່ານ
ຕ້ອງການໂຫຼດມັນແບບໄດນາມິກເພື່ອໃຫ້ແຕ່ລະໂຄງການບໍ່ຈໍາເປັນຕ້ອງມີສໍາເນົາແຍກຕ່າງຫາກ
ຫໍສະຫມຸດ. ຫ້ອງສະໝຸດແບບໄດນາມິກສາມາດປະຫຍັດພື້ນທີ່ໄຟລ໌ທີ່ສາມາດປະຕິບັດໄດ້ ແລະບາງຄັ້ງກໍ່ປັບປຸງ
ການປະຕິບັດລະບົບເນື່ອງຈາກວ່າມີພຽງແຕ່ຫນຶ່ງສໍາເນົາຂອງຫ້ອງສະຫມຸດໂຫຼດສໍາລັບທັງຫມົດຂອງ
ໂຄງການທີ່ແຕກຕ່າງກັນທີ່ໃຊ້ມັນ.

3. ໃນເວລາທີ່ການເຊື່ອມຕໍ່ຂອງທ່ານແມ່ນຍາວຫ້າມ, ການນໍາໃຊ້ຫ້ອງສະຫມຸດແບ່ງປັນສໍາລັບຕ່ອນຂະຫນາດໃຫຍ່ຂອງ
ໂຄງການຢ່າງຫຼວງຫຼາຍສາມາດເລັ່ງການເຊື່ອມຕໍ່.

ການນໍາໃຊ້ຫໍສະຫມຸດຄົງມີຂໍ້ເສຍຕົ້ນຕໍຫນຶ່ງ: ໃນບາງລະບົບ (ເຊັ່ນ Linux), ຄໍາສັ່ງ
ທີ່ທ່ານເຊື່ອມຕໍ່ຫ້ອງສະຫມຸດແມ່ນມີຄວາມສໍາຄັນຫຼາຍ. ຕົວເຊື່ອມຕໍ່ປະມວນຜົນຫ້ອງສະໝຸດ
ໃນຄໍາສັ່ງທີ່ລະບຸໄວ້ໃນເສັ້ນຄໍາສັ່ງຂອງມັນ. ມັນ grabs ທຸກສິ່ງທີ່ມັນຄິດວ່າມັນຕ້ອງການຈາກ
ແຕ່ລະຫ້ອງສະຫມຸດ, ຫຼັງຈາກນັ້ນຍ້າຍໄປຫ້ອງສະຫມຸດຕໍ່ໄປ. ຖ້າບາງຫໍສະຫມຸດຕໍ່ມາຫມາຍເຖິງ a
ສັນຍາລັກທີ່ຍັງບໍ່ໄດ້ຖືກລວມເຂົ້າຈາກຫ້ອງສະຫມຸດທີ່ຜ່ານມາ, ຕົວເຊື່ອມຕໍ່ບໍ່ໄດ້
ຮູ້ວ່າຈະກັບຄືນໄປບ່ອນແລະ grab ມັນຈາກຫ້ອງສະຫມຸດທີ່ຜ່ານມາ. ດັ່ງນັ້ນ, ມັນສາມາດເປັນສິ່ງຈໍາເປັນ
ເພື່ອລາຍຊື່ຫ້ອງສະຫມຸດຫຼາຍຄັ້ງໃນເສັ້ນຄໍາສັ່ງ linker. (ຂ້ອຍໄດ້ເຮັດວຽກຢູ່ໃນໂຄງການ
ບ່ອນທີ່ພວກເຮົາຕ້ອງໄດ້ເຮັດຊ້ໍາບັນຊີລາຍຊື່ທັງຫມົດຂອງຫ້ອງສະຫມຸດສາມເທື່ອ. ໂຄງການນີ້ແມ່ນສິ່ງທີ່ເຮັດ
ຂ້າ​ພະ​ເຈົ້າ​ມັກ​ວິ​ທີ​ທາງ​ເລືອກ​ທີ່​ແນະ​ນໍາ​ຂ້າງ​ລຸ່ມ​ນີ້​, ຂອງ​ການ​ເຊື່ອມ​ຕໍ່​ເພີ່ມ​ເຕີມ​.)

ການນໍາໃຊ້ຫ້ອງສະຫມຸດແບບເຄື່ອນໄຫວມີຂໍ້ເສຍຫຼາຍ. ຫນ້າທໍາອິດ, ໂຄງການຂອງທ່ານສາມາດເລັກນ້ອຍ
ຊ້າກວ່າທີ່ຈະເລີ່ມຕົ້ນຖ້າຫ້ອງສະຫມຸດບໍ່ໄດ້ຖືກນໍາໃຊ້ໂດຍບາງໂຄງການອື່ນ, ເພາະວ່າ
ມັນຕ້ອງໄດ້ຮັບການພົບເຫັນແລະໂຫຼດ. ອັນທີສອງ, ມັນສາມາດເປັນຄວາມຫຍຸ້ງຍາກທີ່ແທ້ຈິງທີ່ຈະໄດ້ຮັບການເຄື່ອນໄຫວທັງຫມົດ
ຫ້ອງສະຫມຸດຕິດຕັ້ງຢູ່ໃນສະຖານທີ່ທີ່ຖືກຕ້ອງ; ທ່ານບໍ່ສາມາດພຽງແຕ່ຄັດລອກໂຄງການທີ່ສາມາດປະຕິບັດໄດ້,
ທ່ານຍັງຕ້ອງເຮັດໃຫ້ແນ່ໃຈວ່າທ່ານຄັດລອກຫ້ອງສະຫມຸດຂອງມັນທັງຫມົດ. ອັນທີສາມ, ໃນບາງລະບົບ, ມັນ
ເປັນການຍາກທີ່ຈະດີບັກລະຫັດພາຍໃນຫ້ອງສະໝຸດທີ່ແບ່ງປັນເພາະວ່າຕົວດີບັກບໍ່ຮອງຮັບ
ເຂົາເຈົ້າໄດ້ດີ.

ຖ້າໂມດູນຂອງເຈົ້າບໍ່ເຄີຍຖືກໃຊ້ໃນໂຄງການອື່ນ, ຫຼັງຈາກນັ້ນມີເຫດຜົນຫນ້ອຍທີ່ຈະໃຊ້
ຫ້ອງສະໝຸດ: ທ່ານໄດ້ຮັບຂໍ້ເສຍທັງໝົດຂອງການໃຊ້ຫ້ອງສະໝຸດ ແລະບໍ່ມີຂໍ້ດີໃດໆ.
ເຕັກນິກທີ່ຂ້ອຍມັກແມ່ນການໃຊ້ການເຊື່ອມໂຍງແບບເລັ່ງລັດ, ບ່ອນທີ່ມັນມີຢູ່.

ນີ້ແມ່ນວິທີທີ່ທ່ານສາມາດເຮັດໄດ້ໃນ Linux:

my_module.o : $(filter_out my_module.o, $(wildcard *.o))
ld -r -o $(output) $(inputs)

ສິ່ງນີ້ຈະເຮັດຄືການສ້າງອັນອື່ນ .o ໄຟລ໌ເອີ້ນວ່າ my_module.o, ເຊິ່ງຈະປະກອບດ້ວຍ
ທັງຫມົດຂອງ .o ໄຟລ໌ຢູ່ໃນໄດເລກະທໍລີຍ່ອຍນີ້. ຕົວເຊື່ອມຕໍ່ຈະແກ້ໄຂເປັນຈໍານວນຫຼາຍຂອງ
ການອ້າງອິງຕາມທີ່ມັນສາມາດເຮັດໄດ້, ແລະຈະປ່ອຍໃຫ້ການອ້າງອິງທີ່ຍັງເຫຼືອຖືກແກ້ໄຂໃນ a
ຂັ້ນ​ຕອນ​ຕໍ່​ໄປ​ຂອງ​ການ​ເຊື່ອມ​ຕໍ່​. ໃນລະດັບສູງສຸດ, ເມື່ອທ່ານສ້າງໂປຼແກຼມຂອງທ່ານໃນທີ່ສຸດ,
ແທນທີ່ຈະເຊື່ອມຕໍ່ກັບ libmy_module.a or libmy_module.so, ທ່ານພຽງແຕ່ຈະເຊື່ອມຕໍ່ກັບ
my_module.o. ເມື່ອທ່ານເຊື່ອມຕໍ່ .o ໄຟລ໌, ທ່ານບໍ່ມີບັນຫາກັບການຂຶ້ນກັບຄໍາສັ່ງໃນ
linker ຄໍາສັ່ງ.

ປ່ອຍໃຫ້ ແຕ່ງໜ້າ ຮູບ ອອກ ທີ່ ຫ້ອງສະຫມຸດ ໂມດູນ ມີ ຈໍາເປັນ

ເຖິງແມ່ນວ່າທ່ານມີຫ້ອງສະຫມຸດທີ່ແທ້ຈິງ, ບ່ອນທີ່ໂຄງການໃດຫນຶ່ງຕ້ອງການພຽງແຕ່ສອງສາມໄຟລ໌ຈາກມັນ
(ແທນທີ່ຈະເປັນແຕ່ລະໂມດູນດຽວ), makepp ອາດຈະສາມາດຄິດອອກວ່າໂມດູນໃດ
ຕ້ອງການຈາກຫ້ອງສະຫມຸດແລະປະກອບມີພຽງແຕ່ຜູ້ທີ່ຢູ່ໃນການກໍ່ສ້າງ. ນີ້ສາມາດຊ່ວຍປະຢັດການລວບລວມ
ເວລາຖ້າຫາກວ່າທ່ານກໍາລັງພັດທະນາຫ້ອງສະຫມຸດພ້ອມກັບໂຄງການ, ເພາະວ່າທ່ານບໍ່ bother ກັບ
ລວບລວມໂມດູນຫ້ອງສະຫມຸດທີ່ບໍ່ຈໍາເປັນສໍາລັບໂຄງການສະເພາະທີ່ທ່ານກໍາລັງເຮັດວຽກຢູ່.

ຖ້າຫ້ອງສະຫມຸດຂອງເຈົ້າປະຕິບັດຢ່າງເຂັ້ມງວດສົນທິສັນຍາທີ່ຫນ້າທີ່ຫຼືຊັ້ນຮຽນທັງຫມົດທີ່ປະກາດໄວ້ໃນ
ແຟ້ມ xyz.h ຖືກປະຕິບັດຢ່າງສົມບູນໃນໄຟລ໌ແຫຼ່ງທີ່ລວບລວມກັບ xyz.o (ເຊັ່ນ, ເຈົ້າ
ຢ່າແບ່ງການປະຕິບັດອອກເປັນ xyz1.o ແລະ xyz2.o), ຫຼັງຈາກນັ້ນທ່ານສາມາດນໍາໃຊ້ໄດ້
"$(infer_objects)" ຟັງຊັນເພື່ອບອກ makepp ທີ່ຈະດຶງພຽງແຕ່ໂມດູນທີ່ກ່ຽວຂ້ອງຈາກ
ຫໍສະໝຸດ. ນີ້ສາມາດເຮັດວຽກໄດ້ດີເປັນເລື່ອງແປກທີ່ສໍາລັບຫ້ອງສະຫມຸດທີ່ມີແມ້ກະທັ້ງຫຼາຍສິບໄຟລ໌ລວມ.
ໂດຍພື້ນຖານແລ້ວ, "$(infer_objects)" ກວດເບິ່ງບັນຊີລາຍຊື່ຂອງ .h ໄຟລ​໌​ທີ່​ລວມ​, ແລະ​ເບິ່ງ​
ສໍາລັບທີ່ສອດຄ້ອງກັນ .o ໄຟລ໌. ຖ້າທ່ານກໍາລັງພັດທະນາຫ້ອງສະຫມຸດແລະໂຄງການຢ່າງໄວວາ
ຮ່ວມກັນ, ນີ້ສາມາດປະຫຍັດເວລາການລວບລວມ, ເພາະວ່າທ່ານບໍ່ເຄີຍເບື່ອທີ່ຈະລວບລວມໂມດູນຂອງ
ຫ້ອງສະຫມຸດທີ່ໂຄງການບໍ່ໄດ້ໃຊ້.

ນີ້ແມ່ນຕົວຢ່າງຂອງວິທີທີ່ຂ້ອຍໃຊ້ມັນ:

my_program: $(infer_objects *.o, $(LIB1)/*.o $(LIB2)/*.o)
$(CXX) $(inputs) -o $(output) $(SYSTEM_LIBRARIES)

ຟັງຊັນ "$(infer_objects )" ກັບຄືນ argument ທໍາອິດຂອງມັນ (ຫຼັງຈາກເຮັດ wildcard
expansion on it), ແລະຍັງເບິ່ງຜ່ານບັນຊີລາຍຊື່ຂອງໄຟລ໌ໃນການໂຕ້ຖຽງທີສອງຂອງຕົນ, ສໍາລັບ
ໄຟລ໌ທີ່ມີຊື່ຄືກັນກັບຊື່ຂອງອັນໃດນຶ່ງ .h ໄຟລ໌ທີ່ລວມຢູ່ໃນໄຟລ໌ໃດໆໃນຄັ້ງທໍາອິດຂອງມັນ
ການໂຕ້ຖຽງ. ຖ້າພົບໄຟລ໌ດັ່ງກ່າວ, ໄຟລ໌ເຫຼົ່ານີ້ຖືກເພີ່ມເຂົ້າໃນບັນຊີລາຍຊື່.

ການກໍ່ສ້າງ a ໄຟຟ້າສະຖິດ ຫ້ອງສະຫມຸດ

ຖ້າ​ຫາກ​ວ່າ​ທ່ານ​ແນ່​ໃຈວ່​າ​ທ່ານ​ຕ້ອງ​ການ​ຫ້ອງ​ສະ​ຫມຸດ​ແລະ​ການ​ເຊື່ອມ​ຕໍ່​ເພີ່ມ​ເຕີມ​ແມ່ນ​ບໍ່​ມີ​ຫຼື​
ບໍ່ແມ່ນສິ່ງທີ່ທ່ານຕ້ອງການເຮັດ, ມີສອງວິທີທີ່ຈະເຮັດມັນ. ຫນ້າທໍາອິດ, ນີ້ແມ່ນຕົວຢ່າງ
ບ່ອນທີ່ໄຟລ໌ທັງຫມົດຖືກລະບຸໄວ້ຢ່າງຊັດເຈນ:

LIBRARY_FILES = abcde

libmine.a: $(LIBRARY_FILES).o
&rm -f $(ຜົນຜະລິດ)
$(AR) cr $(output) $(inputs)
ranlib $(output) # ອາດຈະບໍ່ຈໍາເປັນ, ຂຶ້ນກັບ OS ຂອງທ່ານ.

&rm ແມ່ນຄໍາສັ່ງສ້າງໃນ "rm" ຂອງ makepp. ຖ້າທ່ານຄຸ້ນເຄີຍກັບການຂຽນ makefiles, ທ່ານອາດຈະເປັນ
ແປກໃຈເລັກນ້ອຍໂດຍຄໍາສັ່ງນີ້; ເຈົ້າອາດຈະຖືກໃຊ້ກັບບາງສິ່ງບາງຢ່າງເຊັ່ນນີ້:

libmine.a: $(LIBRARY_FILES).o
$(AR) ru $@ $? #ບໍ່ແນະນຳ!!!!!!!
ranlib $(ຜົນຜະລິດ)

$ ຢູ່ໃສ? (ຍັງເອີ້ນວ່າ "$(changed_inputs)") ແມ່ນຕົວແປອັດຕະໂນມັດທີ່ຫມາຍຄວາມວ່າໄຟລ໌ຕ່າງໆ
ເຊິ່ງມີການປ່ຽນແປງຕັ້ງແຕ່ຄັ້ງສຸດທ້າຍທີ່ຫ້ອງສະໝຸດຖືກສ້າງຂຶ້ນ, ແລະ $@ ແມ່ນປະມານຄືກັນ
ເປັນ "$(output)".

ວິທີການນີ້ບໍ່ໄດ້ຖືກແນະນໍາໃຫ້ສໍາລັບເຫດຜົນຫຼາຍ:

·ສົມມຸດວ່າເຈົ້າເອົາໄຟລ໌ແຫຼ່ງອອກຈາກໄດເລກະທໍລີປະຈຸບັນ. ມັນຍັງຢູ່ໃນ
ຫໍສະໝຸດ, ເພາະວ່າເຈົ້າບໍ່ໄດ້ສ້າງຫໍສະໝຸດຄືນໃໝ່ຕັ້ງແຕ່ຕົ້ນ. ດັ່ງນັ້ນ, ສິ່ງໃດ
ການເຊື່ອມຕໍ່ກັບຫ້ອງສະຫມຸດນີ້ຈະມີ stale ໄດ້ .o ໄຟລ໌, ແລະທີ່ສາມາດ screw ເຖິງຂອງທ່ານ
ກໍ່ສ້າງ. (ຂ້ອຍເຄີຍສັບສົນກັບເລື່ອງນີ້ເມື່ອຂ້ອຍພະຍາຍາມເອົາລະຫັດຕາຍ
ຈາກໂຄງການ: ຂ້ອຍສືບຕໍ່ລຶບໄຟລ໌ແລະມັນຍັງເຊື່ອມຕໍ່, ດັ່ງນັ້ນຂ້ອຍຄິດວ່າລະຫັດແມ່ນ
ຕາຍ. ຢ່າງໃດກໍຕາມ, ເມື່ອຄົນອື່ນກໍ່ສ້າງໂຄງການຄືນໃຫມ່, ມັນບໍ່ໄດ້ເຊື່ອມຕໍ່ໃດໆ
ເພີ່ມເຕີມ! ບັນຫາແມ່ນວ່າເກົ່າ .o ໄຟລ໌ຍັງຢູ່ໃນບ່ອນເກັບມ້ຽນ.)

ນອກຈາກນີ້, ອີງຕາມທາງເລືອກຂອງທ່ານທີ່ຈະ "ar" ແລະການປະຕິບັດຂອງທ່ານ "ar" (ຕົວຢ່າງ, ຖ້າຫາກວ່າທ່ານ
ໃຊ້ຕົວເລືອກ "q" ແທນ "r"), ທ່ານສາມາດລົມກັບມີຫລາຍຮຸ່ນຂອງ
ດຽວກັນ .o ພາຍໃນ .a ໄຟລ໌. ຖ້າສະບັບທີ່ແຕກຕ່າງກັນກໍານົດໂລກທີ່ແຕກຕ່າງກັນ, the
linker ອາດຈະພະຍາຍາມດຶງທັງສອງຂອງພວກເຂົາ. ນີ້ອາດຈະເປັນສິ່ງທີ່ບໍ່ດີ.

ນີ້ແມ່ນເຫດຜົນທໍາອິດທີ່ພວກເຮົາເອົາໄຟລ໌ຫ້ອງສະຫມຸດ, ແລະສ້າງມັນຈາກ scratch. ນີ້ຈະ
ໃຊ້ເວລາດົນກວ່າການອັບເດດໂມດູນໃນຫ້ອງສະໝຸດເລັກນ້ອຍ, ແຕ່ບໍ່ດົນປານໃດ; ສຸດ
ຄອມພິວເຕີທີ່ທັນສະໄຫມ, ຈໍານວນຂອງທີ່ໃຊ້ເວລາບໍລິໂພກໂດຍ ar ໂຄງການແມ່ນຫນ້ອຍເມື່ອປຽບທຽບ
ກັບສິ່ງທີ່ C compiler ໃຊ້ເວລາໃນການກໍ່ສ້າງປົກກະຕິ, ສະນັ້ນມັນບໍ່ຄຸ້ມຄ່າທີ່ຈະກັງວົນ
ກ່ຽວກັບ.

·ຫນຶ່ງໃນວິທີທີ່ makepp ພະຍາຍາມຮັບປະກັນການກໍ່ສ້າງທີ່ຖືກຕ້ອງແມ່ນມັນຈະ
ກໍ່ສ້າງຄືນໃຫມ່ໂດຍອັດຕະໂນມັດຖ້າເສັ້ນຄໍາສັ່ງເພື່ອສ້າງເປົ້າຫມາຍທີ່ກໍານົດໄວ້ມີການປ່ຽນແປງ. ແຕ່
ໃຊ້ $? ຕົວແປສາມາດເຮັດໃຫ້ເກີດບັນຫາ, ເພາະວ່າແຕ່ລະຄັ້ງທີ່ຫ້ອງສະຫມຸດໄດ້ຖືກປັບປຸງ,
ຄໍາສັ່ງກໍ່ສ້າງແມ່ນແຕກຕ່າງກັນ. (ທ່ານ​ສາ​ມາດ​ສະ​ກັດ​ກັ້ນ​ການ​ນໍາ​ໃຊ້​ນີ້​
":build_check ignore_action"; ເບິ່ງ makepp_build_check ສໍາລັບລາຍລະອຽດ.)

· ການ​ປັບ​ປຸງ​ການ​ຮວບ​ຮວມ​ແທນ​ທີ່​ຈະ​ສ້າງ​ໃຫມ່​ມັນ​ຈະ​ເຮັດ​ໃຫ້​ມັນ​ເປັນ​ໄປ​ບໍ່​ໄດ້​ສໍາ​ລັບ​ການ makepp ກັບ​
ເອົາໄຟລ໌ຢ່າງຖືກຕ້ອງເຂົ້າໄປໃນ build cache (ເບິ່ງ makepp_build_cache ສໍາລັບລາຍລະອຽດ).

ບາງຄັ້ງທ່ານອາດພົບວ່າລາຍຊື່ໄຟລ໌ທັງຫມົດແມ່ນເລັກນ້ອຍຖ້າເຈັບປວດ, ໂດຍສະເພາະຖ້າ a
ໂຄງການແມ່ນ undergoing ການພັດທະນາຢ່າງໄວວາແລະບັນຊີລາຍຊື່ຂອງໄຟລ໌ມີການປ່ຽນແປງຢ່າງຕໍ່ເນື່ອງ. ມັນ
ອາດຈະງ່າຍກວ່າທີ່ຈະສ້າງຫ້ອງສະໝຸດໂດຍໃຊ້ຕົວແທນ, ເຊັ່ນນີ້:

libmine.a: $(only_targets *.o)
&rm $(ຜົນຜະລິດ)
$(AR) cr $(output) $(inputs)

ນີ້ເຮັດໃຫ້ທັງຫມົດ .o ໄຟລ໌ໃນໄດເລກະທໍລີປະຈຸບັນເຂົ້າໄປໃນຫ້ອງສະຫມຸດ. ຕົວແທນ
ກົງກັບອັນໃດນຶ່ງ .o ໄຟລ໌ທີ່ມີຢູ່ຫຼືສາມາດສ້າງໄດ້, ດັ່ງນັ້ນມັນຈະເຮັດວຽກເຖິງແມ່ນວ່າໄຟລ໌ບໍ່
ຍັງມີຢູ່.

ຟັງຊັນ "only_targets" ຖືກນໍາໃຊ້ເພື່ອຍົກເວັ້ນ .o ໄຟລ​໌​ທີ່​ບໍ່​ມີ​ທີ່​ສອດ​ຄ້ອງ​ກັນ​
ແຫຼ່ງໄຟລ໌ອີກຕໍ່ໄປ. ສົມມຸດວ່າທ່ານມີໄຟລ໌ທີ່ເອີ້ນວ່າ xyz.c ທີ່​ທ່ານ​ນໍາ​ໃຊ້​ເພື່ອ​ເອົາ​ເຂົ້າ​ໄປ​ໃນ​ຂອງ​ທ່ານ​
ຫໍສະໝຸດ. ນີ້ຫມາຍຄວາມວ່າມີ xyz.o ໄຟລ​໌​ນອນ​ອ້ອມ​ຂ້າງ​. ໃນປັດຈຸບັນທ່ານລຶບ xyz.c
ເນື່ອງຈາກວ່າມັນລ້າສະໄຫມ, ແຕ່ທ່ານລືມລຶບ xyz.o. ໂດຍບໍ່ມີການ "ພຽງແຕ່_targets"
ໜ້າ ທີ່, xyz.o ຍັງຈະຖືກລວມເຂົ້າໃນບັນຊີລາຍຊື່ຂອງ .o ໄຟລ໌ລວມຢູ່ໃນຫ້ອງສະຫມຸດ.

ການກໍ່ສ້າງ a ການເຄື່ອນໄຫວ ຫ້ອງສະຫມຸດ

ຂະບວນການສ້າງຫ້ອງສະໝຸດແບບເຄື່ອນໄຫວແມ່ນຂຶ້ນກັບລະບົບທັງໝົດ. ຂ້ອຍຈະສູງ
ແນະນໍາໃຫ້ໃຊ້ libtool ເພື່ອສ້າງຫ້ອງສະຫມຸດແບບເຄື່ອນໄຫວ (ເບິ່ງ
<http://www.gnu.org/software/libtool/>), ດັ່ງນັ້ນທ່ານບໍ່ຈໍາເປັນຕ້ອງຄິດອອກວິທີການເຮັດມັນ
ເວທີຂອງທ່ານ, ແລະດັ່ງນັ້ນ makefile ຂອງທ່ານຈະສືບຕໍ່ເຮັດວຽກເຖິງແມ່ນວ່າໃນເວລາທີ່ທ່ານປ່ຽນເປັນ
OS ທີ່​ແຕກ​ຕ່າງ​ກັນ​. ເບິ່ງເອກະສານ libtool ສໍາລັບລາຍລະອຽດ. ນີ້ແມ່ນຕົວຢ່າງ Makefile:

LIBTOOL := libtool

libflick.la : $(only_targets *.lo)
$(LIBTOOL) --mode=link $(CC) $(inputs) -o $(output)

%.lo : %.c
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(INCLUDES) -c $(input) -o $(output)

ການກໍ່ສ້າງ on ຫຼາຍ ທີ່ແຕກຕ່າງກັນ ເຄື່ອງ or ເຄືອຂ່າຍ
ຫນຶ່ງໃນບັນຫາທີ່ຫນ້າລໍາຄານທີ່ສຸດກັບ makefiles ແມ່ນວ່າພວກເຂົາເກືອບບໍ່ເຄີຍເຮັດວຽກໃນເວລາທີ່ທ່ານ
ສະຫຼັບໄປໃຊ້ເຄື່ອງອື່ນ ຫຼືເຄືອຂ່າຍອື່ນ. ຖ້າ makefiles ຂອງເຈົ້າຕ້ອງເຮັດວຽກ
ທຸກໆເຄື່ອງທີ່ເປັນໄປໄດ້ໃນໂລກ, ຫຼັງຈາກນັ້ນທ່ານອາດຈະຕ້ອງການການຈັດລຽງຂອງການຕັ້ງຄ່າບາງຢ່າງ
script. ແຕ່ຖ້າທ່ານພຽງແຕ່ຕ້ອງເຮັດວຽກຢູ່ໃນເຄື່ອງຈັກທີ່ແຕກຕ່າງກັນຈໍານວນຫນ້ອຍ, ມີຫຼາຍວິທີ
ທ່ານສາມາດເຂົ້າຫາບັນຫານີ້:

ການນໍາໃຊ້ a ທີ່ແຕກຕ່າງກັນ ປະກອບດ້ວຍ ເອກະສານ in ທັງຫມົດ ໄດ້ ສະພາບແວດລ້ອມ

ໃນຕອນຕົ້ນຂອງແຕ່ລະ makefile, ທ່ານສາມາດປະກອບມີເສັ້ນເຊັ່ນນີ້:

ລວມເອົາ system_defs.mk

ໄຟລ໌ system_defs.mk ປົກກະຕິແລ້ວຈະຖືກຕັ້ງຢູ່ໃນສະຖານທີ່ທີ່ແຕກຕ່າງກັນສໍາລັບແຕ່ລະຄົນ
ສະພາບແວດລ້ອມ. ຖ້າທ່ານຕ້ອງການໃຫ້ໄດເລກະທໍລີສ້າງຂອງທ່ານຄືກັນໃນທຸກເຄື່ອງຈັກ, ຫຼັງຈາກນັ້ນໃສ່
system_defs.mk ໃນໄດເລກະທໍລີຂ້າງເທິງສ້າງໄດເລກະທໍລີ, ຫຼືອື່ນໆສະຫນອງເສັ້ນທາງລວມ
to makepp ໂດຍໃຊ້ຕົວເລືອກເສັ້ນຄໍາສັ່ງ "-I".

ນີ້ແມ່ນປົກກະຕິແລ້ວປະເພດຂອງການເຈັບປວດທີ່ຈະເຮັດ, ແຕ່ມັນເຮັດວຽກໄດ້ດີຖ້າຫາກວ່າມີຈໍານວນ huge ຂອງ
ຄວາມແຕກຕ່າງ.

ການນໍາໃຊ້ if ບົດລາຍງານ

ນີ້ແມ່ນວິທີທີ່ຂີ້ຮ້າຍທີ່ສຸດທີ່ຈະເຮັດ, ແຕ່ປົກກະຕິມັນຈະເຮັດວຽກ.

ifsys i386
CC := gcc
ອື່ນ ifsys sun4u
CC:=cc
ອື່ນ ifsys hpux11
CC = c89
ສິ້ນສຸດ

ຖ້າ​ຫາກ​ວ່າ​ທັງ​ຫມົດ​ທີ່​ທ່ານ​ຕ້ອງ​ການ​ຈະ​ເຮັດ​ແມ່ນ​ເພື່ອ​ຊອກ​ຫາ​ໂຄງ​ການ​ຈໍາ​ນວນ​ຫນຶ່ງ​ຫຼື​ຫ້ອງ​ສະ​ຫມຸດ​ຫຼື​ລວມ​ເອົາ​ໄຟລ​໌​ໃນ​ທີ່​ແຕກ​ຕ່າງ​ກັນ​
ສະຖານທີ່, ອາດຈະມີວິທີທີ່ດີກວ່າ (ເບິ່ງຂ້າງລຸ່ມນີ້).

ໂປຣແກຣມຊອກຫາ, first_available, ຊອກຫາໄຟລ໌

ຫນ້າທີ່ເຫຼົ່ານີ້ສາມາດຄົ້ນຫາໄດເລກະທໍລີທີ່ແຕກຕ່າງກັນໃນລະບົບຂອງເຈົ້າເພື່ອຊອກຫາ
ໄຟລ​໌​ທີ່​ເຫມາະ​ສົມ​. ອັນນີ້ບໍ່ມີປະສິດທິພາບຄືກັບສະຄຣິບ configure, ແນ່ນອນ, ແຕ່ຂ້ອຍພົບມັນ
ເປັນປະໂຫຍດ. ຕົວຢ່າງ, ຂ້ອຍເຮັດສິ່ງຕໍ່ໄປນີ້:

CXX ;= $(find_program g++ c++ pg++ cxx CC aCC)
# ເລືອກເອົາ C++ compiler ທໍາອິດທີ່ມີຢູ່ໃນ PATH.
# (ໂດຍບັງເອີນ, ຖ້າທ່ານບໍ່ກໍານົດ CXX ທັງຫມົດ, ນີ້ແມ່ນ
# ແມ່ນວິທີທີ່ມັນຖືກກໍານົດ.)
TCL_INCLUDE ;= -I$(dir_noslash $(findfile tcl.h,
/usr/local/stow/tcl-8.4.5-nothread/include
/usr/include/tcl8.4 /usr/include/tcl
/net/na1/tcl8.4a3/include /net/na1/tcl8.4a3/include))
# $(findfile ) ຊອກຫາ tcl.h ໃນແຕ່ລະອັນທີ່ລະບຸໄວ້
# ໄດເລກະທໍລີແລະສົ່ງຄືນເສັ້ນທາງເຕັມ. ນີ້ແມ່ນຫຼັງຈາກນັ້ນ
# ປ່ຽນເປັນຕົວເລືອກການລວບລວມໂດຍການລອກເອົາ
# ຊື່ໄຟລ໌ (ອອກຈາກໄດເລກະທໍລີ) ແລະນໍາຫນ້າດ້ວຍ -I.
%.o : %.cpp
$(CXX) $(CXXFLAGS) $(TCL_INCLUDE) $(input) -o $(output)

TCL_LIB ;= $((first_available
/usr/local/stow/tcl-8.4.5-nothread/lib/libtcl8.4.so
/usr/lib/libtcl8.4.so /usr/lib/libtcl.so
/net/na1/tcl8.4a3/lib/libtcl8.4.a
/net/na1/tcl8.4a3/lib/libtcl8.4.sl))
# ຊອກຫາບ່ອນທີ່ຫ້ອງສະຫມຸດ Tcl ຢູ່. ນີ້ແມ່ນຫຼັງຈາກນັ້ນຢ່າງຈະແຈ້ງ
# ລະບຸໄວ້ໃນຄໍາສັ່ງເຊື່ອມຕໍ່:
my_program : *.o
$(CXX) $(CXXFLAGS) $(inputs) -o $(output) $(TCL_LIB)

ໃຊ້​ເວ​ລາ ປະໂຫຍດ of Perl ຂອງ config ຂໍ້ມູນຂ່າວສານ

ເຕັກນິກຂ້າງເທິງອາດຈະບໍ່ພຽງພໍຖ້າຫາກວ່າທ່ານຕ້ອງການຂໍ້ມູນເພີ່ມເຕີມກ່ຽວກັບ
ລະບົບຂອງທ່ານ, ເຊັ່ນວ່າມີສອງເທົ່າຍາວ, ຫຼືຄໍາສັ່ງ byte ແມ່ນຫຍັງ. ແນວໃດກໍ່ຕາມ,
perl ໄດ້ຄິດໄລ່ສິ່ງເຫຼົ່ານີ້ແລ້ວ, ດັ່ງນັ້ນທ່ານພຽງແຕ່ສາມາດນໍາໃຊ້ຄໍາຕອບຂອງມັນ.

script autoconfigure Perl ຂອງ Perl ເຮັດໃຫ້ຂໍ້ມູນການຕັ້ງຄ່າຂອງມັນທັງຫມົດທີ່ມີຢູ່ໂດຍຜ່ານ
ໄດ້ %Config hash. ບໍ່ມີ syntax ເພື່ອເຂົ້າເຖິງ Perl hash ໂດຍກົງໃນ makepp, ແຕ່ທ່ານສາມາດເຮັດໄດ້
ຫຼຸດລົງເຂົ້າໄປໃນ Perl ແລະກໍານົດຕົວແປ scalar, ເຊິ່ງສາມາດເຂົ້າເຖິງໄດ້ໂດຍກົງຈາກ makepp:

perl_begin
# ດຶງເອົາຄ່າອອກຈາກ hash config.
ໃຊ້ Config;
$CC = $Config{'cc'}; # C compiler ທີ່ perl ໃຊ້;
$byteorder_flags = "-DBYTEORDER=$Config{'byteorder'}";
$longdouble_defined = $Config{'d_longdbl'} eq 'define';
$CFLAGS_for_shared_libs = $Config{'cccdlflags'};
$LDFLAGS_for_shared_libs = $Config{'ccdlflags'};
perl_end

ນອກຈາກນັ້ນ, ເມື່ອທ່ານໄດ້ເຮັດ 'ໃຊ້ Config', ທ່ານສາມາດນໍາໃຊ້ຄໍາສັ່ງ "$(perl)", ເຊັ່ນ:
ນີ້:

SHARED_LIB_EXTENSION := $(perl $Config{'dlext'})

ພິມ "perldoc Config" ເພື່ອເບິ່ງວ່າມີຂໍ້ມູນໃດແດ່ທີ່ມີຜ່ານ %Config hash.

ການຕັ້ງຄ່າຂອງ Perl ແມ່ນບ່ອນທີ່ດີທີ່ຈະໄດ້ຮັບສິ່ງຕ່າງໆເຊັ່ນຂໍ້ມູນກ່ຽວກັບປະເພດຈໍານວນເຕັມ, byte
ຄໍາສັ່ງ, ແລະສິ່ງອື່ນໆທີ່ປົກກະຕິແລ້ວຕ້ອງການ script config ແຍກຕ່າງຫາກເພື່ອຊອກຫາສະຖານທີ່. ບາງສ່ວນຂອງ
ຂໍ້ມູນຂອງມັນທີ່ກ່ຽວຂ້ອງກັບການປະກົດຕົວຂອງສິ່ງຕ່າງໆໃນລະບົບໄຟລ໌ອາດຈະບໍ່ແມ່ນ
ຖືກຕ້ອງ. ຕົວຢ່າງ, $Config{'cc'} ຫມາຍເຖິງ C compiler ທີ່ perl ສ້າງຂຶ້ນດ້ວຍ,
ເຊິ່ງອາດຈະບໍ່ແມ່ນ C compiler ດຽວກັນທີ່ທ່ານຕ້ອງການໃຊ້. ໃນຄວາມເປັນຈິງ, ມັນອາດຈະບໍ່ມີຢູ່
ໃນລະບົບຂອງທ່ານ, ເພາະວ່າທ່ານອາດຈະຕິດຕັ້ງ Perl ຜ່ານຊຸດຄູ່.

ຄໍາແນະນໍາ ສໍາລັບການ ການນໍາໃຊ້ ຕົວແທນ
ການຈັບຄູ່ ທັງຫມົດ ໄຟ ຍົກເວັ້ນ a ແນ່ນອນ ຊຸດຍ່ອຍ

ຕົວແທນຂອງ Makepp ບໍ່ມີວິທີໃດເລີຍໃນປັດຈຸບັນຂອງການຈັບຄູ່ໄຟລ໌ທັງໝົດ ຍົກເວັ້ນ ທີ່ແນ່ນອນ
ກໍານົດ, ແຕ່ທ່ານສາມາດເຮັດໄດ້ດ້ວຍການປະສົມປະສານຂອງຫນ້າທີ່.

ຕົວຢ່າງ, ສົມມຸດວ່າທ່ານມີໂຄງການທົດສອບສໍາລັບແຕ່ລະໂມດູນໃນຫ້ອງສະຫມຸດ, ແຕ່ເຈົ້າບໍ່ມີ
ຕ້ອງການລວມເອົາໂຄງການທົດສອບຢູ່ໃນຫ້ອງສະຫມຸດ. ຖ້າໂຄງການທົດສອບທັງຫມົດເລີ່ມຕົ້ນດ້ວຍ
ການທົດສອບ, ຫຼັງຈາກນັ້ນທ່ານສາມາດຍົກເວັ້ນພວກເຂົາເຊັ່ນນີ້:

libproduction.a: $(filter_out test*, $(wildcard *.o))

ຟັງຊັນ "$(filter)" ແລະ "$(filter_out)" ເປັນຊຸດຕົວກອງທີ່ມີປະສິດທິພາບຫຼາຍທີ່ຈະເຮັດ.
ທຸກປະເພດຂອງການຕັດກັນທີ່ກໍານົດໄວ້ແລະການປະຕິບັດຄວາມແຕກຕ່າງ. ຍົກ​ຕົວ​ຢ່າງ,

SUBDIRS ;= $(filter_out *test* *$(ARCH)*, $(shell find . -type d -print))
# ສົ່ງຄືນທຸກໄດເລກະທໍລີຍ່ອຍທີ່ບໍ່ມີ
# "ທົດສອບ" ຫຼື $(ARCH) ໃນພວກມັນ.

$(filter $(patsubst test_dir/test_%.o, %.o, $(wildcard test_dir/*.o)),
$(wildcard *.o))
# ສົ່ງຄືນລາຍຊື່ຂອງໄຟລ໌ .o ໃນປະຈຸບັນ
# ໄດເລກະທໍລີທີ່ສອດຄ້ອງກັນ
# test_*.o ໄຟລ໌ຢູ່ໃນໄດເລກະທໍລີຍ່ອຍ test_dir.
$(filter_out $(patsubst man/man3/%.3, %.o, $(wildcard man/man3/*.3)),
$(wildcard *.o))
# ສົ່ງຄືນລາຍຊື່ຂອງໄຟລ໌ .o ໃນປະຈຸບັນ
# ໄດເລກະທໍລີທີ່ບໍ່ມີຫນ້າຄູ່ມື
# ທີ່ມີຊື່ໄຟລ໌ດຽວກັນຢູ່ໃນໄດເລກະທໍລີຍ່ອຍຂອງ man/man3.

ການນໍາໃຊ້ ໄດ້ "$(only_targets )" ຫນ້າທີ່ to ລົບລ້າງ stale .o ໄຟ

ສົມມຸດວ່າທ່ານກໍາລັງສ້າງໂຄງການຫຼືຫ້ອງສະຫມຸດທີ່ມີຄໍາສັ່ງສ້າງເຊັ່ນນີ້:

ໂຄງການ: *.o
$(CC) $(inputs) -o $(output)

ສົມມຸດວ່າຕອນນີ້ເຈົ້າລຶບໄຟລ໌ແຫຼ່ງ. ຖ້າ​ຫາກ​ວ່າ​ທ່ານ​ລືມ​ລົບ​ທີ່​ສອດ​ຄ້ອງ​ກັນ​ .o ແຟ້ມ,
ມັນຈະຍັງຄົງມີການເຊື່ອມໂຍງກັນເຖິງແມ່ນວ່າບໍ່ມີທາງທີ່ຈະສ້າງມັນອີກຕໍ່ໄປ. ໃນ
ໃນອະນາຄົດ, makepp ອາດຈະຮັບຮູ້ສະຖານະການນີ້ໂດຍອັດຕະໂນມັດແລະຍົກເວັ້ນມັນ
ບັນຊີລາຍຊື່ wildcard, ແຕ່ໃນປັດຈຸບັນ, ທ່ານຕ້ອງບອກມັນເພື່ອຍົກເວັ້ນມັນດ້ວຍຕົນເອງ:

ໂປຣແກຣມ: $(only_targets *.o)
$(CC) $(inputs) -o $(outputs)

Makepp ບໍ່ຮູ້ວິທີໃດທີ່ຈະສ້າງ stale ໄດ້ .o ໄຟລ໌ໃດໆນັບຕັ້ງແຕ່ໄຟລ໌ຕົ້ນສະບັບຂອງມັນ
ຫາຍໄປ, ດັ່ງນັ້ນຟັງຊັນ "$(only_targets )" ຈະຍົກເວັ້ນມັນອອກຈາກລາຍຊື່ການເພິ່ງພາອາໄສ.

ຄໍາແນະນໍາ ສໍາລັບການ ຫຼາຍ ໄດເລກະທໍລີ
ຫນຶ່ງໃນເຫດຜົນຕົ້ນຕໍສໍາລັບການຂຽນ makepp ແມ່ນເພື່ອເຮັດໃຫ້ການຈັດການຂອງຫຼາຍງ່າຍດາຍ
ໄດເລກະທໍລີ. Makepp ສາມາດສົມທົບການສ້າງຄໍາສັ່ງຈາກຫຼາຍ makefiles, ສະນັ້ນມັນສາມາດເຮັດໄດ້
ປະຕິບັດຢ່າງຖືກຕ້ອງກັບກົດລະບຽບໃນ makefile ຫນຶ່ງທີ່ຂຶ້ນກັບໄຟລ໌ທີ່ສ້າງຂຶ້ນໂດຍ a
makefile ທີ່​ແຕກ​ຕ່າງ​ກັນ​.

ແມ່ນ​ຫຍັງ to do in ສະຖານທີ່ of ຮຽກຮ້ອງ ເຮັດໃຫ້

Makepp ສະຫນັບສະຫນູນ recursive make ສໍາລັບການເຂົ້າກັນໄດ້ກັບຄືນໄປບ່ອນ, ແຕ່ວ່າມັນແມ່ນແນະນໍາໃຫ້ສູງ
ທີ່ທ່ານ ບໍ່ ໃຊ້​ມັນ. ຖ້າເຈົ້າບໍ່ຮູ້ວ່າມັນແມ່ນຫຍັງ, ດີ.

ເບິ່ງ "ລະບົບທີ່ດີກວ່າສໍາລັບການສ້າງລໍາດັບຊັ້ນ" ໃນ makepp ສໍາລັບລາຍລະອຽດວ່າເປັນຫຍັງທ່ານບໍ່ຕ້ອງການ
ໃຊ້ recursive make, ຫຼືອື່ນໆຄົ້ນຫາຢູ່ໃນເວັບສໍາລັບ "recursive make ພິຈາລະນາເປັນອັນຕະລາຍ".

ແທນທີ່ຈະເຮັດ recursive ເພື່ອເຮັດໃຫ້ເປົ້າຫມາຍ "ທັງຫມົດ" ໃນທຸກ makefile, ມັນແມ່ນ
ປົກກະຕິແລ້ວ ງ່າຍກວ່າທີ່ຈະໃຫ້ makepp ຄິດອອກວ່າເປົ້າໝາຍໃດທີ່ຈະຕ້ອງສ້າງ.
ນອກຈາກນັ້ນ, ຖ້າທ່ານເອົາທັງຫມົດຂອງທ່ານ .o ແລະໄຟລ໌ຫ້ອງສະຫມຸດຢູ່ໃນໄດເລກະທໍລີດຽວກັນກັບ
makefiles, ຫຼັງຈາກນັ້ນ makepp ອັດຕະໂນມັດຈະຄິດອອກວ່າ makefiles ໃດແມ່ນຕ້ອງການເຊັ່ນດຽວກັນ
ສິ່ງດຽວທີ່ຕ້ອງການແມ່ນໃຫ້ມີລະດັບສູງສຸດຂອງເຈົ້າເຮັດໃຫ້ລາຍຊື່ໄຟລ໌ທີ່ຈໍາເປັນ
ສໍາລັບຂັ້ນຕອນການເຊື່ອມໂຍງສຸດທ້າຍ. ເບິ່ງຕົວຢ່າງຂ້າງລຸ່ມນີ້.

ຫນຶ່ງ makefile ສໍາລັບການ ແຕ່ລະຄົນ ໄດເລກະທໍລີ: ກັບ implicit loading

ວິທີທົ່ວໄປທີ່ສຸດໃນການຈັດການຫຼາຍໄດເລກະທໍລີແມ່ນການໃສ່ makefile ໃນແຕ່ລະໄດເລກະທໍລີ
ເຊິ່ງອະທິບາຍວິທີການສ້າງທຸກຢ່າງໃນ ຫຼືຈາກໄດເລກະທໍລີນັ້ນ. ຖ້າເຈົ້າໃສ່ .o ໄຟລ໌ໃນ
ໄດເລກະທໍລີດຽວກັນກັບໄຟລ໌ຕົ້ນສະບັບ, ຫຼັງຈາກນັ້ນການໂຫຼດ implicit (ເບິ່ງ "ການໂຫຼດ implicit" ໃນ
makepp_build_algorithm) ຈະຊອກຫາ makefiles ທັງໝົດໂດຍອັດຕະໂນມັດ. ຖ້າເຈົ້າໃສ່ຂອງເຈົ້າ .o
ໄຟລ໌ຢູ່ໃນໄດເລກະທໍລີທີ່ແຕກຕ່າງກັນ (ຕົວຢ່າງ, ໃນໄດເລກະທໍລີຍ່ອຍທີ່ຂຶ້ນກັບສະຖາປັດຕະຍະກໍາ), ຫຼັງຈາກນັ້ນທ່ານ
ອາດຈະຕ້ອງໄດ້ໂຫລດ makefiles ທີ່ກ່ຽວຂ້ອງທັງຫມົດໂດຍໃຊ້ຄໍາສັ່ງ "load_makefile".

ນີ້ແມ່ນຕົວຢ່າງ makefile ລະດັບສູງສຸດສໍາລັບລໍາດັບຊັ້ນຂອງໄດເລກະທໍລີທີ່ໃຊ້ການໂຫຼດ implicit
ເພື່ອ​ສ້າງ​ໂຄງ​ການ​ທີ່​ປະ​ກອບ​ດ້ວຍ​ຫ້ອງ​ສະ​ຫມຸດ​ແບ່ງ​ປັນ​ຈໍາ​ນວນ​ຫຼາຍ (ແຕ່​ເບິ່ງ "ທ່ານ​ກໍ່​ຕ້ອງ​ການ a
ຫໍສະຫມຸດ?" ໃນ makepp_cookbook, ເນື່ອງຈາກວ່າການສ້າງໂຄງການອອກຈາກຊໍ່ຂອງຫ້ອງສະຫມຸດຮ່ວມກັນ
ບໍ່ຈໍາເປັນຕ້ອງເປັນຄວາມຄິດທີ່ດີ):

# makefile ລະດັບສູງສຸດ:
program : main.o **/*.la # ລິ້ງໃນຫ້ອງສະໝຸດທີ່ແບ່ງປັນຈາກທຸກໄດເລກະທໍລີຍ່ອຍ.
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(inputs) -o $(output) $(LIBS)

ນັ້ນແມ່ນເກືອບທັງຫມົດທີ່ທ່ານຕ້ອງການໃນ makefile ລະດັບເທິງ. ໃນແຕ່ລະໄດເລກະທໍລີຍ່ອຍ, ທ່ານ
ອາດຈະເຮັດບາງສິ່ງບາງຢ່າງເຊັ່ນນີ້:

# Makefile ໃນແຕ່ລະໄດເລກະທໍລີຍ່ອຍ:
include standard_defs.mk # ຄົ້ນຫາ ., .. , ../ .., ແລະອື່ນໆຈົນກ່ວາມັນ
# ຊອກຫາໄຟລ໌ທີ່ລະບຸໄວ້.
# ຍົກເລີກຄຳນິຍາມຕົວແປບາງອັນຢູ່ບ່ອນນີ້
SPECIAL_FLAGS := -do_something_different

ແຕ່ລະ makefile ອາດຈະຄືກັນຫຼາຍຖ້າຄໍາສັ່ງເພື່ອສ້າງເປົ້າຫມາຍ
ແມ່ນຂ້ອນຂ້າງຄ້າຍຄືກັນ.

ໃນ​ທີ່​ສຸດ​, ທ່ານ​ຈະ​ໃສ່​ດັ່ງ​ຕໍ່​ໄປ​ນີ້​ເຂົ້າ​ໄປ​ໃນ​ standard_defs.mk ໄຟລ໌ (ເຊິ່ງອາດຈະເປັນ
ຢູ່ໃນໄດເລກະທໍລີລະດັບສູງສຸດ):

# ການຕັ້ງຄ່າຕົວແປທົ່ວໄປແລະສ້າງກົດລະບຽບສໍາລັບໄດເລກະທໍລີທັງຫມົດ.
CFLAGS := -g -O2
INCLUDE_DIR := $(find_upwards ລວມມີ)
# ຄົ້ນຫາ ., .. , ../ .., ແລະອື່ນໆສໍາລັບໄຟລ໌ຫຼື
# directory ເອີ້ນວ່າປະກອບມີ, ດັ່ງນັ້ນຖ້າທ່ານໃສ່
# ໄຟລ໌ທັງໝົດຂອງເຈົ້າມີຢູ່ໃນນັ້ນ, ນີ້ຈະ
# ຊອກຫາເຂົາເຈົ້າ.
ລວມມີ := -I$(INCLUDE_DIR)

%.lo : %.c
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(INCLUDES) -c $(input) -o $(output)

lib$(relative_to .,..).la: $(only_targets *.lo)
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(output) $(inputs)
# $(relative_to.,..) ສົ່ງຄືນຊື່ຂອງປະຈຸບັນ
# ໄດເລກະທໍລີຍ່ອຍທີ່ກ່ຽວຂ້ອງກັບລະດັບເທິງ
# ໄດເລກະທໍລີຍ່ອຍ. ດັ່ງນັ້ນຖ້າ makefile ນີ້ແມ່ນ xyz / Makefile,
# ກົດລະບຽບນີ້ຈະສ້າງ xyz/libxyz.la.

# ເຜີຍແຜ່ສາທາລະນະປະກອບມີໄຟລ໌ເຂົ້າໄປໃນລະດັບສູງສຸດປະກອບມີໄດເລກະທໍລີ:
$(INCLUDE_DIR)/public_%.h : public_%.h
:build_check symlnk
&ln -fr $(input) $(output)

ຫນຶ່ງ makefile ສໍາລັບການ ແຕ່ລະຄົນ ໄດເລກະທໍລີ: ຢ່າງຊັດເຈນ loading

ຖ້າ​ຫາກ​ວ່າ​ທ່ານ​ຕ້ອງ​ການ​ທີ່​ຈະ​ເອົາ​ທັງ​ຫມົດ​ຂອງ​ທ່ານ​ .o ໄຟລ໌ເຂົ້າໄປໃນໄດເລກະທໍລີຍ່ອຍທີ່ຂຶ້ນກັບສະຖາປັດຕະຍະກໍາ, ຫຼັງຈາກນັ້ນ
ຕົວຢ່າງຂ້າງເທິງນີ້ຄວນຈະຖືກດັດແປງໃຫ້ເປັນບາງສິ່ງບາງຢ່າງເຊັ່ນນີ້:

# makefile ລະດັບສູງສຸດ:
MAKEFILES := $(wildcard **/Makeppfile) # ລາຍການຍ່ອຍຍ່ອຍທັງໝົດເພື່ອ
# ເອົາ makefiles ຈາກ.

load_makefile $(MAKEFILES) # ໂຫຼດພວກມັນທັງໝົດໃນ.

include standard_defs.mk # Get compile command for main.o.

ໂປຣແກຣມ : $(ARCH)/main.o */**/$(ARCH)/*.la
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(inputs) -o $(output) $(LIBS)
# */**/$(ARCH) ບໍ່ລວມໄດເລກະທໍລີຍ່ອຍ
# $(ARCH), ບ່ອນທີ່ພວກເຮົາບໍ່ຕ້ອງການສ້າງ
# ຫ້ອງສະໝຸດທີ່ໃຊ້ຮ່ວມກັນ.

makefile ແຕ່​ລະ​ຄົນ​ຈະ​ຄື​ກັນ​ກັບ​ທີ່​ຜ່ານ​ມາ​:

# Makefile ໃນແຕ່ລະໄດເລກະທໍລີຍ່ອຍ:
ລວມເອົາ standard_defs.mk
# ... ແທນຕົວປ່ຽນໄດ້ທີ່ນີ້

ແລະສຸດທ້າຍ, standard_defs.mk ຈະ​ມີ​ບາງ​ສິ່ງ​ບາງ​ຢ່າງ​ດັ່ງ​ຕໍ່​ໄປ​ນີ້​:

# ການຕັ້ງຄ່າຕົວແປທົ່ວໄປແລະສ້າງກົດລະບຽບສໍາລັບໄດເລກະທໍລີທັງຫມົດ.
ARCH ;= $(shell uname -s)-$(shell uname -m)-$(shell uname -r)
# ບາງຄັ້ງຄົນໃຊ້ພຽງແຕ່ $ (shell uname -m), ແຕ່
# ນີ້ຈະຄືກັນສໍາລັບ FreeBSD ແລະ Linux
# ເປັນ x86. The -r ບໍ່ມີປະໂຫຍດແທ້ໆໃນ Linux,
# ແຕ່ມີຄວາມສໍາຄັນສໍາລັບ OSes ອື່ນໆ: binaries ສໍາລັບ
# ປົກກະຕິແລ້ວ SunOS 5.8 ຈະບໍ່ເຮັດວຽກໃນ SunOS 5.7.
&mkdir -p $(ARCH) # ໃຫ້ແນ່ໃຈວ່າໄດເລກະທໍລີຜົນຜະລິດມີຢູ່.
CFLAGS := -g -O2
INCLUDE_DIR := $(find_upwards ລວມມີ)
# ຄົ້ນຫາ ., .. , ../ .., ແລະອື່ນໆສໍາລັບໄຟລ໌ຫຼື
# directory ເອີ້ນວ່າປະກອບມີ, ດັ່ງນັ້ນຖ້າທ່ານໃສ່
# ໄຟລ໌ທັງໝົດຂອງເຈົ້າມີຢູ່ໃນນັ້ນ, ນີ້ຈະ
# ຊອກຫາເຂົາເຈົ້າ.
ລວມມີ := -I$(INCLUDE_DIR)

$(ARCH)/%.lo : %.c
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(INCLUDES) -c $(input) -o $(output)

$(ARCH)/ lib$(relative_to .,..).la: $(only_targets *.lo)
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(output) $(inputs)
# $(relative_to.,..) ສົ່ງຄືນຊື່ຂອງປະຈຸບັນ
# ໄດເລກະທໍລີຍ່ອຍທີ່ກ່ຽວຂ້ອງກັບລະດັບເທິງ
# ໄດເລກະທໍລີຍ່ອຍ. ດັ່ງນັ້ນຖ້າ makefile ນີ້ແມ່ນ xyz / Makefile,
# ກົດລະບຽບນີ້ຈະສ້າງ xyz/$(ARCH)/libxyz.la.

# ຄັດລອກສາທາລະນະລວມໄຟລ໌ເຂົ້າໄປໃນລະດັບສູງສຸດປະກອບມີໄດເລກະທໍລີ:
$(INCLUDE_DIR)/public_%.h : public_%.h
&cp $(input) $(output)

ອັດຕະໂນມັດ ເຮັດໃຫ້ ໄດ້ makefiles

ຖ້າ makefiles ຂອງທ່ານທັງຫມົດແມ່ນຄ້າຍຄືກັນທີ່ສຸດ (ໃນຕົວຢ່າງຂ້າງເທິງ), ທ່ານສາມາດບອກ Makepp
ເພື່ອສ້າງພວກມັນໂດຍອັດຕະໂນມັດຖ້າພວກເຂົາບໍ່ມີ. ພຽງ​ແຕ່​ເພີ່ມ​ການ​ຕໍ່​ໄປ​ນີ້​ໃນ​ລະ​ດັບ​ສູງ​ສຸດ​ຂອງ​ທ່ານ​
makefile:

SUBDIRS := $(filter_out unwanted_dir1 unwanted_dir2, $(wildcard */**))
$(foreach)/Makeppfile: : foreach $(SUBDIRS)
&echo "include standard_defs.mk" -o $(output)
&echo "_include additional_defs.mk" -o >>$(output)
# ຖ້າມີໄຟລ໌ເພີ່ມເຕີມ_defs.mk, ຫຼັງຈາກນັ້ນ
# ມັນຈະຖືກລວມ, ແຕ່ຖ້າມັນບໍ່ມີ,
# ຄຳຖະແຫຼງການ _include ຈະຖືກລະເລີຍ.

ໃນປັດຈຸບັນ makefiles ຕົວເອງຈະຖືກສ້າງຂື້ນໂດຍອັດຕະໂນມັດ.

ຫນຶ່ງ makefile ພຽງແຕ່ at ໄດ້ top ລະດັບ

ຖ້າ makefiles ທັງໝົດຂອງເຈົ້າຄືກັນ, ເຈົ້າອາດຈະຖາມວ່າ: ເປັນຫຍັງຂ້ອຍຈຶ່ງຕ້ອງມີ makefile ແຕ່ລະອັນ
ລະດັບ? ເປັນຫຍັງຈຶ່ງບໍ່ເອົາສິ່ງນັ້ນເຂົ້າໄປໃນ makefile ລະດັບສູງສຸດ?

ແມ່ນແລ້ວ, ນີ້ສາມາດເຮັດໄດ້. ຂໍ້ເສຍຕົ້ນຕໍແມ່ນວ່າມັນຈະກາຍເປັນການຍາກທີ່ຈະລະບຸ
ທາງເລືອກໃນການສ້າງທີ່ແຕກຕ່າງກັນສໍາລັບແຕ່ລະ subdirectory. ຂໍ້​ເສຍ​ທີ່​ສອງ​ແມ່ນ​ວ່າ​ຂອງ​ທ່ານ​
makefile ອາດຈະອ່ານຍາກກວ່າ.

ນີ້ແມ່ນຕົວຢ່າງຂອງການເຮັດພຽງແຕ່ວ່າ:

# makefile ລະດັບສູງສຸດສໍາລັບລໍາດັບຊັ້ນຂອງໄດເລກະທໍລີ. ສ້າງໂຄງການ
# ອອກຈາກຊຸດຂອງຫ້ອງສະຫມຸດທີ່ໃຊ້ຮ່ວມກັນເປັນຕົວຢ່າງ. (ເບິ່ງຄໍາເຕືອນຂ້າງເທິງ
# ສໍາລັບເຫດຜົນທີ່ທ່ານອາດຈະຕ້ອງການໃຊ້ການເຊື່ອມໂຍງແບບເພີ່ມຫຼືບາງອັນ
# ວິທີການແທນທີ່ຈະເປັນຫ້ອງສະຫມຸດຮ່ວມກັນ.)
makepp_percent_subdirs := 1 # ອະນຸຍາດໃຫ້ % ກົງກັບຫຼາຍໄດເລກະທໍລີ.
SUBDIRS := $(filter_out *CVS* other-unwanted_dirs $(wildcard **))
CFLAGS := -g -O2
ລວມມີ := -Includes

%.lo: %.c
$(LIBTOOL) --mode=compile $(CC) $(INCLUDES) $(CFLAGS) -c $(input) -o $(output)

$(foreach)/ lib$(notdir $(foreach)).la: $(foreach)/*.lo : foreach $(SUBDIRS)
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(output) $(inputs)
# ກົດລະບຽບການສ້າງຫ້ອງສະຫມຸດທັງຫມົດ.

ໂປຣແກຣມ : main.o **/*.la
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(output) $(inputs)

include/$(notdir $(foreach)): $(foreach): foreach **/public_*.h
&cp $(input) $(output)
# ກົດລະບຽບຕົວຢ່າງສໍາລັບການຄັດລອກສາທາລະນະ
# ໄຟລ໌ .h ທີ່ສາມາດເຂົ້າເຖິງໄດ້ໃນບ່ອນທີ່ຖືກຕ້ອງ.

A ເຮັດຄວາມສະອາດ ເປົ້າ​ຫມາຍ

makefiles ແບບດັ້ງເດີມປະກອບດ້ວຍເປົ້າຫມາຍທີ່ສະອາດ, ເຊິ່ງອະນຸຍາດໃຫ້ເອົາທຸກສິ່ງທຸກຢ່າງທີ່ເປັນ
ສ້າງ. ມີສາມເຫດຜົນວ່າເປັນຫຍັງທ່ານບໍ່ຄວນເຮັດສິ່ງນີ້ກັບ makepp:

1. Makepp ໄປສູ່ຄວາມຍາວຫຼາຍເພື່ອຮັບປະກັນການສ້າງທີ່ຖືກຕ້ອງ. ດັ່ງ​ນັ້ນ​ຜູ້​ທີ່​ສິ້ນ​ຫວັງ "ຂ້າ​ພະ​ເຈົ້າ​ບໍ່​ໄດ້
ຮູ້ວ່າແມ່ນຫຍັງຜິດ", ການເຮັດໃຫ້ທ່ານຕ້ອງການທີ່ຈະເລີ່ມຕົ້ນຈາກ scratch ແມ່ນສິ່ງທີ່ຜ່ານມາ.

2. ບາງຄັ້ງຄົນເຮົາຈະພະຍາຍາມປະຢັດເວລາໂດຍການເຮັດສອງຢ່າງທີ່ຂັດກັນໃນເວລາດຽວກັນ:
"ເຮັດໃຫ້ສະອາດທັງຫມົດ". ນີ້ສາມາດສັບສົນລະບົບ wildcard smart ຂອງ makepp, ເພາະວ່າມັນຈະ
ທໍາອິດໄດ້ຮັບຄວາມຈິງກ່ອນທີ່ຈະເຮັດຫຍັງ. ຫຼັງຈາກນັ້ນ, ການປະຕິບັດທີ່ສະອາດ, ເຊິ່ງເຮັດ
ຢ່າບອກ makepp ວ່າມັນເຮັດຫຍັງ (ແທ້ຈິງແລ້ວມັນເຮັດບໍ່ໄດ້, ເພາະວ່າມັນຍົກເລີກບາງສິ່ງບາງຢ່າງ - the
ກົງກັນຂ້າມກັບສິ່ງທີ່ເຄື່ອງມືສ້າງແມ່ນສໍາລັບ). ຫຼັງຈາກນັ້ນ, ມາ "ທັງຫມົດ", ແຕ່ໄຟລ໌ທີ່ທັນສະໄຫມ,
ບ່ອນທີ່ມີ, ຫາຍໄປຢ່າງລຶກລັບ.

3. ມີຄໍາສັ່ງ "makeppclean", ເຊິ່ງເຮັດສິ່ງດຽວກັນ, ແລະມີປະສິດທິພາບຫຼາຍຂຶ້ນ.

ຢ່າງໃດກໍຕາມ, ພວກເຮົາຍັງຄົງຮັກສາພາກປະຫວັດສາດນີ້, ເນື່ອງຈາກວ່າມັນບອກທ່ານບາງສິ່ງບາງຢ່າງກ່ຽວກັບ
ວິທີການ makepp ເຮັດວຽກ: ເປົ້າຫມາຍ phony ເອີ້ນວ່າ "ສະອາດ" ແມ່ນພຽງແຕ່ຊື່ສໍາລັບຊຸດຂອງຄໍາສັ່ງທີ່ຈະ
ເອົາໄຟລ໌ທັງຫມົດທີ່ມາຈາກຂະບວນການຜະລິດ. ປົກກະຕິແລ້ວເປົ້າຫມາຍທີ່ສະອາດເບິ່ງ
ບາງສິ່ງບາງຢ່າງເຊັ່ນນີ້:

$(ລ້າງ​ຜິດ​ພາດ):
&rm -fm $(wildcard *.o .makepp_log)
# -m ແລະ .makepp_log ກໍາຈັດຂີ້ເຫຍື້ອທັງໝົດຂອງ makepp.

ແທນ​ທີ່​ຈະ​ລາຍ​ຊື່​ໄຟລ​໌​ທີ່​ທ່ານ​ຕ້ອງ​ການ​ລຶບ​ຢ່າງ​ຊັດ​ເຈນ​, ທ່ານ​ຍັງ​ສາ​ມາດ​ບອກ makepp ກັບ​
ເອົາທຸກສິ່ງທຸກຢ່າງທີ່ມັນຮູ້ວິທີການສ້າງ, ເຊັ່ນນີ້:

$(ລ້າງ​ຜິດ​ພາດ):
&rm -fm .makepp_log $(only_targets *)

ນີ້ມີປະໂຍດທີ່ວ່າຖ້າໄຟລ໌ໃດໆຂອງແຫຼ່ງຂອງທ່ານສາມາດສ້າງຈາກໄຟລ໌ອື່ນໆ,
ພວກມັນຈະຖືກລຶບຄືກັນ; ໃນອີກດ້ານຫນຶ່ງ, stale .o ໄຟລ໌ (ໄຟລ໌ທີ່ເຄີຍເປັນ
buildable ແຕ່​ວ່າ​ໄຟລ​໌​ທີ່​ມາ​ຂອງ​ຕົນ​ໄດ້​ຖືກ​ລົບ​ອອກ​ນັບ​ຕັ້ງ​ແຕ່​) ຈະ​ບໍ່​ໄດ້​ຮັບ​ການ​ລຶບ​.

ຖ້າ​ຫາກ​ວ່າ​ທ່ານ​ມີ​ການ​ກໍ່​ສ້າງ​ທີ່​ກ່ຽວ​ຂ້ອງ​ກັບ makefiles ໃນ​ລະ​ບົບ​ທີ່​ແຕກ​ຕ່າງ​ກັນ​ຫຼາຍ​, ທາງ​ເທິງ​ຂອງ​ທ່ານ​.
makefile ລະດັບອາດຈະອ້າງເຖິງເປົ້າຫມາຍ "ສະອາດ" (ຫຼືເປົ້າຫມາຍ phony ອື່ນໆ) ໃນທີ່ແຕກຕ່າງກັນ
makefile:

# makefile ລະດັບສູງສຸດ
SUBDIRS := sub1 sub2

# ສ້າງກົດລະບຽບຢູ່ທີ່ນີ້

# ອະນາໄມຫຼັງການກໍ່ສ້າງ:
$(phony clean): $(SUBDIRS)/ສະອາດ
&rm -fm .makepp_log $(only_targets *)

ອີກທາງເລືອກ, ທ່ານສາມາດວາງເປົ້າຫມາຍ "ສະອາດ" ຂອງທ່ານໃນ makefile ລະດັບສູງສຸດ, ແລະມີມັນ
ດໍາເນີນການທັງຫມົດຂອງໄດເລກະທໍລີ, ເຊັ່ນນີ້:

$(ລ້າງ​ຜິດ​ພາດ):
&rm -fm $(ພຽງ_ເປົ້າໝາຍ **/*)

ການນໍາໃຊ້ Qt ຂອງ ໂປເຊດເຊີກ່ອນ
ຕົວຢ່າງນີ້ສະແດງໃຫ້ເຫັນ makefile ສໍາລັບຜົນປະໂຫຍດທີ່ນໍາໃຊ້ຫ້ອງສະຫມຸດ Qt GUI ຂອງ Nokia (ເບິ່ງ
<http://qt.nokia.com>). ສິ່ງດຽວທີ່ຜິດປົກກະຕິເລັກນ້ອຍກ່ຽວກັບເລື່ອງນີ້ແມ່ນເຈົ້າ
ຕ້ອງດໍາເນີນການ preprocessor ທີ່ເອີ້ນວ່າ "moc" ໃນໄຟລ໌ ".h" ສ່ວນໃຫຍ່ທີ່ມີຄໍານິຍາມ widget,
ແຕ່ທ່ານບໍ່ຕ້ອງການແລ່ນ "moc" ໃນໄຟລ໌ ".h" ໃດໆກໍຕາມທີ່ບໍ່ໄດ້ໃຊ້ມາໂຄຣ "Q_OBJECT".

ອັດຕະໂນມັດ ການ ກຳ ນົດ ທີ່ ໄຟ ຕ້ອງການ ໄຟ

ທ່ານສາມາດ, ແນ່ນອນ, ພຽງແຕ່ບັນຊີລາຍຊື່ທັງຫມົດຂອງໄຟລ໌ ".h" ທີ່ຈໍາເປັນຕ້ອງມີ "moc" ດໍາເນີນການໃຫ້ເຂົາເຈົ້າ.
ຢ່າງໃດກໍຕາມ, ຖ້າທ່ານກໍາລັງພັດທະນາ widget ໃຫມ່ຢ່າງໄວວາ, ມັນອາດຈະເປັນສິ່ງລົບກວນ
ສືບຕໍ່ປັບປຸງບັນຊີລາຍຊື່ໃນ makefile. ທ່ານສາມາດໄດ້ຮັບປະມານຄວາມຕ້ອງການທີ່ຈະລາຍຊື່ moc ໄດ້
ໂມດູນຢ່າງຊັດເຈນກັບບາງສິ່ງບາງຢ່າງເຊັ່ນນີ້:

MOC := $(QTDIR)/bin/moc
ໂມດູນ := ໂມດູນໃດກໍ່ຕາມທີ່ເຈົ້າມີຢູ່ໃນໂປຼແກຼມຂອງເຈົ້າ
MOC_MODULES := $(patsubst %.h, moc_%, $(&grep -l /Q_OBJECT/ *.h))
# ສະແກນໄຟລ໌ .h ທັງໝົດສຳລັບ Q_OBJECT macro.

my_program: $(MODULES).o $(MOC_MODULES).o
$(CXX) $(inputs) -o $(output)

moc_%.cxx: %.h # ເຮັດໃຫ້ໄຟລ໌ moc ຈາກໄຟລ໌ .h.
$(MOC) $(input) -o $(output)

%.o: %.cxx
$(CXX) $(CXXFLAGS) -c $(input) -o $(output)

ວິທີນີ້ສະແກນແຕ່ລະອັນຂອງເຈົ້າ .h ໄຟລ໌ທຸກຄັ້ງທີ່ makepp ຖືກແລ່ນ, ຊອກຫາ
"Q_OBJECT" ມະຫາພາກ. ຟັງຄືວ່າແພງ, ແຕ່ມັນອາດຈະໃຊ້ເວລາບໍ່ດົນ. (ໄດ້ .h
ໄຟລ໌ທັງຫມົດຈະຕ້ອງຖືກໂຫລດຈາກແຜ່ນຢ່າງໃດກໍ່ຕາມໂດຍຂະບວນການລວບລວມ, ດັ່ງນັ້ນພວກມັນຈະ
ຖືກເກັບໄວ້.)

#include ໄດ້ .moc ເອກະສານ

ວິທີການອື່ນແມ່ນເພື່ອ "#include" ຜົນຜະລິດຈາກ preprocessor "moc" ໃນ widget ຂອງທ່ານ.
ເອກະສານການຈັດຕັ້ງປະຕິບັດ. ນີ້ຫມາຍຄວາມວ່າທ່ານຕ້ອງຈື່ຈໍາທີ່ຈະຂຽນ "#include", ແຕ່ມັນມີ
ປະໂຫຍດທີ່ມີໂມດູນຫນ້ອຍທີ່ຈະລວບລວມ, ແລະດັ່ງນັ້ນການລວບລວມໄວຂຶ້ນ.
(ສໍາລັບການລວບລວມ C ++ ສ່ວນໃຫຍ່, ເວລາສ່ວນໃຫຍ່ໃຊ້ເວລາໃນການອ່ານໄຟລ໌ header, ແລະ
ຜົນຜະລິດຈາກໂປເຊດເຊີ preprocessor ຈໍາເປັນຕ້ອງປະກອບມີໄຟລ໌ເກືອບຈໍານວນຫຼາຍເທົ່າກັບ widget ຂອງທ່ານ
ແລ້ວ.) ຕົວຢ່າງ:

// my_widget.h
class MyWidget : public QWidget {
Q_OBJECT
//...
}

// my_widget.cpp

#ລວມທັງ "my_widget.h"
#include "my_widget.moc" // my_widget.moc ແມ່ນຜົນຜະລິດຈາກ
// moc preprocessor.
// ສິ່ງທີ່ປະຕິບັດອື່ນໆຢູ່ທີ່ນີ້.
MyWidget::MyWidget(QWidget * parent, const char * name):
QWidget(ພໍ່ແມ່, ຊື່)
{
//...
}

ໃນປັດຈຸບັນທ່ານຈໍາເປັນຕ້ອງມີກົດລະບຽບໃນ makefile ຂອງທ່ານເພື່ອເຮັດໃຫ້ໄຟລ໌ ".moc", ທັງຫມົດເຊັ່ນນີ້:

MOC := $(QTDIR)/bin/moc
# ກົດລະບຽບການສ້າງໄຟລ໌ .moc:
%.moc: %.h
$(MOC) $(input) -o $(output)

Makepp ມີຄວາມສະຫຼາດພໍທີ່ຈະຮູ້ວ່າມັນຈໍາເປັນຕ້ອງສ້າງ "my_widget.moc" ຖ້າມັນບໍ່ມີ
ມີຢູ່ແລ້ວ, ຫຼືຖ້າມັນລ້າສະໄຫມ.

ວິທີທີສອງນີ້ແມ່ນວິທີທີ່ຂ້ອຍໃຊ້ເລື້ອຍໆເພາະວ່າມັນເລັ່ງການລວບລວມຂໍ້ມູນ.

ການທົດແທນ ສໍາລັບການ ບໍ່ເຫັນແກ່ຕົວ ເຮັດໃຫ້ ສໍານວນ
MAKECMDGOALS

ບາງຄັ້ງຄົນມີກົດລະບຽບໃນ makefile ຂອງເຂົາເຈົ້າຂຶ້ນກັບສິ່ງທີ່ເປົ້າຫມາຍທີ່ເຂົາເຈົ້າກໍາລັງສ້າງ,
ການນໍາໃຊ້ຕົວແປພິເສດ "MAKECMDGOALS". ຕົວຢ່າງ, ບາງຄັ້ງຄົນຫນຶ່ງເຫັນສິ່ງຕ່າງໆເຊັ່ນ
ນີ້:

ifneq ($(ການຜະລິດການກັ່ນຕອງ, $(MAKECMDGOALS)),)
CFLAGS := -O2
ອື່ນ
CFLAGS := -g
ສິ້ນສຸດ

ນີ້ຈະເຮັດວຽກໄດ້ດີກັບ makepp. ຢ່າງໃດກໍຕາມ, ຂ້າພະເຈົ້າແນະນໍາໃຫ້ບໍ່ໃຊ້ "MAKEMDGOALS" ສໍາລັບການດັ່ງກ່າວ
ກໍລະນີ (ແລະ GNU ກໍ່ເຮັດຄູ່ມື). ທ່ານກໍາລັງດີກວ່າການວາງ optimized ຂອງທ່ານແລະ
debug-compiled .o ໄຟລ໌ຢູ່ໃນໄດເລກະທໍລີແຍກຕ່າງຫາກ, ຫຼືໃຫ້ພວກເຂົາມີຄໍານໍາຫນ້າທີ່ແຕກຕ່າງກັນຫຼື
suffixes, ຫຼືການນໍາໃຊ້ repositories, ເພື່ອຮັກສາໃຫ້ເຂົາເຈົ້າແຍກຕ່າງຫາກ.

ອາດຈະເປັນເວລາດຽວທີ່ເຈົ້າອາດຈະຕ້ອງການອ້າງອີງ "MAKECMDGOALS" ແມ່ນຖ້າມັນ
ໃຊ້ເວລາດົນໃນການໂຫຼດ makefiles ຂອງທ່ານ, ແລະທ່ານບໍ່ຕ້ອງການມັນສໍາລັບ "ສະອາດ" ເປົ້າຫມາຍຂອງທ່ານ
(ແຕ່ທ່ານບໍ່ຕ້ອງການເປົ້າຫມາຍທີ່ສະອາດ). ຍົກ​ຕົວ​ຢ່າງ,

ifneq ($(MAKECMDGOALS),ສະອາດ)
load_makefile $(wildcard **/Makeppfile)
ອື່ນ
no_implicit_load . # ປ້ອງກັນການໂຫຼດອັດຕະໂນມັດຂອງ makefiles ອື່ນໆ.
ສິ້ນສຸດ

$(ລ້າງ​ຜິດ​ພາດ):
&rm -f $(wildcard **/*.o)

ປະກົດຕົວ ເຮັດໃຫ້ to ການກໍ່ສ້າງ in ທີ່ແຕກຕ່າງກັນ ໄດເລກະທໍລີ

ເບິ່ງ "ຄໍາແນະນໍາສໍາລັບຫຼາຍໄດເລກະທໍລີ" ໃນ makepp_cookbook.

ປະກົດຕົວ ເຮັດໃຫ້ to ການປ່ຽນແປງ ມູນຄ່າ of a ຕົວແປ

ບາງ makefiles reinvoke ຕົວເອງດ້ວຍຄ່າທີ່ແຕກຕ່າງກັນຂອງຕົວແປ, ເຊັ່ນ: debug
ເປົ້າຫມາຍໃນຊິ້ນ makefile ຕໍ່ໄປນີ້

.PHONY: ດີບັກທັງໝົດ

ປັບໃຫ້ເໝາະສົມ:
$(MAKE) ໂປຣແກຣມ CFLAGS=-O2

ດີບັກ:
$(MAKE) ໂປຣແກຣມ CFLAGS=-g

ໂຄງການ: ao bo
$(CC) $(CFLAGS) $^ -o $@

%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@

ຖ້າຜູ້ໃຊ້ພິມ "ເຮັດການດີບັກ", ມັນຈະສ້າງໂຄງການໃນໂຫມດເລີ່ມຕົ້ນດ້ວຍການເປີດໃຊ້ການດີບັກ
ແທນທີ່ຈະມີການເພີ່ມປະສິດທິພາບ.

ວິທີການທີ່ດີກວ່າທີ່ຈະເຮັດມັນແມ່ນການສ້າງສອງໂຄງການທີ່ແຕກຕ່າງກັນ, ມີສອງຊຸດທີ່ແຕກຕ່າງກັນ
ໄຟລ໌ວັດຖຸ, ເຊັ່ນນີ້:

CFLAGS := -O2
DEBUG_FLAGS := -g
ໂມດູນ := ab

ໂປຣແກຣມ: $(MODULES).o
$(CC) $(CFLAGS) $(inputs) -o $(output)

debug/program: debug/$(MODULES).o
$(CC) $(DEBUG_FLAGS) $(inputs) -o $(output)

%.o : %.c
$(CC) $(CFLAGS) -c $(input) -o $(output)

debug/%.o : %.c
$(CC) $(DEBUG_FLAGS) -c $(input) -o $(output)

$(ດີບັກ phony): debug/ໂຄງການ

ປະໂຫຍດຂອງການເຮັດມັນດ້ວຍວິທີນີ້ແມ່ນ (a) ທ່ານບໍ່ຈໍາເປັນຕ້ອງສ້າງໃຫມ່ທັງຫມົດໃນເວລາທີ່ທ່ານ
ປ່ຽນຈາກ debug ໄປຫາ optimized ແລະກັບຄືນໄປບ່ອນອີກເທື່ອຫນຶ່ງ; (ຂ)

ຂ້າງເທິງສາມາດຂຽນໄດ້ຊັດເຈນກວ່າໂດຍໃຊ້ repositories. ຕໍ່ໄປນີ້
makefile ແມ່ນແທ້ທຽບເທົ່າ:

repository debug=. # ເຮັດໃຫ້ໄດເຣັກທໍຣີຍ່ອຍດີບັກມີລັກສະນະເປັນສຳເນົາຂອງ
# ໄດເລກະທໍລີຍ່ອຍໃນປະຈຸບັນ.
load_makefile debug CFLAGS=-g
# ລົບລ້າງ CFLAGS ເມື່ອຖືກເອີ້ນຢູ່ໃນໄດເຣັກທໍຣີຍ່ອຍດີບັກ
CFLAGS := -O2 # ມູນຄ່າຂອງ CFLAGS ເມື່ອຖືກເອີ້ນຢູ່ໃນໄດເລກະທໍລີຍ່ອຍນີ້

ໂຄງການ: ao bo
$(CC) $(CFLAGS) $^ -o $@

%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@

$(ດີບັກ phony): debug/ໂຄງການ
# ຖ້າຜູ້ໃຊ້ພິມ "makepp debug", ກໍ່ສ້າງ
# debug/program ແທນໂຄງການ.

Miscellaneous ຄໍາແນະນໍາ
ວິທີການ do I ການກໍ່ສ້າງ ຫນຶ່ງ ສ່ວນ ແຕກຕ່າງກັນ ພຽງແຕ່ ຄັ້ງດຽວ?

Makepp ເຮັດໃຫ້ມັນຍາກທີ່ຈະເຮັດເພາະວ່າຜົນໄດ້ຮັບແມ່ນບໍ່ສອດຄ່ອງກັບກົດລະບຽບ.
ແຕ່ມີສະຖານະການທີ່ທ່ານອາດຈະຕ້ອງການນີ້, ເຊັ່ນ: ການລວບລວມພຽງແຕ່ຫນຶ່ງໂມດູນກັບ
ຂໍ້​ມູນ​ການ​ແກ້​ໄຂ​ຢ່າງ​ຮຸນ​ແຮງ​. ທ່ານ​ສາ​ມາດ​ບັນ​ລຸ​ໄດ້​ໃນ​ສອງ​ຂັ້ນ​ຕອນ​ໂດຍ​ການ​ສ້າງ​ຄັ້ງ​ທໍາ​ອິດ​
ການເພິ່ງພາອາໄສແຍກຕ່າງຫາກ, ແລະຫຼັງຈາກນັ້ນຍົກເວັ້ນມັນຈາກໄລຍະການເຊື່ອມໂຍງ:

makepp DEBUG=3 buggy.o # ສ້າງມັນດ້ວຍທາງເລືອກອື່ນ.
makepp --dont-build=buggy.o buggy # ໃຊ້ມັນ, ເຖິງແມ່ນວ່າ "ຜິດ" ທາງເລືອກການກໍ່ສ້າງ.

ວິທີການ do I ເຮັດໃຫ້ ໃຫ້ແນ່ໃຈວ່າ my output ໄດເລກະທໍລີ ມີຢູ່?

ທ່ານ​ສາ​ມາດ​ກໍາ​ນົດ​ກົດ​ລະ​ບຽບ​ການ​ສ້າງ​ລາຍ​ການ​ຜົນ​ຜະ​ລິດ​ໄດ້​, ຫຼັງ​ຈາກ​ນັ້ນ​ເຮັດ​ໃຫ້​ແນ່​ໃຈວ່​າ​ແຕ່​ລະ​ໄຟລ​໌​ທີ່​
ໄປຢູ່ໃນໄດເລກະທໍລີຜົນຜະລິດແມ່ນຂຶ້ນກັບມັນ. ແຕ່ປົກກະຕິແລ້ວມັນງ່າຍກວ່າທີ່ຈະເຮັດບາງສິ່ງບາງຢ່າງເຊັ່ນ:
ນີ້:

# ວິທີຄລາສສິກ
dummy := $(ການທົດສອບແກະ -d $(OUTPUT_DIRECTORY) || mkdir -p $(OUTPUT_DIRECTORY))
# ນີ້ປົກກະຕິແລ້ວແມ່ນງ່າຍກວ່າການເຮັດໃຫ້ໄຟລ໌ທັງຫມົດຂຶ້ນກັບ
# $(OUTPUT_DIRECTORY) ແລະມີກົດລະບຽບເພື່ອເຮັດໃຫ້ມັນ.
# ໃຫ້ສັງເກດວ່າເຈົ້າຕ້ອງໃຊ້ := ແທນ = ເພື່ອບັງຄັບມັນ
# ປະຕິບັດທັນທີ.
# ວິທີການທາງເລືອກ: ການນໍາໃຊ້ລະຫັດ Perl, OUTPUT_DIRECTORY local var
perl_begin
-d $OUTPUT_DIRECTORY ຫຼື mkdir $OUTPUT_DIRECTORY;
perl_end
# ວິທີການທີ່ທັນສະໄຫມ, ບໍ່ມີຫຍັງສໍາລັບໄດເລກະທໍລີທີ່ມີຢູ່
&mkdir -p $(OUTPUT_DIRECTORY)

ຫນຶ່ງໃນຄໍາຖະແຫຼງເຫຼົ່ານີ້ຄວນຈະຢູ່ໃກ້ກັບດ້ານເທິງຂອງ makefile ຂອງທ່ານ, ດັ່ງນັ້ນພວກມັນຈະຖືກປະຕິບັດ
ກ່ອນທີ່ຈະມີສິ່ງໃດແດ່ທີ່ອາດຈະຕ້ອງການໄດເລກະທໍລີ.

ວິທີການ do I ຜົນບັງຄັບໃຊ້ a ຄໍາສັ່ງ to ປະຕິບັດ on ທຸກ ສ້າງ?

ວິທີທີ່ງ່າຍທີ່ສຸດແມ່ນບໍ່ໃຊ້ກົນໄກກົດລະບຽບທັງຫມົດ, ແຕ່ພຽງແຕ່ປະຕິບັດມັນ, ເຊັ່ນ:
ນີ້:

dummy := $(ວັນທີແກະ > last_build_timestamp)

ຫຼືເອົາໃສ່ໃນບລັອກ perl, ແບບນີ້:

perl_begin
system("ສັ່ງ​ໃຫ້​ປະ​ຕິ​ບັດ");
perl_end

ວິທີການນີ້ມີຂໍ້ເສຍທີ່ມັນຈະຖືກປະຕິບັດເຖິງແມ່ນວ່າເປົ້າຫມາຍທີ່ບໍ່ກ່ຽວຂ້ອງ
ກໍາລັງດໍາເນີນການ.

ວິທີການທີສອງແມ່ນເພື່ອປະກາດໄຟລ໌ເປັນເປົ້າຫມາຍ phony, ເຖິງແມ່ນວ່າມັນເປັນໄຟລ໌ທີ່ແທ້ຈິງ.
ນີ້ຈະບັງຄັບໃຫ້ makepp ປະຕິບັດຄໍາສັ່ງໃຫມ່ເພື່ອສ້າງມັນທຸກຄັ້ງ, ແຕ່ວ່າພຽງແຕ່ຖ້າມັນ
ປາກົດຢູ່ໃນບັນຊີລາຍຊື່ການເພິ່ງພາອາໄສຂອງກົດລະບຽບບາງຢ່າງ.

ວິທີການ do I ສັ້ນ ໄດ້ ສະແດງ ການກໍ່ສ້າງ ຄໍາສັ່ງ?

ມັກຈະມີຫຼາຍທາງເລືອກໃນການລວບລວມຄໍາສັ່ງທີ່ສະແດງຢູ່ໃນ
ໜ້າຈໍບໍ່ສາມາດອ່ານໄດ້. ທ່ານສາມາດປ່ຽນສິ່ງທີ່ສະແດງໂດຍການສະກັດກັ້ນການສະແດງຂອງ
ຄໍາສັ່ງທັງຫມົດ, ແລະຫຼັງຈາກນັ້ນພິມອອກຢ່າງຊັດເຈນສ່ວນທີ່ຫນ້າສົນໃຈຂອງຄໍາສັ່ງ. ມັນ
ງ່າຍທີ່ຈະພິມອອກພຽງແຕ່ສ່ວນທີ່ກ່ຽວຂ້ອງຂອງຄໍາສັ່ງໂດຍໃຊ້ "$(filter_out )", ເຊັ່ນ:
ນີ້:

ALL_CFLAGS = $(CFLAGS) $(INCLUDES) $(ADDL_CXX_FLAGS) $(DEBUG_FLAGS)

%.o : %.c
@&echo $(notdir $(CC)) ...
$(filter_out -I* $(ADDL_CXX_FLAGS), $(ALL_CFLAGS))
-c $(ປ້ອນຂໍ້ມູນ)
@$(CC) $(ALL_CFLAGS) -c $(input) -o $(output)

("@" ຢູ່ທາງຫນ້າຂອງຄໍາສັ່ງສະກັດກັ້ນການພິມອອກຄໍາສັ່ງ.)

ນີ້ຈະຊ່ວຍໃຫ້ທ່ານເຫັນຕົວເລືອກທີ່ຫນ້າສົນໃຈຫຼາຍທີ່ສຸດແຕ່ຈະບໍ່ສະແດງທັງຫມົດ
ປະ​ກອບ​ມີ​ບັນ​ຊີ​ລາຍ​ການ (ຊຶ່ງ​ໃນ​ນັ້ນ​ມັກ​ຈະ​ມີ​ຫຼາຍ​ຫຼາຍ​!). ຖ້າພາກສ່ວນທີ່ເຈົ້າສົນໃຈ
in ແມ່ນຕິດຕໍ່ກັນໃນຄໍາສັ່ງຂອງທ່ານ, ທ່ານຍັງສາມາດໃຊ້ຟັງຊັນ "ພິມ" (ເຊິ່ງເພີ່ມ a
ແຖວໃໝ່, ສະນັ້ນເຈົ້າບໍ່ຕ້ອງການຫຼາຍອັນ):

ເປົ້າ​ຫມາຍ:
@... $(ພິມໜ້າສົນໃຈ)...

ວິທີການ do I ແປງ a ເອກະສານ ເຂົ້າໄປໃນ ການເພິ່ງພາອາໄສ?

ສໍາລັບບາງຮູບແບບໄຟລ໌ທີ່ບໍ່ຊັດເຈນ, ມັນບໍ່ຄຸ້ມຄ່າທີ່ຈະປະຕິບັດເຄື່ອງສະແກນ. ໃນໂຄງການຫນຶ່ງ
ພວກເຮົາມີໄຟລ໌ xml, ເວົ້າ foobar.xml ເຊິ່ງປະກອບດ້ວຍການເພິ່ງພາອາໄສ foobar.out:







ພວກເຮົາຕັດສິນໃຈປະຕິບັດຕາມຮູບແບບທີ່ງ່າຍດາຍນີ້, ດັ່ງນັ້ນພວກເຮົາບໍ່ຈໍາເປັນຕ້ອງວິເຄາະ xml. ກັບ
buildin & sed, ນີ້ແມ່ນສິ່ງທີ່ພວກເຮົາເຮັດດ້ວຍການທົດແທນທີ່ງ່າຍດາຍສາມຢ່າງສໍາລັບສາມປະເພດຂອງ
ສາຍ:

%.d: %.xml
&sed's! !$(stem).ອອກ: \\! || ສ! (.+) !$$1 \\! || ສ! !# ຫວ່າງ!'
$(input) -o $(output)

ລວມ foobar.d

ພະຍາຍາມລວມເອົາອັນນີ້, ຜະລິດ "foobar.d" ທໍາອິດ:

foobar.out:
a
b
c
# ຫວ່າງ

ຫວ່າງເປົ່າ (ພຽງແຕ່ຄໍາຄິດເຫັນຫຼືຫວ່າງເປົ່າແທ້ໆ) ຫຼີກລ້ຽງການທີ່ຈະກັງວົນກ່ຽວກັບການຕິດຕາມ
backslash. ທາງເລືອກໃນການຜະລິດບັນຊີລາຍຊື່ຫຼາຍແຖວແມ່ນ:

%.d: %.xml
&sed's! !$(stem).ອອກ: \$$((! ||s! !))! || s!<.+?>!!g'
$(input) -o $(output)

ລວມ foobar.d

ນີ້ຜະລິດທຽບເທົ່າ:

foobar.out: $((
a
b
c
))

ຖ້າທ່ານມີການຂຽນຄືນໃຫມ່ທີ່ສັບສົນຫຼາຍ, ໃຫ້ກໍານົດຫນ້າທີ່ພາຍໃນ makefile ຫຼືໃນ a
ໂມດູນທີ່ທ່ານປະກອບມີ. ເຊັ່ນ: ການບໍ່ກຳນົດ $_ ຈະຂ້າມສາຍການປ້ອນຂໍ້ມູນ:

sub myfilter {
ກັບຄືນ undef $_ ຖ້າ /
$stem ຂອງຂ້ອຍ = f_stem;
ສ! !$stem.out: \$((!||s! !))! || s!<.+?>!!g;
}

%.d: %.xml
&sed's! !$(stem).ອອກ: \$$((! ||s! !))! || s!<.+?>!!g'
$(input) -o $(output)

ລວມ foobar.d

ໃຊ້ makepp_cookbook ອອນລາຍໂດຍໃຊ້ບໍລິການ onworks.net



ລ່າສຸດ Linux ແລະ Windows ໂຄງການອອນໄລນ໌