GNU AutoTools Başlangıç Kitabı

Özkan KIRIK

EnderUNIX Yazılım Geliştrime Takımı 
Yazılım Geliştiricisi


İçindekiler
1. Giriş
2. İşlem Sırası
3. Araçlar
4. Autoconf
4.1. Autoconf'a Giriş
4.2. autoconf Makroları
5. Autoheader
6. Automake
6.1. Automake'e Giriş
6.2. Makefile.am Örneği
6.3. Makefile.am
7. Kapsamlı bir AutoTools Projesi

Bölüm 1. Giriş

Bu dokümanda GNU AutoTools (autoheader, autoconf, automake) araçlarının ne olduğu, nerelerde ve nasıl kullanıldığı anlatılacaktır. Yazar, sisteminize gelebilecek hiçbir zararın sorumluluğunu kabul etmemektedir.


Bölüm 2. İşlem Sırası

Günümüzde bir çok yazılım paketi doğrudan autoconf, automake ve autoheader ile çalışmaktadır. Dolaylı olarak da m4 macro işlemcisi, make (GNU veya BSD make) ve aclocal yazılımlarını kullanır.

Yukarıdaki şekilde hangi yazılımın hangi dosyaları giriş olarak kullandığı ve hangi dosyaları yarattığı anlatılmıştır.

Öncelikle automake, Makefile.am dosyasını inceler ve buna uygun olarak Makefile.in dosyasını yaratır.

Ardından autoheader, configure.in dosyasını inceleyerek burada tanımlanan ve config.h dosyasında olması gereken ifadeleri toplayıp config.h.in dosyasını oluşturur.

autoheader'dan sonra autoconf, yine configure.in dosyasını inceler ve configure scriptini yaratır.

Son olarak configure çalıştırılır. Uzantısı .in olan dosyalar genellikle configure tarafından girişi dosyası olarak kullanılır. configure bu dosyalar üzerinde gereken işlemleri yaptıktan sonra .in uzantısını kaldırıp yeni bir dosya olarak kaydeder. Bu sayede Makefile.in dosyasından Makefile oluşur. config.h.in dosyasından config.h oluşur.

configure işleminden sonra Makefile oluşur ve make komutu çalıştırılarak program derlenir.

Kısacası bütün dosyalarınızı hazırladıktan sonra paketinizi aşağıdaki şekilde hazır hale getirebilirsiniz:

      # aclocal && autoheader 
      # automake --add-missing 
      # autoconf 
Yukarıdaki işlemlerle Makefile dosyası ve config.h dosyası hazır hale geliyor.


Bölüm 3. Araçlar

Sisteminizde kurulu olması gereken yazılımlar:

FreeBSD'de bu yazılımları kurmak için Port Kolleksiyonu'na başvuruyoruz.

    # cd /usr/ports/devel/automake19
    # make install clean
    ...
    ...
    #

Port Kolleksiyonu, automake ile birlikte autoconf ve autoheader'i da kuracaktir.

Birçok Linux dağıtımında GNU autotools standart olarak gelmektedir.


Bölüm 4. Autoconf

4.1. Autoconf'a Giriş

autoconf'u daha iyi anlayabilmek için automake aşamasını atlayacağız.

autoconf, configure.in dosyası inceleyerek, orada tanımlanan işleri yapabilecek configure scriptini yaratır. configure scripti ise configure.inde belirlediğiniz, uzantısı .in olan giriş dosyalarını inceleyerek @degisken@ biçimde olan ifadeleri eğer tanımlanmışsa değerleri ile değiştirir. Çıkış dosyasından .in uzantısı kaldırılır.

      -- configure.in --
      ...
      ...
      program_klasoru="/usr/local/deneme"
      AC_SUBST(program_klasoru)
      AC_OUTPUT[deneme.h]
      ------------------
      -- deneme.h.in --
      #define KLASOR @program_klasoru@
      -----------------
      # autoconf 
      # ./configure
      ...
      ...
      ...
      --- deneme.h ---
      #define KLASOR "/usr/local/deneme"
      ----------------

Yukarıda autoconf ve configure'ün çalışma prensibine basit bir örneğe yer verdik. Burada AC_ ile başlayan makrolardan Kısım 4.2 de bahsedilecektir.

