Static library adalah kumpulan object file yang dibungkus dalam satu file archive berformat .a. Saat linker menemukan referensi ke simbol di static library, linker menyalin object file yang relevan dari archive ke dalam executable final. Hasilnya: executable mandiri yang tidak lagi membutuhkan file .a saat dijalankan. Pada chapter ini kita akan membuat static library sederhana dengan ar rcs, memeriksa isinya, dan menggunakannya dari program utama dengan dua gaya command line GCC.
Membuat Static Library #
Kode library kita terdiri dari header mylib.h dan implementasi mylib.c:
/* mylib.h */
#ifndef MYLIB_H
#define MYLIB_H
int tambah(int a, int b);
int kurang(int a, int b);
#endif/* mylib.c */
#include "mylib.h"
int tambah(int a, int b) {
return a + b;
}
int kurang(int a, int b) {
return a - b;
}Langkah pertama adalah mengompilasi mylib.c menjadi object file dengan flag -c. Selanjutnya, kita membungkus object file tersebut menjadi archive .a dengan ar rcs:
gcc -std=c11 -Wall -Wextra -c mylib.c -o mylib.o
ar rcs libmylib.a mylib.o
ls -l libmylib.aOutput yang Dihasilkan:
-rw-rw-r-- 1 z z 1362 libmylib.aMari kita telaah perintah ar rcs libmylib.a mylib.o:
ar: archiver dari GNU Binutils — program yang membuat dan memodifikasi archive.a.r(replace): bilamylib.osudah ada di archive, ganti; bila belum ada, tambahkan. Flagrmembuat perintah idempoten — aman dipanggil berulang.c(create): bila archivelibmylib.abelum ada, buat archive baru tanpa menampilkan pesan peringatan. Tanpac,arakan mengeluh bila file tidak ada.s(symbol index): tulis indeks simbol di awal archive. Indeks ini yang dibaca linker untuk cepat menemukan object file mana di archive yang berisi simbol tertentu. Tanpas, linker tidak bisa memakai archive sebagai library (archive menjadi kumpulan object file biasa, bukan library).
Memeriksa Isi Archive #
Perintah ar -t menampilkan daftar member di dalam archive:
ar -t libmylib.aOutput yang Dihasilkan:
mylib.oPerintah nm juga menerima file archive dan menampilkan symbol table tiap member:
nm libmylib.aOutput yang Dihasilkan:
mylib.o:
0000000000000014 T kurang
0000000000000000 T tambahHeader kosong diikuti nama member (mylib.o:) menandakan bahwa nm menampilkan simbol per member. Simbol tambah dan kurang muncul dengan huruf T (global, section .text) sehingga bisa dirujuk dari file lain.
Menggunakan Static Library dari Program Utama #
Program utama main.c meng-include header library dan memanggil fungsinya:
#include <stdio.h>
#include "mylib.h"
int main(void) {
printf("5 + 3 = %d\n", tambah(5, 3));
printf("10 - 4 = %d\n", kurang(10, 4));
return 0;
}Cara pertama untuk men-link library adalah menyebut path file .a secara langsung:
gcc -std=c11 -Wall -Wextra main.c libmylib.a -o app
./appOutput yang Dihasilkan:
5 + 3 = 8
10 - 4 = 6Cara kedua memakai konvensi -L<path> -l<name>, yang lebih lazim di Makefile dan CMakeLists.txt:
gcc -std=c11 -Wall -Wextra -L. main.c -lmylib -o app2
./app2Output yang Dihasilkan:
5 + 3 = 8
10 - 4 = 6Mari kita telaah flag yang dipakai di command line kedua:
-L.: tambahkan direktori.(direktori saat ini) ke daftar pencarian library. Tanpa flag ini, GCC hanya mencari library di/usr/lib,/usr/lib/x86_64-linux-gnu, dan direktori bawaan lainnya — bukan di direktori kerja kita.-lmylib: link dengan library bernamalibmylib. GCC menerjemahkanmylibmenjadilibmylib.a(ataulibmylib.so) dan mencari di daftar direktori-L. Konvensilib<name>.amenyembunyikan prefixlibdan ekstensi.adari command line, membuat script build lebih bersih.- Urutan
main.c ... -lmylib: GCC memproses argumen dari kiri ke kanan.main.cdibaca terlebih dahulu — linker mencatat bahwamain.cmerujuktambahdankurang(undefined). Baru kemudian-lmylibdiproses — linker mencari di archive dan menemukan definisitambahsertakurang. Bila urutan dibalik (-lmylib main.c), linker akan memproses library lebih dulu, menemukan tidak ada referensi yang perlu diresolve, lalu membuang object file dari archive — akibatnyaundefined reference.
Static Library dengan Banyak Modul #
Library nyata sering berisi banyak object file. Kita bisa menambahkan modul baru dengan ar rcs:
# Update mylib.h dengan deklarasi baru
cat > mylib.h <<'EOF'
#ifndef MYLIB_H
#define MYLIB_H
int tambah(int a, int b);
int kurang(int a, int b);
int kali(int a, int b);
#endif
EOF
# Implementasi fungsi baru di file terpisah
cat > mylib2.c <<'EOF'
#include "mylib.h"
int kali(int a, int b) {
return a * b;
}
EOF
gcc -std=c11 -Wall -Wextra -c mylib2.c -o mylib2.o
ar rcs libmylib.a mylib.o mylib2.o
ar -t libmylib.aOutput yang Dihasilkan:
mylib.o
mylib2.oSekarang archive berisi dua member. Karena flag s dipakai, indeks simbol sudah diperbarui otomatis untuk mencakup simbol di mylib2.o. Linker dapat menemukan tambah di mylib.o dan kali di mylib2.o tanpa campur tangan manual.
Karakteristik Static Library #
Ciri khas static library adalah kode library menjadi bagian dari executable. Mari kita verifikasi dengan ldd dan nm:
ldd appOutput yang Dihasilkan:
linux-vdso.so.1 (0x00007ffecbb7e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc070ef1000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc0710fb000)Tidak ada dependensi ke libmylib.a — kode tambah dan kurang sudah disalin ke executable. Verifikasi dengan nm:
nm app | grep -E "tambah|kurang"Output yang Dihasilkan:
00000000000011a2 T kurang
000000000000118e T tambahSimbol tambah dan kurang sekarang ada di section .text executable app dengan alamat absolut (0x118e dan 0x11a2). Inilah inti static linking: linker menyalin object file yang relevan dari archive ke executable, dan executable bisa didistribusikan tanpa file .a di sistem target.