automake构建工具使用

目录

https://cloud.tencent.com/developer/article/2142074

一、概述

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

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

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

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

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

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

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

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

二、安装

三、基本使用

 1graph TB;
 2source[源码root];
 3configure.scan;
 4configure.in;
 5aclocal.m4;
 6configure;
 7Makefile.am;
 8Makefile.in;
 9Makefile;
10start(开始)
11start2(开始)
12
13start2 --编程-->source;
14source --autoscan--> configure.scan;
15configure.scan --手动编辑--> configure.in;
16configure.in --aclocal--> aclocal.m4;
17configure.in --autoconf--> configure;
18aclocal.m4 --autoconf--> configure;
19start --手动创建--> Makefile.am
20Makefile.am --automake--> Makefile.in;
21configure.in --> Makefile.in;
22Makefile.in --> Makefile
23configure --> Makefile;

1.编写C代码文件

1vim app.c
 1#include <stdio.h>
 2#include <stdlib.h>
 3
 4int main(int argc, char **argv){
 5	int i;
 6	for(i=0; i<argc; i++){
 7		printf("argv[%d]=%s\n", i, argv[i]);
 8	}
 9	return 0;
10}

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

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

1autoscan
2ls
3mv configure.scan configure.ac

3.修改configure.ac文件参数

初始生成的configure.ac:

 1#                                               -*- Autoconf -*-
 2# Process this file with autoconf to produce a configure script.
 3
 4AC_PREREQ([2.71])
 5AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
 6AC_CONFIG_SRCDIR([app.c])
 7AC_CONFIG_HEADERS([config.h])
 8
 9# Checks for programs.
10AC_PROG_CC
11
12# Checks for libraries.
13
14# Checks for header files.
15
16# Checks for typedefs, structures, and compiler characteristics.
17
18# Checks for library functions.
19
20AC_OUTPUT

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

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

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

文件解释:

  • AC_PREREQ宏声明本文件要求的autoconf版本,本例使用的版本为2.71。

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

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

    1AC_INIT([app], [1.1.2], [[email protected]])
    
  • 在下面再自己添加一行AM_INIT_AUTOMAKE(),里面填入: 程序名字,版本号。

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

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

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

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

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

    1AC_OUTPUT(Makefile)
    

修改之后的configure.ac:

 1#                                               -*- Autoconf -*-
 2# Process this file with autoconf to produce a configure script.
 3
 4AC_PREREQ([2.71])
 5AC_INIT([app], [1.1.2], [[email protected]])
 6AM_INIT_AUTOMAKE(app,1.1.2)
 7AC_CONFIG_SRCDIR([app.c])
 8AC_CONFIG_HEADERS([config.h])
 9
10# Checks for programs.
11AC_PROG_CC
12
13# Checks for libraries.
14
15# Checks for header files.
16
17# Checks for typedefs, structures, and compiler characteristics.
18
19# Checks for library functions.
20
21AC_OUTPUT(Makefile)

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

1aclocal
2ls

5.使用autoconf工具生成configure文件

1autoconf
2ls

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

1autoheader

7.手工编辑Makefile.am文件

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

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

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

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

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

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

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

1touch Makefile.am
2vim Makefile.am
1AUTOMAKE_OPTIONS=foreign 
2bin_PROGRAMS=app 
3app_SOURCES=app.c

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

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

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

1automake

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

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

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

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

 1$./configure 
 2checking for a BSD-compatible install... /usr/bin/install -c
 3checking whether build environment is sane... yes
 4checking for a race-free mkdir -p... /usr/bin/mkdir -p
 5checking for gawk... gawk
 6checking whether make sets $(MAKE)... yes
 7checking whether make supports nested variables... yes
 8checking for gcc... gcc
 9checking whether the C compiler works... yes
