autotools:autoconf/automake生成Makefile流程详解
生成Makefile文件详解,主要流程如下:

项目维护者手动修改的文件除了可选的NEWS README AUTHORS ChangeLog文件之外,就是一个 configure.ac 文件 和 每个源码文件夹下的 Makefile.am 文件了,父目录Make file.am中“SUBDIRS = 子目录”定义子目录,。
1. 在工程根目录下, 运行 autoscan 生成 configure.ac
对源文件创建后,我们就可以在工程根目录下,通过autoscan命令对该目录进行扫描,生成configure.scan文件。这里configure.scan其实是一个模板文件,我们需要手动修改一下其内容,并将其改名为configure.ac.
首先切换到该目录,然后执行命令,具体如下:
vmuser@ubuntu:~/user/vmuser/myproject/ autoscan vmuser@ubuntu:~/user/vmuser/myproject/ mv configure.scan configure.ac
后缀*代表执行过程,[]代表可选项 your source files --> [autoscan*] --> [configure.scan] --> configure.ac
编辑 configure.ac
1) AC_INIT 里面的参数: AC_INIT(main,1.0, suntroop@google.com); #定义软件包"全"名称,版本号,联系方式。 2) 添加宏 AM_INIT_AUTOMAKE; #指定包名称和版本 3) 在 AC_OUTPUT 后添加输出文件Makefile。
针对交叉编译环境,使用如下宏定义:
AC_PROG_CXX(arm-linux-gnueabihf-g++)
AC_PROG_CC(arm-linux-gnueabihf-gcc)
# -*- 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_INIT(main, 1.0, suntroop@google.com) AC_CONFIG_SRCDIR([TestPrepare/test_prepare.c])
# 生成config.h文件保存configure.ac定义的宏,此文件可被源文件包含 AC_CONFIG_HEADERS([config.h])
# 用来存储本地宏文件,.m4的文件都将被保存进此目录,acloacl命令会自动创建此目录
AC_CONFIG_MACRO_DIRS([m4])
# 用来存储一些辅助脚本文件
AC_CONFIG_AUX_DIR([build-aux])
# 初始化automake
AM_INIT_AUTOMAKE(hello, 1.0)
# Checks for programs. #AC_PROG_CC(arm-linux-gcc)
AC_PROG_CC(gcc)
#AC_PROG_LIBTOOL
AC_PROG_RANLIB
AX_CHECK_DOCBOOK
# 初始化要连接的obj目录
AC_CONFIG_LIBOBJ_DIR([src])
# Checks for libraries. # Checks for header files. AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h netinet/in.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h termios.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE AC_TYPE_SSIZE_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T # Checks for library functions. AC_FUNC_MALLOC AC_CHECK_FUNCS([gettimeofday inet_ntoa memset select socket])
#多个目录包含Makefile.am
AC_CONFIG_FILES([Makefile test_example/Makefile test_src/Makefile])
AC_OUTPUT
#单个目录包含Makefile.am,使用 AC_OUTPUT(Makefile),不使用 AC_CONFIG_FILES
2. 在工程根目录下, 运行 aclocal 生成 aclocal.m4
执行aclocal命令即可生成文件aclocal.m4,该文件是一个宏定义文件,该文件内容的生成依赖于configure.ac文件。
aclocal会根据confgure.ac文件的内容,搜索本地的m4文件(通常在类似目录下面/usr/share/aclocal-1.15/),然后生成一个在本目录下面使用的aclocal.m4文件
vmuser@ubuntu:~/user/vmuser/myproject/ aclocal vmuser@ubuntu:~/user/vmuser/myproject/ file aclocal.m4 aclocal.m4: M4 macro processor script, ASCII text
[acinclude.m4] ----.
|
[local macros] --+--> aclocal* --> aclocal.m4
|
configure.ac ----'
3. 在工程根目录下, 运行 autoheader 生成 config.h.in
vmuser@ubuntu:~/user/vmuser/myproject/ autoheader vmuser@ubuntu:~/user/vmuser/myproject/ file config.h.in config.h.in: C source, ASCII text
configure.ac --.
| .------> autoconf* -----> configure
[aclocal.m4] --+---+
| `-----> [autoheader*] --> [config.h.in]
[acsite.m4] ---'
这个文件config.h.in是一个模板文件,后面会利用该文件生成config.h文件。该文件包含一些宏定义
4. 在工程根目录下, 手动创建 Makefile.am
生成Makefile.in文件之前, 需要首先手动的创建一个Makefile.am文件,该文件用于描述源文件与目标文件的关系。本文对应的Makefile.am文件如下所示:
vmuser@ubuntu:~/user/vmuser/myproject/ touch Makefile.am
vmuser@ubuntu:~/user/vmuser/myproject/ file Makefile.am

编辑 Makefile.am, 如果要生成多个目标文件,需要在这里写多个源文件与目标文件的对应关系。这种情况是非常常见的,比如一些复杂的项目中通常会包含主程序,测试程序,静态/动态库等等。
详见:附录B
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = main # 生成的可执行文件名称
main_SOURCES = plc_main.c calendar.c sort.c # 程序依赖的源文件
INCLUDES = = -I/usr/local/libmemcached/include/ #表示连接时所需要的头文件
SUBDIRS = etc man # 表示在处理目录之前,要递归处理哪些子目录
SUBDIRS += subst
5. 在工程根目录下, 运行 automake 生成 Makefile.in
vmuser@ubuntu:~/user/vmuser/myproject/ automake --add-missing vmuser@ubuntu:~/user/vmuser/myproject/ file Makefile.in
Makefile.in: makefile script, ASCII text, with very long lines
configure.ac --.
+--> automake* --> Makefile.in
Makefile.am ---'
使用命令 “ automake --add-missing ” 或 “ automake -a ”,automake 会根据 Makefile.am 产生一些文件,包括最重要的Makefile.in 文件
6. 在工程根目录下, 运行 autoconf 生成 configure
生成configure文件的方法很简单,我们执行如下命令即可:
vmuser@ubuntu:~/user/vmuser/myproject/ autoconf vmuser@ubuntu:~/user/vmuser/myproject/ file configure
configure: POSIX shell script, ASCII text executable
configure.ac --.
| .------> autoconf* -----> configure
[aclocal.m4] --+---+
| `-----> [autoheader*] --> [config.h.in]
[acsite.m4] ---'
7. 在工程根目录下, 运行 ./configure 生成 Makefile
生成Makefile文件的方法很简单,我们执行如下命令即可:
vmuser@ubuntu:~/user/vmuser/myproject/ ./configure
vmuser@ubuntu:~/user/vmuser/myproject/ file Makefile
Makefile: ASCII text, with very long lines
vmuser@ubuntu:~/user/vmuser/myproject/ ./configure --help
.-------------> [config.cache]
configure* ------------+-------------> config.log
|
[config.h.in] -. v .-> [config.h] -.
+--> config.status* -+ +--> make*
Makefile.in ---' `-> Makefile ---'
8. 在工程根目录下, 运行 make && make install 生成 目标文件
生成Makefile文件的方法很简单,我们执行如下命令即可:
vmuser@ubuntu:~/user/vmuser/myproject/ make && make install vmuser@ubuntu:~/user/vmuser/myproject/ make clean //只清除之前编译的可执行文件及配置文件。
vmuser@ubuntu:~/user/vmuser/myproject/ make disclean //清除所有生成的文件。
vmuser@ubuntu:~/user/vmuser/myproject/ make uninstall //卸载
当configure.ac 和 Makefile.am 发生改变时,需要更新 “已经生成的配置文件”, 此时需要使用 autoreconf命令。
9. 在工程根目录下, 运行 autoreconf -ivf 整体更新配置文件生成configure
autoreconf 重复运行 autoconf, autoheader, aclocal, automake, libtoolize, and autopoint (when appropriate) 在特殊目录及其子目录下更新GNU构建系统。默认只更新老的文件。不会传递–autoconf-dir=dir 或 --localdir=dir。
最终更新Makefile.in、configure编译脚本等文件。但是不会执行./configure 。所以需要手动执行: ./configure && make && make install
vmuser@ubuntu:~/user/vmuser/myproject/ autoreconf -ivf vmuser@ubuntu:~/user/vmuser/myproject/ ./configure && make && make install
| autoreconf 选项 | 含义 |
| -v | 详细报告处理 |
| -d | 不删除临时文件 |
| -f | 认为所有的文件都是过期的文件,强制执行 |
| -i | 复制辅助文件 |
| -s | 创建符号链接,而不是复制 |
| -W<分类> | 报告语法错误的信息 |
| -m | 当可以使用时,重新运行命令./configure和make |
| --no-recursive | 不重建子包 |
| -B<目录> | 将目录作为搜索路径 |
| -I<目录> | 追加目录作为搜索路径 |
附录 A configure配置脚本常用选项:
--host
指需要运行的位置,默认为build,也就是本机编译出来的程序,由本机使用. 比如当本机编译出来的程序, 要在arm板上运行时, 就要设为 arm-linux
例如:
./configure --host=arm-linux //默认: ./configure --target=build
--target
指运行目标,比如gdb程序,通过在pc本机里运行,来调试开发板里的应用程序,所以--host设为build,--target设为arm-linux
例如:
./configure --target=arm-linux
--prefix
安装路径前缀,指使用make install 后,生成的安装路径在哪
例如:
./configure --prefix=/work/my_bin
./configure --prefix=$PWD/tmp //安装在./tmp目录下
PS:若该软件根目录下的Makefile里,有"--prefix ="之类的字段,也可以直接在安装处指定路径,比如:
#make install prefix=$PWD/tmp //指定安装在./tmp目录下
CFLAGS
指定头文件(.h文件)的路径,一般是用来安装了库包后,安装目录下会有两个文件(include和lib),再来安装应用程序包时,就需要指定(include)头文件路径
例如:
./configure CFLAGS=”-I/usr/include -std=c99” //-I: include -std=c99 -std=gnu99, -std=c11 or -std=gnu11
LDFLAGS
指定库文件的路径,一般是用来安装了库包后, 安装目录下会有两个文件(include和lib),再来安装应用程序包时,就需要指定(lib)库文件路径
例如:
./configure LDFLAGS=”-L/usr/include” //-L: lib
CC
指定编译器,默认为gcc、cc或者HOST-gcc
例如:
./configure CC=arm-linux-gcc //ln -s /cross-tools/bin/arm-linux-gnueabihf-gcc /usr/bin/x86_64-linux-gnu-gcc
./configure --cc=arm-linux-gcc //或者 --cc=gcc 或者 --cc=/usr/bin/x86_64-linux-gnu-gcc
AR
指定编译器,默认为gcc、cc或者HOST-gcc
例如:
./configure AR=arm-linux-gcc //ln -s /cross-tools/bin/arm-linux-gnueabihf-ar /usr/bin/arm-linux-gcc
./configure --ar=arm-linux-ar //或者 --ar=ar 或者 --ar=/usr/bin/x86_64-linux-gnu-ar
附录B Makefile.am常用语法
AUTOMAKE_OPTIONS = foreign //设置automake的选项,automake提供了三种软件等级:foreign、gnu和gnits,当当前库文件编译所需源文件不在当前目录时要设置参数subdir-objects
目标1:bin目录可执行程序
bin_PROGRAMS = XXX YYY #编译并安装, 生成的目标“可执行应用程序”名称,如果有多个,用空格隔开,与configure.ac中AC_INIT对应库名对应 noinst_PROGRAMS = XXX #只编译不安装,“可执行应用程序”名称 noinst_HEADERS = xxx.h #只编译不安装,所需要的目标“头文件”。这个表示该头文件只是参加可执行文件的编译,而不用安装到安装目录下。如果需要安装到系统中,可以用include_HEADERS来代替
INCLUDES=-I$(top_srcdir)/Core/inc/ #链接时,所需要的“头文件所在路径”
XXX_SOURCES = Main/main.c Ether/ether_server.c test.h #编译时,生成目标文件所需要的“源代码文件”
XXX_CFLAGS = -g -O2 -std=c99 -I$(top_srcdir)/Core/inc/
#编译时,C预处理/编译“选项”,
XXX_CPPFLAGS = -DCONFIG_DIR=\"$(sysconfdir)\" -DLIBRARY_DIR=\"$(pkglibdir)\" #编译时,C/C++预处理/编译“选项”,一般用来指定所需要头文件目录
INCLUDES=-I$(top_srcdir)/Core/inc/ #链接时,所需要的“头文件所在路径”
XXX_LDADD = $(top_srcdir)/Core/lib/libecpucore.a #链接时,。所需要的“静态库”名称
XXX_LDFLAGS=-D_GNU_SOURCE #链接时,所需要的库文件的标识, 如-l,-shared等“选项”
LIBS = -lpthread -ldl #链接时,所需要的“动态库”名称
DEFS+=-D_GNU_SOURCE
样例:
AUTOMAKE_OPTIONS = foreign bin_PROGRAMS = ecpu.bin
INCLUDES = -I$(top_srcdir)/CANopen/inc/ -I$(top_srcdir)/CANopen/inc/linux/ \
-I$(top_srcdir)/CANopen/dictionary/ -I$(top_srcdir)/CANopen/hardware/
ecpu_bin_CFLAGS = --static -g -O2 -std=c99 -I$(top_srcdir)/Core/inc/ -I$(top_srcdir)/Ether/
ecpu_bin_SOURCES = Main/main.c Ether/cu_com.c Ether/ssw_com.c Ether/ether_server.c SerialPort/rs485.c \
MoveControl/Schedule/mod_state.c \
MoveControl/Schedule/schedule_move.c \
MoveControl/Schedule/test_list.c \
MoveControl/Schedule/test_order.c
SUBDIRS = CANopen
ecpu_bin_LDADD = $(top_srcdir)/Core/lib/libecpucore.a $(top_srcdir)/CANopen/libcanopen.a LIBS=-lpthread -ldl
目标2:lib目录静态库文件
lib_LIBRARIES=libXXX.a #编译并安装, 生成的目标“静态库”名称 noinst_LIBRARIES = libXXX.a #只编译不安装,生成的目标“静态库”名称 libXXX_a_SOURCES = tinyxml2.h tinyxml2.cpp #编译时,生成目标文件所需要的“源代码文件”
样例:
noinst_LIBRARIES = libcanopen.a noinst_HEADERS = hardware/canopen_cfg.h
INCLUDES=-I$(top_srcdir)/CANopen/inc/ -I$(top_srcdir)/CANopen/inc/linux/ \
-I$(top_srcdir)/CANopen/dictionary/ -I$(top_srcdir)/CANopen/hardware/
libcanopen_a_CFLAGS = -std=c99
libcanopen_a_SOURCES = hardware/canopen_cfg.h dictionary/Master.c dictionary/Master.h dictionary/Master.od \
hardware/can0.c hardware/can0.h hardware/timer0.c hardware/ timer0.h \
src/dcf.c src/emcy.c src/lifegrd.c src/lss.c src/nmtMaster.c src/nmtSlave.c \
src/objacces.c src/pdo.c src/sdo.c src/states.c src/sync.c src/timer.c
目标3:lib目录动态库文件
https://www.freesion.com/article/52611144144/
目标4:include目录头文件
include_HEADERS = XXX.h #编译并安装, 所需要的“头文件”。这个表示哪些头文件将在执行make install命令之后被安装到系统include目录下
目标5:data目录数据文件
data_DATA = XXXX YYYY #编译并安装,所需要的目标数据文件,不能执行。
变量:
SUBDIRS=src/lib src/ModuleA/apple/shell src/ModuleA/apple/core #表示编译当前目录之前,先编译哪些子目录,多个目录用空格分开 CURRENTPATH=$(shell /bin/pwd) #表示当前目录
INCLUDES=-I$(top_srcdir)/Core/inc/ #链接时,所需要的“头文件所在路径”
export INCLUDES
$(top_builddir) #表示生成目标文件的最上层目录,用于引用.o等编译出来的目标文件。
$(top_srcdir) #表示工程的最顶层目录,其实也是第一个Makefile.am的入口目录,用于引用源程序
./configure –-prefix=/usr/local/app/ 其实在调用这个之后,就定义了一个变量$(prefix), 表示安装的路径:
bindir = $(prefix)/bin libdir = $(prefix)/lib datadir = $(prefix)/share sysconfdir = $(prefix)/etc includedir = $(prefix)/include
浙公网安备 33010602011771号