Daha geniş kapsamlı bir örnek;

      --- deneme.c ---
      #include <stdio.h>
      #include "config.h"
      int main(int argc, char **argv) {
        printf("Bu programin sürümü %s\n", SURUM);
        return 0;
      }
      ----------------
      --- config.h.in ---
      #define SURUM @surum@
      -------------------
      --- configure.in ---
      AC_INIT(deneme.c)
      dnl C derleyicisini bul ve test et
      AC_PROG_CC
      AC_LANG_C
      dnl surum degiskenini tanimla ve giris dosyalarinda incelenmek uzere gerekenleri yap
      surum="0.1"
      AC_SUBST(surum)
      dnl Makefile.in dosyasını oku ve Makefile'i yarat
      dnl config.h.in dosyasını oku ve config.h'i yarat
      AC_OUTPUT([
      Makefile
      config.h
      ])
      --------------------
      --- Makefile.in ---
      CC = @CC@
      CFLAGS = @CFLAGS@
      all: deneme-bin
      deneme-bin: deneme.c
        $(CC) $(CFLAGS) deneme.c -o deneme
      clean:
        rm -f deneme
      distclean:
        rm -f config.h Makefile
      -------------------

Yukarıdaki mini projeyi aşama aşama uygulayalım:

      # ls
      Makefile.in config.h.in configure.in deneme.c
      # autoconf
      # ./configure
      ...
      ...
      # ls
      Makefile Makefile.in config.h config.h.in configure.in deneme.c
      # make
      ...
      ...
      # ls
      Makefile Makefile.in config.h config.h.in configure.in deneme deneme.c

İlk başlangıçta autoconf çalıştırılarak, configure.in dosyasından configure scripti oluşturuluyor. configure scripti ile Makefile.in ve config.h.in dosyalarının içerisinde @...@ biçiminde yeralan ifadelerin değerleri yerine konuluyor ve Makefile ve config.h oluşturuluyor. make komutu ile derleme işlemi gerçekleştiriliyor.


4.2. autoconf Makroları