10checking for C compiler default output file name... a.out
11checking for suffix of executables... 
12checking whether we are cross compiling... no
13checking for suffix of object files... o
14checking whether the compiler supports GNU C... yes
15checking whether gcc accepts -g... yes
16checking for gcc option to enable C11 features... none needed
17checking whether gcc understands -c and -o together... yes
18checking whether make supports the include directive... yes (GNU style)
19checking dependency style of gcc... gcc3
20checking that generated files are newer than configure... done
21configure: creating ./config.status
22config.status: creating Makefile
23config.status: creating config.h
24config.status: executing depfiles commands

10.使用Makefile编译,运行程序

 1$make
 2make  all-am
 3make[1]: 进入目录“/home/zhaoxiaoqi/code/c/test-automake”
 4gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT app.o -MD -MP -MF .deps/app.Tpo -c -o app.o app.c
 5mv -f .deps/app.Tpo .deps/app.Po
 6gcc  -g -O2   -o app app.o  
 7make[1]: 离开目录“/home/zhaoxiaoqi/code/c/test-automake”
 8
 9$./app 1 2 3
10argv[0]=./app
11argv[1]=1
12argv[2]=2
13argv[3]=3

11.Make支持的其他命令

1#清除目标文件
2make clean 
3#将源文件打包
4make dist
5#编译源文件生成目标文件
6make
7#将目标文件拷贝到指定目录下
8make install

四、configure文件详解

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

现在目录下有main.c, print.c, sum.c三个c文件,config.h,sum.h两个头文件

修改Makefile.am内容:

1AUTOMAKE_OPTIONS=foreign 
2bin_PROGRAMS=app 
3app_SOURCES=main.c print.c sum.c

六、Makefile.am格式详解

Makefile.am中可用的全局变量

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

例:

1SUBDIRS=src/lib src/ModuleA/apple/shell src/ModuleA/apple/core 
2CURRENTPATH=$(shell /bin/pwd) 
3INCLUDES=-I $(CURRENTPATH)/src/include -I $(CURRENTPATH)/src/ModuleA/apple/include 
4export INCLUDES

Makefile.am中可用的路径变量

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

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

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

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

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

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

例:

1devicedir = ${prefix}/dev 
2device_DATA = package 
3#package文件会作为数据文件安装到dev目录之下这相当于定义了一种安装类型devicedir所以想怎么安装就怎么安装后面的XXXXXdirdir是固定不变的

Makefile.am一般格式

PROGRAMS。表示可执行文件

LIBRARIES。表示静态库文件

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

HEADERS。头文件。

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

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

文件类型 书写格式 示例
软件规范 AUTOMAKE_OPTIONS=foreign 有三个候选项: foreign(国外),gnu(GNU),gnits 如果使用foreign等级,它只检测必须的文
可执行文件 bin_PROGRAMS=foo
foo_SOURCES=xxx.c
foo_LDADD=
foo_LDFLAGS=
foo_DEPENDENCIES=
bin_PROGRAMS=foo (设置可执行文件的名称) 如果可执行文件的名称为foo,后面的代码前缀,都需要填foo
静态库 lib_LIBRARIES=libfoo.a
foo_a_SOURCES=
foo_a_LDADD=
foo_a_LIBADD=
foo_a_LDFLAGS=
如果程序里使用了静态库编译,需要在configure.ac文件里增加以下宏定义代码 AC_PROG_RANLIB
动态库 lib_LTLIBRARIES=libfoo.la
foo_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。

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

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

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

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

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

 1$tree -C
 2.
 3├── main
 4│   └── main.c
 5├── print
 6│   ├── print.c
 7│   └── print.h
 8└── sum
 9    ├── sum.c
10    └── sum.h

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

