Linux下automake工具使用(自动构建Makefile文件)

1,404 阅读11分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

一、前言

linux环境下,当项目工程很大的时候,编译的过程很复杂,所以需要使用make工具,自动进行编译安装,但是手写makefile文件比较复杂,所幸在GNU的计划中,设计出了一种叫做Autoconf/Automake的工具,用来自动生成makefile文件,为编译和安装程序提供了一个方便快捷的入口。

无论是在Linux还是在Unix环境中,make都是一个非常重要的编译命令。不管是自己进行项目开发还是安装应用软件,我们都经常要用到make或 make install。利用make工具,我们可以将大型的开发项目分解成为多个更易于管理的模块,对于一个包括几百个源文件的应用程序,使用make和 makefile工具就可以轻而易举的理顺各个源文件之间纷繁复杂的相互关系。

但是如果通过查阅make的帮助文档来手工编写Makefile,对任何程序员都是一场挑战。

下面将介绍如何利用 GNU Autoconf 及 Automake 这两套工具来协助我们自动产生 Makefile文件,并且让开发出来的软件可以像大多数源码包那样,只需"./configure", "make","make install" 就可以把程序安装到系统中。

目前automake支持三种目录层次:flat、shallow和deep。

  1. flat指的是所有文件都位于同一个目录中。

就是所有源文件、头文件以及其他库文件都位于当前目录中,且没有子目录。Termutils就是这一类。

  1. shallow指的是主要的源代码都储存在顶层目录,其他各个部分则储存在子目录中。

就是主要源文件在当前目录中,而其它一些实现各部分功能的源文件位于各自不同的目录。automake本身就是这一类。

  1. deep指的是所有源代码都被储存在子目录中;顶层目录主要包含配置信息。

就是所有源文件及自己写的头文件位于当前目录的一个子目录中,而当前目录里没有任何源文件。

二、安装Automake工具

  1. 先检查当前系统里是否安装了工具。
[wbyq@wbyq tmp]$ which autoscan

安装成功的提示:

[wbyq@wbyq tmp]$ which autoscan/usr/bin/autoscan
  1. 如果系统没有安装Automake工具,红帽子系统可以挂载光盘找到安装包进行安装

如果是ubuntu系统可以通过命令在线下载工具: sudo apt-get install autoconf automake libtool

三、Automake工具使用方法

3.1 现在一个目录下,编写好一个C代码文

3. 2 执行autoscan命令生成configure.scan文件

生成configure.scan文件之后,将文件修改成configure.ac文件,如果没有这个.ac文件,执行aclocal命令的时候会报错。

3.3 修改configure.ac文件参数

AC_PROG_RANLIB如果是多线程的程序的话要加入这句话,要不运行automake命令时会出错

每个configure.ac文件都是以AC_INIT开头,以AC_OUTPUT结束。

AC_INIT测试程序测试函数库测试头文件测试类型定义测试结构测试编译器特性测试库函数测试系统调用AC_OUTPUT

关键字解释:

AC_INIT()中分别的是: 软件包的名字,版本,作者的联系方式(一般是Email)

示例: AC_INIT([app], [1.1.2], [1126626497@qq.com])

在下面再自己添加一行AM_INIT_AUTOMAKE(),里面填入: 程序名字,版本号。

示例: AM_INIT_AUTOMAKE(app,1.1.2)

最后AC_OUTPUT()填写生成的文件名称。

AC_OUTPUT(Makefile)

(1)AC_PREREQ宏声明本文件要求的autoconf版本,本例使用的版本为2.63。

(2)AC_INIT宏用来定义软件的名称和版本等信息,”FULL-PACKAGE-NAME”为软件包名称,”VERSION”为软件版本号,”BUG-REPORT-ADDRESS”为BUG报告地址(一般为软件作者邮件地址)。

(3)AC_CONFIG_SRCDIR宏用来侦测所指定的源码文件是否存在,来确定源码目录的有效性。此处为当前目录下的app.c。

