Saat proyek C memakai banyak library eksternal (OpenSSL, libcurl, zlib, glib, SDL), kita harus tahu path header (-I/usr/include/openssl), path library (-L/usr/lib/x86_64-linux-gnu), nama library (-lcrypto -lssl), dan versi library. Pengetahuan ini berbeda-beda di tiap distro dan versi library — bila kita hardcode flag di Makefile, kode build mudah rusak saat dipindahkan ke mesin lain. pkg-config menyelesaikan masalah ini: setiap library yang terinstal menyertakan file .pc berisi metadata (path, flag, versi), dan pkg-config membaca metadata tersebut untuk menghasilkan flag yang benar. Pada chapter ini kita akan melihat pkg-config beraksi dengan library kustom dan dengan libcrypto (OpenSSL) yang terinstal di sistem.
File .pc dan Cara Kerjanya #
Setiap library yang mendukung pkg-config menyertakan file berakhiran .pc (biasanya di /usr/lib/x86_64-linux-gnu/pkgconfig/). File ini berformat teks dengan struktur key-value sederhana. Contoh isi zlib.pc di Debian:
prefix=/usr
exec_prefix=${prefix}
libdir=${prefix}/lib/x86_64-linux-gnu
sharedlibdir=${libdir}
includedir=${prefix}/include
Name: zlib
Description: zlib compression library
Version: 1.3.1
Requires:
Libs: -L${libdir} -L${sharedlibdir} -lz
Cflags: -I${includedir}Mari kita telaah struktur file .pc di atas:
prefix=/usr: variabelprefixmenyimpan path instalasi library. Variabel ini dirujuk dengan sintaks${prefix}di baris lain.exec_prefix,libdir,includedir: variabel turunan yang menggabungkanprefixdengan subdirektori spesifik. Pemisahan ini memudahkan library diinstal di lokasi non-standar (misal/opt/zlib-1.3.1).Name:: nama library untuk ditampilkan saatpkg-config --list-all.Description:: ringkasan satu baris tentang library.Version:: versi library — penting untuk pengecekanpkg-config --atleast-version=1.2.Requires:: daftar library lain yang menjadi dependensi. Saatpkg-configmenampilkan flag, flag dariRequiresjuga ikut.Libs:: flag linker yang harus ditambahkan ke GCC saat men-link library ini.Cflags:: flag compiler yang harus ditambahkan saat mengompilasi source yang memakai library ini (terutama-Ipath header).
Menggunakan pkg-config dengan Library Sistem #
Mari kita periksa library libcrypto (komponen kriptografi OpenSSL) yang sudah terinstal di sandbox:
pkg-config --modversion libcryptoOutput yang Dihasilkan:
3.5.7Untuk memeriksa keberadaan library tanpa mengeluarkan flag, gunakan --exists:
pkg-config --exists --print-errors libcrypto
echo "exit: $?"Output yang Dihasilkan:
exit: 0Exit status 0 menandakan library ditemukan. Bila library tidak ada, exit status menjadi 1 dan --print-errors menampilkan pesan Package libfoo was not found. Pola ini sering dipakai di awal configure script untuk memeriksa prasyarat build.
Untuk mendapatkan flag compiler dan linker:
pkg-config --cflags --libs libcryptoOutput yang Dihasilkan:
-lcrypto Kosong di bagian depan berarti tidak ada flag -I (header OpenSSL ada di path default /usr/include), dan -lcrypto adalah satu-satunya flag linker yang diperlukan. Bila library dipasang di lokasi non-standar, output akan berisi -I/opt/foo/include -L/opt/foo/lib -lfoo.
Mengompilasi Program dengan Library Sistem #
Program berikut memakai SHA256() dari OpenSSL untuk menghitung hash sebuah pesan:
#include <stdio.h>
#include <openssl/sha.h>
int main(void) {
const unsigned char msg[] = "halo dunia";
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256(msg, sizeof(msg) - 1, hash);
printf("sha256(\"%s\") = ", msg);
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
printf("%02x", hash[i]);
}
printf("\n");
return 0;
}Kompilasi dengan flag dari pkg-config:
gcc -std=c11 -Wall -Wextra sha_demo.c $(pkg-config --cflags --libs libcrypto) -o sha_demo
./sha_demoOutput yang Dihasilkan:
sha256("halo dunia") = 09b50b2f685e7a783eeee02d8070e670d48af118a4b00f7bfebe9f8f0e5d3d52Konstruksi $(pkg-config --cflags --libs libcrypto) adalah command substitution shell — output perintah pkg-config disisipkan sebagai argumen tambahan ke gcc. Inilah cara idiomatik memakai pkg-config di command line.
Membuat .pc untuk Library Sendiri #
Bila kita menulis library sendiri dan ingin dipakai dengan pkg-config, buat file .pc. Misal kita punya library mymath.so dengan struktur direktori berikut:
/tmp/test_pkg_config/
lib/
mymath.h
libmymath.so
pkgconfig/
mymath.pcFile mymath.pc berisi:
prefix=/tmp/test_pkg_config
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/lib
Name: mymath
Description: Tiny math library for demo
Version: 1.0.0
Libs: -L${libdir} -lmymath
Cflags: -I${includedir}Agar pkg-config menemukan file .pc di lokasi non-standar, set variabel PKG_CONFIG_PATH:
export PKG_CONFIG_PATH=/tmp/test_pkg_config/pkgconfig
pkg-config --cflags --libs mymathOutput yang Dihasilkan:
-I/tmp/test_pkg_config/lib -L/tmp/test_pkg_config/lib -lmymathSekarang flag header dan library untuk mymath bisa dipakai seperti library sistem:
gcc -std=c11 -Wall -Wextra main.c $(pkg-config --cflags --libs mymath) -o app
LD_LIBRARY_PATH=/tmp/test_pkg_config/lib ./appOutput yang Dihasilkan:
kuadrat(7) = 49Integrasi dengan Makefile #
Pola umum di Makefile adalah memakai $(shell pkg-config ...) untuk meng-capture flag saat Makefile dibaca:
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra $(shell pkg-config --cflags libcrypto)
LDFLAGS = $(shell pkg-config --libs libcrypto)
sha_demo: sha_demo.c
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
clean:
rm -f sha_demo
.PHONY: cleanmake clean && make
./sha_demoOutput yang Dihasilkan:
rm -f sha_demo
gcc -std=c11 -Wall -Wextra sha_demo.c -o sha_demo -lcrypto
sha256("halo dunia") = 09b50b2f685e7a783eeee02d8070e670d48af118a4b00f7bfebe9f8f0e5d3d52Perhatikan bahwa --cflags libcrypto di sistem ini menghasilkan string kosong (header OpenSSL ada di path default) sehingga tidak ada argumen tambahan setelah -Wall -Wextra. Bila kita pindah ke mesin yang menginstal OpenSSL di /opt/openssl, Makefile yang sama tetap bekerja karena pkg-config akan otomatis menyertakan flag -I/opt/openssl/include dan -L/opt/openssl/lib.