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

举报
DS小龙哥 发表于 2022/10/04 12:40:17 2022/10/04
【摘要】 linux环境下,当项目工程很大的时候,编译的过程很复杂,所以需要使用make工具,自动进行编译安装,但是手写makefile文件比较复杂,所幸在GNU的计划中,设计出了一种叫做Autoconf/Automake的工具,用来自动生成makefile文件,为编译和安装程序提供了一个方便快捷的入口。

一、前言

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就是这一类。

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

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

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

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

二、安装Automake工具

1. 先检查当前系统里是否安装了工具。

[wbyq@wbyq tmp]$ which autoscan

安装成功的提示:

[wbyq@wbyq tmp]$ which autoscan

/usr/bin/autoscan


2. 如果系统没有安装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=foreign

bin_PROGRAMS=app

app_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]$ ./configure

checking for a BSD-compatible install... /usr/bin/install -c

checking whether build environment is sane... yes

checking for a thread-safe mkdir -p... /bin/mkdir -p

checking for gawk... gawk

checking whether make sets $(MAKE)... yes

checking for gcc... gcc

checking for C compiler default output file name... a.out

checking whether the C compiler works... yes

checking whether we are cross compiling... no

checking for suffix of executables...

checking for suffix of object files... o

checking whether we are using the GNU C compiler... yes

checking whether gcc accepts -g... yes

checking for gcc option to accept ISO C89... none needed

checking for style of include used by make... GNU

checking dependency style of gcc... gcc3

checking how to run the C preprocessor... gcc -E

checking for grep that handles long lines and -e... /bin/grep

checking for egrep... /bin/grep -E

checking for ANSI C header files... yes

checking for sys/types.h... yes

checking for sys/stat.h... yes

checking for stdlib.h... yes

checking for string.h... yes

checking for memory.h... yes

checking for strings.h... yes

checking for inttypes.h... yes

checking for stdint.h... yes

checking for unistd.h... yes

checking for stdlib.h... (cached) yes

configure: creating ./config.status

config.status: creating Makefile

config.status: creating config.h

config.status: executing depfiles commands


3.10 使用Makefile编译,运行程序

[wbyq@wbyq tmp]$ make //编译程序

[wbyq@wbyq tmp]$ ./app 123 456 789 //运行程序

argv[0]=./app

argv[1]=123

argv[2]=456

argv[3]=789

3.11 Make支持的其他命令

[wbyq@wbyq app-1.1.2]$ make clean //清除目标文件

[wbyq@wbyq app-1.1.2]$ make dist //将源文件打包

