Cross-Compilation & Toolchain
TEKNİK REHBER CROSS-COMPILATION PKG-CONFIG 2026

pkg-config —
cross ortamda kütüphane bulma.

PKG_CONFIG_LIBDIR ile native path sızmasını önle. Wrapper script yaz. libssl, libcurl ve zlib'i cross sysroot'tan otomatik bul.

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ı

/usr/lib/pkgconfig/openssl.pc●
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

bash●
# 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 DOSYASI KONUMU

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

PKG_CONFIG_PATH
Varsayılan arama dizinlerine eklenen yollar. Yani varsayılan dizinler (/usr/lib/pkgconfig vb.) hâlâ aranır. Cross ortamda tehlikelidir — host sistemin .pc dosyaları sızmaya devam eder.
PKG_CONFIG_LIBDIR
Varsayılan arama dizinlerini tamamen değiştirir. Sadece bu dizinler aranır. Cross-compile'da kullanılması gereken değişken budur — host .pc dosyaları devre dışı kalır.

Karşılaştırma

bash●
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

bash●
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.

bash●
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)
NOT

--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/arm-linux-gnueabihf-pkg-config●
#!/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 "$@"
bash●
# ç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

bash●
# 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

PKG_CONFIG_PATH içinde host dizini
Çözüm: export PKG_CONFIG_PATH="" — PATH'i tamamen boşalt.
PKG_CONFIG_LIBDIR ayarlanmamış
Varsayılan dizinler (/usr/lib/pkgconfig) aranmaya devam eder. Çözüm: LIBDIR'i sysroot'a ayarla.
PKG_CONFIG_SYSROOT_DIR eksik
.pc dosyasındaki mutlak yollar sysroot ön eki almaz. -L/usr/lib host'u işaret eder.
CMake'in kendi pkg-config çağrısı
CMake bazen wrapper scripti yok sayar. 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ı

CMakeLists.txt●
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ı

toolchain.cmake●
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

bash●
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

${SYSROOT}/usr/lib/pkgconfig/openssl.pc●
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}
${SYSROOT}/usr/lib/pkgconfig/libcurl.pc●
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

bash●
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

bash●
# 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

bash●
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

bash●
# 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 SETUP

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.