Īss ievads Makefiles atklātā pirmkoda programmatūras izstrādē ar GNU Make


GNU Make ir izstrādes lietderība, kas nosaka konkrētas kodu bāzes daļas, kuras jāpārkompilē, un var izdot komandas, lai veiktu šīs darbības kodu bāzē. Šo konkrēto make utilītu var izmantot ar jebkuru programmēšanas valodu, ja to kompilēšanu var veikt no čaulas, izdodot komandas.

Lai izmantotu GNU Make, mums ir jāizstrādā daži noteikumu kopumi, kas nosaka attiecības starp dažādiem mūsu programmas failiem un komandas katra faila atjaunināšanai. Tie ir ierakstīti īpašā failā ar nosaukumu “ makefile ’. Komanda ‘ make ’ izmanto datu bāzi ‘ makefile ’ un pēdējos failu modifikācijas laikus, lai izlemtu, kuri visi faili ir jāpārkompilē vēlreiz.

Makefile saturs

Parasti ‘ makefiles ’ ietilpst 5 veidu lietas, proti: netieši noteikumi, izteikti noteikumi, mainīgas definīcijas, direktīvas un komentāri.

  1. precīzs noteikums norāda, kā izveidot/pārtaisīt vienu vai vairākus failus (kurus sauc par mērķiem, paskaidrosim vēlāk) un kad tas jādara.
  2. netiešā kārtula norāda, kā izveidot/pārtaisīt vienu vai vairākus failus, pamatojoties uz to nosaukumiem. Tajā aprakstīts, kā mērķa faila nosaukums ir saistīts ar vienu failu ar nosaukumu, kas līdzīgs mērķim.
  3. mainīgā definīcija ir līnija, kas norāda virknes vērtību mainīgajam, kas jāaizstāj vēlāk.
  4. direktīva ir instrukcija, kā padarīt kaut ko īpašu, lasot makefailu.
  5. Tiek izmantots simbols “#”, kas apzīmē komentāra sākumu makefiles iekšpusē. Rinda, kas sākas ar “#”, tiek vienkārši ignorēta.

Informācija, kas make stāsta, kā pārkompilēt sistēmu, nāk no datu bāzes, ko sauc par makefile , lasīšanas. Vienkāršs makefile sastāv no šādas sintakses kārtulām:

target ... : prerequisites ... 
	recipe 
... 
...

mērķis ir definēts kā programmas ģenerēts izvades fails. Tas var būt arī viltus mērķi , kas tiks paskaidrots tālāk. Mērķa failu piemēri ir izpildāmie faili, objektu faili vai viltus mērķi, piemēram, tīrs , instalēt , atinstalēt utt.

Priekšnoteikums ir fails, ko izmanto kā ievadi mērķa failu izveidošanai.

recepte ir darbība, kuru make veic, lai izveidotu mērķa failu, pamatojoties uz priekšnoteikumiem. Pirms katras receptes makefiles iekšpusē ir jāievieto tabulēšanas rakstzīme, ja vien mēs nenorādām mainīgo ‘.RECIPEPREFIX’, lai definētu kādu citu rakstzīmi kā receptes prefiksu.

final: main.o end.o inter.o start.o
	gcc -o final main.o end.o inter.o start.o
main.o: main.c global.h
	gcc -c main.c
end.o: end.c local.h global.h
	gcc -c end.c
inter.o: inter.c global.h
	gcc -c inter.c
start.o: start.c global.h
	gcc -c start.c
clean:
	rm -f main.o end.o inter.o start.o

Iepriekš minētajā piemērā izpildāmā final izveidošanai izmantojām 4 C avota failus un divus galvenes failus. Šeit katrs ‘.o’ fails ir gan mērķis, gan priekšnoteikums makefile iekšpusē. Tagad apskatiet pēdējo mērķa vārdu tīrs . Tā ir tikai darbība, nevis mērķa fails.

Tā kā kompilācijas laikā mums tas parasti nav vajadzīgs, tas nav ierakstīts kā priekšnoteikums citos noteikumos. Mērķus, kas neattiecas uz failiem, bet ir tikai darbības, sauc par viltus mērķiem. Viņiem nebūs nekādu priekšnoteikumu kā citiem mērķa failiem.

Pēc noklusējuma make sākas ar pirmo mērķi ‘ makefile ’ un tiek saukts par ‘ noklusējuma mērķis ’. Ņemot vērā mūsu piemēru, mūsu pirmais mērķis ir galīgais . Tā kā tā priekšnosacījumi ietver citus objektu failus, tie ir jāatjaunina pirms galīgā izveidošanas. Katrs no šiem priekšnoteikumiem tiek apstrādāts saskaņā ar saviem noteikumiem.

Kompilācija notiek, ja avota failos vai galvenes failos ir veiktas izmaiņas vai objekta fails vispār nepastāv. Pēc nepieciešamo objektu failu atkārtotas apkopošanas make izlemj, vai saistīt final no jauna. Tas jādara, ja fails final nepastāv vai kāds no objekta failiem ir jaunāks par to.

Tādējādi, ja mēs mainām failu inter.c , tad, palaižot make , tas atkārtoti kompilēs avota failu, lai atjauninātu objekta failu inter.o un pēc tam saistiet galīgais .

Šajā piemērā mums bija divreiz jāuzskaita visi objekta faili kārtulā final , kā parādīts zemāk.

final: main.o end.o inter.o start.o
	gcc -o final main.o end.o inter.o start.o

Lai izvairītos no šādas dublēšanās, mēs varam ieviest mainīgos, lai saglabātu objektu failu sarakstu, kas tiek izmantoti makefile iekšpusē. Izmantojot mainīgo OBJ, mēs varam pārrakstīt makefile paraugu uz līdzīgu, kas parādīts zemāk.

OBJ = main.o end.o inter.o start.o
final: $(OBJ)
	gcc -o final $(OBJ)
main.o: main.c global.h
	gcc -c main.c
end.o: end.c local.h global.h
	gcc -c end.c
inter.o: inter.c global.h
	gcc -c inter.c
start.o: start.c global.h
	gcc -c start.c
clean:
	rm -f $(OBJ)

Kā redzējām piemērā makefile , mēs varam definēt noteikumus avota direktorija tīrīšanai, noņemot nevēlamos objektu failus pēc apkopošanas. Pieņemsim, ka mums ir mērķa fails ar nosaukumu tīrs . Kā likt atšķirt divas iepriekš minētās situācijas? Šeit parādās viltus mērķu jēdziens.

Neīstais mērķis ir tāds, kas patiesībā nav faila nosaukums, drīzāk tas ir tikai receptes nosaukums, kas jāizpilda ikreiz, kad no makefile tiek izteikts nepārprotams pieprasījums. Viens no galvenajiem iemesliem viltus mērķa izmantošanai ir izvairīties no konflikta ar tāda paša nosaukuma failu. Cits iemesls ir uzlabot veiktspēju.

Lai izskaidrotu šo lietu, es atklāšu vienu negaidītu pavērsienu. clean recepte pēc noklusējuma netiks izpildīta, palaižot make . Tā vietā ir nepieciešams izsaukt to pašu, izdodot komandu make clean .

.PHONY: clean
clean:
	rm -f $(OBJ)

Tagad mēģiniet izveidot makefiles savai kodu bāzei. Jūtieties brīvi komentēt šeit ar savām šaubām.