2.project顶层目录下的操作过程

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

    1autoscan
    
  2. 将configure.scan改名成configure.in (早期in, 现在常用.ac)

    1mv configure.scan configure.in
    
  3. 修改configure.in

     1[wbyq@wbyq project]$ cat configure.in 
     2# -*- Autoconf -*- 
     3# Process this file with autoconf to produce a configure script.  
     4   
     5AC_PREREQ([2.63]) 
     6AC_INIT([app], [1.2.3], [[email protected]]) 
     7AC_CONFIG_SRCDIR([main/main.c]) 
     8AC_CONFIG_HEADERS([config.h]) 
     9AM_INIT_AUTOMAKE(app,1.2.3) 
    10AC_PROG_RANLIB #使用了静态库编译,需要此宏定义 
    11   
    12# Checks for programs. AC_PROG_CC  
    13   
    14# Checks for libraries.  
    15   
    16# Checks for header files.  
    17   
    18# Checks for typedefs, structures, and compiler characteristics.  
    19   
    20# Checks for library functions.  
    21   
    22   
    23AC_OUTPUT(Makefile 
    24       main/Makefile 
    25       sum/Makefile 
    26       print/Makefile)
    
  4. 分别执行aclocal、autoconf、autoheader命令

    1ls
    2aclocal
    3ls
    4autoconf
    5ls
    
  5. 创建Makefile.am文件

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

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

    1EXTRA_DIST=doc/help.txt
    

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

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

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

1AUTOMAKE_OPTIONS=foreign 
2bin_PROGRAMS=app #本目录的文件编译成可执行文件app 
3app_SOURCES=main.c 
4app_LDADD=$(top_srcdir)/sum/libsum.a $(top_srcdir)/print/libprint.a 
5INCLUDES=-I$(top_srcdir)/print/ -I$(top_srcdir)/sum

app_LDADD 指定需要的库文件

INCLUDES 指定需要的头文件

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

1[wbyq@wbyq project]$ cat print/Makefile.am 
2AUTOMAKE_OPTIONS=foreign 
3noinst_LIBRARIES=libprint.a 
4libprint_a_SOURCES=print.h print.c 
5INCLUDES=-I$(top_srcdir)/sum

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

1[wbyq@wbyq project]$ cat sum/Makefile.am 
2AUTOMAKE_OPTIONS=foreign 
3noinst_LIBRARIES=libsum.a 
4libsum_a_SOURCES=sum.h sum.c

6.编译

1[wbyq@wbyq project]$ automake --add-missing 
2[wbyq@wbyq project]$./configure --prefix=$PWD/_install 
3[wbyq@wbyq project]$ make 
4[wbyq@wbyq project]$ make install

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

目录结构

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

 1$tree -C
 2.
 3├── key
 4│   ├── key.c
 5│   ├── key.h
 6│   └── Makefile.am
 7├── led
 8│   ├── led.c
 9│   ├── led.h
10│   └── Makefile.am
11├── Makefile.am
12└── user
13    ├── main.c
14    └── Makefile.am

main.c:

1#include <stdio.h> 
2#include "key.h" 
3#include "led.h" 
4
5int main(char argc,char **argv) { 
6	led_init(); key_init(); 
7	return 0; 
8}

led.c:

1 #include "led.h" 
2 
3 void led_init(void) { 
4 	printf("led_init\n"); 
5 }

led.h:

1#ifndef LED_H 
2#define LED_H 
3
4#include <stdio.h> 
5void led_init(void); 
6
7#endif  

key.c:

1#include "key.h" 
2#include "led.h" 
3
4void key_init(void) { 
5	led_init(); 
6	printf("key_init\n"); 
7}

key.h:

1#ifndef KEY_H 
2#define KEY_H 
3#include <stdio.h> 
4void key_init(void); 
5#endif 

调用关系图:

1graph LR;
2main.c --> led.c & key.c;
3key.c --> led.c;
4

顶层Makefile.am文件代码(自己创建)

1AUTOMAKE_OPTIONS=foreign #软件规范 
2SUBDIRS=led key user #执行本目录前,需要递归执行make的目录

user/Makefile.am文件代码(自己创建)

1AUTOMAKE_OPTIONS=foreign #软件规范 
2bin_PROGRAMS=app #可执行文件名称 
3app_SOURCES=main.c #可执行需要的源文件 
4app_LDADD=$(top_srcdir)/led/libled.a $(top_srcdir)/key/libkey.a #可执行文件需要的库文件 
5INCLUDES=-I$(top_srcdir)/led -I$(top_srcdir)/key #编译需要的头文件 EXTRA_DIST=$(top_srcdir)/led/led.h $(top_srcdir)/key/key.h #打包时需要额外添加的文件 
6#make dist打包命令

