Automake + 条件コンパイル

条件コンパイルを試したメモ。
ある条件のときに、特定のソースコードをコンパイルから除外 or 包含する。
libevent の configure を参考にしました。
通信システム(select, poll, epoll, …etc)の有無をチェックしてコンパイル対象を選択するとこが今回の目的にピッタリ。

書いたコード一覧

hello.c

#include <stdio.h>  
#include <hello.h>  
#include "config.h"  
  
#ifdef HAVE_DOG  
extern const struct helloop dogop;  
#endif  
#ifdef HAVE_CAT  
extern const struct helloop catop;  
#endif  
  
const struct helloop *ops[] = {   
#ifdef HAVE_DOG  
    &dogop,  
#endif  
#ifdef HAVE_CAT  
    &catop,  
#endif  
    NULL  
};  
  
int main()  
{  
    int i;  
    for( i = 0; ops[i] != NULL; ++i ){  
        ops[i]->func( i );  
    }     
    return 0;  
}  

hello.h

#ifndef HELLO_H_  
#define HELLO_H_  
   
struct helloop  
{  
    void (*func)(int);  
};  
   
#endif  

dog.c

#include <stdio.h>  
#include "hello.h"  
  
static void func_dog( int num );  
  
const struct helloop dogop = {   
    func_dog  
};  
  
static void func_dog( int num )  
{  
    printf( "Hello dog. num:%d\n", num );  
}  

cat.c

#include <stdio.h>  
#include "hello.h"  
  
void func_cat( int num );  
  
const struct helloop catop = {   
    func_cat  
};  
  
void func_cat( int num )  
{  
    printf( "Hello cat. num:%d\n", num );  
}  

configure.ac

AC_PREREQ(2.59)  
AC_INIT(automake-cond, 0.1, none)  
AC_CONFIG_SRCDIR([hello.h])  
AC_CONFIG_HEADER([config.h])  
AM_INIT_AUTOMAKE  
AC_PROG_CC  
  
# テストコード。  
# yes なら dog.c をコンパイル対象に。  
have_dog="yes"  
if test "$have_dog" = "yes"  
then  
    AC_SUBST([COMPILE_OBJS], 'dog.$(OBJEXT)')  
    AC_DEFINE(HAVE_DOG, 1, [Define dog.])  
fi  
  
# yes なら cat.c をコンパイル対象に。  
have_cat="no"  
if test "$have_cat" = "yes"  
then  
    AC_SUBST([COMPILE_OBJS], 'cat.$(OBJEXT)')  
    AC_DEFINE(HAVE_CAT, 1, [Define cat.])  
fi  
  
AC_C_CONST  
AC_CONFIG_FILES([Makefile])  
AC_OUTPUT  

Makefile.am

bin_PROGRAMS = hello  
hello_SOURCES = hello.c hello.h  
EXTRA_hello_SOURCES = dog.c cat.c  
hello_LDADD = @COMPILE_OBJS@  
hello_DEPENDENCIES = @COMPILE_OBJS@  

実行

configure.ac の中で have_dog=yes, have_cat=no と設定しているから最終的に dog.c がコンパイル&リンクされ func_dog() が呼ばれる。

$ ./configure  
$ make  
$ ./hello  
Hello dog. num:0  

参考

autotools + 使い方
ソースの条件コンパイル