autoconf automake 进一步解读

autoconf automake 进一步解读

author:hjjdebug
date: 2019年 12月 28日 星期六 22:06:34 CST


学习其工作原理


如何进一步控制Makefile 的生成,
例如 修改编译选项时,添加调试信息, 添加-D宏定义,添加第三方库包含路径,添加第三方库,

开源软件,一般只要configure 能通过,make 是没有什么问题的,可见configure 成为成功的关键.
1. 修改configure.ac 从而修改configure 文件
2. 修改Makefile.am,从而修改Makefile

configure 文件是一个脚本文件,主要用来检查目标文件的依赖,例如头文件是否存在,
    链接的库文件是否存在等.

./configure 的传入参数将影响Makefile 的生成
例如你想修改CFLAGS, 添加调试信息,不优化,可用如下语法:
./configure CFLAGS=-g -O0

./configure --help 可以看到它的使用帮助,
前面一些选项用来修改默认的路径,下面一些选项则是用来说明如何影响源码的编译
Some influential environment variables:
  CC          C compiler command
  CFLAGS      C compiler flags
  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
              nonstandard directory <lib dir>
  LIBS        libraries to pass to the linker, e.g. -l<library>
  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
              you have headers in a nonstandard directory <include dir>


configure.ac 中的常见的语法.
AM_INIT_AUTOMAKE: 想生成Makefile, 必须要调用该宏
AC_SEARCH_LIBS:
Macro: AC_SEARCH_LIBS (FUNCTION, SEARCH-LIBS, [ACTION-IF-FOUND],
           [ACTION-IF-NOT-FOUND], [OTHER-LIBRARIES])
configure.ac 中不叫函数调用,而叫宏调用, 也有传入参数, 例如该宏,
    第一个参数,被检查的函数名称
    第二个参数,被检查的库名称
    第三个参数,发现了怎么办
    第四个参数,未发现怎么办
    第五个参数,其它的库
AC_CHECK_LIB:
Macro: AC_CHECK_LIB (LIBRARY, FUNCTION, [ACTION-IF-FOUND],
           [ACTION-IF-NOT-FOUND], [OTHER-LIBRARIES])
这两个函数第一和第二参数调换了一下位置