key/Makefile.am文件代码(自己创建)

1AUTOMAKE_OPTIONS=foreign #软件规范 
2lib_LIBRARIES=libkey.a #生成的静态库文件 
3libkey_a_SOURCES=key.c key.h #生成静态库需要的源文件。 格式:libkey_a_SOURCES --将原来的.换成_
4key_a_LDADD=$(top_srcdir)/led/libled.a
5INCLUDES=-I$(top_srcdir)/led

led/Makefile.am文件代码(自己创建)

1AUTOMAKE_OPTIONS=foreign #软件规范 
2lib_LIBRARIES=libled.a #生成的静态库文件(lib开头表示执行make installs时会一起发布,加noinst就不会一起发布) 
3libled_a_SOURCES=led.c led.h #生成静态库需要的源文件。 格式:libkey_a_SOURCES --将原来的.换成_

顶层目录下的configure.ac 文件代码

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

  2. 修改configure.scan 文件后缀为.ac或者.in

  3. 修改configure.ac 文件参数

  4. configure.ac文件代码如下:

     1# -*- Autoconf -*- 
     2# Process this file with autoconf to  produce a configure script.  
     3   
     4AC_PREREQ([2.63]) 
     5AC_INIT([app], [1.2.3],  [[email protected]]) 
     6AC_CONFIG_SRCDIR([user/main.c])  
     7AC_CONFIG_HEADERS([config.h]) 
     8AM_INIT_AUTOMAKE(app,1.2.3) 
     9AC_PROG_RANLIB #表示使用静态库 
    10# Checks for programs. 
    11AC_PROG_CC 
    12# Checks for library  functions.  
    13AC_OUTPUT(Makefile user/Makefile led/Makefile key/Makefile)
    
  5. aclocal

  6. autoconf

  7. autoheader

  8. automake –add-missing

  9. ./configure –prefix=$PWD/_install

  10. make && make install

  11. tree _install/ -C

    1_install/
    2├── bin
    3│   └── app
    4└── lib
    5    ├── libkey.a
    6    └── libled.a
    7    
    83 directories, 3 files
    

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

目录结构

与八的一模一样。

顶层Makefile.am文件代码(自己创建)

1AUTOMAKE_OPTIONS=foreign #软件规范 
2SUBDIRS=led key user #执行本目录前,需要递归执行make的目录

user/Makefile.am文件代码(自己创建)

和八对比文件名有所变化。从.a变成了.la。

1AUTOMAKE_OPTIONS=foreign #软件规范 
2bin_PROGRAMS=app #可执行文件名称 
3app_SOURCES=main.c #可执行需要的源文件 
4app_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打包命令

key/Makefile.am文件代码(自己创建)

1AUTOMAKE_OPTIONS=foreign #软件规范 
2lib_LTLIBRARIES=libkey.la #生成的动态库文件 
3libkey_la_SOURCES =key.c key.h #生成静态库需要的源文件。 格式:libkey_la_SOURCES --将原来的.换成_
4key_a_LDADD=$(top_srcdir)/led/libled.la
5INCLUDES=-I$(top_srcdir)/led

led/Makefile.am文件代码(自己创建)

1AUTOMAKE_OPTIONS=foreign #软件规范 
2lib_ LTLIBRARIES =libled.la #生成的动态库文件(lib开头表示执行make installs时会一起发布,加noinst就不会一起发布) 
3libled_la_SOURCES=led.c led.h #生成静态库需要的源文件。 格式:libkey_la_SOURCES --将原来的.换成_

