configure.ac和Makefile.am的格式解析概述

26 篇文章 4 订阅

1.1. Autotools相关工具链

1.1.1. Autotools

Autotools是一系列工具

  • autoscan
    可以通过调用autoscan命令,得到一个初始化的configure.scan文件。然后重命名为configure.ac后,在此基础上编辑configure.ac。
    autoscan会扫描源码,并生成一些通用的宏调用,输入的声明,以及输出的声明。尽管autoscan十分方便,但是没人能够在构建之前,就把源码完全写好。
    因此,autoscan通常用于初始化configure.ac,即生成configure.ac的雏形文件configure.scan
  • aclocal
    configure.ac实际是依靠宏展开来得到configure。因此,能否成功生成,取决于宏定义是否能够找到。
    autoconf会从自身安装路径下寻找事先定义好的宏。然而对于像automake,libtool,gettex等第三方扩展宏,autoconf便无从知晓。
    因此,aclocal将在configure.ac同一个目录下生成aclocal.m4,在扫描configure.ac过程中,将第三方扩展和开发者自己编写的宏定义复制进去。
    如此一来,autoconf遇到不认识的宏时,就会从aclocal.m4中查找
  • autoconf
    autoconf是 用来产生configure文件的 .configure是 一个脚本,它能设置源程序来适应各种不同的操作系统平台,并且根据不同的 系统来产生合适的 Makefile,从而可以使你的源代码能在不同的操作系统平台上被编译出来.
  • autoheader
    autoheader命令扫描configure.ac文件,并确定如何生成config.h.in。每当configure.ac变化时,都可以通过执行autoheader更新config.h.in。
    在configure.ac通过AC_CONFIG_HEADERS([config.h])告诉autoheader应当生成config.h.in的路径,
    config.h包含了大量的宏定义,其中包括软件包的名字等信息,程序可以直接使用这些宏。
    更重要的是,程序可以根据其中的对目标平台的可移植相关的宏,通过条件编译,动态的调整编译行为。
  • automake
    手工编写Makefile是一件相当繁琐的事情,并且随着项目的复杂程序变大,编写难度越来越大。automake工具应运而生。
    可以编辑Makefile.am文件,并依靠automake来生成Makefile.in

1.1.2. 其他相关工具

  • m4
    m4是一个经典的宏工具。autoconf正是构建在m4之上,可以理解为autoconf预先定义了大量的,用户检查系统可移植性的宏,这些宏在展开就是大量的shell脚本。
    所以编写configure.ac就需要对这些宏掌握熟练,并且合理调用。
  • libtool
    libtool试图解决不同平台下,库文件的差异。libtool实际是一个shell脚本,实际工作中,调用了目标平台的cc编译器和链接器,以及给予合适的命令行参数。
    libtool可以单独使用,也可以跟autotools集成使用。
  • autoreconf
    早期autoreconf并不存在,软件开发者就自己编写脚本,按照顺序调用autoconf,autoheader,automake等工具.
    autoreconf程序能够自动按照合理的顺序调用autoconf,automake,aclocal程序

 

1.2. 工具链的流程

1.2.1 autotools完整流程

1.2.2 autoreconf

1.2.3 behind autoreconf

1.2.4 configure生成Makefile

 

your source files --> [autoscan*] --> [configure.scan] --> configure.ac


[acinclude.m4] --.
                 |
[local macros] --+--> aclocal* --> aclocal.m4
                 |
configure.ac ----'


configure.ac --.
               |   .------> autoconf* -----> configure
[aclocal.m4] --+---+
               |   `-----> [autoheader*] --> [config.h.in]
[acsite.m4] ---'


configure.ac --.
               +--> automake* --> Makefile.in
Makefile.am ---'


                         .-------------> [config.cache]
configure* --------------+------------> config.log
                         |
[config.h.in] -.         v          .-> [config.h] -.
               +--> config.status* -+               +--> make*
Makefile.in ---'                    `-> Makefile ---'