AC_CHECK_LIB(nsl, t_open)            //查libnsl.so 中的t_open()函数
AC_SEARCH_LIBS(socket, socket)        //查libsochet.so 中的socket()函数    
AC_CHECK_HEADER([stdio.h],
        [AC_DEFINE([HAVE_STDIO_H], 1,
           [Define to 1 if you have <stdio.h>.])],
        [AC_MSG_ERROR([sorry, can't do anything for you])])

dnl: 该宏是一个注释宏, 查info m4知,
The builtin 'dnl' stands for "Discard to Next Line":

运行预处理命令:
Macro: AC_PREPROC_IFELSE (INPUT, [ACTION-IF-TRUE],
          [ACTION-IF-FALSE])
For instance:
     AC_INIT([Hello], [1.0], [bug-hello@example.org])
     AC_DEFINE([HELLO_WORLD], ["Hello, World\n"],
       [Greetings string.])
     AC_PREPROC_IFELSE(
        [AC_LANG_PROGRAM([[const char hw[] = "Hello, World\n";]],
                         [[fputs (hw, stdout);]])],
        [AC_MSG_RESULT([OK])],
        [AC_MSG_FAILURE([unexpected preprocessor failure])])

results in:

     checking for gcc... gcc
     checking for C compiler default output file name... a.out
     checking whether the C compiler works... yes
     checking whether we are cross compiling... no
     checking for suffix of executables...
     checking for suffix of object files... o
     checking whether we are using the GNU C compiler... yes
     checking whether gcc accepts -g... yes
     checking for gcc option to accept ISO C89... none needed
     checking how to run the C preprocessor... gcc -E
     OK

常用的AC 宏举例: 望文生意,辅以练习,还是容易理解的. 我这里摘自unpv13e 项目,一个网络书的例子
AC_CACHE_VAL(ac_cv_ipv4,
AC_CANONICAL_HOST
AC_CHECK_FUNCS(bzero)
AC_CHECK_FUNCS(getaddrinfo)
AC_CHECK_FUNCS(inet_pton)
AC_CHECK_FUNC_PROTO(getnameinfo, netdb.h)
AC_CHECK_FUNC_PROTO(inet_aton, arpa/inet.h)
AC_CHECK_FUNC_PROTO(snprintf, stdio.h)
AC_CHECK_HEADERS(sys/types.h sys/socket.h sys/time.h time.h [], [
AC_CHECK_LIB(nsl, t_open)
AC_CHECK_LIB(pthread, pthread_create)
AC_CHECK_LIB(xti, t_open)
AC_CHECK_MEMBER([struct msghdr.msg_control],
AC_CHECK_MEMBER([struct sockaddr.sa_len],
AC_CHECK_TYPE([struct sockaddr_dl],
AC_CHECK_TYPES([struct sockaddr_storage],
AC_CONFIG_HEADER(config.h)
AC_DEFINE(HAVE_ADDRINFO_STRUCT, 1, Define to 1 if <netdb.h> defines struct addrinfo),,[
AC_DEFINE(HAVE_DEV_TCP, 1, Define to 1 if the /dev/tcp device exists)
AC_DEFINE(HAVE_DEV_XTI_TCP, 1, Define to 1 if the /dev/xti/tcp device exists)
AC_DEFINE(SA_FAMILY_T, uint16_t)
AC_DEFINE([ss_family],[__ss_family],[define to __ss_family if sockaddr_storage has that instead of ss_family]),
AC_HEADER_STDC
AC_HEADER_TIME
AC_INIT(lib/unp.h)
AC_MSG_CHECKING(for $HOME/libbind.a)
AC_MSG_CHECKING(for IPv4 support)
AC_MSG_ERROR([cannot find ss_family in sockaddr_storage]),[
AC_MSG_RESULT($ac_cv_ipv4)
AC_MSG_RESULT(no)
AC_MSG_RESULT(no, using ./libunp.a)
AC_MSG_RESULT(yes)
AC_OUTPUT(Makefile Make.defines)
AC_PROG_CC
AC_PROG_RANLIB
AC_REVISION($Revision: 1.13 $)
AC_SEARCH_LIBS(socket, socket)
AC_SUBST(LIBFREE_OBJS)
AC_TRY_RUN([
//自定义的宏
AC_UNPXTI_CHECK_TYPE(t_scalar_t, int32_t, scalar type)
AC_UNP_CHECK_TYPE(int16_t, short, 16 bit signed type)
AC_UNP_CHECK_TYPE(int32_t, int, 32 bit signed type)


2. 修改Makefile.am, 再调用./configure
看一下生成的Makefile, 原来它们使用了如下的宏!
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
    $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)

LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@

我们可以在Makefile.am 中定义AM_CPPFLAGS 定义第三方包含路径,定义宏变量
用法:
AM_CPPFLAGS= -I ./lib        #可以将包含路径定义在AM_CPPFLAGS中
在AM_CFLAGS 定义优化, 在AM_LDFLAGS 中定义第三方库路径
(注意:不要和configure中CFLAGS, CPPFLAGE重复定义)
INCLUDES 在Makefile.am 中已经不推荐使用了, 在Makefile.am 中最好使用AM_打头的宏


编译
.c.o:
    $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
hello$(EXEEXT): $(hello_OBJECTS) $(hello_DEPENDENCIES) $(EXTRA_hello_DEPENDENCIES)

链接:
    @rm -f hello$(EXEEXT)
    $(AM_V_CCLD)$(LINK) $(hello_OBJECTS) $(hello_LDADD) $(LIBS)

AM_V_CC 是空
AM_V_CCLD 是空
EXEEXT 为空
hello_OBJECTS 推导为hello.o ....

其它相关宏:
bin_PROGRAMS 是Makefile.am 中定义的, 后面会被Makefile使用
PROGRAMS = $(bin_PROGRAMS)

通过查看demo Makefile, 对编写Makefile.am 中使用的宏就心里有底了.


automake 目标:
bin_PROGRAMS    (前面的bin表示安装到bin 目录)
noinst_LIBRARIES (noinst 是不安装)
lib_LTLIBRARIES (后缀名为.la,例如libmytest.la, lib是安装到lib目录,LT是libtool简写)
SUBDIRS (递归,层次调用时使用)
关键字只是后半部分, 初次相见感觉有点怪异,习惯就好了.

库文件举例: XXX_LTLIBRARIES, XXX_LIBRARIES
不安装XXX换成noinst, 安装到lib换成lib, 前者libtool生成的库,后者一般库
libtool编译的库对夸平台移植是个福音.

添加一个宏定义 例如:-DONPC=1
修改优化选项        :可修改CFLAGS, 或通过configure 传递
添加第三方包含路径    :可修改AM_CPPFLAGS
添加第三方库路径    :添加到_LDADD变量中


$cat Makefile.am
一个简单的例子,使用了关键的几个变量! 这也是最主要的几个宏了.
AUTOMAKE_OPTIONS=foreign
SUBDIRS=lib
bin_PROGRAMS=hello
hello_SOURCES=main.c        #添加源文件 _SOURCES
hello_LDADD=lib/libhello.a    #添加第三方库 _LDADD
AM_CPPFLAGS = -I ./lib        #添加包含路径,直接修改_CPPFLAGS

除了自定义的宏,还有内部定义的宏调用, 多看多练就熟悉了, 也不多,就是Makefile 中常见的东西.
总之是为了make 出执行文件或库文件为目的, 查找头文件,库文件,等等功能

ubuntu下有一个check 包,里面有一个automake和cmake 的例子,可以参考下
/usr/share/doc/check/examples ,可以一阅.


想深入了解autoconf, automake, 可以读其info 文档.

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值