Repository Debian mengemas puluhan ribu package, tetapi kadang kebutuhan kita jatuh di luar jangkauannya: versi terbaru yang belum sempat dikemas, opsi kompilasi yang tidak diaktifkan pengempannya, atau software kecil yang belum dikemas siapa pun. Untuk kondisi seperti itu, jalur tertua di dunia Unix tetap terbuka: mengambil source code lalu membangunnya sendiri. Kabar baiknya, toolchain yang dibutuhkan — compiler gcc dan build automation make — sudah terpasang di lingkungan ini, sehingga seluruh contoh pada Chapter ini benar-benar dijalankan, bukan sekadar dibayangkan.
Toolchain: gcc, make, dan Paket -dev #
Kompilasi adalah penerjemahan source code menjadi instruksi mesin. Tiga komponen berperan di dalamnya:
| Komponen | Peran |
|---|---|
gcc | compiler keluarga GNU: menerjemahkan C menjadi object file, lalu menggabungkannya menjadi binary |
make | build automation: membandingkan waktu modifikasi file, lalu hanya membangun ulang yang berubah |
libc6-dev | header dan pustaka pengembangan libc — termasuk stdio.h yang kita #include |
build-essential | metapackage: menarik gcc, g++, make, dan libc6-dev sekaligus |
Perhatikan baris libc6-dev — inilah wajah konsep paket -dev. Package biasa membawa file yang dibutuhkan program saat berjalan, sedangkan package berakhiran -dev membawa file yang dibutuhkan saat mengompilasi: deklarasi header dan tautan ke pustaka. Kita sudah melihat build-essential menarik gcc dan make lewat relasi Depends pada Chapter Package Dependencies
. Gejala kekurangan toolchain sangat khas: compiler berhenti dengan pesan fatal error: stdio.h: No such file or directory — obatnya satu kalimat, sudo apt install build-essential.
Kompilasi Pertama: dari halo.c ke Binary #
gcc sebenarnya pengemudi empat tahap — preprosesor, compiler, assembler, lalu linker — tetapi kita cukup memanggilnya sekali. Program C terkecil yang masih berguna kita tulis dengan heredoc, lalu langsung dikompilasi dan dijalankan:
cat > halo.c << 'AKHIR'
#include <stdio.h>
int main(void)
{
printf("Halo dari C!\n");
return 0;
}
AKHIR
gcc -Wall -o halo halo.c
./haloOutput yang Dihasilkan:
Halo dari C!Bedah program dan perintahnya baris per baris:
- Baris 1 (
#include <stdio.h>): memuat deklarasi fungsi input/output standar — tanpa baris ini, compiler tidak mengenalprintf. - Baris 3–7 (fungsi
main): titik masuk program; eksekusi binary dimulai dari fungsi ini. - Baris 5 (
printf): menulis satu baris teks ke stdout;\nmenandai akhir baris. - Baris 6 (
return 0): mengembalikan exit code0, tanda sukses — konsep yang kita kenal dari Chapter Exit Codes . gcc -Wall -o halo halo.c:-Wallmengaktifkan kelompok warning agar kejanggalan terlihat sebelum menjadi bug, dan-o halomenamai binary hasil (tanpa-ohasilnya bernamaa.out). Diamnyagccadalah kabar baik: tanpa warning, tanpa error../halo: menjalankan binary baru; awalan./wajib karena direktori kerja tidak termasuk dalamPATH.
Makefile: Resep Build yang Diingat make #
Satu file bisa dijalankan langsung dengan gcc, tetapi proyek nyata berisi puluhan file — dan mengompilasi semuanya setiap perubahan kecil adalah pemborosan. make mengatasinya dengan aturan sederhana: sebuah target dibangun ulang hanya bila prasyaratnya lebih baru, dilihat dari waktu modifikasi file. Aturan itu ditulis dalam Makefile:
cat > halo.c << 'AKHIR'
#include <stdio.h>
int main(void)
{
printf("Halo dari C!\n");
return 0;
}
AKHIR
cat > Makefile << 'AKHIR'
all: halo
halo: halo.c
gcc -Wall -o halo halo.c
clean:
rm -f halo
AKHIR
rm -f halo
make
./halo
make halo
make clean
lsOutput yang Dihasilkan:
gcc -Wall -o halo halo.c
Halo dari C!
make: 'halo' is up to date.
rm -f halo
Makefile
halo.cBedah Makefile dan eksekusinya:
- Baris 1 (
all: halo): target pertama menjadi target default, sehinggamaketanpa argumen membangunnya;alladalah nama kebiasaan untuk “seluruh hasil”. - Baris 3–4 (
halo: halo.cdan resepnya): aturan membangun targethalodari prasyarathalo.c; baris resep wajib diawali karakter TAB — bukan spasi. rm -f halodanmake: penghapusan di awal memastikan keadaan bersih, danmakemenampilkan tiap resep sebelum menjalankannya.make halo: karenahalobarusan dibuat dan lebih baru darihalo.c, make menolak bekerja dengan alasan up to date — penghematan inilah alasan make ada.make clean: target tanpa prasyarat untuk menghapus hasil build, ditutuplssebagai konfirmasi bahwahalosudah terhapus.
Jabatan TAB itu serius. Menulis resep dengan spasi biasa menghasilkan error yang paling sering dijumpai pemula Makefile:
printf 'all:\n echo halo\n' > Makefile
make 2>&1Output yang Dihasilkan:
Makefile:2: *** missing separator. Stop.printf sengaja menulis baris resep dengan spasi di depan, bukan TAB, dan make langsung menolaknya: pesan missing separator berarti awalan resep tidak ditemukan. Editor yang diam-diam mengubah TAB menjadi spasi adalah penyebab klasiknya — sebagian editor punya mode khusus untuk Makefile. Rincian sintaks make ada di make(1)
, dan opsi compiler di gcc(1)
.
Alur Klasik Tarball: configure, make, make install #
Software yang didistribusikan sebagai source biasanya berbentuk arsip tarball berisi source code dan script persiapan. Alur pembangunannya telah menjadi standar de facto selama puluhan tahun:
tar -xf program-1.2.3.tar.gz
cd program-1.2.3
./configure --prefix=/usr/local
make
sudo make installPeran tiap langkah: tar -xf mengekstrak arsip menjadi folder program-1.2.3/. Script ./configure memeriksa sistem — apakah compiler ada, apakah pustaka yang dibutuhkan tersedia dalam versi cocok — lalu menulis Makefile yang disesuaikan; opsi --prefix menentukan lokasi pemasangan nanti. Selanjutnya make menjalankan Makefile hasil configure, dan sudo make install menyalin binary, pustaka, serta dokumentasi ke lokasi target — butuh root karena tujuannya di luar home directory. Sebagai contoh tampilan, pembukaan ./configure pada proyek nyata berbentuk seperti ini:
checking for gcc... gcc
checking whether the C compiler works... yes
checking for stdio.h... yes
configure: creating ./config.status
config.status: creating MakefileBaris-baris checking adalah pemeriksaan sistem tadi; dua baris terakhir menandakan Makefile berhasil ditulis dan siap dijalankan make. Proyek modern sebagian bermigrasi ke CMake atau Meson, tetapi hasil akhirnya sama: satu set aturan build yang menjembatani source code menjadi binary.
make install dan Wilayah /usr/local #
Langkah sudo make install menimbulkan pertanyaan penting: mengapa targetnya /usr/local, bukan /usr? Jawabannya ada pada pembagian wilayah dalam Filesystem Hierarchy Standard:
| Lokasi | Diisi oleh | Isi tipikal |
|---|---|---|
/usr/bin, /usr/lib | package manager (dpkg, dnf, pacman) | software dari repository |
/usr/local/bin, /usr/local/lib | administrator, lewat make install | hasil kompilasi sendiri |
/usr/local direservasikan khusus untuk software yang dibangun sendiri sehingga tidak pernah bertabrakan dengan milik package manager. Perilaku make install bisa kita lihat dengan aman tanpa root — cukup arahkan PREFIX ke folder kerja:
cat > halo.c << 'AKHIR'
#include <stdio.h>
int main(void)
{
printf("Halo dari C!\n");
return 0;
}
AKHIR
cat > Makefile << 'AKHIR'
PREFIX ?= /usr/local
all: halo
halo: halo.c
gcc -Wall -o halo halo.c
install: halo
install -D halo $(PREFIX)/bin/halo
clean:
rm -f halo
AKHIR
rm -f halo
make install PREFIX="$PWD/akar-lokal"
akar-lokal/bin/halo
ls akar-lokal/binOutput yang Dihasilkan:
gcc -Wall -o halo halo.c
install -D halo /home/budi/akar-lokal/bin/halo
Halo dari C!
haloBedah baris-baris pentingnya:
PREFIX ?= /usr/local(baris 1 Makefile): operator?=berarti “pakai nilai ini hanya bila belum ditentukan”, sehinggamake install PREFIX=...di baris perintah bisa menimpanya tanpa mengubah file.install -D halo $(PREFIX)/bin/halo: perintahinstallmenyalin file sekaligus membuat direktori tujuannya — inilah yang dikerjakansudo make installsesungguhnya, hanya saja ke/usr/local.make install PREFIX="$PWD/akar-lokal": memakai folder kerja sebagai target sehingga tidak butuh root. Path/home/budipada output mengikuti folder kerja di mesin masing-masing.
Agar Hasil Kompilasi Tetap Terlacak #
Kelemahan make install klasik ada pada jejaknya: penghapusan bergantung pada target uninstall yang kebetulan disediakan — jika memang disediakan. Dua alat bantu menjawabnya. checkinstall dulu paling populer: alat ini mengintip eksekusi make install, mencatat file yang disentuhnya, lalu mengemasnya menjadi file .deb sehingga tercatat di database dpkg dan bisa dilepas dengan apt remove — sayangnya checkinstall sudah lama tidak hadir di repository Debian, meski masih tersedia di Ubuntu; cara manualnya membangun .deb dengan dpkg-deb --build sudah kita praktikkan di Chapter apt dan dpkg
. Alternatif lain adalah GNU stow: tiap program dipasang ke foldernya sendiri di bawah /usr/local/stow/, lalu stow membuat symlink dari /usr/local/bin ke sana — mengganti versi cukup menghapus tautan lama tanpa menyentuh binary. Rinciannya ada di stow(8)
.
Alur di atas menuntut toolchain yang sehat: compiler terpasang, header -dev lengkap, dan ruang disk cukup. Ketika salah satunya absen, kompilasi berhenti dengan pesan error yang — sama seperti pesan apt — dirancang untuk dibaca sampai habis. Kebiasaan membaca dan menindaklanjuti pesan error itu adalah materi Chapter berikutnya: Troubleshooting Packages.