Bu bölümde autoconf ta kullanabileceğiniz öntanımlı makrolara yer vereceğiz

  • AC_INIT(sourcefile)

    autoconf'u hazırlar, configure.in dosyasında çağrılan ilk makro olmalıdır. sourcefile ifadesi yerine main fonksiyonunu içeren kaynak kod dosyasının adını yazın.

           Örnek:
            AC_INIT(deneme.c)
    


  • AC_PROG_CC

    Kullanılacak olan C derleyicisini bulur ve CC değişkenine atar. Eğer CFLAGS değişkeni daha önceden tanımlanmamışsa bu değişkeni de tanımlar.

  • AC_PROG_CXX

    Kullanılacak olan C++ derleyicisini bulur ve CXX değişkenine atar. Eğer CXXFLAGS değişkeni daha önceden tanımlanmamışsa bu değişkeni de tanımlar.

  • AC_LANG_C

    C derleyicisini test eder.

  • AC_LANG_CPLUSPLUS

    C++ derleyicisini test eder.

  • AC_PROG_INSTALL

    INSTALL değişkenine BSD uyumlu install yazılımının tam yolunu atar.

  • AC_PATH_X

    X Window sisteminin başlık dosyalarını ve kütüphanelerini bulmaya çalışır. x_includes ve x_libraries değişkenlerine ilgili klasörleri atar.

  • AC_PATH_PROG(a, b [,c [,d]])

    • a=değişken adı

    • b=aranılan program adı

    • c=program bulunamazsa değişkenin alacağı değer

    • d=programı aramak istediğiniz klasor

    PATH çevre değişkeninde tanımlı olan klasörlerde ismini belirttiğiniz programı arar. Eğer program bulunursa belirtilen değişkene tam yolunu atar. Bulunamazsa c parametresi ile belirtilen değer atanır.
           Örnek:
            AC_PATH_PROG(ifconfig_path, ifconfig, FALSE, $PATH:/usr/obj)
    


  • AC_OUTPUT(dosyalar)

    Hangi dosyaların giriş olacağı burada belirlenir. Giriş dosyaları buraya yazılan dosya isimlerinin sonuna .in uzantısı getirilerek belirlenir. Dosyalar üzerinde gerekli değiştirme işlemleri uygulandıktan sonra çıkış dosyaları yaratılır.

           Örnek:
            AC_OUTPUT(Makefile spec)
    
    Yukarıdaki kullanımda Makefile.in dosyası incelenir ve Makefile yaratılır. Aynı şekilde spec.in dosyası incelenip, spec dosyası yaratılır.

  • AC_CONFIG_HEADER(header_dosyalari)

    Burada belirlenen header dosyaları AC_OUTPUT tarafından otomatik olarak işleme alınır. Genellikle dosya adı config.h olarak seçilir. Burada belirlenen dosya AC_OUTPUT tarafından işlem göreceği için config.h.in dosyasına ihtiyaç vardır. Bu dosyayı Bölüm 5 de anlatılan autoheader sizin için otomatik olarak oluşturur.

  • AC_CHECK_FUNCS(a, [,b [,c]])

    • a=Aradığınız fonksiyonların listesi (boşluklarla ayırın)

    • b=Fonksiyon bulunduğu zaman yapılacak işlem

    • c=Fonksiyon bulunamadığı zaman yapılacak işlem

    Belirlenen fonksiyonların standart C kütüphanesinde olup olmadığını kontrol eder.
           Örnek:
            AC_CHECK_FUNCS(dup2 inet_ntoa memset realpath strchr, [], \
                  [AC_MSG_ERROR(temel fonksiyonlar bulunamadi)])
    


  • AC_CHECK_LIB(a, b, [,c [,d]])

    • a=Fonksiyonun aranacağı kütüphane adı

    • b=Aranan fonksiyon adı

    • c=Fonksiyon bulunursa yapılacak işlem

    • d=Fonksiyon bulunamazsa yapılacak işlem

    Aranan fonksiyonun, belirlenen kütüphanede yer alıp almadığını kontrol eder.
           Örnek:
            AC_CHECK_LIB(crypt,crypt, [], \
                         [AC_MSG_ERROR(crypt kütüphanesi bulunamadı)])
    


  • AC_CHECK_HEADERS(a, [,b [,c]])

    • a=Aranılan başlık(header) dosyaları (boşlukla ayrılmış)

    • b=Başlık dosyası bulunduğu zaman yapılacak işlem

    • c=Başlık dosyası bulunamadığı zaman yapılacak işlem

    Aranılan başlık (header) dosyalarının olup olmadığını kontrol eder.
           Örnek:
            AC_CHECK_HEADERS(arpa/inet.h sys/socket.h sys/time.h, [], \
                      [AC_MSG_ERROR(Başlık dosyaları bulunamadı)])
    


  • AC_HEADER_STDC

    stdlib.h, stdarg.h, string.h ve float.h başlıklarının olup olmadığını kontrol eder. Eğer bulabilirse STDC_HEADERS değişkenini tanımlar.

  • AC_DEFINE(a, b, [,c])

    • a=Tanımlanacak sabit'in adı

    • b=Sabit'in alacağı değer. (değişken kullanmayın çünkü bu makro Full Quoted'dir. Sabit'e değişken bir değer atayacaksanız AC_DEFINE_UNQUOTED makrona bakınız.)

    • c=Bu parametre, başlık dosyanızda bu sabit'in açıklaması olarak kullanılacaktır.

    AC_CONFIG_HEADER makrosu ile belirtilen başlık (header) dosyalarında #define ile başlayan ifadeleri yaratmak için kullanılır. Bu sayede programınızda configure ile topladığınız verileri kullanabilirsiniz.
           Örnek:
            AC_CONFIG_HEADER(config.h)
            AC_CHECK_LIB(crypt, crypt, AC_DEFINE(CRYPT_VARMI, 1, [Crypt fonkiyonu varmi]), \
                AC_DEFINE(CRYPT_VARMI, 0, [Crypt fonksiyonu varmi]))
            --- config.h.in ---
            /*Crypt fonksiyonu var mi*/
            #undef CRYPT_VARMI
            ----------------
    
           # ./configure
            ...
            ...
    
           --- config.h ---
            /*Crypt fonksiyonu var mi*/
            #define CRYPT_VARMI 1  
            ----------------
    
    Yukarıdaki örnekte crypt fonksiyonunun bulunduğu kabul ettik.

  • AC_DEFINE_UNQUOTED(a, b, [,c])

    • a=Tanımlanacak sabit'in adı

    • b=Sabit'in alacağı değer. (Değişken kullanabilirsiniz. Bu makro unquoted'dir.

    • c=Bu parametre, başlık dosyanızda bu sabit'in açıklaması olarak kullanılacaktır.

    AC_CONFIG_HEADER makrosu ile belirtilen başlık (header) dosyalarında #define ile başlayan ifadeleri yaratmak için kullanılır. Bu sayede programınızda configure ile topladığınız verileri kullanabilirsiniz. Aşağıda AC_DEFINE ile AC_DEFINE_UNQUOTED arasındaki fark örneklenmiştir.
           Örnek:
            AC_CHECK_HEADER(config.h)
            organizasyon="EnderUNIX"
            AC_DEFINE(ORGANIZATION, "$organizasyon", [Organizasyon Adi])
    
           # ./configure
            ...
            ...
    
           --- config.h ---
            /*Organizasyon Adi*/
            #define ORGANIZASYON "$organizasyon"
            ----------------
    
    Yukarıdaki örnekte görüdüğü gibi ifade olduğu gibi alınmıştır (Full Quoted). Şimdi de AC_DEFINE_UNQUOTED örneğini inceleyelim.
           Örnek:
            AC_CHECK_HEADER(config.h)
            organizasyon="EnderUNIX"
            AC_DEFINE_UNQUOTED(ORGANIZATION, "$organizasyon", [Organizasyon Adi])
    
           # ./configure
            ...
            ...
    
           --- config.h ---
            /*Organizasyon Adi*/
            #define ORGANIZASYON "EnderUNIX"
            ----------------
    
    Son örnekte ise alıntı yapılmamış (unQoted) değişkenin değeri yerine konulmuştur.

  • AC_SUBST(degisken_adi)

    Önceden tanımlanmış olan degisken_adi isimli degiskeni AC_OUTPUT ta tanımlanan dosyaların içerisinde arar. Orada tanimlanan dosyalarda @degisken_adi@ seklinde gecen ifadelerin yerine değerlerini yazar.

           surum="0.1"
            AC_SUBST(surum)
            AC_OUTPUT(Makefile)
            --- Makefile.in ---
            VERSION=@surum@
            ...
            ...
            -------------------
    
           # ./configure
            ...
            ...
    
           --- Makefile ---
            VERSION=0.1
            ...
            ...
            ----------------
    


  • AC_MSG_ERROR(mesaj)

    Kullanıyıcıyı tanımladığınız mesaj ile uyarır ve configure scriptinden çıkış değeri (exit code) 0(sıfır) olmayan bir şekilde çıkar. Genelde bir kütüphane veya başlık dosyasını bulamadığınızda bu fonksiyona ihtiyaç duyulur.

           AC_CHECK_HEADERS(stdio.h sys/socket.h, [], \
                      AC_MSG_ERROR(Basliklar bulunamadi))
    


  • AC_MSG_WARNING(mesaj)

    Kullanıcıyı tanımladığınız mesaj ile uyarır, ancak configure'den çıkmaz. Genelde opsiyonel bir kütüphane bulunamadığında kullanıcıyı bilgilendirmek için kullanılır.

  • AC_ARG_ENABLE(a, b, [,c [,d]])

    • a=Opsiyon adı (--enable-opsiyon)

    • b=./configure --help çalıştırıldığına bu opsiyon için gösterilecek açıklama

    • c=Bu opsiyon varsa yapılacak işlem

    • d=Bu opsiyon yoksa yapılacak işlem

    Bu makro, configure ile birlikte --enable-opsiyon parametresinin verilip verilmediğini kontrol eder.
           Örnek:
            AC_ARG_ENABLE(ssl, [SSL'i destekle], SSL_KULLAN="EVET", SSL_KULLAN="HAYIR")
    


  • AC_CANICAL_HOST

    İşletim sistemini tespit eder ve bu değeri host_os değişkenine atar.

           Örnek:
            AC_CANONICAL_HOST
            case "$host_os" in
            linux*)
              AC_DEFINE(LINUX, 1, [Linux kullaniliyor])
              ;;
            freebsd*)
              AC_DEFINE(FREEBSD, 1, [FreeBSD Kullaniliyor])
              ;;
            *)
              AC_MSG_ERROR([Desteklenmeyen işletim sistemi: $host_os.])
              ;;
            esac
    



