autoconfig实现条件编译

版权声明:本文为博主原创文章,未经允许,不得转载。 https://blog.csdn.net/weixin_41944449/article/details/82467903

  在使用开源框架的时候,可以发现大部分的源码都是使用自动生成Makefile工具生成Makefile,而这一过程大多数的又是通过configure.ac配置生成Makefile。在这里,我们不讨论它是如何进行该操作的,而是想记录一下,当我们需要给源码打patch的时候,如何实现与外部一些库的链接以及源码的宏定义区分。
  相信很多人在Makefile以及源码中做过以下的操作:

#include <stdio.h>

#ifdef THREAD_TEST
#include <pthread.h>
void *threadTest(void)
{
    printf("thread:hello, world\n");
    return NULL;
}
#endif

int main(void)
{
#ifdef THREAD_TEST
    pthread_t thread_id;

    pthread_create(&thread_id, NULL, threadTest, NULL);
    pthread_join(thread_id, NULL);
#endif
    printf("hello, world\n");

    return 0;
}

  在源文件中通过宏定义来选择编译不同的代码,而这个宏定义,为了灵活,将会在Makefile中通过-DTHREAD_TEST这样的一个形式传进来,同时还需要通过-lpthread链接线程库。接下来,我们将要进入主题,在configure.ac中,我们又是怎样实现类似这样的操作呢,在源码中通过宏定义实现编译不同的源码,以及在Makefile.am中,根据不同的参数实现链接不同的库。
  首先的,我们可能需要在Makefile实现类似以下的功能:

ifeq ($(USE_THREAD),y)
    LIBS += -lpthread
endif

  然后在上层Makefile编译的时候,该Makefile将会根据是否定义了USE_THREAD这个宏而链接pthread库,但是,在Makefile.am中修改,添加上类似的操作,却是发现没有生效的,为什么呢?
  在configure.ac和Makefile.am结合,通过configure配置再生成编译使用的Makefile,这样单纯的修改Makefile.am并不会生效的,需要通过修改configure.ac,在配置的时候,该文件传参数到Makefile.am,而后再相应的生成Makefile,这样才可以在生成的Makefile生成类似的操作,下面我们将简单介绍一下如何配置configure.ac以达到这样的功能。
  了解configure.ac的小伙伴应该知道,使用AC_ARG_ENABLE宏可以为configure增加–enable-feature 或者 –disable-feature这样的选项。

AC_ARG_ENABLE (feature, help-string, [action-if-given], [action-if-not-given]) 
#如果configure中加了给定的选项,就执行action-if-given,否则执行action-if-not-given

  同时,在configure.ac中可以通过AM_CONDITIONAL实现根据条件来定义宏,看到这里,小伙伴们是不是貌似知道怎么实现了呢。

 AM_CONDITIONAL([TESTCONFIG],  [test x$testConfig = xtrue])
 #如果testConfig的值为true,那么将会定义TESTCONFIG这个宏

  我们大概了解上面之后,下面让我们来实现,通过configure.ac和Makefile.am实现条件编译吧,代码如下:

#configure.ac代码
AC_ARG_ENABLE(testConfig,
               [AC_HELP_STRING([--enable-testConfig],[enable testConfig build])],
               [ case "${enableval}" in
                 yes) testConfig=true ;;
                 no)  testConfig=false ;;
          *)   AC_MSG_ERROR(bad value ${enableval} for --enable-testConfig) ;;
       esac],
       [testConfig=true])
 AM_CONDITIONAL([TESTCONFIG],  [test x$testConfig = xtrue])
#Makefile.am代码
if TESTCONFIG
    LIBS += -lpthread
    CFLAGS += -DTHREAD_TEST
endif

  在这两个文件添加上面的代码之后,将会根据configure时传进来的参数而决定是否定义宏。使用configure.ac和Makefile.am生成Makefile,需要在源码目录执行configure,就是在该命令后面添加相应的参数,实现条件编译。下面将就上述实现的代码进一步了解这个过程。
  我们在上面通过AC_ARG_ENABLE增加了–enable-testConfig这个编译选项,在执行configure时,将是这样的一种方式执行./configure --enable-testConfig=yes或者./configure --enable-testConfig=no

  • 当–enable-testConfig=yes,将是testConfig=true,接着AM_CONDITIONAL将会因为testConfig=true而#define TESTCONFIG
  • 当–enable-testConfig=no,将是testConfig=false,接着AM_CONDITIONAL没有进行任何操作;
  • 又当我们在./configure时忽略--enable-testConfig选项,那么,由于我们在AC_ARG_ENABLE定义该选项的时候,第四个参数,当外部没有设置时,将会执行第四个参数,在这里也就是[testConfig=true],所以,一样的,AM_CONDITIONAL将会定义宏TESTCONFIG。

  实现了相应宏的定义之后,我们就可以在Makefile.am中,通过判断会否存在这个宏而在编译的时候,将不同的参数传递给编译器,如上例子,如果定义了宏TESTCONFIG,将会在链接库的时候,增加-lpthread,同时通过-DTHREAD_TEST传递了宏定义THREAD_TEST,这样在源码中,就可以根据这个宏定义选择编译不同的代码段。
  可能有小伙伴感到疑惑,我在configure.ac中就定义了一个宏定义,这个宏定义能不能传到gcc编译器中进行编译呢,我测试过,这个是不行的,也就是在configure.ac中通过AM_CONDITIONAL定义的宏,是不能通过编译器参数传递影响编译代码段的,需要在Makefile.am中根据AM_CONDITIONAL定义的宏再通过-D传递宏定义到编译器。
  以上,为如何通过configure.ac和Makefile.am进行条件编译的操作解析。


  以上是个人理解,有理解错误的地方,欢迎指出,感谢

猜你喜欢

转载自blog.csdn.net/weixin_41944449/article/details/82467903