sintaks makefile. "Pengagihan" fail dengan teks sumber ke dalam direktori. Kompilasi daripada pelbagai sumber

make ialah utiliti untuk membina program secara automatik. Membolehkan anda menjejaki perubahan dalam kod sumber program dan tidak menyusun keseluruhan projek, tetapi hanya fail yang telah berubah atau yang bergantung padanya perubahan yang dibuat. Untuk projek besar ini memberikan penjimatan masa yang ketara.

Dalam siaran ini saya akan cuba memberitahu anda cara membuat fail make.

Secara lalai, peraturan binaan dibaca daripada fail yang dipanggil Makefile.

Struktur Makefile boleh diwakili seperti berikut:

MATLAMAT: TINDAKAN BERGANTUNG

Tetapi biasanya lebih banyak digunakan peraturan yang kompleks, Sebagai contoh:

MATLAMAT: GOAL1 GOAL2 ACTION GOAL1: DEPENDENCE1 ACTION1 GOAL2: DEPENDENCE2 ACTION2

MATLAMAT adalah apa yang kita dapat hasil daripada TINDAKAN. Ini boleh menjadi fail, direktori, atau hanya SASARAN abstrak yang tidak mempunyai sambungan dengan mana-mana objek pada cakera keras. Satu titik bertindih diletakkan selepas nama sasaran. Apabila anda menjalankan arahan make tanpa parameter, peraturan pertama yang ditemui akan dilaksanakan. Untuk melaksanakan peraturan lain, anda perlu menentukannya pada arahan make

Buat MATLAMAT2

PERGANTUNGAN adalah MATLAMAT kita bergantung. Ini boleh menjadi fail, direktori atau SASARAN lain. Buat membandingkan tarikh dan masa perubahan MATLAMAT dan objek yang menjadi tumpuan matlamat. Jika objek yang menjadi tumpuan matlamat telah diubah lewat daripada matlamat dicipta, maka TINDAKAN akan dilaksanakan. TINDAKAN juga dilakukan jika TARGET bukan nama fail atau direktori.

TINDAKAN ialah satu set arahan yang mesti dilaksanakan. Perintah mesti didahului oleh aksara tab. Jika ruang dimasukkan dan bukannya aksara tab, mesej ralat akan dipaparkan semasa penyusunan:

Makefile:13: ***pembatas hilang. Berhenti.

Makefile:13: *** pemisah hilang. Berhenti.

Contoh Makefile:

semua: test.elf test.elf: test1.o test2.o gcc -o test.elf test1.o test2.o test1.o test1.c gcc -c test1.c -o test1.o test2.o test2.c gcc -c test2.c -o test2.o

Pertimbangkan contoh terakhir:
Semua dilaksanakan dahulu kerana berada di permulaan Makefile. semuanya bergantung pada test.elf dan tiada fail atau direktori bernama semua, jadi ia akan sentiasa menyemak sasaran bernama test.elf.

test.elf bergantung pada test1.o dan test2.o, jadi target test1.o akan diperiksa dahulu kemudian test2.o

Apabila menyemak ujian sasaran1.o, tarikh dan masa pengubahsuaian fail ujian1.o dan ujian1.c dibandingkan. Jika fail test1.o tidak wujud atau fail test1.c telah diubah suai kemudian daripada test1.o maka perintah gcc -c test1.c -o test1.o akan dilaksanakan.

Ujian sasaran2.o akan disemak dengan cara yang sama.

Selepas ini, tarikh dan masa pengubahsuaian fail test.elf dan fail test1.o test2.o dibandingkan. Jika test1.o atau test2.o lebih baharu maka perintah gcc -o test.elf test1.o test2.o akan dilaksanakan

Dengan cara ini, perubahan dalam fail test1.c dan test2.c dijejaki.

P/S Saya harap nota ini akan memudahkan penciptaan makefile, tetapi jika anda mempunyai sebarang pertanyaan, tulis di komen, saya akan cuba menjawab.

Selalunya, membina projek pada OS Linux, dengan mengambil kira kebergantungan dan kemas kini, dilakukan oleh utiliti buat, yang menggunakan skrip binaan pra-format untuk ini. Kami telah berulang kali menggunakan bantuan utiliti ini dalam artikel sebelumnya, dan artikel ini akan ditumpukan secara eksklusif kepada isu penggunaan utiliti buat.

buat utiliti

Utiliti buat secara automatik menentukan bahagian projek besar yang telah berubah dan perlu disusun semula, dan melakukan tindakan yang perlu untuk berbuat demikian. Tetapi, sebenarnya, skop pembuatan tidak terhad kepada membina program, ia juga boleh digunakan untuk menyelesaikan masalah lain di mana beberapa fail harus dikemas kini secara automatik apabila fail lain diubah.

Utiliti buat tersedia untuk sistem pengendalian yang berbeza, dan disebabkan ciri pelaksanaan, bersama dengan pelaksanaan "asli", banyak sistem pengendalian mempunyai pelaksanaan GNU gmake, dan gelagat pelaksanaan ini dalam sesetengah sistem pengendalian, contohnya, Solaris, mungkin berbeza dengan ketara. Oleh itu, adalah disyorkan untuk menentukan nama utiliti tertentu dalam skrip binaan. Dalam OS Linux, kedua-dua nama ini adalah sinonim, dilaksanakan melalui pautan simbolik, seperti yang ditunjukkan di bawah:

