00 pkg-config nedir — .pc dosyası anatomisi
pkg-config, bir kütüphanenin derleme bayraklarını (include path, link flags) standart bir dosya formatından okur. Build sistemleri doğrudan kütüphane yolunu sabitlemek yerine pkg-config sorgular.
Örnek .pc dosyası
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib/arm-linux-gnueabihf
includedir=${prefix}/include
Name: OpenSSL
Description: Secure Sockets Layer and cryptography libraries and tools
Version: 3.0.2
Requires: libssl libcrypto
Libs: -L${libdir} -lssl -lcrypto
Libs.private: -ldl -lpthread
Cflags: -I${includedir}
pkg-config sorgulama
# derleme bayrakları (CFLAGS için)
pkg-config --cflags openssl
# -I/usr/include
# link bayrakları (LDFLAGS için)
pkg-config --libs openssl
# -lssl -lcrypto
# her ikisi birden
pkg-config --cflags --libs openssl
# -I/usr/include -lssl -lcrypto
# sürüm kontrolü
pkg-config --modversion openssl
# 3.0.2
# minimum sürüm kontrolü
pkg-config --atleast-version=1.1.0 openssl && echo "OK"
# gcc ile doğrudan kullanım
gcc $(pkg-config --cflags --libs openssl) -o app main.c
.pc dosyaları genellikle /usr/lib/pkgconfig/, /usr/share/pkgconfig/ veya /usr/lib/<arch>/pkgconfig/ altında bulunur. Cross ortamda bunların sysroot altındaki karşılıkları okunmalıdır.
01 PKG_CONFIG_PATH vs PKG_CONFIG_LIBDIR farkı
Bu iki değişken benzer görünse de cross-compile açısından kritik bir farkları vardır. Yanlış kullanım native kütüphanelerin cross binary'ye karışmasına yol açar.
/usr/lib/pkgconfig vb.) hâlâ aranır. Cross ortamda tehlikelidir — host sistemin .pc dosyaları sızmaya devam eder.Karşılaştırma
SYSROOT="${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot"
# YANLIŞ: PKG_CONFIG_PATH host dizinlerini hâlâ arar
export PKG_CONFIG_PATH="${SYSROOT}/usr/lib/pkgconfig"
pkg-config --libs openssl
# -lssl -lcrypto ← hangi openssl? host mu, target mı?
# tehlike: /usr/lib/pkgconfig/openssl.pc de bulunur
# DOĞRU: PKG_CONFIG_LIBDIR yalnızca hedef sysroot'u arar
export PKG_CONFIG_LIBDIR="${SYSROOT}/usr/lib/pkgconfig:${SYSROOT}/usr/share/pkgconfig"
export PKG_CONFIG_PATH="" # PATH'i boşalt
pkg-config --libs openssl
# -lssl -lcrypto ← kesinlikle sysroot'taki openssl
# mevcut .pc dosyalarını kontrol et
ls ${SYSROOT}/usr/lib/pkgconfig/
02 PKG_CONFIG_SYSROOT_DIR — path ön eki
.pc dosyasındaki prefix=/usr satırı mutlak yol içerir. Cross ortamda bu yolun başına sysroot eklenmesi gerekir — aksi hâlde linker host sistemini arar.
Sorun ve çözüm
SYSROOT="${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot"
# PKG_CONFIG_SYSROOT_DIR olmadan
export PKG_CONFIG_LIBDIR="${SYSROOT}/usr/lib/pkgconfig"
pkg-config --libs zlib
# -L/usr/lib -lz ← YANLIŞ: /usr/lib host sistemi
# PKG_CONFIG_SYSROOT_DIR ile
export PKG_CONFIG_SYSROOT_DIR="${SYSROOT}"
export PKG_CONFIG_LIBDIR="${SYSROOT}/usr/lib/pkgconfig:${SYSROOT}/usr/share/pkgconfig"
export PKG_CONFIG_PATH=""
pkg-config --libs zlib
# -L${SYSROOT}/usr/lib -lz ← DOĞRU: sysroot altındaki lib
Mekanizma açıklaması
.pc dosyasında: prefix=/usr
Libs: -L${prefix}/lib -lz
PKG_CONFIG_SYSROOT_DIR=/home/user/.../sysroot
pkg-config çıktısı:
-L/home/user/.../sysroot/usr/lib -lz
↑
SYSROOT_DIR + /usr/lib
03 pkg-config --cross-compile modu
--cross-compile bayrağı pkg-config'e cross ortamda olduğunu bildirir. Bu bayrak bazı güvenlik kontrollerini devre dışı bırakır.
SYSROOT="${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot"
export PKG_CONFIG_SYSROOT_DIR="${SYSROOT}"
export PKG_CONFIG_LIBDIR="${SYSROOT}/usr/lib/pkgconfig"
export PKG_CONFIG_PATH=""
# cross-compile bayrağı ile sorgula
pkg-config --cross-compile --cflags --libs openssl
# Makefile'da kullanım
CFLAGS += $(shell PKG_CONFIG_SYSROOT_DIR=${SYSROOT} \
PKG_CONFIG_LIBDIR=${SYSROOT}/usr/lib/pkgconfig \
PKG_CONFIG_PATH= \
pkg-config --cross-compile --cflags openssl)
LDFLAGS += $(shell PKG_CONFIG_SYSROOT_DIR=${SYSROOT} \
PKG_CONFIG_LIBDIR=${SYSROOT}/usr/lib/pkgconfig \
PKG_CONFIG_PATH= \
pkg-config --cross-compile --libs openssl)
--cross-compile, pkg-config'in Libs.private alanındaki -I ve -L path'lerindeki doğruluğu kontrol etmesini atlar. Cross ortamda bu kontrolün false positive vermesi engellenir.
04 Wrapper script — arm-linux-gnueabihf-pkg-config
Her sorguda ortam değişkenlerini elle yazmak yerine, cross toolchain için özel bir pkg-config wrapper scripti oluşturmak en temiz çözümdür. Birçok build sistemi PKG_CONFIG değişkeni ile bu scripti kullanır.
Wrapper scripti
#!/bin/bash
# pkg-config wrapper — ARM Cortex-A53 cross ortamı
# Kullanım: PKG_CONFIG=arm-linux-gnueabihf-pkg-config cmake ...
SYSROOT="${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot"
export PKG_CONFIG_SYSROOT_DIR="${SYSROOT}"
export PKG_CONFIG_LIBDIR="${SYSROOT}/usr/lib/pkgconfig:${SYSROOT}/usr/share/pkgconfig"
export PKG_CONFIG_PATH=""
exec pkg-config "$@"
# çalıştırma izni ver ve PATH'e ekle
chmod +x ~/bin/arm-linux-gnueabihf-pkg-config
export PATH="${HOME}/bin:${PATH}"
# test
arm-linux-gnueabihf-pkg-config --libs openssl
# -L/home/.../sysroot/usr/lib -lssl -lcrypto
# build sistemlerine bildir
export PKG_CONFIG=arm-linux-gnueabihf-pkg-config
# configure script ile kullanım
PKG_CONFIG=arm-linux-gnueabihf-pkg-config \
./configure --host=arm-unknown-linux-gnueabihf
# CMake ile kullanım
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-DPKG_CONFIG_EXECUTABLE=$(which arm-linux-gnueabihf-pkg-config) \
..
05 Ortak sorunlar — native path sızması
Cross-compile sırasında en sık karşılaşılan sorun, host sistemin kütüphanelerinin hedef binary'ye karışmasıdır. Bu genellikle linker hatası veya çalışma zamanı hatası olarak ortaya çıkar.
Teşhis yöntemleri
# binary'nin bağlı olduğu kütüphaneleri kontrol et
arm-linux-gnueabihf-readelf -d ./app | grep NEEDED
# 0x00000001 (NEEDED) Shared library: [libssl.so.3]
# 0x00000001 (NEEDED) Shared library: [libc.so.6]
# dynamic interpreter'ı kontrol et (ARM olmalı)
arm-linux-gnueabihf-readelf -l ./app | grep interpreter
# [Requesting program interpreter: /lib/ld-linux-armhf.so.3] ← DOĞRU
# [Requesting program interpreter: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2] ← YANLIŞ
# pkg-config hangi .pc dosyasını okuduğunu göster
PKG_CONFIG_DEBUG_SPEW=1 pkg-config --libs openssl 2>&1 | grep "File"
# mevcut tüm .pc dizinlerini listele
pkg-config --variable pc_path pkg-config
Sızma nedenleri ve çözümleri
export PKG_CONFIG_PATH="" — PATH'i tamamen boşalt./usr/lib/pkgconfig) aranmaya devam eder. Çözüm: LIBDIR'i sysroot'a ayarla.PKG_CONFIG_EXECUTABLE değişkeni ile zorla.06 CMake FIND_PACKAGE ile pkg-config entegrasyonu
CMake'in PkgConfig modülü, pkg-config sorgularını CMake target'larına dönüştürür. Cross ortamda toolchain.cmake ile birlikte kullanılır.
CMakeLists.txt — pkg-config kullanımı
cmake_minimum_required(VERSION 3.20)
project(myapp C)
# pkg-config modülünü yükle
find_package(PkgConfig REQUIRED)
# openssl bul
pkg_check_modules(OPENSSL REQUIRED openssl>=1.1.0)
# curl bul
pkg_check_modules(CURL REQUIRED libcurl>=7.68.0)
add_executable(myapp main.c)
# include ve link bayrakları otomatik eklenir
target_include_directories(myapp PRIVATE
${OPENSSL_INCLUDE_DIRS}
${CURL_INCLUDE_DIRS}
)
target_link_libraries(myapp PRIVATE
${OPENSSL_LIBRARIES}
${CURL_LIBRARIES}
)
# IMPORTED target kullanımı (daha modern)
pkg_check_modules(ZLIB REQUIRED IMPORTED_TARGET zlib)
target_link_libraries(myapp PRIVATE PkgConfig::ZLIB)
toolchain.cmake — pkg-config ayarları
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CROSS_TRIPLE "arm-unknown-linux-gnueabihf")
set(TOOLCHAIN_DIR "$ENV{HOME}/x-tools/${CROSS_TRIPLE}")
set(SYSROOT "${TOOLCHAIN_DIR}/${CROSS_TRIPLE}/sysroot")
set(CMAKE_C_COMPILER "${TOOLCHAIN_DIR}/bin/${CROSS_TRIPLE}-gcc")
set(CMAKE_CXX_COMPILER "${TOOLCHAIN_DIR}/bin/${CROSS_TRIPLE}-g++")
set(CMAKE_SYSROOT "${SYSROOT}")
# pkg-config wrapper
set(PKG_CONFIG_EXECUTABLE "$ENV{HOME}/bin/arm-linux-gnueabihf-pkg-config"
CACHE STRING "pkg-config wrapper for ARM cross-compile" FORCE)
# cmake'e sysroot path'i bildir
set(ENV{PKG_CONFIG_SYSROOT_DIR} "${SYSROOT}")
set(ENV{PKG_CONFIG_LIBDIR}
"${SYSROOT}/usr/lib/pkgconfig:${SYSROOT}/usr/share/pkgconfig")
set(ENV{PKG_CONFIG_PATH} "")
07 Pratik: libssl ve libcurl için cross .pc dosyası
Sysroot'ta .pc dosyası yoksa ya da yanlışsa, elle oluşturmak gerekebilir. Özellikle hedef rootfs'ten kopyalanan kütüphaneler için bu durum yaygındır.
Sysroot'a kütüphane kopyalama
SYSROOT="${HOME}/x-tools/arm-unknown-linux-gnueabihf/arm-unknown-linux-gnueabihf/sysroot"
TARGET_ROOT="/mnt/rpi-rootfs" # mount edilmiş hedef rootfs
# OpenSSL kütüphane ve başlıklarını kopyala
mkdir -p ${SYSROOT}/usr/include/openssl
mkdir -p ${SYSROOT}/usr/lib/pkgconfig
cp -r ${TARGET_ROOT}/usr/include/openssl/ ${SYSROOT}/usr/include/
cp ${TARGET_ROOT}/usr/lib/arm-linux-gnueabihf/libssl.so* ${SYSROOT}/usr/lib/
cp ${TARGET_ROOT}/usr/lib/arm-linux-gnueabihf/libcrypto.so* ${SYSROOT}/usr/lib/
cp ${TARGET_ROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig/openssl.pc ${SYSROOT}/usr/lib/pkgconfig/
Manuel .pc dosyası oluşturma
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: OpenSSL
Description: Secure Sockets Layer and cryptography libraries
Version: 3.0.2
Requires: libssl libcrypto
Libs: -L${libdir} -lssl -lcrypto
Cflags: -I${includedir}
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libcurl
Description: Library to transfer files with ftp, http, etc.
Version: 7.81.0
Libs: -L${libdir} -lcurl
Libs.private: -lssl -lcrypto -lz -lpthread
Cflags: -I${includedir}
Doğrulama
export PKG_CONFIG_SYSROOT_DIR="${SYSROOT}"
export PKG_CONFIG_LIBDIR="${SYSROOT}/usr/lib/pkgconfig"
export PKG_CONFIG_PATH=""
pkg-config --modversion openssl
# 3.0.2
pkg-config --cflags --libs openssl
# -I${SYSROOT}/usr/include -L${SYSROOT}/usr/lib -lssl -lcrypto
# derleme testi
arm-unknown-linux-gnueabihf-gcc \
$(pkg-config --cflags --libs openssl) \
-o ssl_test ssl_test.c
08 Static linking — --static bayrağı
Bazı embedded sistemlerde dinamik kütüphaneleri dağıtmak yerine statik link tercih edilir. pkg-config, --static ile statik linking için bayraklar sağlar.
--static bayrağı ile sorgulama
# dinamik linking için bayraklar
pkg-config --libs openssl
# -lssl -lcrypto
# statik linking için bayraklar (Libs.private dahil)
pkg-config --static --libs openssl
# -lssl -lcrypto -ldl -lpthread
# (statik link için tüm bağımlılıklar listelenir)
Statik binary derleme
CROSS=arm-unknown-linux-gnueabihf
SYSROOT="${HOME}/x-tools/${CROSS}/${CROSS}/sysroot"
export PKG_CONFIG_SYSROOT_DIR="${SYSROOT}"
export PKG_CONFIG_LIBDIR="${SYSROOT}/usr/lib/pkgconfig"
export PKG_CONFIG_PATH=""
# statik bağlantılı binary
${CROSS}-gcc \
--sysroot=${SYSROOT} \
-static \
$(pkg-config --static --cflags --libs openssl) \
-o app_static main.c
# dinamik bağımlılık yok mu kontrol et
${CROSS}-readelf -d app_static | grep NEEDED
# (boş çıktı — bağımlılık yok)
# QEMU'da dinamik linker gerektirmeden çalıştır
qemu-arm-static app_static
Yocto sysroot'unu elle kullanmak
# Yocto SDK sysroot'u genellikle bu konumdadır:
YOCTO_SDK="/opt/poky/4.0.15/sysroots"
YOCTO_SYSROOT="${YOCTO_SDK}/cortexa53-poky-linux"
# pkg-config'i Yocto sysroot'u ile kullan
export PKG_CONFIG_SYSROOT_DIR="${YOCTO_SYSROOT}"
export PKG_CONFIG_LIBDIR="${YOCTO_SYSROOT}/usr/lib/pkgconfig:\
${YOCTO_SYSROOT}/usr/share/pkgconfig"
export PKG_CONFIG_PATH=""
# Yocto'da çapraz derleyici
export CC="${YOCTO_SDK}/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gcc"
pkg-config --list-all | head -20
# Yocto'nun sysroot'undaki tüm kütüphaneler listelenir
Yocto SDK kurulum scripti (environment-setup-cortexa53-poky-linux) tüm bu değişkenleri otomatik ayarlar. source komutuyla yükle: source /opt/poky/4.0.15/environment-setup-cortexa53-poky-linux. Kendi toolchain'in için aynı yaklaşımı uygulayabilirsin.