(4)AC_CONFIG_HEADER宏用于生成config.h文件,以便autoheader使用。

(5)AC_PROG_CC用来指定编译器,如果不指定,选用默认gcc。 比如: AC_PROG_CC(gcc)

(6)AC_OUTPUT用来设定 configure 所要产生的文件,如果是makefile,configure会把它检查出来的结果带入makefile.in文件产生合适的makefile。使用Automake时,还需要一些其他的参数,这些额外的宏用aclocal工具产生。

3.4 执行aclocal命令生成aclocal.m4文件

[wbyq@wbyq tmp]$ aclocal

3.5 使用autoconf工具生成configure文件

[wbyq@wbyq tmp]$ autoconf

3.6 使用autoheader生成config.h.in文件

[wbyq@wbyq tmp]$ autoheader

3.7 手工编辑Makefile.am文件

Automake工具会根据config.in中的参量把Makefile.am转换成Makefile.in文件。在使用Automake之前,要先手动建立Makefile.am文件。

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

[wbyq@wbyq tmp]$ touch Makefile.am

文件创建之后,需要写三项代码:

第一项:软件规范,有三个候选项:foreign(国外),gnu(GNU),gnits

如果使用foreign等级,它只检测必须的文件

第二项:生成的可执行文件名

第三项:生成可执行文件所需的原始文件,有多个文件时用空格隔开。

示例:

AUTOMAKE_OPTIONS=foreignbin_PROGRAMS=appapp_SOURCES=app.c

3.8 使用automake命令生成Makefile.in文件

添加选项--add-missing 可以让automake工具自动添加必要的脚本文件

注意: 不能在共享目录下执行,因为共享目录下是windows文件系统(FA32/NTFS),不支持link操作。

不然会报以下错误:

示例:

[wbyq@wbyq tmp]$ automake --add-missing

3.9 运行configure配置生成最终的Makefile文件

configure脚本为了让一个程序能够在各种不同类型的机器上运行而设计的。在使用make编译源代码之前,configure会根据自己所依赖的库而在目标机器上进行匹配。

约定俗成的,所有的configure脚本都把脚本文件名起为configure,一般来讲都是shell脚本,根据所在的系统环境生成makefile文件。

configure脚本运行时扫描当前环境,生成一个名为config.status的子脚本。子脚本将Makefile.in文件转换为适应于当前系统环境的Makefile文件。

[wbyq@wbyq tmp]./configurecheckingforaBSDcompatibleinstall.../usr/bin/installccheckingwhetherbuildenvironmentissane...yescheckingforathreadsafemkdirp.../bin/mkdirpcheckingforgawk...gawkcheckingwhethermakesets./configurechecking for a BSD-compatible install... /usr/bin/install -cchecking whether build environment is sane... yeschecking for a thread-safe mkdir -p... /bin/mkdir -pchecking for gawk... gawkchecking whether make sets(MAKE)... yeschecking for gcc... gccchecking for C compiler default output file name... a.outchecking whether the C compiler works... yeschecking whether we are cross compiling... nochecking for suffix of executables...checking for suffix of object files... ochecking whether we are using the GNU C compiler... yeschecking whether gcc accepts -g... yeschecking for gcc option to accept ISO C89... none neededchecking for style of include used by make... GNUchecking dependency style of gcc... gcc3checking how to run the C preprocessor... gcc -Echecking for grep that handles long lines and -e... /bin/grepchecking for egrep... /bin/grep -Echecking for ANSI C header files... yeschecking for sys/types.h... yeschecking for sys/stat.h... yeschecking for stdlib.h... yeschecking for string.h... yeschecking for memory.h... yeschecking for strings.h... yeschecking for inttypes.h... yeschecking for stdint.h... yeschecking for unistd.h... yeschecking for stdlib.h... (cached) yesconfigure: creating ./config.statusconfig.status: creating Makefileconfig.status: creating config.hconfig.status: executing depfiles commands

3.10 使用Makefile编译,运行程序

