自动生成Makefile

1 如何自动生成Makefile

需要工具:GNU autoconf, automake, m4, perl

2 automake 支持3种目录层次结构

  • flat:指所有源代码文件都存储在顶层目录中,且没有子目录。
  • shallow:指主要源代码文件存储在顶层目录中,其它实现部分功能的源代码文件(主要是库)存储在子目录中。
  • deep:指所有源代码文件都存储在子目录中,顶层目录不包含任何源代码文件,只包含配置信息。

3 生成Makefile的步骤

  1. 首先进入project工程的顶层目录;
    $cd project/
    
  2. 运行autoscan命令,生成文件configure.scan;
    $./autoscan
    
  3. 将configure.scan文件重命名为configure.ac(老版本使用后缀.in(已经淘汰),新版本使用.ac),并修改configure.ac文件;
    $mv configure.scan configure.ac
    
  4. 运行aclocal命令;
    $aclocal
    
  5. 运行autoconf命令,生成可执行文件configure;
    $autoconf
    
  6. 在project顶层目录下手动新建NEWS、README、AUTHORS、ChangeLog文件,使用touch命令创建空文件即可;
    $touch NEWS README AUTHORS
    
  7. 在project各层目录下根据需要新建Makefile.am文件,并编辑Makefile.am文件;
    $vi Makefile.am
    
  8. 运行automake命令,利用Makefile.am文件生成Makefile.in文件;
    $automake
    
  9. 运行./configure,生成makefile文件。
    $./configure
    

4 编辑configure.ac文件

利用autoscan工具可以生成configure.scan文件,这里需要将configure.scan文件重命名为configure.ac文件。configure.ac调用一系列autoconf宏来测试程序需要的或者利用到的特性是否存在,以及这些特性的功能。configure.scan内容如下:

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
AC_CHECK_HEADERS([stdlib.h])
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([common/Makefile
                 src/Makefile])
AC_OUTPUT

每个configure.scan文件都是以AC_INIT开头,以AC_OUTPUT结束。现在开始修改configure.ac文件

$mv configure.scan configure.ac
$vim configure.in

修改后的configure.ac内容如下

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.61])
AC_INIT([Jupiter], [1.0], [bugs@jupiter.org])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
AC_PROG_RANLIB
AC_PROG_INSTALL
AM_PROG_CC_C_O
# Checks for header files (1).
AC_HEADER_STDC
# Checks for command line options
AC_ARG_ENABLE([async-exec],
  [AS_HELP_STRING([--disable-async-exec],
    [disable asynchronous execution @<:@default: no@:>@])],
  [async_exec=${enableval}],
  [async_exec=yes])
if test "x${async_exec}" = xyes; then
  have_pthreads=no
  AC_SEARCH_LIBS([pthread_create], [pthread],
    [have_pthreads=yes])
  if test "x${have_pthreads}" = xyes; then
    AC_CHECK_HEADERS([pthread.h], [],
      [have_pthreads=no])
  fi
  if test "x${have_pthreads}" = xno; then
    echo "---------------------------------------"
    echo "Unable to find pthreads on this system."
    echo "Building a single-threaded version.    "
    echo "---------------------------------------"
    async_exec=no
  fi
fi
if test "x${async_exec}" = xyes; then
  AC_DEFINE([ASYNC_EXEC], 1, [async exec enabled])
fi
# Checks for header files (2).
AC_CHECK_HEADERS([stdlib.h])
# Checks for libraries.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile
         common/Makefile
                 src/Makefile])
AC_OUTPUT
echo \
"-------------------------------------------------
 ${PACKAGE_NAME} Version ${PACKAGE_VERSION}
 Prefix: '${prefix}'.
 Compiler: '${CC} ${CFLAGS} ${CPPFLAGS}'
 Package features:
   Async Execution: ${async_exec}
 Now type 'make @<:@<target>@:>@'
   where the optional <target> is:
     all                - build all binaries
     install            - install everything
--------------------------------------------------"