[wbyq@wbyq app-1.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 as

VAR=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 specify

an 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 names


Optional 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 extractors


Some influential environment variables:

CC C compiler command

CFLAGS C compiler flags

LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a

nonstandard 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> if

you have headers in a nonstandard directory <include dir>

CPP C preprocessor


Use these variables to override the choices made by `configure' or to help

it 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/core

CURRENTPATH=$(shell /bin/pwd)

INCLUDES=-I$(CURRENTPATH)/src/include -I$(CURRENTPATH)/src/ModuleA/apple/include

export 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)/lib, datadir = $(prefix)/share, sysconfdir = $(prefix)/etc等等。

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

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

示例:

devicedir = ${prefix}/dev

device_DATA = package

package文件会作为数据文件安装到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=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。

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

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文件。

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

[wbyq@wbyq project]$ mv configure.scan configure.in

3. 修改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(Makefile

main/Makefile

sum/Makefile

print/Makefile)

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

5. 创建Makefile.am文件

[wbyq@wbyq project]$ touch Makefile.am

编辑内容如下:

AUTOMAKE_OPTIONS=foreign

SUBDIRS= print sum main #表示本目录的直接下级目录需要编译

#注意:顺序不能反,按照调用顺序来写。

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

EXTRA_DIST=doc/help.txt

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

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

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

AUTOMAKE_OPTIONS=foreign

bin_PROGRAMS=app #本目录的文件编译成可执行文件app

app_SOURCES=main.c

app_LDADD=$(top_srcdir)/sum/libsum.a $(top_srcdir)/print/libprint.a

INCLUDES=-I$(top_srcdir)/print/ -I$(top_srcdir)/sum

app_LDADD 指定需要的库文件

INCLUDES 指定需要的头文件

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

内容:

[wbyq@wbyq project]$ cat print/Makefile.am

AUTOMAKE_OPTIONS=foreign

noinst_LIBRARIES=libprint.a

libprint_a_SOURCES=print.h print.c

INCLUDES=-I$(top_srcdir)/sum

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

内容:

[wbyq@wbyq project]$ cat sum/Makefile.am

AUTOMAKE_OPTIONS=foreign

noinst_LIBRARIES=libsum.a

libsum_a_SOURCES=sum.h sum.c

7.6 编译

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

[wbyq@wbyq project]$./configure --prefix=$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");

}

调用关系图

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

[wbyq@wbyq project]$ cat Makefile.am

AUTOMAKE_OPTIONS=foreign #软件规范

SUBDIRS=led key user #执行本目录前,需要递归执行make的目录

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

[wbyq@wbyq project]$ cat user/Makefile.am

AUTOMAKE_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打包命令


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

[wbyq@wbyq project]$ cat key/Makefile.am

AUTOMAKE_OPTIONS=foreign #软件规范

lib_LIBRARIES=libkey.a #生成的静态库文件

libkey_a_SOURCES=key.c key.h #生成静态库需要的源文件。 格式:libkey_a_SOURCES --将原来的.换成_


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

[wbyq@wbyq project]$ cat led/Makefile.am

AUTOMAKE_OPTIONS=foreign #软件规范

lib_LIBRARIES=libled.a #生成的静态库文件(lib开头表示执行make installs时会一起发布,加noinst就不会一起发布)

libled_a_SOURCES=led.c led.h #生成静态库需要的源文件。 格式:libkey_a_SOURCES --将原来的.换成_


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

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

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

3. 修改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(Makefile

user/Makefile

led/Makefile

key/Makefile)


7. 执行命令: aclocal\autoconf\autoheader

8. automake --add-missing

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

10. make && make install

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


九、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");

}

调用关系图


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

[wbyq@wbyq project]$ cat Makefile.am

AUTOMAKE_OPTIONS=foreign #软件规范

SUBDIRS=led key user #执行本目录前,需要递归执行make的目录

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

[wbyq@wbyq project]$ cat user/Makefile.am

AUTOMAKE_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打包命令

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

[wbyq@wbyq project]$ cat key/Makefile.am

AUTOMAKE_OPTIONS=foreign #软件规范

lib_LTLIBRARIES=libkey.la #生成的动态库文件

libkey_la_SOURCES =key.c key.h #生成静态库需要的源文件。 格式:libkey_la_SOURCES --将原来的.换成_


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

[wbyq@wbyq project]$ cat led/Makefile.am

AUTOMAKE_OPTIONS=foreign #软件规范

lib_ LTLIBRARIES =libled.la #生成的动态库文件(lib开头表示执行make installs时会一起发布,加noinst就不会一起发布)

libled_la_SOURCES=led.c led.h #生成静态库需要的源文件。 格式:libkey_la_SOURCES --将原来的.换成_


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

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

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

3. 修改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(Makefile

user/Makefile

led/Makefile

key/Makefile)


7. 执行命令: aclocal\autoconf\autoheader

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

9. automake --add-missing

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

11. make && make install

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

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

格式:

wbyqdir=$(prefix)/wbyq_666

wbyq_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_H

int 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@wbyq project]$ mv configure.scan configure.ac

[wbyq@wbyq project]$ vim configure.ac

[wbyq@wbyq project]$ cat configure.ac

AC_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_CC

AC_OUTPUT(Makefile main/Makefile print/Makefile sum/Makefile)

[wbyq@wbyq project]$ aclocal

[wbyq@wbyq project]$ autoconf

[wbyq@wbyq project]$ autoheader

[wbyq@wbyq project]$ vim Makefile.am

[wbyq@wbyq project]$ cat Makefile.am

AUTOMAKE_OPTIONS=foreign

SUBDIRS= sum print main

[wbyq@wbyq project]$ vim main/Makefile.am

[wbyq@wbyq project]$ cat main/Makefile.am

AUTOMAKE_OPTIONS=foreign

bin_PROGRAMS=app

app_SOURCES=main.c

app_LDADD=$(top_srcdir)/print/libprint.a $(top_srcdir)/sum/libsum.a #顺序很重要

INCLUDES=-I$(top_srcdir)/print/ -I$(top_srcdir)/sum/

[wbyq@wbyq project]$ vim sum/Makefile.am

[wbyq@wbyq project]$ cat sum/Makefile.am

AUTOMAKE_OPTIONS=foreign

lib_LIBRARIES=libsum.a

libsum_a_SOURCES=sum.h sum.c

[wbyq@wbyq project]$ vim print/Makefile.am

[wbyq@wbyq project]$ cat print/Makefile.am

AUTOMAKE_OPTIONS=foreign

noinst_LIBRARIES=libprint.a

libprint_a_SOURCES=print.h print.c

#print_a_LDADD=$(top_srcdir)/sum/libsum.a

INCLUDES=-I$(top_srcdir)/sum

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

[wbyq@wbyq project]$ ./configure --prefix=$PWD/_install

[wbyq@wbyq project]$ make && make install

[wbyq@wbyq project]$ tree _install/ -C

_install/

├── bin

│   └── app

└── lib

├── libprint.a

└── libsum.a

2 directories, 3 files






【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。