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:

text
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:

  1. prefix=/usr: variabel prefix menyimpan path instalasi library. Variabel ini dirujuk dengan sintaks ${prefix} di baris lain.
  2. exec_prefix, libdir, includedir: variabel turunan yang menggabungkan prefix dengan subdirektori spesifik. Pemisahan ini memudahkan library diinstal di lokasi non-standar (misal /opt/zlib-1.3.1).
  3. Name:: nama library untuk ditampilkan saat pkg-config --list-all.
  4. Description:: ringkasan satu baris tentang library.
  5. Version:: versi library — penting untuk pengecekan pkg-config --atleast-version=1.2.
  6. Requires:: daftar library lain yang menjadi dependensi. Saat pkg-config menampilkan flag, flag dari Requires juga ikut.
  7. Libs:: flag linker yang harus ditambahkan ke GCC saat men-link library ini.
  8. Cflags:: flag compiler yang harus ditambahkan saat mengompilasi source yang memakai library ini (terutama -I path header).

Menggunakan pkg-config dengan Library Sistem #

Mari kita periksa library libcrypto (komponen kriptografi OpenSSL) yang sudah terinstal di sandbox:

bash
pkg-config --modversion libcrypto

Output yang Dihasilkan:

text
3.5.7

Untuk memeriksa keberadaan library tanpa mengeluarkan flag, gunakan --exists:

bash
pkg-config --exists --print-errors libcrypto
echo "exit: $?"

Output yang Dihasilkan:

text
exit: 0

Exit 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:

bash
pkg-config --cflags --libs libcrypto

Output yang Dihasilkan:

text
-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:

c
#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:

bash
gcc -std=c11 -Wall -Wextra sha_demo.c $(pkg-config --cflags --libs libcrypto) -o sha_demo
./sha_demo

Output yang Dihasilkan:

text
sha256("halo dunia") = 09b50b2f685e7a783eeee02d8070e670d48af118a4b00f7bfebe9f8f0e5d3d52

Konstruksi $(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:

text
/tmp/test_pkg_config/
  lib/
    mymath.h
    libmymath.so
  pkgconfig/
    mymath.pc

File mymath.pc berisi:

text
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:

bash
export PKG_CONFIG_PATH=/tmp/test_pkg_config/pkgconfig
pkg-config --cflags --libs mymath

Output yang Dihasilkan:

text
-I/tmp/test_pkg_config/lib -L/tmp/test_pkg_config/lib -lmymath

Sekarang flag header dan library untuk mymath bisa dipakai seperti library sistem:

bash
gcc -std=c11 -Wall -Wextra main.c $(pkg-config --cflags --libs mymath) -o app
LD_LIBRARY_PATH=/tmp/test_pkg_config/lib ./app

Output yang Dihasilkan:

text
kuadrat(7) = 49

Integrasi dengan Makefile #

Pola umum di Makefile adalah memakai $(shell pkg-config ...) untuk meng-capture flag saat Makefile dibaca:

makefile
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: clean
bash
make clean && make
./sha_demo

Output yang Dihasilkan:

text
rm -f sha_demo
gcc -std=c11 -Wall -Wextra  sha_demo.c -o sha_demo -lcrypto 
sha256("halo dunia") = 09b50b2f685e7a783eeee02d8070e670d48af118a4b00f7bfebe9f8f0e5d3d52

Perhatikan 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.