Jika Anda ingin menjalankan atau memperbarui tugas saat file tertentu diperbarui, tombol make utilitas dapat berguna. make utilitas memerlukan file, Makefile (atau makefile ), yang mendefinisikan serangkaian tugas yang akan dieksekusi. Anda mungkin pernah menggunakan make untuk mengkompilasi program dari kode sumber. Sebagian besar proyek open source menggunakan make untuk mengkompilasi biner akhir yang dapat dieksekusi, yang kemudian dapat diinstal menggunakan make install .
Dalam artikel ini, kita akan menjelajahi make dan Makefile menggunakan contoh dasar dan lanjutan. Sebelum Anda mulai, pastikan bahwa make diinstal di sistem Anda.
Contoh dasar
Mari kita mulai dengan mencetak "Hello World" klasik di terminal. Buat direktori kosong myproject berisi file Makefile dengan konten ini:
say_hello:
echo "Halo Dunia"
Sekarang jalankan file dengan mengetikkan make di dalam direktori myproject . Outputnya adalah:
$ make
echo "Halo Dunia"
Halo Dunia
Pada contoh di atas, say_hello berperilaku seperti nama fungsi, seperti dalam bahasa pemrograman apa pun. Ini disebut target . Prasyarat atau dependensi mengikuti sasaran. Demi kesederhanaan, kami belum mendefinisikan prasyarat apa pun dalam contoh ini. Perintah echo "Hello World" disebut resep . resep menggunakan prasyarat untuk membuat target . Target, prasyarat, dan resep bersama-sama membuat aturan .
Untuk meringkas, di bawah ini adalah sintaks dari aturan umum:
target:prasyaratresep
Sebagai contoh, target mungkin berupa file biner yang bergantung pada prasyarat (file sumber). Di sisi lain, prasyarat juga bisa menjadi target yang bergantung pada dependensi lain:
final_target:sub_target final_target.c
Recipe_to_create_final_target
sub_target:sub_target.c
Recipe_to_create_sub_target
Target tidak harus berupa file; itu bisa saja hanya nama untuk resepnya, seperti dalam contoh kita. Kami menyebutnya "target palsu".
Kembali ke contoh di atas, ketika make dieksekusi, seluruh perintah echo "Hello World" ditampilkan, diikuti oleh output perintah yang sebenarnya. Kita sering tidak menginginkan itu. Untuk menekan gema perintah yang sebenarnya, kita perlu memulai echo dengan @ :
say_hello:
@echo "Halo Dunia"
Sekarang coba jalankan make lagi. Outputnya hanya akan menampilkan ini:
$ make
Halo Dunia
Mari tambahkan beberapa target palsu lagi:generate dan clean ke Makefile :
say_hello:
@echo "Hello World"
hasilkan:
@echo "Membuat file teks kosong..."
sentuh file-{1. .10}.txt
bersih:
@echo "Membersihkan..."
rm *.txt
Jika kita mencoba menjalankan make setelah perubahan, hanya target say_hello akan dieksekusi. Itu karena hanya target pertama di makefile yang menjadi target default. Sering disebut tujuan default , inilah alasan Anda akan melihat all sebagai target pertama di sebagian besar proyek. Ini adalah tanggung jawab all untuk memanggil target lain. Kami dapat mengganti perilaku ini menggunakan target palsu khusus yang disebut .DEFAULT_GOAL .
Mari kita sertakan itu di awal makefile kita:
.DEFAULT_GOAL := generate
Ini akan menjalankan target generate sebagai default:
$ make
Membuat file teks kosong...
touch file-{1..10}.txt
Seperti namanya, target palsu .DEFAULT_GOAL hanya dapat menjalankan satu target pada satu waktu. Inilah sebabnya mengapa sebagian besar makefile menyertakan all sebagai target yang dapat memanggil target sebanyak yang dibutuhkan.
Mari sertakan target palsu all dan hapus .DEFAULT_GOAL :
all:say_hello generate
say_hello:
@echo "Hello World"
generate:
@echo "Membuat file teks kosong.. ."
sentuh file-{1..10}.txt
clean:
@echo "Membersihkan..."
rm *.txtSebelum menjalankan
make, mari sertakan target palsu khusus lainnya,.PHONY, di mana kita mendefinisikan semua target yang bukan file.makeakan menjalankan resepnya terlepas dari apakah file dengan nama itu ada atau waktu modifikasi terakhirnya. Berikut makefile lengkapnya:.PHONY:all say_hello generate clean
all:say_hello generate
say_hello:
@echo "Hello World"
generate:
@echo "Membuat file teks kosong..."
sentuh file-{1..10}.txt
clean:
@echo "Membersihkan naik..."
rm *.txt
makeharus meneleponsay_hellodangenerate:$ make
Hello World
Membuat file teks kosong...
touch file-{1..10}.txtIni adalah praktik yang baik untuk tidak memanggil
cleandiallatau menjadikannya sebagai target pertama.cleanharus dipanggil secara manual saat pembersihan diperlukan sebagai argumen pertama untukmake:$ bersihkan
Bersihkan...
rm *.txtSekarang setelah Anda memiliki gagasan tentang cara kerja makefile dasar dan cara menulis makefile sederhana, mari kita lihat beberapa contoh lanjutan.
Contoh lanjutan
Variabel
Lebih banyak sumber daya Linux
- Lembar contekan perintah Linux
- Lembar contekan perintah Linux tingkat lanjut
- Kursus online gratis:Ikhtisar Teknis RHEL
- Lembar contekan jaringan Linux
- Lembar contekan SELinux
- Lembar contekan perintah umum Linux
- Apa itu container Linux?
- Artikel Linux terbaru kami
Dalam contoh di atas, sebagian besar nilai target dan prasyarat adalah hard-coded, tetapi dalam proyek nyata, ini diganti dengan variabel dan pola.
Cara paling sederhana untuk mendefinisikan variabel dalam makefile adalah dengan menggunakan = operator. Misalnya, untuk menetapkan perintah gcc ke variabel CC :
CC = gcc
Ini juga disebut variabel diperluas rekursif , dan digunakan dalam aturan seperti yang ditunjukkan di bawah ini:
halo:hello.c
${CC} hello.c -o halo
Seperti yang mungkin sudah Anda duga, resepnya berkembang seperti di bawah ini ketika diteruskan ke terminal:
gcc hello.c -o hello
Keduanya ${CC} dan $(CC) adalah referensi yang valid untuk memanggil gcc . Tetapi jika seseorang mencoba untuk menetapkan kembali variabel ke dirinya sendiri, itu akan menyebabkan loop tak terbatas. Mari kita verifikasi ini:
CC =gcc
CC =${CC}
semua:
@echo ${CC}
Menjalankan make akan mengakibatkan:
$ make
Makefile:8:*** Variabel rekursif 'CC' mereferensikan dirinya sendiri (akhirnya). Berhenti.
Untuk menghindari skenario ini, kita dapat menggunakan := operator (ini juga disebut variabel yang diperluas secara sederhana ). Kita seharusnya tidak memiliki masalah menjalankan makefile di bawah ini:
CC :=gcc
CC :=${CC}
semua:
@echo ${CC}
Pola dan fungsi
Makefile berikut dapat mengkompilasi semua program C dengan menggunakan variabel, pola, dan fungsi. Mari kita telusuri baris demi baris:
# Penggunaan:
# make # kompilasi semua biner
# make clean # hapus SEMUA biner dan objek
.PHONY =all clean
CC =gcc # compiler yang akan digunakan
LINKERFLAG =-lm
SRCS :=$(wildcard *.c)
BINS :=$(SRCS:%. c=%)
semua:${BINS}
%:%.o
@echo "Memeriksa.."
${CC} ${LINKERFLAG} $<-o $@
%.o:%.c
@echo "Membuat objek.."
${CC} -c $<
bersih:
@echo "Membersihkan..."
rm -rvf *.o ${BINS}
-
Baris dimulai dengan
#adalah komentar. -
Baris
.PHONY = all cleanmendefinisikan target palsualldanclean. -
Variabel
LINKERFLAGmendefinisikan flag yang akan digunakan dengangccdalam resep. -
SRCS := $(wildcard *.c):$(wildcard pattern)adalah salah satu fungsi untuk nama file . Dalam hal ini, semua file dengan.cekstensi akan disimpan dalam variabelSRCS. -
BINS := $(SRCS:%.c=%):Ini disebut sebagai referensi substitusi . Dalam hal ini, jikaSRCSmemiliki nilai'foo.c bar.c',BINSakan memiliki'foo bar'. -
Baris
all: ${BINS}:Target palsuallmemanggil nilai di${BINS}sebagai target individu. -
Aturan:
%:%.o
@echo "Memeriksa.."
${CC} ${LINKERFLAG} $< -o $@Mari kita lihat contoh untuk memahami aturan ini. Misalkan
fooadalah salah satu nilai dalam${BINS}. Kemudian%akan cocok denganfoo(%dapat cocok dengan nama target apa pun). Di bawah ini adalah aturan dalam bentuk yang diperluas:foo:foo.o
@echo "Memeriksa.."
gcc -lm foo.o -o fooSeperti yang ditunjukkan,
%digantikan olehfoo.$<digantikan olehfoo.o.$<dipola untuk mencocokkan prasyarat dan$@cocok dengan targetnya. Aturan ini akan dipanggil untuk setiap nilai di${BINS} -
Aturan:
%.o:%.c
@echo "Membuat objek.."
${CC} -c $<Setiap prasyarat dalam aturan sebelumnya dianggap sebagai target untuk aturan ini. Di bawah ini adalah aturan dalam bentuk yang diperluas:
foo.o:foo.c
@echo "Membuat objek.."
gcc -c foo.c -
Terakhir, kami menghapus semua file biner dan objek di target
clean.
Di bawah ini adalah penulisan ulang makefile di atas, dengan asumsi itu ditempatkan di direktori yang memiliki satu file foo.c:
# Penggunaan:
# make # kompilasi semua biner
# make clean # hapus SEMUA biner dan objek
.PHONY =all clean
CC =gcc # compiler yang akan digunakan
LINKERFLAG =-lm
SRCS :=foo.c
BINS :=foo
semua :foo
foo:foo.o
@echo "Memeriksa.."
gcc -lm foo.o -o foo
foo.o :foo.c
@echo "Membuat objek.."
gcc -c foo.c
clean:
@echo "Membersihkan..."
rm -rvf foo.o foo
Untuk lebih lanjut tentang makefile, lihat manual GNU Make, yang menawarkan referensi dan contoh lengkap.
Anda juga dapat membaca Pengantar GNU Autotools kami untuk mempelajari cara mengotomatiskan pembuatan makefile untuk proyek pengkodean Anda.