00 Autotools nedir?
Autotools, GNU projesi tarafından geliştirilen ve taşınabilir yazılım dağıtımı için tasarlanmış bir araç zinciridir. Hedef sistem hakkında hiçbir varsayım yapılmaksızın ./configure && make && make install üçlüsünün her platformda çalışmasını sağlar.
Ne zaman kullanılır?
.tar.gz ile dağıtılan ve derleyici bağımsızlığı gereken projeler--host / --build mekanizması ile kolay cross-compileAraç zinciri bileşenleri
Geliştirici yazdığı dosyalar:
configure.ac + Makefile.am
│
│ autoreconf -fvi
▼
┌──────────────────────────────────┐
│ autoconf → configure script │
│ automake → Makefile.in │
│ libtoolize → ltmain.sh │
│ aclocal → aclocal.m4 │
└──────────────┬───────────────────┘
│
│ ./configure --prefix=/usr
▼
┌──────────────────────────────────┐
│ Makefile (platforma özgü) │
└──────────────┬───────────────────┘
│
▼
make → make install
CMake / Meson karşılaştırması
| Kriter | Autotools | CMake | Meson |
|---|---|---|---|
| Tarball dağıtımı | Mükemmel | İyi | Orta |
| Öğrenme eğrisi | Dik | Orta | Kolay |
| Cross-compile | Yerleşik | Toolchain file | Cross file |
| Ekosistem entegrasyonu | GNU ekosistemi | Geniş | Büyüyor |
| Windows desteği | Zayıf | İyi | İyi |
01 configure.ac yazımı
configure.ac, projenin derleme gereksinimlerini M4 macro dili ile tanımlar. autoconf bu dosyayı işleyerek platform bağımsız configure betiğini üretir.
dnl -*- Autoconf -*-
dnl configure.ac — libsensor projesi
dnl ── Proje başlığı ────────────────────────────────────────────
AC_INIT([libsensor], [1.2.0], [dev@example.com])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIRS([m4])
dnl Automake başlatma: tarball standartları
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
dnl Libtool desteği
LT_INIT
dnl ── Dil ve derleyici ─────────────────────────────────────────
AC_PROG_CC
AC_PROG_CC_STDC
AM_PROG_CC_C_O dnl per-target CFLAGS için gerekli
dnl C derleyicisini doğrula
AC_LANG([C])
dnl ── Sistem özellikleri ───────────────────────────────────────
AC_FUNC_MMAP
AC_CHECK_FUNCS([clock_gettime nanosleep])
dnl Pthread desteği
AX_PTHREAD([
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CC="$PTHREAD_CC"
], [AC_MSG_ERROR([pthread gerekli])])
dnl ── Header kontrolleri ───────────────────────────────────────
AC_CHECK_HEADERS([stdint.h sys/ioctl.h linux/i2c-dev.h], [],
[AC_MSG_ERROR([Gerekli header bulunamadı])])
dnl ── Kütüphane kontrolleri ────────────────────────────────────
dnl libm kontrolü
AC_CHECK_LIB([m], [sqrt],
[LIBS="-lm $LIBS"],
[AC_MSG_ERROR([libm gerekli])])
dnl OpenSSL (opsiyonel)
AC_ARG_WITH([openssl],
AS_HELP_STRING([--with-openssl], [OpenSSL şifreleme desteği]),
[with_openssl=$withval], [with_openssl=auto])
AS_IF([test "x$with_openssl" != "xno"],
[PKG_CHECK_MODULES([OPENSSL], [openssl >= 1.1.0],
[AC_DEFINE([HAVE_OPENSSL], [1], [OpenSSL mevcut])],
[AS_IF([test "x$with_openssl" = "xyes"],
[AC_MSG_ERROR([OpenSSL bulunamadı])])])])
dnl ── Çıktı dosyaları ──────────────────────────────────────────
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([
Makefile
src/Makefile
tests/Makefile
libsensor.pc dnl pkg-config dosyası
])
AC_OUTPUT
dnl Özet
AC_MSG_NOTICE([
── libsensor yapılandırması tamamlandı ─────
Versiyon : $PACKAGE_VERSION
Prefix : $prefix
CC : $CC
CFLAGS : $CFLAGS
OpenSSL : $with_openssl
─────────────────────────────────────────────
])
Sık kullanılan macro'lar
| Macro | İşlev |
|---|---|
AC_INIT | Proje adı, versiyon, hata e-postası tanımla |
AC_PROG_CC | C derleyicisini bul ve ayarla |
AC_CHECK_LIB | Belirtilen kütüphane ve fonksiyonu bul |
AC_CHECK_HEADER | Header dosyasının varlığını kontrol et |
PKG_CHECK_MODULES | pkg-config ile bağımlılık bul |
AC_DEFINE | config.h'a #define ekle |
AC_ARG_WITH | --with-feature configure seçeneği ekle |
AC_ARG_ENABLE | --enable-feature configure seçeneği ekle |
AC_SUBST | Makefile.in'de kullanılacak değişken ata |
AC_OUTPUT | Yapılandırmayı bitir ve dosyaları oluştur |
02 Makefile.am yazımı
Makefile.am, Automake'in Makefile.in üretmek için kullandığı üst seviyeli tanım dosyasıdır. Hangi programlar ve kütüphaneler derleneceğini, hangi kaynak dosyalardan oluşacağını basit bir sözdizimi ile belirtir.
Kök Makefile.am
# Alt dizinler
SUBDIRS = src tests
# Dağıtıma dahil edilecek ek dosyalar
EXTRA_DIST = \
README.md \
COPYING \
m4/ax_pthread.m4 \
libsensor.pc.in
# pkg-config dosyasını pkgconfig dizinine kur
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libsensor.pc
# Header dosyalarını install et
include_HEADERS = include/sensor.h include/sensor_types.h
src/Makefile.am — kütüphane ve program
# ── Shared library ──────────────────────────────────────────────
lib_LTLIBRARIES = libsensor.la
libsensor_la_SOURCES = \
sensor.c \
i2c.c \
filter.c \
internal.h
# Halka açık headerlar (install edilir)
libsensor_la_includedir = $(includedir)/sensor
libsensor_la_include_HEADERS = \
../include/sensor.h \
../include/sensor_types.h
# libtool versiyonlama: current:revision:age
libsensor_la_LDFLAGS = \
-version-info 3:0:1 \
-no-undefined
libsensor_la_CFLAGS = \
-I$(top_srcdir)/include \
$(OPENSSL_CFLAGS)
libsensor_la_LIBADD = \
-lm \
$(OPENSSL_LIBS)
# ── Uygulama binary ──────────────────────────────────────────────
bin_PROGRAMS = sensor-cli
sensor_cli_SOURCES = \
cli/main.c \
cli/options.c \
cli/options.h
sensor_cli_CFLAGS = -I$(top_srcdir)/include
sensor_cli_LDADD = libsensor.la -lm
# ── Yüklenmeyecek yardımcı program ──────────────────────────────
noinst_PROGRAMS = sensor-test-helper
Automake birincil değişkenler
make check sırasında derlenir03 libtool ve shared library
libtool, farklı platformlarda shared ve static library oluşturmayı soyutlar. -version-info parametresiyle kütüphane ABI versiyonlaması yönetilir; bu sayede geriye dönük uyumluluk korunur.
Versiyon bilgisi: current:revision:age
| Parametre | Anlam | Değiştiğinde |
|---|---|---|
current | Arayüz numarası | ABI değiştiğinde artır |
revision | Uygulama değişikliği | Kod değişti ama ABI aynı → artır; ABI değişince 0 yap |
age | Geriye dönük uyumluluk | Ekleme yaptıysan artır; kaldırma/değiştirme yaptıysan 0 yap |
# Örnek: -version-info 3:0:1
# soname: libsensor.so.2 (= current - age = 3 - 1 = 2)
# Dosya: libsensor.so.2.0.1 (= so.<iface>.<rev>.<age>)
# libtool ile derleme
make
ls -la src/.libs/
# libsensor.la — libtool archive
# libsensor.so → libsensor.so.2 (symlink)
# libsensor.so.2 → libsensor.so.2.0.1 (symlink)
# libsensor.so.2.0.1 — gerçek shared library
# libsensor.a — static library
.la dosyası
# .la dosyası libtool metadata'sı
cat src/.libs/libsensor.la
# dlname='libsensor.so.2'
# library_names='libsensor.so.2.0.1 libsensor.so.2 libsensor.so'
# dependency_libs='-lm'
# installed=yes
# shouldnotlink=no
dlopen ile dinamik yükleme
#include <dlfcn.h>
#include <stdio.h>
typedef int (*sensor_read_fn)(int channel, float *value);
int load_sensor_plugin(const char *path)
{
void *handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
if (!handle) {
fprintf(stderr, "dlopen hatası: %s\n", dlerror());
return -1;
}
/* Sembol yükle */
dlerror(); /* hata temizle */
sensor_read_fn fn = (sensor_read_fn)dlsym(handle, "sensor_read");
const char *err = dlerror();
if (err) {
fprintf(stderr, "dlsym hatası: %s\n", err);
dlclose(handle);
return -1;
}
/* Kullan */
float val;
int ret = fn(0, &val);
printf("Sensor değeri: %.2f (ret=%d)\n", val, ret);
dlclose(handle);
return 0;
}
04 Cross-compilation
Autotools'un en güçlü özelliklerinden biri, --host / --build / --target üçlüsüyle cross-compilation desteğidir. Gömülü Linux hedefleri için sysroot ve pkg-config ayarları da yapılmalıdır.
Terminoloji
# ARM64 Linux için cross-compile
./configure \
--host=aarch64-linux-gnu \
--build=x86_64-linux-gnu \
--prefix=/usr \
--with-sysroot=/opt/sysroots/aarch64-linux-gnu
# Ortam değişkenleri ile de ayarlanabilir
export CC=aarch64-linux-gnu-gcc
export AR=aarch64-linux-gnu-ar
export STRIP=aarch64-linux-gnu-strip
./configure --host=aarch64-linux-gnu --prefix=/usr
pkg-config cross ayarları
# Cross-compile için pkg-config sysroot yolu
export PKG_CONFIG_SYSROOT_DIR=/opt/sysroots/aarch64-linux-gnu
export PKG_CONFIG_LIBDIR=$PKG_CONFIG_SYSROOT_DIR/usr/lib/pkgconfig
export PKG_CONFIG_PATH=
# Doğrulama: hedef sistemin kütüphane bilgisi görünmeli
pkg-config --libs glib-2.0
# -L/opt/sysroots/aarch64-linux-gnu/usr/lib -lglib-2.0
# Alternatif: aarch64-linux-gnu-pkg-config wrapper
# Bazı dağıtımlar bunu hazır sağlar
aarch64-linux-gnu-pkg-config --cflags libpng
Yocto SDK ile cross-compile
# Yocto SDK kurulumu
chmod +x poky-glibc-x86_64-core-image-minimal-aarch64-toolchain-4.0.sh
./poky-glibc-x86_64-core-image-minimal-aarch64-toolchain-4.0.sh
# SDK ortamını aktifleştir — tüm değişkenleri otomatik ayarlar
source /opt/poky/4.0/environment-setup-cortexa53-poky-linux
# Şimdi configure normal gibi çalışır
./configure $CONFIGURE_FLAGS
make
make install DESTDIR=/tmp/staging
05 Custom macro
Özel configure kontrolleri yazmak için Autoconf M4 macro sistemi kullanılır. Tekrar kullanılabilir macro'lar m4/ dizinine konur ve autoconf-archive projesi hazır macro'ların zengin bir kaynağıdır.
AC_MSG_CHECKING / AC_MSG_RESULT
dnl AX_CHECK_I2C
dnl Sistemde i2c-dev desteği olup olmadığını kontrol et
dnl Başarı: HAVE_I2C=yes, I2C_CFLAGS ve I2C_LIBS ayarlanır
AC_DEFUN([AX_CHECK_I2C], [
AC_MSG_CHECKING([I2C kernel header için])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
], [
int fd = 0;
ioctl(fd, I2C_SLAVE, 0x48);
])
],
[
AC_MSG_RESULT([evet])
HAVE_I2C=yes
AC_DEFINE([HAVE_I2C], [1], [linux/i2c-dev.h mevcut])
],
[
AC_MSG_RESULT([hayır])
HAVE_I2C=no
AS_IF([test "x$1" = "xrequired"],
[AC_MSG_ERROR([I2C desteği gerekli ancak bulunamadı])])
]
)
AM_CONDITIONAL([HAVE_I2C], [test "x$HAVE_I2C" = "xyes"])
])
configure.ac'de kullanım
dnl m4/ax_check_i2c.m4 yüklenir
AX_CHECK_I2C([required]) dnl required = hata ver, yoksa
dnl veya opsiyonel
AX_CHECK_I2C([optional]) dnl optional = sadece uyar
autoconf-archive'den hazır macro'lar
# Ubuntu/Debian
sudo apt install autoconf-archive
# Projeye kopyala
cp /usr/share/aclocal/ax_pthread.m4 m4/
cp /usr/share/aclocal/ax_cxx_compile_stdcxx.m4 m4/
# configure.ac'de kullanım
AX_PTHREAD # pthread tespiti
AX_CXX_COMPILE_STDCXX([17]) # C++17 gereksinimi
AX_CHECK_COMPILE_FLAG([-march=native], [
CFLAGS="$CFLAGS -march=native"
]) # Derleyici flag desteği
Koşullu derleme — AM_CONDITIONAL
AC_ARG_ENABLE([mqtt],
AS_HELP_STRING([--enable-mqtt], [MQTT yayın desteği (varsayılan: hayır)]),
[enable_mqtt=$enableval], [enable_mqtt=no])
AS_IF([test "x$enable_mqtt" = "xyes"], [
PKG_CHECK_MODULES([MOSQUITTO], [libmosquitto >= 2.0.0],
[AC_DEFINE([ENABLE_MQTT], [1], [MQTT desteği])],
[AC_MSG_ERROR([libmosquitto >= 2.0.0 gerekli])])
])
AM_CONDITIONAL([ENABLE_MQTT], [test "x$enable_mqtt" = "xyes"])
if ENABLE_MQTT
libsensor_la_SOURCES += mqtt_publisher.c
libsensor_la_CFLAGS += $(MOSQUITTO_CFLAGS)
libsensor_la_LIBADD += $(MOSQUITTO_LIBS)
endif
06 Out-of-tree build
Out-of-tree (VPATH) build, kaynak dizinini temiz tutar ve farklı konfigürasyonları (native, cross, debug, release) aynı anda paralel olarak oluşturmaya olanak tanır.
Out-of-tree build adımları
# Kaynak kodu /src/libsensor'da
ls /src/libsensor/
# configure.ac Makefile.am src/ tests/ include/
# Önce configure script'i üret (kaynak dizinde bir kez)
cd /src/libsensor
autoreconf -fvi
# Çıktı: configure, Makefile.in, config.h.in, ...
# Native build için ayrı dizin
mkdir -p /build/libsensor-native
cd /build/libsensor-native
/src/libsensor/configure --prefix=/usr/local
make -j$(nproc)
make install
# Cross build için ayrı dizin (aynı anda)
mkdir -p /build/libsensor-aarch64
cd /build/libsensor-aarch64
/src/libsensor/configure \
--host=aarch64-linux-gnu \
--prefix=/usr
make -j$(nproc)
make install DESTDIR=/tmp/rootfs
make distcheck
# Dağıtım tarball'ını test et
# Bu komut:
# 1. make dist ile tarball oluşturur
# 2. Tarball'ı açar
# 3. Out-of-tree build yapar
# 4. make check çalıştırır
# 5. make distclean çalıştırır
# 6. make install DESTDIR=/tmp test eder
make distcheck
# Başarılı olursa:
# libsensor-1.2.0.tar.gz
# ==========================================
# libsensor-1.2.0 archives ready for distribution:
# libsensor-1.2.0.tar.gz
# Başarısız olursa kaynak dağıtım kötü anlaşılmıştır:
# EXTRA_DIST veya eksik dosyaları gözden geçirin
make dist ve tarball içeriği
# Tarball oluştur
make dist
# İçeriği kontrol et
tar tzf libsensor-1.2.0.tar.gz | head -30
# libsensor-1.2.0/configure
# libsensor-1.2.0/Makefile.in
# libsensor-1.2.0/config.h.in
# libsensor-1.2.0/src/sensor.c
# ...
# Önemli: configure script tarball'a dahildir
# Kullanıcı autotools kurmak zorunda değil!
07 pkg-config entegrasyonu
pkg-config, kütüphanenin compile ve link bayraklarını standart bir arabirim üzerinden açıklar. Autotools projesi .pc dosyasını otomatik olarak üretip kurabilir.
.pc şablon dosyası
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libsensor
Description: Gömülü sensör okuma kütüphanesi
Version: @PACKAGE_VERSION@
URL: https://github.com/example/libsensor
# Bağımlılıklar (diğer pkg-config paketleri)
Requires:
Requires.private: libm
# Compile bayrakları
Cflags: -I${includedir}/sensor
# Link bayrakları
Libs: -L${libdir} -lsensor
Libs.private: -lm
configure.ac'de .pc dosyası üretimi
dnl configure.ac'de AC_CONFIG_FILES listesine ekle
AC_CONFIG_FILES([
Makefile
src/Makefile
libsensor.pc dnl ← .pc dosyası
])
dnl prefix bilgisini aktar (pkgconfig için)
AC_SUBST([PACKAGE_VERSION])
AC_SUBST([prefix])
AC_SUBST([libdir])
AC_SUBST([includedir])
Kök Makefile.am'de kurulum
# pkg-config dizinine kur
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libsensor.pc
# Şablon dosyasını dağıtıma dahil et
EXTRA_DIST = libsensor.pc.in
PKG_CHECK_MODULES kullanımı
dnl libsensor'u kullanan başka bir proje
PKG_CHECK_MODULES([SENSOR], [libsensor >= 1.2.0],
[AC_DEFINE([HAVE_LIBSENSOR], [1], [libsensor mevcut])],
[AC_MSG_ERROR([libsensor >= 1.2.0 gerekli])])
dnl Makefile'da kullanım:
dnl $(SENSOR_CFLAGS) ve $(SENSOR_LIBS) otomatik tanımlanır
# Kurulduktan sonra test et
pkg-config --cflags libsensor
# -I/usr/include/sensor
pkg-config --libs libsensor
# -L/usr/lib -lsensor
pkg-config --modversion libsensor
# 1.2.0
# Cross-compile pkg-config sorgusu
PKG_CONFIG_LIBDIR=/opt/sysroot/usr/lib/pkgconfig \
pkg-config --libs libsensor
08 Pratik: Kütüphane paketi ve ARM cross-compile
Sıfırdan bir Autotools kütüphane projesi kuracağız: configure.ac, Makefile.am, libtool versiyonlama, pkg-config ve ARM cross-compile akışı.
Proje başlatma
# Dizin yapısı
mkdir -p libsensor/{src,include,m4,tests,build-aux}
cd libsensor
# Gerekli dosyalar oluşturulsun
touch NEWS README AUTHORS ChangeLog
# autoconf-archive macro'larını kopyala
cp /usr/share/aclocal/ax_pthread.m4 m4/
Tüm dosyaları oluşturma
# 1. autoreconf ile configure üret
autoreconf --force --verbose --install
# Şunları oluşturur:
# configure
# Makefile.in (her Makefile.am için)
# config.h.in
# build-aux/install-sh
# build-aux/missing
# build-aux/ltmain.sh
# 2. Native build
mkdir build-native && cd build-native
../configure --prefix=/usr/local --enable-shared --disable-static
make -j$(nproc) V=1
# 3. Test çalıştır
make check
# PASS: tests/test_sensor
# PASS: tests/test_i2c
# 4. ARM64 cross-compile
cd ..
mkdir build-arm64 && cd build-arm64
../configure \
--host=aarch64-linux-gnu \
--build=x86_64-linux-gnu \
--prefix=/usr \
--with-sysroot=/opt/sysroots/aarch64-linux-gnu \
PKG_CONFIG_SYSROOT_DIR=/opt/sysroots/aarch64-linux-gnu \
PKG_CONFIG_LIBDIR=/opt/sysroots/aarch64-linux-gnu/usr/lib/pkgconfig
make -j$(nproc)
# 5. Staging dizinine kur
make install DESTDIR=/tmp/arm-staging
ls /tmp/arm-staging/usr/lib/
# libsensor.so.2.0.1
# libsensor.so.2 -> libsensor.so.2.0.1
# pkgconfig/libsensor.pc
Tarball ve dağıtım
# Temiz tarball oluştur ve doğrula
cd ../build-native
make distcheck
# Başarılı çıktı:
# =============================================
# libsensor-1.2.0 archives ready for distribution:
# libsensor-1.2.0.tar.gz
# Tarball boyutu ve içeriği
ls -lh libsensor-1.2.0.tar.gz
tar tzf libsensor-1.2.0.tar.gz | wc -l
# check_PROGRAMS: sadece 'make check' ile derlenir
check_PROGRAMS = test_sensor test_i2c
test_sensor_SOURCES = test_sensor.c
test_sensor_CFLAGS = -I$(top_srcdir)/include
test_sensor_LDADD = $(top_builddir)/src/libsensor.la
test_i2c_SOURCES = test_i2c.c
test_i2c_CFLAGS = -I$(top_srcdir)/include
test_i2c_LDADD = $(top_builddir)/src/libsensor.la
# Test listesi (make check ile çalışır)
TESTS = test_sensor test_i2c
Autotools ile hazırlanan bu kütüphane projesi, autoreconf -fvi && ./configure && make && make install akışıyla hem native hem de cross-compile ortamında derlenebilir. make distcheck her değişiklikten sonra dağıtım bütünlüğünü doğrular. libsensor.pc ile diğer projeler kütüphaneyi PKG_CHECK_MODULES ile kolayca bulabilir.