Bölüm 5. Autoheader

autoheader, configure.in de yazılı olan AC_CONFIG_HEADER makrosu ile belirlenmiş olan dosya için include dosyasını yaratır.

      Örnek:
      AC_CONFIG_HEADER(config.h)
      # autoheader
Bu işlemden sonra config.h.in dosyası yaratılır. config.h.in içeriğinde ise AC_DEFINE ve AC_DEFINE_UNQUOTED ile belirlediğiniz tanımlamaların #undef olarak yer aldığını görebilirsiniz.

configure, yukarıdaki örneğimize göre config.h.in dosyasını prototip olarak alacak ve topladığı verilere göre config.h'ı yaratacaktır.

    --- configure.in ---
    AC_INIT(deneme.c)
    AC_CONFIG_HEADER(config.h)
    AC_PROG_CC
    AC_LANG_C
    AC_HEADER_STDC
    AC_CHECK_FUNCS(atol)
    AC_DEFINE(DENEME, 1, [Ornek define])
    AC_OUTPUT(Makefile)
    --------------------
    # autoheader
    --- config.h.in ---
    /* config.h.in   Generated automatically from configure.in by autoheader */
    /* Define if you have the ANSI C header files */
    #undef STDC_HEADERS
    /* Define if you have the atol function */
    #undef HAVE_ATOL
    /* Ornek define */
    #undef DENEME
    -------------------
    # ./configure
    ...
    ...
    --- config.h ---
    /* config.h      Generated automatically by configure */
    /* config.h.in   Generated automatically from configure.in by autoheader */
    /* Define if you have the ANSI C header files */
    #define STDC_HEADERS 1
    /* Define if you have the atol function */
    #define HAVE_ATOL 1
    /* Ornek define */
    #define DENEME 1
    ----------------