所以需要项目维护者手动修改的文件除了可选的NEWS README AUTHORS ChangeLog文件之外,就是configure.ac文件和每个源码文件夹下的Makefile.am文件了。

  1. 调用autoscan脚本,生成[configure.scan]文件,并将该文件重命名为[configure.ac]。
  2. 修改[configure.ac],配置项目需要的各种自动化探测项。
  3. 编写自定义宏,为每个宏提供一个单独的*.m4文件。
  4. 调用aclocal收集[configure.ac]中用到的各种非autoconf的宏,包括自定义宏。
  5. 调用autoheader,扫描[configure.ac]、[acconfig.h],生成默认的[config.h.in]宏定义文件。具体文件名称可以在AC_CONFIG_HEADERS中配置。
  6. 编写[Makefile.am]文件,配置编译目标及其源码组成。
  7. 如果[configure.ac]配置了AC_PROG_LIBTOOL或LT_INIT,需要执行libtoolize –automake –copy –force。
  8. 调用automake –add-miss,将每个Makefile.am转化成[Makefile.in]。
  9. 调用autoconf,利用M4解析[configure.ac],生成configure脚本。

基本上只需要修改红色表示的三个步骤就可以配置好工程
 

1.3. autoconf

1.3.1. configure.ac文件

configure.ac用于生成configure脚本,以下以clist工程举例。

例如有以下文件结构

.
├── clist                   // clist库
│   ├── clist.c
│   ├── clist.h
│   ├── CMakeLists.txt      // 该文件是用于cmake的,忽略
│   ├── config.h.in         // 该文件是用于cmake的,忽略
│   └── Makefile.am
├── CMakeLists.txt          // 该文件是用于cmake的,忽略
├── configure.ac 
├── .gitignore              // 该文件是用于git的,忽略
├── LICENSE
├── m4
│   └── .gitignore          // 该文件是用于git的,忽略
├── Makefile.am
├── README.md
└── samples                 // 测试程序,需要链接clist库
    ├── CMakeLists.txt      // 该文件是用于cmake的,忽略
    ├── Makefile.am
    ├── memcheck.stp        // 该文件是用于systemstap的,忽略
    └── test.c

其中需要在autotools构建中用到的文件除了源码文件之外,还有./configure.ac./Makefile.am./clist/Makefile.am./samples/Makefile.am./m4/
m4为空文件夹,是为了后续存放自动生成的m4宏文件避免autoconf告警,由于git无法提交空文件夹,故在其下add了一个.gitignore文件。

使用autoscan扫描目录后,修改自动生成的configure.scan为configure.ac,并修改如下

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])

AC_INIT([clist], [1.0.1.1114], [tangm421@outlook.com])
AC_CONFIG_SRCDIR([clist/clist.c])
AC_CONFIG_HEADER(config.h)
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])

#m4_pattern_forbid([^PKG_])

AM_INIT_AUTOMAKE
AM_PROG_AR([AC_MSG_ERROR([cannot find any available compression tool for \$AR])])

AC_DISABLE_SHARED
LT_INIT()
# Checks for programs.
AC_PROG_CC
#AC_DISABLE_SHARED  // 这类宏放在LT_INIT之后是无效的

#AC_PROG_INSTALL    // 若使用这两个老式宏,AC_PROG_CC最好放在此宏之前,否则会有N多警告
#AC_PROG_LIBTOOL
dnl AC_PROG_RANLIB  // 若使用了libtool则需要将AC_PROG_RANLIB去掉,且#注释无效

AC_CANONICAL_HOST

#AC_PROG_MAKE_SET

# Checks for libraries.

# Checks for header files.
#AC_CHECK_HEADERS([malloc.h stdio.h stdlib.h string.h])

# Checks for typedefs, structures, and compiler characteristics.
#AC_CHECK_HEADER_STDBOOL

AC_CHECK_HEADERS([db_cxx.h],
 [echo "db_cxx.h found"],
 [AC_MSG_WARN([db_cxx.h not found])],
 [#ifdef HAVE_FOO_H
 # include <inttypes.h>
 #endif
 ])

AC_MSG_NOTICE([Using native OSTYPE value from \$host_os: $host_os, ARCH/LARCH value from \$host_cpu: $host_cpu])