5 configure.ac文件说明

  • 修改AC_INIT(package_name, package_verison, owner_email)

    package_name:工程名字

    package_version:当前工程的版本号

    owner_email:工程所有者邮箱

  • 增加AM_INIT_AUTOMAKE(必须)
  • 增加AC_CONFIG_FILES(Makefile, …)

    指明了所有要生成的Makefile的路径,必须与工程中所有Makefile.am的路径保持一致。

  • 给configure配置自定义参数

    configure常用的参数格式主要有两种:–enable-xxx和–disable-xxx; –with-xxx和–with-out-xxx分别通过以下两个宏来定义这两种参数

    AC_ENABLE(option-name, help-string, [action-if-given], [action-if-not-givin])
    AC_ARG_WITH(option-name, help-string, [action-if-given], [action-if-not-givin])
    

    option-name:参数名称

    help-string:当执行./configure –help时,用于描述参数的帮助信息

    action-if-given:当用户传递了设置的参数时,执行对应的sh脚本指令。ex:./configure –enable-xxx

    action-if-not-ginven:当用户没有传递设置的参数时,执行对应的sh脚本指令。ex:./configure

    下面举例说明:

    AC_ARG_ENABLE([async-exec],
       [AS_HELP_STRING([--disable-async-exec],
         [disable asynchronous execution @<:@default: no@:>@])],
       [async_exec=${enableval}],
       [async_exec=yes])
    
    if test "x${async_exec}" = xyes; then
       have_pthreads=no
       AC_SEARCH_LIBS([pthread_create], [pthread],
         [have_pthreads=yes])
      if test "x${have_pthreads}" = xyes; then
         AC_CHECK_HEADERS([pthread.h], [],
           [have_pthreads=no])
      fi
    
      if test "x${have_pthreads}" = xno; then
        echo "---------------------------------------"
        echo "Unable to find pthreads on this system."
        echo "Building a single-threaded version.    "
        echo "---------------------------------------"
        async_exec=no
      fi
    fi
    if test "x${async_exec}" = xyes; then
      AC_DEFINE([ASYNC_EXEC], 1, [async exec enabled])
    fi
    

    定义了一个参数async-exec,当传入参数./configure –disable-async-exec时,执行async_exec=${enableval},这里介绍一下变量enableval,当传入参数时会同时给该变量赋值,如果传入参数的形式是–disabe-xxx或–without-xxx,则enableval的值为no;如果传入参数的形式是–enable-xxx或者–with-xxx,则enableval的值为yes。所以这里async_exec的值为no。当没有传输设置的参数时,即./configure,则执行[async_exec=yes]。接下来判断"x${async_exec}"的值,如果等于xyes,则执行AC_SEARCH_LIBS宏,该宏的作用是检查系统中是否存在线程库pthread。接着执行AC_CHECK_HEADERS宏,该宏的作用是检查系统中是否包含头文件pthread.h。否则打印出错信息。最后调用宏AC_DEFINE,该宏的作用是定义一个c的宏,第一个参数是宏名,第二个参数是该宏的值,第三个参数起描述作用。

6 Makefile.am文件说明

Makefile.am是一种比Makefile更高层次的规则,主要作用是指定要生成什么目标,它由什么源文件生成,要安装到什么目录等。 Makefile的一般格式

File TypeFormat
Excutable Filesbin_PROGRAMS = foo
 foo_SOURCES = xxx.c
 foo_LDADD =
 foo_LDFLAGS =
 foo_DEFENDENCIES =
Static Liblib_LIBRARIES = libfoo.a
 foo_a_SOURCES =
 foo_a_LDADD =
 foo_a_LIBADD =
 foo_a_LDFLAGS =
Header Filesinclude_HEADERS = foo.h
Data Filesdata_DATA = data1 data2
  • 可执行文件的生成

要生成一个可执行文件,需要在Makefile.am中写一套可执行文件的规则,如上表所示。这里使用源文件hello.c生成可执行文件hello,该可执行文件需要链接库libtest.so。

bin_PROGRAMS = hello
hello_SOURCES = hello.c
hello_LDADD = -ltest
hello_LDFLAGS = -l./include

其中大写字母部分,比如_PROGRAMS被称为primary。primary表示如何处理等号后面所跟的参数,这里指hello。小写字母部分,比如bin则表示安装目录,这里生成的目标hello最后会被安装在${prefix}/bin/目录下。

  • 库的生成

要生成一个库,需要在Makefile.am中加入一套动态库规则,如上表所示。这里使用源文件test1.c和test2.c生成动态库libtest.so,库的版本号为1.0.10,库需要额外链接一个叫libhello.so的库。 lib_LTLIBRARIES = test.la test_la_SOURCES = test1.c test2.c test_la_LIBADD = -lhello

hello_la_LDFLAGES = -version-info 1.0.10 指定库的版本信息,其它参数 -avoid-version 生成不带版本号的库 -all-static 生成静态库

对于可执行文件和静态库类型,如果只想编译,不想安装到系统中,可以用noinst_PROGRAMS代替bin_PROGRAMS,noinst_LIBRARIES代替lib_LIBRARIES。

Makefile.am中可用的全局变量

Variables含义
INCLUDES比如链接时所需要的头文件
LDADD比如链接时所需要的库文件
LDFLAGS比如链接时所需要的库文件选项标志
EXTRA_DIST源程序和一些默认的文件将自动打入.tar.gz包
 其它文件若要进入.tar.gz包,则使用这种方法
SUBDIRS在处理本目录之前要递归处理哪些子目录

参考资料:

  1. http://mij.oltrelinux.com/devel/autoconf-automake/
  2. http://www.freesoftwaremagazine.com/articles/automatically_writing_makefiles_with_autotools
  3. https://www.ibm.com/developerworks/cn/linux/l-makefile/

Date: 2015-04-15T01:04+0800

Author: yijun

Org version 7.9.3f with Emacs version 24

Validate XHTML 1.0

转载于:https://www.cnblogs.com/yijun/p/4427422.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值