Programınızda bu tanımlamaları kullanabilmek için #include "config.h" işlemini yapmayı unutmayın.


Bölüm 6. Automake

6.1. Automake'e Giriş

Autoconf bölümünde (Bkz. Bölüm 4) verdiğimiz Makefile.in dosyasında "install","uninstall" hedefleri yoktu. Tarball'un içinde olması gereken README, INSTALL ve Lisans dosyaları gibi dosyalar yok.

Bütün bunların bir araya getirilmesini sağlayan yazılım automaketir. automake, Makefile.am dosyasını inceleyerek gerekli hedefleri (install, uninstall, dist, clean gibi) yazılımınıza göre hazırlar ve bunun sonucunda Makefile.in dosyasını üretir. Üretilen bu dosyayı configure kullanacağı için, automake'in configure'den önce çalıştırılması gerekmektedir.

Automake kullanırken, configure.in dosyasındaki bazı autoconf makrolarını (AC_*), automake makrolarıyla (AM_*) değiştirmek gerekiyor.

AC_INIT makrosundan hemen sonra AM_INIT_AUTOMAKE(package,version) makrosu çağrılmalıdır. AC_CONFIG_HEADER yerine de AM_CONFIG_HEADER makrosu kullanılmalı.

      -- configure.in --
      AC_INIT(deneme.c)
      AM_INIT_AUTOMAKE(deneme,0.1)
      AM_CONFIG_HEADER(config.h)
      ...
      ...
      ...
      ------------------

6.2. Makefile.am Örneği

Örnek olarak aşağıdaki Makefile.am dosyasını inceleyelim

   -- Makefile.am -- 
    bin_PROGRAMS = deneme
    deneme_SOURCES = deneme.c
    noinst_HEADERS = deneme.h config.h
    man_MANS = deneme.8
    EXTRA_DIST = deneme.jpg
    ---------------------------

  • bin_PROGRAMS

    Derlenip, yüklenecek olan programları, bu alana boşluklarla ayırarak yazıyoruz. Bu bölümde ismi geçen programlar @prefix@/bin klasörüne install edilir.

  • deneme_SOURCES

    _SOURCES takısından önce belirlenen progarm için gerekli kaynak kod dosyalarının listesidir. bin_PROGRAMS bölümündeki her program için ayrı bir _SOURCES bölümü olmalıdır.

  • noinst_HEADERS

    Tarball'da olması gereken, ancak @prefix@/include klasörüne yüklenmesi gerekmeyen başlık (header) dosyalarının listesi.

  • man_MANS

    Yüklenecek man sayfalarının listesi

  • EXTRA_DIST

    Tarball'da olması gereken diğer dosyaların listesi. Örneğin scriptler, resim dosyaları, data dosyaları vb.