$ ls -l /usr/bin/*make lrwxrwxrwx 1 root root 4 Okt 28 2008 /usr/bin/gmake -> buat -rwxr-xr-x 1 root root 162652 25 Mei 2008 /usr/bin/make ... $ make --version GNU Make 3.81 ...

Secara lalai, nama fail skrip binaan ialah Makefile. Utiliti buat menyediakan perhimpunan lengkap ditentukan matlamat terdapat dalam skrip, contohnya:

$ buat $ buat bersih

Jika sasaran tidak dinyatakan secara eksplisit, maka berurutan pertama sasaran dalam fail skrip. Anda juga boleh menentukan mana-mana fail skrip lain yang akan digunakan untuk pemasangan:

$ make -f Makefile.my

Fail paling mudah Makefile terdiri daripada binaan sintaksis dua jenis: matlamat dan definisi makro. Penerangan sasaran terdiri daripada tiga bahagian: nama sasaran, senarai kebergantungan dan senarai perintah shell yang diperlukan untuk membina sasaran. Nama sasaran ialah senarai fail bukan kosong yang sepatutnya dibuat. Senarai kebergantungan - senarai fail bergantung pada sasaran yang dibina. Nama sasaran dan senarai kebergantungan membentuk pengepala sasaran, ditulis pada satu baris dan dipisahkan oleh titik bertindih (":"). Senarai arahan ditulis daripada baris seterusnya, dan semua arahan bermula dengan aksara tab yang diperlukan. banyak penyunting teks boleh dikonfigurasikan untuk menggantikan aksara tab dengan ruang. Fakta ini patut diambil kira dan menyemak bahawa editor di mana anda sedang mengedit Makefile, tidak menggantikan tab dengan ruang, kerana masalah ini berlaku agak kerap. Mana-mana baris dalam urutan senarai arahan yang tidak bermula dengan tab (perintah lain) atau " # " (komen) - dianggap sebagai penyempurnaan matlamat semasa dan permulaan yang baharu.

Utiliti buat mempunyai banyak parameter dalaman dengan nilai lalai, yang paling penting ialah peraturan untuk memproses akhiran, serta takrifan pembolehubah persekitaran dalaman. Data ini dipanggil pangkalan data buat dan boleh dilihat seperti ini:

$ make -p >make.suffix make: *** Tiada sasaran dinyatakan dan tiada fail make ditemui. Berhenti. $ cat make.akhiran # GNU Make 3.81 # Hak Cipta (C) 2006 Percuma Yayasan Perisian, Inc. ... # Buat Pangkalan Data, dicetak Kha 14 Apr 14:48:51 2011 ... CC = cc LD = ld AR = ar CXX = g++ COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $ ( SASARAN_ARCH) -c COMPILE.C = $(COMPILE.cc) ... AKHIR:= .out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l . s .S .mod .sym \ .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch... # Peraturan Tersirat ... %.o: %.c # arahan untuk dilaksanakan (dibina -in): $(COMPILE.c) $(OUTPUT_OPTION) $< ...

Nilai semua pembolehubah ini ialah: CC, LD, AR, EXTRA_CFLAGS, ... boleh digunakan oleh fail skrip sebagai definisi tersirat dengan nilai lalai. Di samping itu, anda boleh menentukan sendiri peraturan pemprosesan lalai untuk dipilih akhiran(sambungan nama fail), seperti yang ditunjukkan dalam contoh di atas untuk fail sumber Kod C: %.c.

Kebanyakan persekitaran pembangunan bersepadu (IDE) atau pakej untuk mencipta pemasangan mudah alih (contohnya, automake atau autoconf) mempunyai tugas untuk mencipta fail Makefile untuk utiliti buat.

Bagaimana untuk mempercepatkan make build

perhimpunan projek mudah berlaku agak cepat, tetapi memandangkan pertumbuhan projek semasa ia berkembang, masa binaan, yang sebahagian besarnya dibelanjakan untuk penyusunan, boleh meningkat dengan ketara. Contoh yang terkenal seperti ini ialah perhimpunan Inti Linux, yang, bergantung pada jenis peralatan, boleh mengambil masa dari beberapa puluh minit hingga beberapa jam masa pemproses. Keadaan ini diburukkan lagi oleh fakta bahawa apabila bekerja pada projek (pengubahsuaian kod, penyahpepijatan, mencari ralat, ujian, dll.) anda mungkin perlu membina semula projek itu beberapa dozen kali sehari. Oleh itu, peluang untuk mempercepatkan proses ini menjadi benar-benar relevan.

Memandangkan hari ini sistem pemproses tunggal (teras tunggal) hampir digantikan dengan konfigurasi berbilang teras, pemasangan banyak projek boleh dipercepatkan dengan ketara (berkali-kali) menggunakan peluang buat jalankan berbilang kerja binaan secara selari menggunakan kekunci –j seperti di bawah:

$ man make ... -j , --jobs[=jobs] Menentukan bilangan kerja (arahan) untuk dijalankan serentak. ...

Mari semak faedah yang disediakan oleh ciri ini pada contoh praktikal. Sebagai standard untuk pemasangan, mari kita ambil projek pelayan NTP, yang tidak mengambil masa yang lama untuk dipasang, tetapi juga tidak terlalu cepat:

$ pwd /usr/src/ntp-4.2.6p3

Mula-mula, mari jalankan perhimpunan pada 4 pemproses nuklear Atom (model 1.66Ghz tidak terlalu laju) tetapi dengan keadaan pepejal yang sangat pantas pemacu SSD:

$ cat /proc/cpuinfo | head -n10 processor: 0 vendor_id: GenuineIntel cpu family: 6 model: 28 model name: Intel(R) Atom(TM) CPU 330 @ 1.60GHz stepping: 2 cpu MHz: 1596.331 saiz cache: 512 KB $ make clean # mulakan bina dalam empat utas $ masa buat -j4 ... pengguna sebenar 1m5.023s 2m40.270s sys 0m16.809s $ buat bersih # jalankan binaan masuk mod standard tanpa selari $ masa buat ... pengguna 2m6.534s sebenar 1m56.119s sys 0m12.193s $ buat bersih # jalankan binaan dengan tahap selari yang dipilih secara automatik $ masa buat -j ... pengguna 1m5.708s sebenar 2m43.230s sys 0m16. 301s

Seperti yang anda lihat, penggunaan paralelisme (tersurat atau tersirat) membolehkan anda mempercepatkan pemasangan hampir dua kali - 1 minit berbanding 2. Mari kita bina projek yang sama pada pemproses 2 teras yang lebih pantas, tetapi dengan pemproses konvensional yang agak perlahan pemacu HDD:

$ cat /proc/cpuinfo | head -n10 processor: 0 vendor_id: GenuineIntel cpu family: 6 model: 23 model name: Pentium(R) Dual-Core CPU E6600 @ 3.06GHz stepping: 10 cpu MHz: 3066.000 saiz cache: 2048 KB ... $ time make . .. pengguna sebenar 0m31.591s 0m21.794s sys 0m4.303s $ masa buat -j2 ... pengguna sebenar 0m23.629s 0m21.013s sys 0m3.278s

Walaupun kelajuan pemasangan akhir telah meningkat sebanyak 3-4 kali, peningkatan dalam bilangan pemproses hanya kira-kira 20%, kerana "pautan lemah" di sini ialah pemacu perlahan, yang membolehkan kelewatan semasa menulis nombor besar fail projek .obj kecil.

Catatan: Saya ingin mengingatkan anda bahawa bukan setiap perhimpunan buat, yang berjalan dengan jayanya pada satu pemproses (seperti yang berlaku secara lalai atau apabila menentukan -j1), juga akan berjalan dengan jayanya dengan bilangan pemproses yang lebih besar yang terlibat. Ini disebabkan oleh gangguan dalam penyegerakan operasi dalam kes pemasangan yang kompleks. Contoh paling jelas bagi binaan sedemikian yang gagal dalam kes pelaksanaan selari ialah binaan kernel Linux untuk beberapa versi kernel. Kemungkinan pelaksanaan selari buat perlu disahkan secara eksperimen untuk projek yang sedang dipasang. Tetapi dalam kebanyakan kes, ciri ini boleh digunakan dan membolehkan anda mempercepatkan proses pemasangan dengan ketara!

Jika kaedah ini mempercepatkan proses binaan adalah berdasarkan fakta bahawa kini sebahagian besar sistem adalah berbilang pemproses (berbilang teras), kaedah berikut menggunakan fakta bahawa jumlah memori RAM komputer moden(2-4-8 GB) dengan ketara melebihi jumlah memori yang diperlukan untuk penyusunan kod program. Dalam kes ini, kompilasi, yang kekangan utamanya ialah penciptaan banyak fail objek, boleh dialihkan ke kawasan cakera yang dicipta khas ( cakera RAM, tmpfs), terletak dalam ingatan:

$ jumlah percuma terpakai penimbal kongsi percuma dicache Mem: 4124164 1516980 2607184 0 248060 715964 -/+ penimbal/cache: 552956 3571208 Tukar: 4606972 0 2 $df697m grep tmp tmpfs 2014 1 2014 1% /dev/shm

Kini anda boleh memindahkan sementara fail projek yang dipasang ke tmpfs(kami masih menggunakan pelayan NTP dari contoh sebelumnya), ke direktori /dev/shm:

$ pwd /dev/shm/ntp-4.2.6p3 $ buat -j ... pengguna sebenar 0m4.081s 0m1.710s sys 0m1.149s

DALAM dalam kes ini Kedua-dua kaedah meningkatkan prestasi digunakan secara serentak, dan peningkatan berbanding kompilasi asal adalah hampir satu susunan magnitud. Benar, contoh ini dijalankan pada sistem dengan HDD yang perlahan, di mana pemasangan selari hampir tidak memberikan keuntungan dan memerlukan kira-kira 30 saat.

Kaedah mempercepatkan ini boleh digunakan untuk membina kernel Linux, yang mana, seperti yang telah disebutkan, bangunan selari tidak berfungsi. Untuk memanfaatkan memori RAM, salin pokok sumber kernel ke direktori /dev/shm:

$ pwd /dev/shm/linux-2.6.35.i686 $ masa buat bzImage ... HOSTCC arch/x86/boot/tools/build BUILD arch/x86/boot/bzImage Peranti Root ialah (8, 1) Persediaan ialah 13052 bait (dipadatkan kepada 13312 bait). Sistem ialah 3604 kB CRC 418921f4 Kernel: arch/x86/boot/bzImej sedia (#1) sebenar 9m23.986s pengguna 7m4.826s sys 1m18.529s

Seperti yang anda lihat, membina kernel Linux mengambil masa kurang daripada 10 minit, yang merupakan hasil yang luar biasa baik.

Sebagai kesimpulan, kami boleh menasihati anda untuk mengoptimumkan keadaan pemasangan projek dengan teliti untuk peralatan yang digunakan untuk ini, dan, memandangkan semasa proses penyahpepijatan pemasangan dilakukan ratusan kali, anda boleh menjimatkan banyak masa!

Membina modul kernel

Kes khas membina aplikasi ialah membina modul kernel Linux (pemacu). Bermula dari versi kernel 2.6, untuk membina modul, Makefile, dibina berdasarkan penggunaan makro, dan apa yang perlu kita lakukan ialah menulis (untuk fail kod kita sendiri yang dipanggil mod_params.c), templat berikut untuk memasang modul:

Penyenaraian 1. Makefile untuk membina modul kernel
SEMASA = $(shell uname -r) KDIR = /lib/modules/$(CURRENT)/build PWD = $(shell pwd) TARGET = mod_params obj-m:= $(SASARAN).o lalai: $(BUAT) - C $(KDIR) M=$(PWD) modul ...$ make make -C /lib/modules/2.6.18-92.el5/build \ M=examples/modules-done_1/hello_printk modules make: Memasuki direktori `/usr/src/kernels/2.6.18-92.el5- i686" CC [M] /examples/modules-done_1/hello_printk/hello_printk.o Membina modul, peringkat 2. MODPOST CC /examples/modules-done_1/hello_printk/hello_printk.mod.o LD [M] examples/modules-done_1/ hello_printk/hello_printk.ko buat: Meninggalkan direktori `/usr/src/kernels/2.6.18-92.el5-i686" $ ls -l *.o *.ko -rw-rw-r-- 1 olej 74391 Mac 19 15:58 hello_printk.ko -rw-rw-r-- 1 olej olej 42180 Mac 19 15:58 hello_printk.mod.o -rw-rw-r-- 1 olej olej 33388 Mac 19 15:58 hello_printk.o $ fail hello_printk.ko hello_printk.ko: ELF 32-bit LSB boleh dipindahkan, Intel 80386, versi 1 (SYSV), tidak dilucutkan $ /sbin/modinfo nama fail hello_printk.ko: hello_printk.ko pengarang: Oleg Tsiliuric lesen: GPL srcversion: 83915F228EC39FFCBAF99FD bergantung: vermagic: 2.6.18-92.el5 SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1

Kesimpulan

Artikel itu membincangkan aspek bekerja dengan utiliti make, yang tidak sering diterangkan dalam literatur, tetapi boleh menjadi sangat berguna dalam kerja amali. Kami juga telah menyelesaikan perbincangan tentang isu berkaitan penghantaran dan pemasangan perisian dalam OS Linux.

Dalam artikel seterusnya kami akan memulakan pengenalan kami kepada perpustakaan API yang terdapat dalam sistem POSIX.

Utiliti buat direka untuk mengautomasikan pembinaan projek. Jika mana-mana fail projek boleh dijana daripada fail lain, utiliti membolehkan anda melengkapkan proses binaan dengan paling banyak dengan cara yang terbaik, meminimumkan bilangan fail yang diproses apabila boleh.

Dari segi sejarah, utiliti itu bertujuan untuk membina projek dalam bahasa C dalam sistem operasi Unix, bagaimanapun, boleh digunakan untuk bekerja dengan mana-mana projek. Versi pertama sistem telah dicipta pada tahun 1977.

Hari ini, yang paling biasa ialah tiga pilihan utiliti, digabungkan prinsip umum berfungsi, tetapi berbeza dalam sintaks dan keupayaan bahasa:

    GNU make adalah pilihan yang paling biasa dan berfungsi

    BSD make (pmake) - digunakan dalam projek BSD, kira-kira setara dalam fungsi dengan GNU make

    nmake (Microsoft make) - berfungsi di bawah Windows, mempunyai sedikit fungsi, sahaja prinsip asas buat.

Kami bekerja dengan GNU make. hidup sistem BSD(terutamanya FreeBSD, ia mungkin tersedia sebagai gmake, di Linux just make).

Prinsip asas

Utiliti make berjalan pada peraturan, direkodkan secara khas fail konfigurasi. Peraturan menentukan sasaran, kebergantungan antara matlamat dan satu set perintah untuk melengkapkan setiap matlamat.

Matlamat mungkin sepadan fail tertentu. Selain itu, sasaran mungkin tidak sepadan dengan mana-mana fail tunggal dan boleh digunakan untuk mengumpulkan sasaran lain atau urutan arahan tertentu. Sasaran sedemikian dipanggil sasaran palsu.

Setiap matlamat mungkin bergantung pada penyempurnaan matlamat lain. Pencapaian matlamat memerlukan penyelesaian awal matlamat lain yang bergantung kepada matlamat tersebut.

Dalam kes pergantungan antara fail yang sepadan dengan sasaran, sasaran hanya dilaksanakan jika fail yang bergantung padanya adalah lebih baharu daripada fail yang sepadan dengan sasaran. Ini membolehkan anda menjana semula hanya fail yang bergantung pada fail yang diubah, dan tidak berpotensi berprestasi proses yang panjang membina semula semua fail projek.

Oleh itu, makefile mentakrifkan graf pergantungan yang melaluinya utiliti make melaksanakan matlamat tertentu, meminimumkan bilangan operasi binaan sebanyak mungkin.

Berlari membuat

Walaupun fakta bahawa anda boleh menentukan fail peraturan sewenang-wenangnya untuk dibuat, sebagai peraturan yang mereka gunakan nama standard Makefile. Beberapa nama alternatif lalai juga disokong, tetapi masuk akal untuk menggunakan nama yang paling biasa.

Sehubungan itu, pasukan

$buat

akan menggunakan Makefile yang terletak di direktori semasa.

Apabila anda menjalankan make, anda boleh menentukan sasaran untuk dilaksanakan. Jika tiada sasaran ditentukan, sasaran lalai digunakan, yang dinyatakan secara eksplisit dalam fail peraturan atau sasaran pertama yang ditentukan digunakan secara tersirat.

Menentukan sasaran secara eksplisit dilakukan dengan pernyataan DEFAULT_GOAL dalam Makefile:

. DEFAULT_GOAL: semua

Sebagai contoh, arahan

$ bersihkan

akan menyebabkan sasaran bersih memproses Makefile yang terletak dalam direktori semasa.

Anda boleh menentukan beberapa matlamat sekaligus.

Pelaksanaan matlamat boleh dikonfigurasikan menggunakan pembolehubah (lebih lanjut mengenai perkara di bawah). Apabila anda menjalankan make, anda boleh menentukan nilai pembolehubah:

$ make build PREFIX =/usr/local

Nilai pembolehubah PREFIX akan tersedia dalam peraturan Makefile dan boleh digunakan semasa binaan.

Perintah itu juga menyokong beberapa pilihan tambahan, yang mana yang paling penting adalah yang berikut:

    F - membolehkan anda menentukan secara eksplisit fail peraturan

    C - pergi ke direktori yang ditentukan sebelum pelaksanaan, boleh, sebagai contoh, digunakan untuk menjalankan make dari direktori luar kepada direktori projek

    B - melumpuhkan pemeriksaan masa sasaran bergantung dan memaksa mereka untuk dilaksanakan sepenuhnya

Sintaks membuat asas

Konstruk asas yang digunakan dalam membuat fail adalah seperti berikut:

Sasaran: dep1 dep2 ... command1 command2 ...

    sasaran - sasaran

    dep1 , dep2 - sasaran yang bergantung kepada sasaran

    command1 , command2 - arahan dilaksanakan untuk mencapai sasaran

Sebagai contoh:

Gaya. css: src/ less/ app. less lessc src/ less/ app. kurang > gaya. css

Coretan ini menentukan bahawa fail style.css bergantung pada fail src/less/app.less dan untuk membinanya anda perlu menjalankan perintah lessc src/less/app.less > style.css . Fail style.css hanya akan dijana semula jika fail src/less/app.less lebih baharu daripada fail style.css (melainkan suis -B ditentukan semasa menjalankan make).

Setiap arahan dalam perihalan sasaran mesti didahului oleh aksara tab. Pada dasarnya, ini boleh dikonfigurasikan, tetapi lebih baik menggunakan konvensyen yang diterima umum. Jika anda menggunakan ruang dan bukannya tab, make tidak akan berfungsi.

Perintah Shell digunakan sebagai arahan pemprosesan sasaran. Teks arahan dipaparkan; untuk mengelakkannya daripada dipaparkan, arahan mesti bermula dengan simbol @.

Setiap arahan dijalankan secara berasingan jurubahasa cangkerang, jadi arahan tidak berkaitan antara satu sama lain. Dalam erti kata lain, satu baris arahan - satu shell. Tingkah laku ini boleh diatasi menggunakan sasaran khas .ONESHELL .

Jika arahan (atau senarai kebergantungan) perlu ditulis pada beberapa baris, gunakan aksara \ sempang.

Sasaran PHONY

Sasaran bukan fail yang bertujuan untuk melaksanakan satu set perintah atau kebergantungan kumpulan diisytiharkan seperti berikut:

.FONI: bersih bersih: rm *. o temp

Terdapat beberapa pengisytiharan.PHONY; biasanya satu ditakrifkan dan semua matlamat yang berkaitan ditulis di sana.

Dalam contoh kami, memanggil make clean akan melaksanakan sasaran bersih, yang pastinya akan mengalih keluar fail sementara.

Jika sasaran palsu mempunyai kebergantungan dalam bentuk sasaran palsu lain, maka kebergantungan dilaksanakan sebelum sasaran bergantung. Oleh itu, kami mendapat mekanisme yang menyerupai subrutin. Sebagai contoh, kita boleh mentakrifkan semua sasaran yang mengumpul semua fail projek, dan memisahkan sasaran css, js dan php yang mengumpul fail css, fail js dan memproses fail php.

Oleh itu, dalam Makefile kita boleh menulis:

.FONI: semua css js php semua: css js php css: www/ style. css ... berikut ialah arahan js: www/ js/ app. js ... berikut adalah arahan php: ... ini adalah arahan sekali lagi

Akibatnya, kita boleh menggunakan buat semua untuk membina semula semua fail dan, katakan, membuat css untuk membina semula fail CSS sahaja.

Pembolehubah

Anda boleh menggunakan pembolehubah dalam makefile, walaupun lebih tepat untuk mengatakan bahawa anda boleh menggunakan makro.

Pembolehubah ditakrifkan oleh tugasan dalam makefile atau boleh dihantar secara luaran.

Pembolehubah ialah takrifan makro, dan pembolehubah sentiasa dinilai pada saat terakhir sebelum penggantian. Makro boleh digunakan di mana-mana sahaja dalam teks makefile.

CC= gcc IDIR=../ sertakan CFLAGS=- I$ (IDIR) DEPS= hellomake. o hellofunc. p NAMA= hellomake $ (NAMA ) : $ (DEPS ) $ (CC ) - o $ (NAMA ) $ (DEPS )

Penggantian dilakukan menggunakan binaan $(VAR), berbanding dengan shell, yang menggunakan $VAR .

Jika pembolehubah shell digunakan dalam arahan shell, anda mesti memetik tanda $ dengan menduplikasinya, sebagai contoh:

Rumah Cetak: echo $$HOME

Selain pembolehubah makro, terdapat juga pembolehubah yang lebih tradisional, di mana nilainya ditetapkan serta-merta. Untuk bekerja dengan mereka, gunakan operator:=. Dalam keadaan kami, sudah cukup untuk menggunakan pembolehubah biasa.

Selalunya anda ingin menentukan pembolehubah hanya jika ia belum ditakrifkan. Untuk melakukan ini, gunakan operator ?=:

MYSQL_CHARSET ?= UTF8

Sehubungan itu, jika kita memanggil

buat pangkalan data cipta

Pengekodan UTF8 akan digunakan, dan sekiranya berlaku

Buat pangkalan data cipta MYSQL_CHARSET= CP1251

CP1251 akan digunakan.

Jika pembolehubah mengandungi berbilang baris, anda boleh menggunakan sintaks define:

Tentukan MYSQL_APP_CONF_TEMPLATE [ mysql] hos=$ (MYSQL_SERVER ) port=$ (MYSQL_PORT ) pengguna=$ (MYSQL_USER ) kata laluan= "$(MYSQL_PASSWORD)" endef

Pembolehubah Automatik

Buat menyokong satu set pembolehubah automatik yang menjadikan peraturan penulisan lebih mudah. Contohnya, pembolehubah $@ sepadan dengan sasaran semasa (yang di sebelah kiri :), dan pembolehubah $^ sepadan dengan senarai kebergantungan (yang di sebelah kanan :). Oleh itu, sebagai contoh, anda boleh menulis:

www/js/skrip. js: src/ js/ jquery. js src/ js/ plugin1. js src/ js/ plugin2. js cat $^ > $@

Akibatnya, www/js/script.js akan menjadi hasil gabungan tiga fail js.

Senarai lengkap pembolehubah sedemikian diberikan dalam dokumentasi; yang paling menarik bagi kami ialah:

    $@ - nama sasaran

    $< - имя первой зависимости

    $? - nama semua kebergantungan yang lebih baharu daripada sasaran

    $^ - nama semua kebergantungan sasaran

DENGAN senarai penuh boleh didapati dalam dokumentasi: Automatic Variables.

Pelaksanaan bersyarat

Anda boleh menggunakan syarat dalam Makefile. Sekali lagi, kita bercakap tentang membuat pemprosesan makro, jadi syarat beroperasi pada peringkat makefile, bukan pada peringkat arahan. Biasanya, ungkapan bersyarat digunakan untuk menentukan matlamat tertentu bergantung pada nilai pembolehubah. Sebagai contoh:

ifdef $(APP) persediaan: ... else persediaan: @ echo "Ralat, aplikasi tidak ditakrifkan" endif

Sebagai syarat, anda boleh menyemak kepastian pembolehubah, serta nilainya:

Foo: $ (objek) ifeq ($ (CC), gcc) $ (CC) - o foo $ (objek) $ (libs_for_gcc) lain $ (CC) - o foo $ (objek) $ (normal_libs) endif

Keupayaan penuh ungkapan bersyarat boleh didapati dalam dokumentasi: Sintaks bersyarat.

Peraturan templat

Peraturan corak membolehkan anda menentukan peraturan untuk menukar satu fail kepada yang lain berdasarkan kebergantungan antara nama mereka. Sebagai contoh, kita boleh menentukan peraturan untuk mendapatkan fail objek daripada fail bahasa C:

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

Perhatikan penggunaan pembolehubah %< , которая в таких правилах используется для получения имени исходного файла.

Templat tidak perlu dihadkan kepada sambungan fail. Jika fail sumber dan output sepadan antara satu sama lain dan terdapat sebarang pergantungan dalam nama mereka, peraturan corak boleh digunakan.

Termasuk fail make lain

Fail make boleh termasuk fail make lain dengan pernyataan include:

sertakan buat1. mk buat2. mk

Oleh itu, anda boleh membina sistem modular daripada fail; selalunya masuk akal untuk dimasukkan dalam pernyataan bersyarat.

Fungsi

Make mentakrifkan satu set besar fungsi yang boleh digunakan dalam pembolehubah (makros). Panggilan fungsi dilakukan oleh konstruk:

$(fungsi arg1, arg2,... )

Fungsi membolehkan anda memproses rentetan, nama fail, mengatur gelung pada satu set nilai, mengatur panggilan bersyarat fungsi lain.

Beberapa contoh dari sarang. Kita mendapatkan masa semasa(perhatikan penggunaan := :

HIVE_TIME := $ (tarikh cangkang +% Y/% m/% d\ % H:% M:% S)

Termasuk fail container.mk hanya jika ia wujud:

sertakan $ (shell find $ (HIVE_ETC_DIR ) - nama bekas. mk)

Pembentukan nama pangkalan data MySQL mengikut nama projek:

MYSQL_DB ?= $ (subst -, _,$ (HIVE_NAME) _$ (APP))

Menambah awalan dan akhiran pada nama fail

$ (addprefix src/ less/,$ (tambahan . less, app ui catalog) )

Anda boleh membaca lebih lanjut mengenai fungsi dalam dokumentasi Fungsi.

Fungsi sendiri

Anda boleh mencipta fungsi berparameter anda sendiri dengan mentakrifkan pembolehubah yang mengandungi pembolehubah khas $1 , $2 , ... sepadan dengan hujah yang diluluskan. Panggil fungsi tersuai dihasilkan oleh makro panggilan khas:

$(pembolehubah panggilan, param, param,... )

Contoh yang sangat bodoh:

Hive_red = " \0 33 [Variable="abc"] [Sasaran]

Tanda kurung persegi bermakna kehadiran bahagian ini adalah pilihan.
Sasaran- nama matlamat yang perlu diselesaikan.
Pembolehubah ="abc"-takrifan semula pembolehubah. Nilai pembolehubah yang dimasukkan baris arahan, mempunyai keutamaan yang lebih tinggi daripada definisi dalam makefile.
Pilihan:
-f fail- tetapan nama yang jelas makefile, jika tugas itu ditinggalkan, maka fail akan dicari GNUmakefile, makefile atau Makefile .
-n- meniru tindakan tanpa pelaksanaan sebenar, digunakan untuk nyahpepijat.
-t- menukar masa pengubahsuaian matlamat tanpa pelaksanaan sebenar.
-q- menyemak keperluan untuk mengemas kini matlamat tanpa benar-benar melengkapkannya.

Penggunaan MAKE yang lebih maju

Susunan peraturan adalah tidak material. Secara lalai matlamat utama buat adalah tujuan peraturan pertama dalam yang pertama buat-fail. Jika terdapat berbilang sasaran dalam peraturan pertama, maka hanya sasaran pertama diambil sebagai sasaran lalai. Sasaran yang bermula dengan titik tidak digunakan sebagai sasaran lalai melainkan ia mengandungi satu atau lebih aksara "/", i.e. mentakrifkan laluan ke fail; Selain itu, sasaran yang mentakrifkan peraturan templat tidak digunakan secara lalai.
TARGET atau DEPENDENCY boleh menjadi senarai fail yang dipisahkan oleh ruang atau corak dalam gaya cangkerang.
Templat ditafsirkan pada masa peraturan dilaksanakan; apabila menetapkan kepada pembolehubah, templat tidak ditafsirkan; untuk menetapkan senarai fail kepada pembolehubah, gunakan fungsi khas kad bebas.

objek:= $(wildcard *.o
sunting: *.o
cc -o edit *.o

Untuk penjanaan automatik bergantung pada fail pengepala dalam bahasa SI, anda boleh menggunakan arahan gcc -M fail.c atau gcc -MM fail.c. Pilihan kedua tidak menjana kebergantungan pada fail pengepala sistem. Anda boleh menggunakan pembolehubah automatik dalam COMMANDS. Pembolehubah ini mempunyai nilai yang dikira semula untuk setiap peraturan yang dilaksanakan berdasarkan sasaran dan kebergantungan peraturan.

Pembolehubah automatik Tujuan
$@ Nama fail sasaran peraturan. Dalam peraturan templat dengan berbilang sasaran, nama sasaran yang menyebabkan perintah peraturan dilaksanakan.
$< Nama pergantungan pertama. Jika sasaran menerima arahannya daripada peraturan tersirat, maka ini akan menjadi pergantungan pertama yang ditambahkan oleh peraturan tersirat.
$? Nama semua kebergantungan yang lebih baharu daripada sasaran, dengan ruang di antaranya.
$^ Nama semua kebergantungan, dengan ruang di antaranya. Jika anda berulang kali menentukan kebergantungan yang sama untuk matlamat, nilai pembolehubah " $^ " hanya akan mengandungi satu salinan namanya.
$+ Pembolehubah ini serupa dengan pembolehubah " $^ ", hanya kebergantungan yang ditentukan diduplikasi berulang kali dalam susunan yang dinyatakan dalam makefile. Ini amat berguna untuk digunakan dalam memautkan perintah yang mengulangi nama perpustakaan dalam susunan tertentu adalah penting
$* Asas yang dipadankan dengan peraturan tersirat (lihat di bawah). Dalam peraturan corak, pangkalan ialah bahagian nama fail yang sepadan dengan aksara " % " dalam templat sasaran. Jika sasaran ialah fail " dir/a.foo.b", dan templat sasaran ialah " a.%.b", maka asasnya ialah " dir/foo". Base berguna untuk mencipta nama fail yang dikaitkan dengan peraturan. Dalam peraturan eksplisit, pangkalan tidak ditakrifkan sebagai nama fail tanpa sambungan, jika sambungan sedemikian boleh dibezakan. Tidak disyorkan untuk menggunakan pembolehubah ini dalam peraturan eksplisit

Peraturan tersirat ditakrifkan untuk banyak bahasa pengaturcaraan dan digunakan mengikut sambungan fail sumber. Secara lalai, senarai sambungan adalah seperti berikut: .keluar, .a, .ln, .o, .c, .cc, .C, cpp, .p, .f, .F, .r, .y, .l, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch, .web, .sh, .elc, .el. Apabila menggunakan peraturan tersirat, pembolehubah digunakan, dengan mengatasi yang anda boleh mengawal proses penukaran fail, contohnya, tentukan pengkompil bukan standard atau lulus pilihan kepadanya.

Contoh MakeFile

Contoh makefile

Menggunakan tindakan lalai.

#sasaran lalai - edit fail
edit: main.o kbd.o command.o display.o \

cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o

main.o: main.c defs.h
cc -c utama.c
kbd.o: perintah kbd.c defs.h.h
cc -c kbd.c
perintah.o: perintah.c defs.h perintah.h
arahan cc -c.c
display.o: display.c defs.h buffer.h
paparan cc -c.c
insert.o: insert.c defs.h buffer.h
cc -c insert.c
search.o: search.c defs.h buffer.h
cc -c carian.c
files.o: files.c defs.h buffer.h arahan.h
cc -c files.c
utils.o: utils.c defs.h
cc -c utils.c
bersih:
rm edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o

lalai, buat bermula dengan peraturan pertama (tidak mengira peraturan yang nama sasarannya bermula dengan " . "). Ini dipanggil sasaran lalai utama. Dalam kes kami, ini adalah peraturannya edit. Jika fail edit lebih baru daripada fail objek yang bergantung padanya, maka tiada apa yang akan berlaku. Jika tidak, sebelum ini buat dapat memproses sepenuhnya peraturan ini, ia mesti memproses peraturan secara rekursif untuk fail yang bergantung padanya edit. Setiap fail ini diproses mengikut peraturannya sendiri. Penyusunan semula mesti dilakukan jika fail sumber atau mana-mana fail pengepala yang disebut antara kebergantungan dikemas kini lewat daripada fail objek, atau jika fail objek tidak wujud.
peraturan bersih tidak sepadan dengan mana-mana fail yang dibuat dan sepadan, bersih Ia tidak bergantung pada apa-apa dan tidak termasuk dalam senarai tanggungan. Apabila dilancarkan secara lalai bersih tidak akan dipanggil. Untuk melaksanakannya, anda mesti menyatakan sasaran secara eksplisit pada permulaan buat: bersihkan
Pembolehubah dan tindakan lalai (peraturan tersirat) boleh digunakan untuk memendekkan entri


insert.o search.o files.o utils.o

edit: $(objek)
cc -o edit $(objek)
utama.o: defs.h
kbd.o: perintah defs.h.h
perintah.o: defs.h perintah.h
paparan.o: defs.h buffer.h
insert.o: defs.h buffer.h
search.o: defs.h buffer.h
files.o: arahan defs.h buffer.h.h
utils.o: defs.h
.FONI: bersih
bersih:
-rm edit $(objek)

Pembolehubah objek membenarkan penggunaan senarai fail objek yang pernah ditulis, dan untuk fail objek dalam buat peraturan lalai tersirat terbina dalam

fail.c: fail.o cc -c fail.c

Tujuan Khas .FONI dibina ke dalam buat dan mentakrifkan kebergantungannya sebagai nama sasaran yang tidak mempunyai fail yang sepadan. Jika peraturan ini langkau, kemudian buat fail dalam direktori semasa dengan nama bersih akan menyekat pelaksanaan bersihkan.
Menggunakan peraturan lalai membolehkan anda menukar gaya entri pergantungan:

objek = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o

edit: $(objek)
cc -o edit $(objek)

$(objek): defs.h
kbd.o command.o files.o: command.h
display.o insert.o search.o files.o: buffer.h

Entri ini menunjukkan bahawa semua fail objek bergantung pada fail pengepala defs.h, tetapi bagi sesetengah daripadanya kebergantungan tambahan disemak.

Pada satu ketika, saya sangat terlepas manual seperti itu untuk memahami perkara asas tentang pembuatan. Saya fikir ia akan menarik sekurang-kurangnya seseorang. Walaupun teknologi ini semakin pupus, ia masih digunakan dalam banyak projek. Tidak ada karma yang mencukupi untuk hab "Terjemahan", sebaik sahaja peluang itu muncul, saya akan menambahkannya di sana juga. Ditambah pada Terjemahan. Jika terdapat kesilapan dalam reka bentuk, sila nyatakan. Saya akan membaikinya.

Artikel itu akan menarik minat terutamanya kepada mereka yang mempelajari pengaturcaraan dalam C/C++ pada sistem seperti UNIX dari akar umbinya, tanpa menggunakan IDE.

Menyusun projek dengan tangan adalah tugas yang sangat membosankan, terutamanya apabila terdapat lebih daripada satu fail sumber, dan untuk setiap daripada mereka anda perlu memasukkan arahan penyusunan dan pemautan setiap kali. Tetapi ia tidak begitu buruk. Sekarang kita akan belajar cara membuat dan menggunakan Makefiles. Makefile ialah satu set arahan untuk membuat program, yang membantu untuk memasang projek perisian secara literal dalam satu sentuhan.

Untuk berlatih, anda perlu mencipta projek mikroskopik ala Hello World daripada empat fail dalam satu direktori:

main.cpp

#termasuk #include "functions.h" menggunakan namespace std; int main())(print_hello(); cout<< endl; cout << "The factorial of 5 is " << factorial(5) << endl; return 0; }


hello.cpp

#termasuk #include "functions.h" menggunakan namespace std; batal print_hello())( cout<< "Hello World!"; }


faktorial.cpp

#include "functions.h" int factorial(int n)( if(n!=1)( return(n * factorial(n-1)); ) else return 1; )


fungsi.h

batal print_hello(); int faktorial(int n);


Anda boleh memuat turun semuanya secara pukal dari sini
Pengarang menggunakan bahasa C++, yang tidak perlu diketahui sama sekali, dan pengkompil g++ dari gcc. Mana-mana pengkompil lain kemungkinan besar akan berfungsi juga. Fail diperbetulkan sedikit supaya ia disusun dengan gcc 4.7.1
buat program
Jika anda berlari
buat
maka program akan cuba mencari fail dengan nama lalai Makefile dalam direktori semasa dan melaksanakan arahan daripadanya. Jika terdapat beberapa makefiles dalam direktori semasa, anda boleh menunjuk kepada yang anda perlukan seperti ini:
make -f MyMakefile
Terdapat banyak parameter lain yang kami belum perlukan lagi. Anda boleh mengetahui tentang mereka dalam halaman lelaki.
Proses membina
Pengkompil mengambil fail kod sumber dan menghasilkan fail objek daripadanya. Penghubung kemudian mengambil fail objek dan mendapatkan daripadanya fail boleh laku. Perhimpunan = kompilasi + menghubungkan.
Kompilasi dengan tangan
Cara termudah untuk membina program:
g++ main.cpp hello.cpp factorial.cpp -o hello
Menyusahkan untuk menaip ini setiap kali, jadi kami akan mengautomasikannya.
Makefile yang paling mudah
Ia harus mengandungi bahagian berikut:
sasaran: pasukan tanggungan
Untuk contoh kami, makefile akan kelihatan seperti ini:
semua: g++ main.cpp hello.cpp factorial.cpp -o hello
Sila ambil perhatian bahawa baris arahan mesti bermula dengan tab! Simpan ini sebagai Makefile-1 dalam direktori projek anda dan jalankan binaan dengan make -f Makefile-1
Dalam contoh pertama sasaran dipanggil semua . Ini ialah sasaran lalai untuk fail make dan akan dilaksanakan jika tiada sasaran lain dinyatakan secara eksplisit. Juga, sasaran ini dalam contoh ini tidak mempunyai kebergantungan, jadi buat serta-merta mula melaksanakan arahan yang diingini. Dan arahan itu, seterusnya, melancarkan pengkompil.
Menggunakan kebergantungan
Menggunakan berbilang sasaran dalam satu makefile berguna untuk projek besar. Ini disebabkan oleh fakta bahawa jika anda menukar satu fail, anda tidak perlu membina semula keseluruhan projek, tetapi anda boleh bertahan dengan membina semula hanya bahagian yang diubah. Contoh:
semua: hello hello: main.o factorial.o hello.o g++ main.o factorial.o hello.o -o hello main.o: main.cpp g++ -c main.cpp faktorial.o: factorial.cpp g++ -c factorial.cpp hello.o: hello.cpp g++ -c hello.cpp clean: rm -rf *.o hello
Ini harus disimpan di bawah nama Makefile-2 semua dalam direktori yang sama

Kini sasaran semua hanya mempunyai kebergantungan, tetapi tiada arahan. Dalam kes ini, apabila dipanggil, make akan melaksanakan secara berurutan semua kebergantungan yang dinyatakan dalam fail untuk sasaran ini.
Matlamat baharu, bersih, juga telah ditambah. Ia digunakan secara tradisional untuk membersihkan semua hasil binaan projek dengan cepat. Pembersihan dimulakan seperti ini: make -f Makefile-2 clean

Menggunakan Pembolehubah dan Komen
Pembolehubah digunakan secara meluas dalam makefiles. Sebagai contoh, ini adalah cara yang mudah untuk mengambil kira kemungkinan projek itu akan disusun dengan pengkompil yang berbeza atau dengan pilihan yang berbeza.
# Ini ialah ulasan yang mengatakan pembolehubah CC menentukan pengkompil yang digunakan untuk membina CC=g++ # Ini adalah ulasan lain. Beliau menerangkan bahawa pembolehubah CFLAGS mengandungi bendera yang dihantar kepada pengkompil CFLAGS=-c -Wall all: hello hello: main.o factorial.o hello.o $(CC) main.o factorial.o hello.o -o hello utama .o: utama.cpp $(CC) $(CFLAGS) utama.cpp faktorial.o: faktorial.cpp $(CC) $(CFLAGS) faktorial.cpp hello.o: hello.cpp $(CC) $(CFLAGS ) hello.cpp clean: rm -rf *.o hello
Ini ialah Makefile-3
Pembolehubah adalah perkara yang sangat mudah. Untuk menggunakannya, anda hanya menetapkan nilai sebelum menggunakannya. Selepas itu, anda boleh menggantikan nilainya di tempat yang betul dengan cara ini: $(VAR)
Apa yang perlu dilakukan seterusnya
Selepas arahan ringkas ini, anda sudah boleh cuba membuat fail buatan sendiri. Seterusnya anda perlu membaca buku teks dan manual yang serius. Sebagai kord terakhir, anda boleh cuba membukanya sendiri dan merealisasikan makefile sejagat, yang boleh disesuaikan dengan hampir mana-mana projek dalam dua sentuhan:
CC=g++ CFLAGS=-c -Wall LDFLAGS= SOURCES=main.cpp hello.cpp factorial.cpp OBJEK=$(SUMBER:.cpp=.o) EXECUTABLE=hello all: $(SUMBER) $(EXECUTABLE) $(EXECUTABLE) ): $(OBJEK) $(CC) $(LDFLAGS) $(OBJEK) -o $@ .cpp.o: $(CC) $(CFLAGS) $< -o $@
Makefile-4
Semoga berjaya!