[wbyq@wbyq tmp]make//编译程序[wbyq@wbyqtmp] make //编译程序[wbyq@wbyq tmp] ./app 123 456 789 //运行程序argv[0]=./appargv[1]=123argv[2]=456argv[3]=789

3.11 Make支持的其他命令

[wbyq@wbyq app-1.1.2]makeclean//清除目标文件[wbyq@wbyqapp1.1.2] make clean //清除目标文件[wbyq@wbyq app-1.1.2] make dist //将源文件打包[wbyq@wbyq app-1.1.2]make//编译源文件生成目标文件[wbyq@wbyqapp1.1.2] make //编译源文件生成目标文件[wbyq@wbyq app-1.1.2] make install //将目标文件拷贝到指定目录下

四、configure文件详解

configure' configures app 1.2.3 to adapt to many kinds of systems.Usage: ./configure [OPTION]... [VAR=VALUE]...To assign environment variables (e.g., CC, CFLAGS...), specify them asVAR=VALUE. See below for descriptions of some of the useful variables.Defaults for the options are specified in brackets.Configuration:-h, --help 显示此帮助并退出--help=short 显示特定于此包的选项--help=recursive 显示所有包含的简短帮助-V, --version 显示版本信息并退出-q, --quiet, --silent 不要打印“检查...”消息--cache-file=FILE 在FILE中缓存测试结果[已禁用]-C, --config-cache alias for --cache-file=config.cache'-n, --no-create do not create output files--srcdir=DIR find the sources in DIR [configure dir or ..']Installation directories:--prefix=PREFIX 在PREFIX中安装与体系结构无关的文件[/usr/local]--exec-prefix=EPREFIX 在EPREFIX中安装与体系结构相关的文件[PREFIX]By default, make install' will install all the files in/usr/local/bin', /usr/local/lib' etc. You can specifyan installation prefix other than /usr/local' using --prefix',for instance --prefix=$HOME'.For better control, use the options below.Fine tuning of the installation directories:--bindir=DIR 用户可执行文件 [EPREFIX/bin]--sbindir=DIR 系统管理可执行文件 [EPREFIX/sbin]--libexecdir=DIR 程序可执行文件 [EPREFIX/libexec]--sysconfdir=DIR read-only single-machine data [PREFIX/etc]--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]--localstatedir=DIR modifiable single-machine data [PREFIX/var]--libdir=DIR 目标代码库 [EPREFIX/lib]--includedir=DIR C header files [PREFIX/include]--oldincludedir=DIR C header files for non-gcc [/usr/include]--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]--datadir=DIR read-only architecture-independent data [DATAROOTDIR]--infodir=DIR info documentation [DATAROOTDIR/info]--localedir=DIR locale-dependent data [DATAROOTDIR/locale]--mandir=DIR man documentation [DATAROOTDIR/man]--docdir=DIR documentation root [DATAROOTDIR/doc/app]--htmldir=DIR html documentation [DOCDIR]--dvidir=DIR dvi documentation [DOCDIR]--pdfdir=DIR pdf documentation [DOCDIR]--psdir=DIR ps documentation [DOCDIR]Program names:--program-prefix=PREFIX prepend PREFIX to installed program names--program-suffix=SUFFIX append SUFFIX to installed program names--program-transform-name=PROGRAM run sed PROGRAM on installed program namesOptional Features:--disable-option-checking ignore unrecognized --enable/--with options--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)--enable-FEATURE[=ARG] include FEATURE [ARG=yes]--disable-dependency-tracking speeds up one-time build--enable-dependency-tracking do not reject slow dependency extractorsSome influential environment variables:CC C compiler commandCFLAGS C compiler flagsLDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in anonstandard directory <lib dir>LIBS libraries to pass to the linker, e.g. -l<library>CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> ifyou have headers in a nonstandard directory <include dir>CPP C preprocessorUse these variables to override the choices made by configure' or to helpit to find libraries and programs with nonstandard names/locations.Report bugs to 1126626497@qq.com.

五、多个文件生成Makefile示例(同级目录)

​ 在目录下有3个.c、2个头文件

​ configure.ac文件内容:

​ Makefile.am文件内容:

六、Makefile.am格式详解

6.1 Makefile.am中可用的全局变量

变量含义示例
INCLUDES链接所需要的头文件
LDADD链接所需要的库文件
LDFLAGS链接所需要的库文件选项标志
EXTRA_DIST配置打包时需要打包的其他文件
SUBDIRS设置处理本目录之前需要递归处理的子目录

示例:

SUBDIRS=src/lib src/ModuleA/apple/shell src/ModuleA/apple/coreCURRENTPATH=(shell/bin/pwd)INCLUDES=I(shell /bin/pwd)INCLUDES=-I(CURRENTPATH)/src/include -I$(CURRENTPATH)/src/ModuleA/apple/includeexport INCLUDES

6.2 Makefile.am中可用的路径变量

在Makefile.am中尽量使用相对路径,系统预定义了两个基本路径:

路径变量含义
$(top_srcdir)工程最顶层目录,用于引用源程序
$(top_builddir)定义了生成目标文件最上层目录,用于引用.o 等一些编译出来的目标文件
$(prefix)定义了软件的安装的路径
  1. automake标准安装路径

默认安装路径为:$(prefix) = /usr/local,可以通过./configure --prefix=<new_path>的方法来覆盖。

其它的预定义目录还包括:bindir = (prefix)/bin,libdir=(prefix)/bin, libdir = (prefix)/lib, datadir = (prefix)/share,sysconfdir=(prefix)/share, sysconfdir = (prefix)/etc等等。

  1. 定义一个新的安装路径

比如test, 可定义testdir = (prefix)/test,然后testDATA=test1test2,则test1test2会作为数据文件安装到(prefix)/test, 然后test_DATA =test1 test2,则test1,test2会作为数据文件安装到(prefix)/ /test目录下。

示例:

devicedir = ${prefix}/devdevice_DATA = packagepackage文件会作为数据文件安装到dev目录之下,这相当于定义了一种安装类型:devicedir,所以想怎么安装就怎么安装,后面的XXXXXdir,dir是固定不变的

6.3 Makefile.am一般格式Makefile.am一般格式

PROGRAMS。表示可执行文件

LIBRARIES。表示静态库文件

LTLIBRARIES。表示动态库文件,前面的LT表示libtool。

HEADERS。头文件。

SCRIPTS。脚本文件,这个可以被用于执行。如:example_SCRIPTS,如果用这样的话,需要我们自己定义安装目录下的example目录

DATA。数据文件,不能执行。

文件类型书写格式示例
软件规范AUTOMAKE_OPTIONS=foreign有三个候选项:foreign(国外),gnu(GNU),gnits如果使用foreign等级,它只检测必须的文
可执行文件bin_PROGRAMS=foofoo_SOURCES=xxx.cfoo_LDADD=foo_LDFLAGS=foo_DEPENDENCIES=bin_PROGRAMS=foo(设置可执行文件的名称)如果可执行文件的名称为foo,后面的代码前缀,都需要填foo
静态库lib_LIBRARIES=libfoo.afoo_a_SOURCES=foo_a_LDADD=foo_a_LIBADD=foo_a_LDFLAGS=如果程序里使用了静态库编译,需要在configure.ac文件里增加以下宏定义代码AC_PROG_RANLIB
动态库lib_LTLIBRARIES=libfoo.lafoo_la_SOURCES=foo_la_LDADD=foo_la_LIBADD=foo_la_LDFLAGS=如果程序里使用了动态库编译,需要在configure.ac文件里增加以下宏定义代码AC_PROG_LIBTOOL表示利用libtool 来自动生成动态库编译共享库前,需要运行以下命令:libtoolize -f -c
头文件include_HEADERS=xx.h xx.h xx.h软件发布时需要的头文件make install之后,会将头文件放到安装目录下的include目录里。
数据文件data_DATA=data1 xxx2 xxx3

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

如果有帮助文档,不需要编译,但是需要随着软件发布一起发布,可以按下面格式进行定义:

EXTRA_DIST=led/led.h key/key.h

七、auotomake多级目录生成Makefile(不发布静态库)

7.1 创建待编译的源码(模拟真实项目环境)

在第一章里简单介绍了使用automake自动产生makefile的几个关键步骤,所有文件都在同一个目录下。但在比较大的项目中,很少将所有文件放在一个目录下的。下面将针对这种情况做个简单介绍。

多级目录结构的软件,一般是单个程序、库文件或模块放在各自的目录中。automake要求每个目录都有自己的Makefile.am文件来编译各自目录 下的代码。在顶级的目录中,有一个Makefile.am文件,该文件通过SUBDIRS指明了这个目录下有多少个直接下级目录的代码需要编译。下级目录的Makefile.am也指明自己需要编译的下级目录。通过这样的层层递归i,从而完成多级目录结构的编译。

下面模拟了一个项目工程:

顶层目录是project,在project目录下分别是main\print\sum目录。 main目录里的main.c是包含main函数的主程序,分别调用了sum和print目录下.c文件里的函数。

7.2 project顶层目录下的操作过程

  1. 执行autoscan命令生成configure.scan文件

在project目录下运行autoscan命令生成configure.scan文件。

  1. 将configure.scan改名成configure.in (早期in现在常用.ac)
[wbyq@wbyq project]$ mv configure.scan configure.in
  1. 修改configure.in文件
[wbyq@wbyq project]$ cat configure.in# -- Autoconf --# Process this file with autoconf to produce a configure script.AC_PREREQ([2.63])AC_INIT([app], [1.2.3], [112626497@qq.com])AC_CONFIG_SRCDIR([main/main.c])AC_CONFIG_HEADERS([config.h])AM_INIT_AUTOMAKE(app,1.2.3)AC_PROG_RANLIB #使用了静态库编译,需要此宏定义# Checks for programs.AC_PROG_CC# Checks for libraries.# Checks for header files.# Checks for typedefs, structures, and compiler characteristics.# Checks for library functions.AC_OUTPUT(Makefilemain/Makefilesum/Makefileprint/Makefile)

  1. 分别执行aclocal、autoconf、autoheader命令

  1. 创建Makefile.am文件
[wbyq@wbyq project]$ touch Makefile.am

编辑内容如下:

AUTOMAKE_OPTIONS=foreignSUBDIRS= print sum main #表示本目录的直接下级目录需要编译#注意:顺序不能反,按照调用顺序来写。

如果有帮助文档,不需要编译,但是需要随着软件发布一起发布,可以按下面格式进行定义:

EXTRA_DIST=doc/help.txt

doc/help.txt不需要编译,但要发布该文件。如果有多个文件,则用空格分开。

7.3 main目录下创建Makefile.am文件

在main目录下建立Makefile.am文件。

AUTOMAKE_OPTIONS=foreignbin_PROGRAMS=app #本目录的文件编译成可执行文件appapp_SOURCES=main.capp_LDADD=(topsrcdir)/sum/libsum.a(top_srcdir)/sum/libsum.a (top_srcdir)/print/libprint.aINCLUDES=-I(topsrcdir)/print/I(top_srcdir)/print/ -I(top_srcdir)/sum

app_LDADD 指定需要的库文件

INCLUDES 指定需要的头文件

7.4 print目录下创建Makefile.am文件

内容:

[wbyq@wbyq project] cat print/Makefile.amAUTOMAKE_OPTIONS=foreignnoinst_LIBRARIES=libprint.alibprint_a_SOURCES=print.h print.cINCLUDES=-I(top_srcdir)/sum

7.5 sum目录下创建Makefile.am文件

内容:

[wbyq@wbyq project]$ cat sum/Makefile.amAUTOMAKE_OPTIONS=foreignnoinst_LIBRARIES=libsum.alibsum_a_SOURCES=sum.h sum.c

7.6 编译

[wbyq@wbyq project]automakeaddmissing[wbyq@wbyqproject] automake --add-missing[wbyq@wbyq project]./configure --prefix=PWD/install[wbyq@wbyqproject]PWD/_install[wbyq@wbyq project] make[wbyq@wbyq project]$ make install

八、auotomake多级目录生成Makefile(发布静态库)

  1. 目录结构如下

在main.里调用了led.c和key.c里的函数。

(1)​ main.c代码

[wbyq@wbyq project]$ cat user/main.c#include <stdio.h>#include "key.h"#include "led.h"int main(char argc,char **argv){led_init();key_init();return 0;}

(2)​ led.c和led.h代码

[wbyq@wbyq project] cat led/led.h#ifndef LED_H#define LED_H#include <stdio.h>void led_init(void);#endif[wbyq@wbyq project] cat led/led.c#include "led.h"void led_init(void){printf("led_init\n");}

(3)​ key.c和key.h代码

[wbyq@wbyq project] cat key/key.h#ifndef KEY_H#define KEY_H#include <stdio.h>void key_init(void);#endif[wbyq@wbyq project] cat key/key.c#include "key.h"#include "led.h"void key_init(void){led_init();printf("key_init\n");}

调用关系图

  1. 顶层Makefile.am文件代码(自己创建)
[wbyq@wbyq project]$ cat Makefile.amAUTOMAKE_OPTIONS=foreign #软件规范SUBDIRS=led key user #执行本目录前,需要递归执行make的目录
  1. user/Makefile.am文件代码(自己创建)
[wbyq@wbyq project] cat user/Makefile.amAUTOMAKE_OPTIONS=foreign #软件规范bin_PROGRAMS=app #可执行文件名称app_SOURCES=main.c #可执行需要的源文件app_LDADD=(top_srcdir)/led/libled.a (top_srcdir)/key/libkey.a #可执行文件需要的库文件INCLUDES=-I(top_srcdir)/led -I(top_srcdir)/key #编译需要的头文件EXTRA_DIST=(top_srcdir)/led/led.h $(top_srcdir)/key/key.h #打包时需要额外添加的文件 make dist打包命令
  1. key/Makefile.am文件代码(自己创建)
[wbyq@wbyq project]$ cat key/Makefile.amAUTOMAKE_OPTIONS=foreign #软件规范lib_LIBRARIES=libkey.a #生成的静态库文件libkey_a_SOURCES=key.c key.h #生成静态库需要的源文件。 格式:libkey_a_SOURCES --将原来的.换成_
  1. led/Makefile.am文件代码(自己创建)
[wbyq@wbyq project]$ cat led/Makefile.amAUTOMAKE_OPTIONS=foreign #软件规范lib_LIBRARIES=libled.a #生成的静态库文件(lib开头表示执行make installs时会一起发布,加noinst就不会一起发布)libled_a_SOURCES=led.c led.h #生成静态库需要的源文件。 格式:libkey_a_SOURCES --将原来的.换成_
  1. 顶层目录下的configure.ac 文件代码
1. 执行autoscan 命令生成configure.scan 文件2. 修改configure.scan 文件后缀为.ac或者.in3. 修改configure.ac 文件参数4. configure.ac文件代码如下:[wbyq@wbyq project]$ cat configure.ac# -- Autoconf --# Process this file with autoconf to produce a configure script.AC_PREREQ([2.63])AC_INIT([app], [1.2.3], [112662497@qq.com])AC_CONFIG_SRCDIR([user/main.c])AC_CONFIG_HEADERS([config.h])AM_INIT_AUTOMAKE(app,1.2.3)AC_PROG_RANLIB #表示使用静态库# Checks for programs.AC_PROG_CC# Checks for library functions.AC_OUTPUT(Makefileuser/Makefileled/Makefilekey/Makefile)
  1. 执行命令: aclocal\autoconf\autoheader

  2. automake --add-missing

  3. ./configure --prefix=$PWD/_install

  4. make && make install

  5. 在安装目录下的文件结果

九、auotomake多级目录生成Makefile(发布动态库+静态库)

  1. 目录结构如下

在main.里调用了led.c和key.c里的函数。

在main.里调用了led.c和key.c里的函数。

(1)​ main.c代码

[wbyq@wbyq project]$ cat user/main.c#include <stdio.h>#include "key.h"#include "led.h"int main(char argc,char **argv){led_init();key_init();return 0;}

(2)​ led.c和led.h代码

[wbyq@wbyq project] cat led/led.h#ifndef LED_H#define LED_H#include <stdio.h>void led_init(void);#endif[wbyq@wbyq project] cat led/led.c#include "led.h"void led_init(void){printf("led_init\n");}

(3)​ key.c和key.h代码

[wbyq@wbyq project] cat key/key.h#ifndef KEY_H#define KEY_H#include <stdio.h>void key_init(void);#endif[wbyq@wbyq project] cat key/key.c#include "key.h"#include "led.h"void key_init(void){led_init();printf("key_init\n");}

调用关系图

  1. 顶层Makefile.am文件代码(自己创建)
[wbyq@wbyq project]$ cat Makefile.amAUTOMAKE_OPTIONS=foreign #软件规范SUBDIRS=led key user #执行本目录前,需要递归执行make的目录
  1. user/Makefile.am文件代码(自己创建)
[wbyq@wbyq project] cat user/Makefile.amAUTOMAKE_OPTIONS=foreign #软件规范bin_PROGRAMS=app #可执行文件名称app_SOURCES=main.c #可执行需要的源文件app_LDADD=(top_srcdir)/led/libled.la (top_srcdir)/key/libkey.la #可执行文件需要的动态库文件INCLUDES=-I(top_srcdir)/led -I(top_srcdir)/key #编译需要的头文件EXTRA_DIST=(top_srcdir)/led/led.h $(top_srcdir)/key/key.h #打包时需要额外添加的文件 make dist打包命令

  1. key/Makefile.am文件代码(自己创建)
[wbyq@wbyq project]$ cat key/Makefile.amAUTOMAKE_OPTIONS=foreign #软件规范lib_LTLIBRARIES=libkey.la #生成的动态库文件libkey_la_SOURCES =key.c key.h #生成静态库需要的源文件。 格式:libkey_la_SOURCES --将原来的.换成_
  1. led/Makefile.am文件代码(自己创建)
[wbyq@wbyq project]$ cat led/Makefile.amAUTOMAKE_OPTIONS=foreign #软件规范lib_ LTLIBRARIES =libled.la #生成的动态库文件(lib开头表示执行make installs时会一起发布,加noinst就不会一起发布)libled_la_SOURCES=led.c led.h #生成静态库需要的源文件。 格式:libkey_la_SOURCES --将原来的.换成_
  1. 顶层目录下的configure.ac 文件代码
1. 执行autoscan 命令生成configure.scan 文件2. 修改configure.scan 文件后缀为.ac或者.in3. 修改configure.ac 文件参数4. configure.ac文件代码如下:[wbyq@wbyq project]$ cat configure.ac# -- Autoconf --# Process this file with autoconf to produce a configure script.AC_PREREQ([2.63])AC_INIT([app], [1.2.3], [112662497@qq.com])AC_CONFIG_SRCDIR([user/main.c])AC_CONFIG_HEADERS([config.h])AM_INIT_AUTOMAKE(app,1.2.3)AC_PROG_LIBTOOL#使用动态库# Checks for programs.AC_PROG_CC# Checks for library functions.AC_OUTPUT(Makefileuser/Makefileled/Makefilekey/Makefile)
  1. 执行命令: aclocal\autoconf\autoheader

  2. 执行命令: libtoolize -f -c #共享库必须要执行

  3. automake --add-missing

  4. ./configure --prefix=$PWD/_install

  5. make && make install

  6. 在安装目录下的文件结果

十、自定义安装目录示例(make install)

格式:

wbyqdir=(prefix)/wbyq666wbyqDATA=(prefix)/wbyq_666wbyq_DATA=(top_srcdir)/666.c $(top_srcdir)/888.c

wbyq:表示是新的路径类型。

wbyq_666:表示在安装路径下创建的目录名称。

666.c、888.c :是执行make install 拷贝到wbyq_666目录下的文件。

十一、多级目录与函数的嵌套调用生成Makefile

[wbyq@wbyq project] cat main/main.c#include <stdio.h>#include "print.h"int main(){int a=123;int b=456;print(a,b);}[wbyq@wbyq project] cat sum/sum.h#ifndef _SUM_H#define _SUM_Hint sum(int,int);#endif[wbyq@wbyq project] cat sum/sum.c#include "sum.h"int sum(int a,int b){int c;c=sum(a,b);return c;}[wbyq@wbyq project] cat print/print.h#ifndef _PRINT_H#define _PRINT_H#include "sum.h"#include <stdio.h>void print(int,int);#endif[wbyq@wbyq project]$ cat print/print.c#include "print.h"void print(int a,int b){int c;c=sum(a,b);printf("%d\n",c);}

图11.1 C文件的调用关系图

[wbyq@wbyq project]autoscan[wbyq@wbyqproject] autoscan[wbyq@wbyq project] mv configure.scan configure.ac[wbyq@wbyq project]vimconfigure.ac[wbyq@wbyqproject] vim configure.ac[wbyq@wbyq project] cat configure.acAC_PREREQ([2.63])AC_INIT([app], [1.2.3], [112662497@qq.com])AC_CONFIG_SRCDIR([main/main.c])AC_CONFIG_HEADERS([config.h])AM_INIT_AUTOMAKE(app,1.2.3)AC_PROG_RANLIB #使用了静态库编译,需要此宏定义AC_PROG_CCAC_OUTPUT(Makefile main/Makefile print/Makefile sum/Makefile)[wbyq@wbyq project]aclocal[wbyq@wbyqproject] aclocal[wbyq@wbyq project] autoconf[wbyq@wbyq project]autoheader[wbyq@wbyqproject] autoheader[wbyq@wbyq project] vim Makefile.am[wbyq@wbyq project]catMakefile.amAUTOMAKEOPTIONS=foreignSUBDIRS=sumprintmain[wbyq@wbyqproject] cat Makefile.amAUTOMAKE_OPTIONS=foreignSUBDIRS= sum print main[wbyq@wbyq project] vim main/Makefile.am[wbyq@wbyq project]catmain/Makefile.amAUTOMAKEOPTIONS=foreignbinPROGRAMS=appappSOURCES=main.cappLDADD= cat main/Makefile.amAUTOMAKE_OPTIONS=foreignbin_PROGRAMS=appapp_SOURCES=main.capp_LDADD=(top_srcdir)/print/libprint.a (top_srcdir)/sum/libsum.a #顺序很重要INCLUDES=-I(top_srcdir)/print/ -I(topsrcdir)/sum/[wbyq@wbyqproject](top_srcdir)/sum/[wbyq@wbyq project] vim sum/Makefile.am[wbyq@wbyq project] cat sum/Makefile.amAUTOMAKE_OPTIONS=foreignlib_LIBRARIES=libsum.alibsum_a_SOURCES=sum.h sum.c[wbyq@wbyq project] vim print/Makefile.am[wbyq@wbyq project] cat print/Makefile.amAUTOMAKE_OPTIONS=foreignnoinst_LIBRARIES=libprint.alibprint_a_SOURCES=print.h print.c#print_a_LDADD=(top_srcdir)/sum/libsum.aINCLUDES=-I(topsrcdir)/sum[wbyq@wbyqproject](top_srcdir)/sum[wbyq@wbyq project] automake --add-missing[wbyq@wbyq project]./configureprefix= ./configure --prefix=PWD/_install[wbyq@wbyq project] make && make install[wbyq@wbyq project] tree _install/ -C_install/├── bin│   └── app└── lib├── libprint.a└── libsum.a2 directories, 3 files