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.make
akan 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
make
harus meneleponsay_hello
dangenerate
:$ make
Hello World
Membuat file teks kosong...
touch file-{1..10}.txtIni adalah praktik yang baik untuk tidak memanggil
clean
diall
atau menjadikannya sebagai target pertama.clean
harus 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 clean
mendefinisikan target palsuall
danclean
. -
Variabel
LINKERFLAG
mendefinisikan flag yang akan digunakan dengangcc
dalam resep. -
SRCS := $(wildcard *.c)
:$(wildcard pattern)
adalah salah satu fungsi untuk nama file . Dalam hal ini, semua file dengan.c
ekstensi akan disimpan dalam variabelSRCS
. -
BINS := $(SRCS:%.c=%)
:Ini disebut sebagai referensi substitusi . Dalam hal ini, jikaSRCS
memiliki nilai'foo.c bar.c'
,BINS
akan memiliki'foo bar'
. -
Baris
all: ${BINS}
:Target palsuall
memanggil nilai di${BINS}
sebagai target individu. -
Aturan:
%:%.o
@echo "Memeriksa.."
${CC} ${LINKERFLAG} $< -o $@Mari kita lihat contoh untuk memahami aturan ini. Misalkan
foo
adalah 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.