#AC_DEFINE(PROJECT_IMPORTEXPORT, [], [Only usefull for windows])
#AH_TEMPLATE(PROJECT_IMPORTEXPORT, [Only usefull for windows])
AC_DEFINE_UNQUOTED(PROJECT_IMPORTEXPORT, ${PROJECT_IMPORTEXPORT:""}, [Only usefull for windows])

AC_ARG_ENABLE(clist-debug,
[AS_HELP_STRING([--enable-clist-debug], [Enable clist debug print])],
 AC_SUBST(LIBCLIST_CPPFLAGS, "-DCLIST_DEBUG"),
 AC_SUBST(LIBCLIST_CPPFLAGS, ""))

# Checks for library functions.
#AC_FUNC_MALLOC

AC_CONFIG_FILES([Makefile clist/Makefile samples/Makefile])
AC_OUTPUT

#AC_OUTPUT([Makefile clist/Makefile samples/Makefile])

1.3.2. configure.ac文件的标准布局

configure.ac调用Autoconf宏的顺序并不重要,但有一些例外。每个configure.ac必须在检查之前包含对AC_INIT的调用,并在末尾包含对AC_OUTPUT的调用(参阅Output)。此外,某些宏依赖于首先被调用的其他宏,因为它们会检查某些变量的先前设置值来决定要做什么。这些宏在各个描述中都有说明(参阅Existing Tests),并且如果调用它们的顺序不正确,它们还会在创建配置时向您发出警告。

为了鼓励一致性,以下是建议的调用Autoconf宏的顺序

Autoconf requirements
AC_INIT(package, version, bug-report-address)
information on the package
checks for programs
checks for libraries
checks for header files
checks for types
checks for structures
checks for compiler characteristics
checks for library functions
checks for system services
AC_CONFIG_FILES([file...])
AC_OUTPUT

1.3.3. configure.ac常见宏说明

 

AC_PREREQ

原型:AC_PREREQ(VERSION)
功能:需要的最低autoconf版本

AC_PREREQ([2.65])

AC_INIT

原型:AC_INIT(PACKAGE, VERSION, BUG-REPORT-ADDRESS)
功能:autoconf初始化。告诉autoconf包名称,版本,报告bug的Email

 

AM_INIT_AUTOMAKE

原型:AM_INIT_AUTOMAKE([OPTIONS…])
功能:初始化automake
参数:

AM_INIT_AUTOMAKE([foreign -Wall -Werror])

 AC_CHECK_HEADERS 或 AC_CHECK_HEADER
原型:
AC_CHECK_HEADERS(HEADERS…)
AC_CHECK_HEADER(HEADER, [ACT-IF-FOUND], [ACT-IF-NOT])
功能:检查头文件。代码中可以使用HAVE_XXX_H的方式检查该头文件是否存在
 

# 配置文件中的定义
AC_CHECK_HEADERS([string.h])

# 代码中的定义
#if HAVE_STRING_H
#include <string.h>
#else
/* replace header file */
#endif

AC_CONFIG_SRCDIR
原型:AC_CONFIG_SRCDIR ( unique-file-in-source-dir )
功能:确认某些关键文件在正确的目录中

AC_CONFIG_HEADERS
原型:AC_CONFIG_HEADERS(HEADERS…)
功能:创建头文件

# 创建config.h
AC_CONFIG_HEADERS([config.h])

# 创建config.h, 它的输入文件是config.h.ini, 在autoheader时被创建
AC_CONFIG_HEADERS([config.h:config.h.ini])

AC_CHECK_PROGS
原型:AC_CHECK_PROGS (variable, progs-to-check-for, [ value-if-not-found ], [ path = ‘$PATH’])
功能:将variable定义为第一个发现的程序,如果没有发现就设置为VAL-IF-NOT-FOUND
 

# 如果发现tar,gtar,就设置到变量$TAR中,如果没有发现就设置为‘:’
AC_CHECK_PROGS([TAR], [tar gtar], [:])
if test "$TAR" = :; then
AC_MSG_ERROR([This package needs tar])
fi

AC_DEFINE

原型:AC_DEFINE(VARIABLE, VALUE, DESCRIPTION)
功能:定义一个宏并输出到config.h中
注意:该宏是用于生成C语言的宏。如果value是一个shell变量可以使用AC_DEFINE_UNQUOTED

AC_SUBST