顶层目录下的configure.ac 文件代码

  • autoscan

  • mv configure.scan configure.ac

  • vim configure.ac

    八使用的是AC_PROG_RANLIB #表示使用静态库

     1# -*- Autoconf -*- 
     2# Process this file with autoconf to produce a configure script.  
     3AC_PREREQ([2.63]) 
     4AC_INIT([app], [1.2.3], [[email protected]]) 
     5AC_CONFIG_SRCDIR([user/main.c]) 
     6AC_CONFIG_HEADERS([config.h]) 
     7AM_INIT_AUTOMAKE(app,1.2.3) 
     8AC_PROG_LIBTOOL#使用动态库 
     9  
    10# Checks for programs. 
    11AC_PROG_CC 
    12# Checks for library functions.  
    13AC_OUTPUT(Makefile user/Makefile led/Makefile key/Makefile)
    
  • aclocal\autoconf\autoheader

  • libtoolize -f -c #共享库必须要执行

  • automake –add-missing

  • ./configure –prefix=$PWD/_install

  • make && make install

  • tree -C

    1  
    

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

1wbyqdir=$(prefix)/wbyq_666 
2wbyq_DATA=$(top_srcdir)/666.c $(top_srcdir)/888.c

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

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

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

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

C文件及调用关系图

main/main.c:

1#include <stdio.h> 
2#include "print.h" 
3
4int main() { 
5	int a=123; 
6	int b=456; 
7	print(a,b); 
8} 

sum/sum.h:

1#ifndef _SUM_H 
2#define _SUM_H 
3int sum(int,int); 
4#endif

sum/sum.c:

1#include "sum.h" 
2
3int sum(int a,int b) { 
4	int c; 
5	c=a+b;
6	return c; 
7} 

print/print.h:

1#ifndef _PRINT_H 
2#define _PRINT_H 
3#include "sum.h" 
4#include <stdio.h> 
5void print(int,int); 
6#endif 

print/print.c:

1#include "print.h" 
2
3void print(int a,int b) { 
4	int c; 
5	c=sum(a,b); 
6	printf("%d\n",c); 
7}
1graph LR;
2	main.c --> print.c;
3	print.c --> sum.c;

automake操作

  1. autoscan

  2. mv configure.scan configure.ac

  3. vim configure.ac

  4. cat configure.ac

     1AC_PREREQ([2.63]) 
     2AC_INIT([app], [1.2.3], [[email protected]]) 
     3AC_CONFIG_SRCDIR([main/main.c]) 
     4AC_CONFIG_HEADERS([config.h]) 
     5AM_INIT_AUTOMAKE(app,1.2.3) 
     6AC_PROG_RANLIB #使用了静态库编译,需要此宏定义 
     7AC_PROG_CC AC_OUTPUT(Makefile 
     8                  main/Makefile 
     9                  print/Makefile 
    10                  sum/Makefile) 
    
  5. aclocal

  6. autoconf

  7. autoheader

  8. vim Makefile.am

  9. cat Makefile.am

    1AUTOMAKE_OPTIONS=foreign 
    2SUBDIRS= sum print main  #顺序
    
  10. vim main/Makefile.am

  11. cat main/Makefile.am

    1AUTOMAKE_OPTIONS=foreign 
    2bin_PROGRAMS=app 
    3app_SOURCES=main.c 
    4app_LDADD=$(top_srcdir)/print/libprint.a $(top_srcdir)/sum/libsum.a #顺序很重要 
    5INCLUDES=-I$(top_srcdir)/print/ -I$(top_srcdir)/sum/
    
  12. vim sum/Makefile.am

  13. cat sum/Makefile.am

    1AUTOMAKE_OPTIONS=foreign 
    2lib_LIBRARIES=libsum.a 
    3libsum_a_SOURCES=sum.h sum.c
    
  14. vim print/Makefile.am

  15. cat print/Makefile.am

    1AUTOMAKE_OPTIONS=foreign 
    2noinst_LIBRARIES=libprint.a 
    3libprint_a_SOURCES=print.h print.c 
    4#重要
    5print_a_LDADD=$(top_srcdir)/sum/libsum.a 
    6INCLUDES=-I$(top_srcdir)/sum
    
  16. automake –add-misiing

  17. ./configure –prefix=$PWD/_install

  18. make && make install

  19. tree _install

    1├── bin │   
    2        └── app 
    3└── lib 
    4	├── libprint.a 
    5	└── libsum.a