6.3. Makefile.am

Bu bölümde Makefile.am dosyasında yer alabilecek başlıca ifadelere değineceğim.

  • SUBDIRS

    Proje dosyalarınızı klasörlere ayırmışsanız, bu değişken ile belirlediğiniz klasörlerin içindeki Makefile.am dosyasının da işleme tabii tutulmasını sağlıyoruz.

         SUBDIRS = src images doc
    

    Her alt klasör kendi Makefile.am dosyasını içermelidir.

  • bin_PROGRAMS

    Derlenip, yüklenecek olan programları, bu alana boşluklarla ayırarak yazıyoruz. Bu bölümde ismi geçen programlar @prefix@/bin klasörüne install edilir.

  • sbin_PROGRAMS

    Derlenip, yüklenecek olan programları, bu alana boşluklarla ayırarak yazıyoruz. Bu bölümde ismi geçen programlar @prefix@/sbin klasörüne install edilir.

  • *_SOURCES

    _SOURCES takısından önce belirlenen progarm için gerekli kaynak kod dosyalarının listesidir. *_PROGRAMS bölümündeki her program için ayrı bir _SOURCES bölümü olmalıdır.

  • include_HEADERS

    Hem Tarball'a dahil edilecek hem de install işlemi esnasında @prefix@/include klasörüne yüklenecek olan başlık (header) dosyalarının listesi

  • noinst_HEADERS

    Tarball'da olması gereken, ancak @prefix@/include klasörüne yüklenmesi gerekmeyen başlık (header) dosyalarının listesi.

  • bin_SCRIPTS

    Derlenmeden, rwx r-x r-x haklarıyla @prefix@/bin klasörüne yüklenecek scriptlerin listesi

  • sbin_SCRIPTS

    Derlenmeden, rwx r-x r-x haklarıyla @prefix@/sbin klasörüne yüklenecek scriptlerin listesi

  • pkgdata_DATA

    @prefix@/share/program klasörüne r-x r-x r-x haklarıyla yüklenecek olan dosyaların listesi

  • man_MANS

    Yüklenecek man sayfalarının listesi

  • EXTRA_DIST

    Tarball'da olması gereken diğer dosyaların listesi. Örneğin scriptler, resim dosyaları, data dosyaları vb.


Bölüm 7. Kapsamlı bir AutoTools Projesi

Makefile.am

SUBDIRS = src data
pkgdata_DATA = \
  README\
  COPYING\
  AUTHORS\
  ChangeLog\
  NEWS\
  TODO
EXTRA_DIST = $(pkgdata_DATA)


configure.in

AC_INIT(src/testdaemon.c)
AM_INIT_AUTOMAKE(testdaemon, 0.1)
AM_CONFIG_HEADER(src/config.h)
if test "x${prefix}" = "xNONE"; then
  prefix=${ac_default_prefix}
fi
AC_CANONICAL_HOST
AC_MSG_CHECKING([for supported operating system])
case "$host_os" in
linux*)
  AC_DEFINE([LINUX], 1, [Define for the Linux operating system.])
  ;;
freebsd*)
  AC_DEFINE([FREEBSD], 1, [Define for the freebsd operating system.])
  ;;
*)
  AC_MSG_ERROR([Non supprted operating system: $host_os. exiting.])
  ;;
esac
AC_MSG_RESULT($host_os)
AC_DEFINE_UNQUOTED(OS, "$host_os", [Operating System])
AC_PROG_INSTALL
AC_LANC_C
AC_PROG_CC
AC_HEADER_STDC
AC_CHECK_HEADERS(ctype.h sys/time.h unistd.h,,AC_MSG_ERROR([Gerekli Header Dosyalari bulunamadı]))
AC_OUTPUT([
Makefile 
src/Makefile 
data/Makefile
])


src/Makefile.am

sbin_programs = testdaemon
bin_programs = testpasswd
testdaemon_SOURCES = testdaemon.c
testctl_SOURCES = testpasswd.c
noinst_HEADERS = testdaemon.h testpasswd.h


data/Makefile.am

sbin_SCRIPTS = testctl
man_MANS = testdaemon.8
EXTRA_DIST = $(sbin_SCRIPTS) $(man_MANS)