原型:AC_SUBST(VARIABLE, [VALUE])
功能:定义一个宏到Makefile中,可以在Makefile.am中以@XXX@的形式使用

AC_CHECK_LIB

原型:AC_CHECK_LIB(LIBRARY, FUNCT, [ACT-IF-FOUND], [ACT-IF-NOT])
功能:检查库是否存在并且包括函数FUNCT

AC_CHECK_LIB([efence], [malloc], [EFENCELIB=-lefence])
AC_SUBST([EFENCELIB])

AM_CONDITIONAL(

原型:AM_CONDITIONAL(NAME, CONDITION)
功能:执行CONDITION中的shell语句,如果成功则定义变量NAME

# 仅当系统中存在bar.h文件时定义WANT_BAR
AC_CHECK_HEADER([bar.h], [use_bar=yes])
AM_CONDITIONAL([WANT_BAR], [test "$use_bar" = yes])

1.3.5. 常用变量

autoconf 4.8.1 Preset Output Variables

Autoconf会预设一些输出变量,例如:

 

1.4. automake

1.4.1. Makefile.am文件

Makefile.am是一种比Makefile更高层次的规则。只需指定要生成什么目标,它由什么源文件生成,要安装到什么目录等构成。

  • 原则1:每个目录一个Makefile.am文件;同时在configure.ac的AC_CONFIG_FILES宏中指定输出所有的Makefile文件
  • 原则2:父目录需要包含子目录,在父目录下的Makefile.am中添加: SUBDIRS = 子目录
  • 原则3:Makefile.am中指明当前目录如何编译

Makefile.am用以生成最终的Makefile编译脚本,以下还是以clist工程为例

./Makefile.am

AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4

SUBDIRS = clist
SUBDIRS += samples

cmakedatadir = $(datadir)/cmake
nobase_dist_cmakedata_DATA = ./CMakeLists.txt
nobase_dist_cmakedata_DATA += clist/CMakeLists.txt
nobase_dist_cmakedata_DATA += ./samples/CMakeLists.txt

这里我把foreign选项放在了最顶层的Makefile.am中,由于configure.ac文件中加入了AC_CONFIG_MACRO_DIR宏,故此处必须加上ACLOCAL_AMFLAGS = -I m4
SUBDIRS是一个特殊变量,列出了在处理当前目录之前应递归到的所有目录。所有在此声明的子目录也参与到构建工程,故也需要Makefile.am文件。
关于此文件中的最后几行则是在执行make install时将几个cmake文件按照原始文件结构层次安装到$(datadir)/cmake目录下,并且允许在分发(执行make dist)时将这几个cmake文件按照层次结构也包含在内。

./clist/Makefile.am

lib_LTLIBRARIES = libclist.la

libclist_la_CPPFLAGS = @LIBCLIST_CPPFLAGS@

libclist_la_SOURCES = config.h clist.c

include_HEADERS = clist.h

子目录clist下用来编译clist库,因为启用了libtool(libtool将共享库和静态库抽象为一个统一的概念,称为libtool库。 libtool库是使用.la后缀的文件,并且可以指定静态库,共享库或两者。在运行./configure之前,无法确定它们的确切性质:并非所有平台都支持所有类型的库,并且用户可以显式选择应构建的库。由于共享库和静态库的目标文件必须以不同的方式进行编译,因此在编译过程中也会使用libtool。 libtool构建的对象文件称为libtool对象:这些文件使用.lo后缀。 Libtool库是从这些libtool对象构建的)所以此处库名为libclist.la,使用libclist_la_为前缀添加预编译指令、源码文件及包含文件。LIBCLIST_CPPFLAGS则是先前的configure.ac文件中声明的一个automake变量在此处引用。

./samples/Makefile.am

#AM_CFLAGS = -I$(top_srcdir)/clist

bin_PROGRAMS = sample

sample_CFLAGS = -I$(top_srcdir)/clist
sample_SOURCES = test.c
sample_LDADD = ../clist/libclist.la

sample_CPPFLAGS = -D_BINDIR='"$(bindir)"'

nodist_sample_SOURCES = mydefines.h
BUILT_SOURCES = mydefines.h
CLEANFILES = mydefines.h
mydefines.h: Makefile
	echo '#define INSTALL_BINDIR "$(bindir)"' > $@

子目录samples用来编译测试程序,程序名为sample,使用sample_为前缀添加C编译标志、源码以及链接库。
关于此文件中的最后几行,是为了说明后面如何引用预定义的变量的问题,BUILT_SOURCES则是为了在构建sample之前生成mydefines.h,关于BUILT_SOURCES变量的说明参阅automake 9.4 Built Sources

在静态库和动态库同时存在时,libtool默认链接的动态库

1.4.2. 语法说明

1.4.2.1. 统一命名规范

automake 3.3 The Uniform Naming Scheme

Automake变量通常遵循统一的命名规范,可以轻松决定程序(和其他派生对象)的构建方式以及安装方式。该规范还支持configure时确定应构建的内容。

make时,某些变量用于确定要构建的对象。变量名由几部分组成,这些部分串联在一起,其中指示构建的部分通常称为

1.4.2.2. 元

就拿_PROGRAMS为例,以_PROGRAMS结尾的变量,列出了生成的Makefile应该生成的程序。用Automake语言来说,此_PROGRAMS后缀称为

bin_PROGRAMS的bin部分告诉automake应该将生成的程序安装在bindir中。回想一下,GNU Build System使用一组变量来表示目标目录,并允许用户自定义这些位置。任何这样的目录变量都可以放在前面(省略dir后缀),以告诉automake在何处安装列出的文件。

Automake可以识别与不同类型的文件相对应的其他元变量,例如_PROGRAMS,_LIBRARIES,_LTLIBRARIES等。

当前_PROGRAMS_LIBRARIES_LTLIBRARIES_LISP_PYTHON_JAVA_SCRIPTS_DATA_HEADERS_MANS_TEXINFOS

将没有前缀的定义为变量(例如 PROGRAMS)是错误的!

1.4.2.3. 目录

automake 3.3 The Uniform Naming Scheme

某些变量用于确定应该把创建了的对象安装在哪里。这些变量中在前面的部分指示了应将哪个标准目录作为安装目录。标准目录名在GNU标准中给出(参考GUN编码标准中的目录变量)。automake通过前缀pkg扩展了这些标准目录变量,这些扩展的与标准的相同,但附加了$(PACKAGE)。例如:

GNU编码标准中的目录变量,如:prefixexec_prefixbindirlibdirincludedirdatarootdirdatadir等。

在构造变量名称时,通用的dir后缀被保留了。因此,使用bin_PROGRAMS而不是bindir_PROGRAMS。在使用automake扩展目录时,同样适用于此规则。例如,以下代码片段会将./CMakeLists.txt安装到$(datadir)/cmake文件夹中。

cmakedatadir = $(datadir)/cmake
nobase_dist_cmakedata_DATA = ./CMakeLists.txt

在autotools中,编译和安装的规则是在一起的:安装目录_编译类型=编译目标

 

 

1.4.2.4. 前缀

automake 3.3 The Uniform Naming Scheme

某些还可由一个或者多个前缀和变量串联起来形成。某些前缀如下:

  • EXTRA_

    对于每个,都可以插入一个EXTRA_前缀。该前缀用于储存根据configure的运行结果,可能创建、也可能不创建的对象列表。引入该变量是因为Automake必须静态地知道需要创建的对象的完整列表以创建在所有情况下都能够工作的Makefile.in
    例如:EXTRA_LTLIBRARIES = lib1.la lib2.la,这两个库不会被明确的构建,如果其在任何地方都不会作为Makefile依赖项出现,就不会被构建。一般该前缀用在条件编译的情形下比较常见。

  • check_

    该前缀表示仅仅在运行make check命令的时候才创建这些对象。

  • inst_ / noinst_

    用于控制make install时的安装行为。
    inst_表示应构建相关对象,且进行安装。
    noinst_表示应构建相关对象,但不安装。这通常用于构建程序包其余部分所需的对象,例如静态库或帮助程序脚本。

  • dist_ / nodist_

    用于控制make dist时的发布行为。
    任何_SOURCES变量都可以使用dist_作为前缀,以将列出的文件添加到发行版中。类似地,nodist_可用于从发行版中省略文件。

  • nobase_

默认情况下,在子目录中指定的可安装文件在安装前将删除其目录名称。例如,在此示例中,头文件将安装为$(cmakedatadir)/CMakeLists.txt。

dist_cmakedata_DATA += clist/CMakeLists.txt

 但是,可以使用nobase_前缀来规避此路径剥离。在此示例中,头文件将安装为$(cmakedatadir)/clist/CMakeLists.txt。

nobase_dist_cmakedata_DATA += clist/CMakeLists.txt

 当与其他前缀混合出现时,应首先指定该前缀

1.4.2.5. 衍生变量

automake 3.5 How derived variables are named

有时Makefile变量名是从用户提供的某些文本中派生而来的。例如,_PROGRAMS中列出的程序名称将被重写为_SOURCES变量的名称。Automake把这些文本规范化,以使它可以不必服从Makefile的变量名规则。进行变量引用时,名称中的所有字符(字母,数字,@和下划线除外)都将变为下划线。

例如,如果程序名为sniff-glue,则派生变量名称将为sniff_glue_SOURCES,而不是sniff-glue_SOURCES。同样的,名称为libmumble++.a的库的源文件应在libmumble___a_SOURCES变量中列出。

1.4.2.6. 用户保留变量

automake 3.6 Variables reserved for the user

GNU编码标准保留了一些Makefile变量,以供“用户”(构建软件包的人)使用,这些变量有些可能会被Autoconf预设。例如:

Automake为每个用户标志变量引入了一个特定于automake的影子变量(没有为CC之类的变量引入影子变量,因为它们没有意义)。影子变量的名称是在用户变量名前加上AM_。例如,CFLAGS的影子变量为AM_CFLAGS。软件包维护者(即Makefile.am和configure.ac文件的作者)可以根据需要调整这些影子变量。

1.4.2.7. 目标变量

automake 27.6 Program and Library Variables

与每个程序相关联的是变量集合,可用于修改该程序的构建方式。每个库都有类似的此类变量列表。程序或库的规范名称用作命名这些变量的基础。以程序或库名为maude举例,常见的变量如下:

1.4.2.8. 其他

SUBDIRS
EXTRA_DIST
BUILT_SOURCES

 1.4.3. Makefile.am常用变量说明

当一些头文件不需要在外部被引用时,也应该列在_SOURCES中,而不是_HEADERS。例如,库的头文件一般列出在_HEADERS,程序的头文件一般列出在_SOURCES中。另外有一些参与目标构建但既不属于目标对象,又不需要被外部引用的头文件,则可以使用noinst_HEADERS,比较典型的如configure生成的config.h文件。

_LDADD_LIBADD不适合传递程序特定的链接器标志(-l,-L,-dlopen和-dlpreopen除外)。

1.5. 一些常见问题

1.5.1. 标识变量的顺序问题

automake 27.6 Flag Variables Ordering

以CPPFLAGS为例,automake中有三个有关该标识变量,CPPFLAGSAM_CPPFLAGSmaude_CPPFLAGS,用于传递给C/C++预处理器,CPPFLAGS是用户变量,AM_CPPFLAGS是Automake变量,而mumble_CPPFLAGS是特定于目标对象的变量,也即每个目标变量。
编译时,automake始终使用这些变量中的两个,如果maude_CPPFLAGS定义了,则使用该变量,否则,使用AM_CPPFLAGS,第二个变量始终是CPPFLAGS。该规则也同样适用于其他类似标记。 例如:

bin_PROGRAMS = foo bar
foo_SOURCES = xyz.c
bar_SOURCES = main.c
foo_CPPFLAGS = -DFOO
AM_CPPFLAGS = -DBAZ

xyz.o将使用$(foo_CPPFLAGS)$(CPPFLAGS)进行编译(因为xyz.o是foo目标的一部分),而main.o将使用$(AM_CPPFLAGS)$(CPPFLAGS)进行编译(因为bar目标变量未定义)。

推荐使用额外自定义的变量,然后使用目标对象的标记变量追加。例如:

AM_CFLAGS = $(WARNINGCFLAGS)
bin_PROGRAMS = prog1 prog2
prog1_SOURCES = ...
prog2_SOURCES = ...
prog2_CFLAGS = $(LIBFOOCFLAGS) $(AM_CFLAGS)
prog2_LDFLAGS = $(LIBFOOLDFLAGS)

1.5.2. 如何引用预定义的变量

autoconf 20.5 How Do I #define Installation Directories?

例如想将bindir定义到程序中使用,直接使用以下方式是行不通的:

AC_DEFINE_UNQUOTED([INSTALL_BINDIR], [$bindir], [Define to the read-only architecture-independent data directory.])

最终得到的结果是:

#define DINSTALL_BINDIR "${prefix}/bin"

 因为该行为是GNU编码标准强制规定的,要达到目的,不能使用AC_DEFINE,而是使用Makefile通过编译标识传递,或者定义到专门的头文件中。

  • 方式一:使用Makefile通过编译标识传递
AM_CPPFLAGS = -DINSTALL_BINDIR='"$(bindir)"'
  • 方式二:创建一个专用头文件
DISTCLEANFILES = mydefines.h
    mydefines.h: Makefile
            echo '#define INSTALL_BINDIR "$(bindir)"' >$@

根据配置编译不同模块 

  1. 使用AC_DEFINE或AC_DEFINE_UNQUOTED定义C语言使用的宏
  2. 使用AM_CONDITIONAL或AC_SUBST定义Makefile使用的宏

 配置特殊宏

  1. 新建一个单独的目录,用于存放自定义宏,一般定义为m4
  2. 为每个宏定义一个文件,以.m4结尾
  3. 使用AC_DEFUN定义具体的宏
  4. 运行aclocal -Im4生成aclocal.m4
  5. 在根目录下的Makefile.am中添加ACLOCAL_AMFLAGS = -I m4

1.6. clist示例工程

clist

1.7. 参考资料

autoconf
automake
libtool
autoconf宏定义
Autotools 工具
绝世秘籍之GNU构建系统与Autotool概念分析
automake,autoconf使用详解
Autoconf中文手册

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
非常抱歉,我混淆了configure.acMakefile.am文件。下面是正确的步骤: 1. 在主项目的configure.ac文件中,使用AC_CONFIG_SUBDIRS宏指定需要包含的子项目目录,例如: ``` AC_CONFIG_SUBDIRS([subdir1 subdir2 subdir3]) ``` 2. 在每个子项目的configure.ac文件中,必须使用AC_CONFIG_AUX_DIR宏来指定子项目中的config.sub和config.guess文件的位置,例如: ``` AC_CONFIG_AUX_DIR([.]) ``` 3. 在每个子项目的Makefile.am文件中,使用ACLOCAL_AMFLAGS变量来指定包含的宏定义文件的位置,例如: ``` ACLOCAL_AMFLAGS = -I m4 ``` 其中,m4是包含宏定义文件的目录。 4. 在每个子项目的Makefile.am文件中,使用AUTOMAKE_OPTIONS变量指定需要使用外部子目录功能,例如: ``` AUTOMAKE_OPTIONS = subdir-objects ``` 5. 在每个子项目的Makefile.am文件中,定义生成的库文件和头文件,并使用INCLUDES变量指定需要包含的头文件路径,例如: ``` lib_LTLIBRARIES = libsubdir1.la libsubdir1_la_SOURCES = subdir1.c subdir1.h INCLUDES = -I$(top_srcdir)/subdir1 ``` 其中,lib_LTLIBRARIES变量指定生成的库文件名,libsubdir1_la_SOURCES变量指定生成库文件所需的源文件和头文件,INCLUDES变量指定需要包含的头文件路径。 6. 最后,在主项目的Makefile.am文件中,使用SUBDIRS变量指定包含的子目录,例如: ``` SUBDIRS = subdir1 subdir2 subdir3 ``` 这样,在主项目的configure脚本执行时,会自动进入每个子项目的目录执行其对应的configure脚本,然后生成各自的Makefile文件。同时,每个子项目的库和头文件也会被自动编译和链接到主项目中。 使用外部子目录功能可以自动化生成子项目的Makefile文件,避免了手动执行子项目的configure脚本的步骤。同时,也可以更灵活地控制子项目的编译和链接过程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值