一样新的东西的由来,往往因为之前的东西用的很不爽,然后更具弊端创造出更加容易使用的东西,比如在大型的项目中,如Linux,他是通过Makefile的方式进行编译。但是,Makefile复杂的语法结构,难于让人领会。在一个很大的项目中,维护Makefile是一个非常头疼的烦恼事。于是一个新的产物Autotools就出来了,他用来生成复杂的Makefile,很大程度降低了我们的开发难度。
Autotools并不是单独一个工具,而是一系列工具:
- autoscan
- aclocal
- autoconf
- autoheader
- automake
autotools提供的这一系列工具,最终的目的就是生成Makefile,这个Makefile是自动生成的。
首先我们创建一个测试代码main.c,通过简单的例子来说明autotools的使用流程,源文件内容如下:
代码语言:javascript复制#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Rice Autotools!!!n");
return 0;
}
- autoscan工具: 执行autoscan命令,该命令主要用于扫描工作目录,并生成configure.scan文件。然后将configure.scan文件重新命名成configure.ac,然后对这个文件进行配置。这样我们才能执行以下的命令。
rice@rice:~/rice-autotools$ autoscan
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/${ <-- HERE [^}]*}/ at /usr/bin/autoscan line 361.
rice@rice:~/rice-autotools$ ls
autoscan.log configure.scan main.c
rice@rice:~/rice-autotools$ mv configure.scan configure.ac
rice@rice:~/rice-autotools$ ls
autoscan.log configure.scan main.c
rice@rice:~/rice-autotools$
configure.ac的文件内容:
代码语言:javascript复制# -*- 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_CONFIG_SRCDIR([main.c])
AC_CONFIG_HEADERS([config.h])
# 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
我们将其修改为下面的内容:
代码语言:javascript复制# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT(rice, 1.0, 980307037@qq.com)
AM_INIT_AUTOMAKE(rice, 1.0)
AC_CONFIG_SRCDIR([main.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
AC_CHECK_HEADERS([stdlib.h])
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
其中configure.ac的标签说明:
标签 | 说明 |
---|---|
AC_PREREQ | 声明autoconf要求的版本号 |
AC_INIT | 定义软件名称、版本号、联系方式 |
AM_INIT_AUTOMAKE | 必须要的,参数为软件名称和版本号 |
AC_CONFIG_SCRDIR | 宏用来侦测所指定的源码文件是否存在, 来确定源码目录的有效性.。此处为当前目录下main.c。 |
AC_CONFIG_HEADER | 宏用于生成config.h文件,以便 autoheader 命令使用。 |
AC_PROG_CC | 指定编译器,默认GCC |
AC_CONFIG_FILES | 生成相应的Makefile文件,不同文件夹下的Makefile通过空格分隔。例如:AC_CONFIG_FILES([Makefile, src/Makefile]) |
AC_OUTPUT | 用来设定 configure 所要产生的文件,如果是makefile,configure 会把它检查出来的结果带入makefile.in文件产生合适的makefile。 |
- aclocal工具: 执行aclocal命令。扫描 configure.ac 文件生成 aclocal.m4文件, 该文件主要处理本地的宏定义,它根据已经安装的宏、用户定义宏和 acinclude.m4文件中的宏将configure.ac文件需要的宏集中定义到文件 aclocal.m4 中。
rice@rice:~/rice-autotools$ aclocal
rice@rice:~/rice-autotools$ ls
aclocal.m4 autom4te.cache autoscan.log configure.ac main.c
rice@rice:~/rice-autotools$
- autoconf工具: 执行autoconf命令。此命令将configure.ac文件中的宏展开,生成configure脚本。这个过程可能会用到aclocal.m4中定义的宏。
rice@rice:~/rice-autotools$ autoconf
rice@rice:~/rice-autotools$ ls
aclocal.m4 autom4te.cache autoscan.log configure configure.ac main.c
rice@rice:~/rice-autotools$
- autoheader工具: 执行autoheader命令。该命令生成 config.h.in 文件。该命令通常会从 "acconfig.h” 文件中复制用户附加的符号定义。该例子中没有附加的符号定义, 所以不需要创建 "acconfig.h” 文件。
rice@rice:~/rice-autotools$ autoheader
rice@rice:~/rice-autotools$ ls
aclocal.m4 autom4te.cache autoscan.log config.h.in configure configure.ac main.c
rice@rice:~/rice-autotools$
- 创建Makefile.am: 创建Makefile.am文件。Automake工具会根据configure.in中的参量把Makefile.am转换成Makefile.in文件。最终通过Makefile.in生成Makefile文件,所以Makefile.am这个文件非常重要,定义了一些生成Makefile的规则 。
Makefile.am文件内容:
代码语言:javascript复制AUTOMARK_OPTIONS = foreign
bin_PROGRAMS = rice
rice_SOURCES = main.c
- AUTOMAKE_OPTIONS:由于GNU对自己发布的软件有严格的规范, 比如必须附带许可证声明文件COPYING等,否则automake执行时会报错. automake提供了3中软件等级:foreign, gnu和gnits, 供用户选择。默认级别是gnu. 在本例中, 使用了foreign等级, 它只检测必须的文件。
- bin_PROGRAMS = rice:生成的可执行文件名称,生成多个可执行文件,可以用空格隔开。
- rice_SOURCES:生成可执行文件rice需要依赖的源文件。其中rice_为可执行文件的名称。
- automake工具: 执行automake命令。该命令生成Makefile.in文件。使用选项"--add-missing" 可以让Automake自动添加一些必需的脚本文件。如果发现一些文件不存在(NEWS,README,AUTHORS,ChangLog),可以通过手工 touch命令创建。
rice@rice:~/rice-autotools$ automake --add-missing
configure.ac:6: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see:
configure.ac:6: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
configure.ac:11: installing './compile'
configure.ac:6: installing './install-sh'
configure.ac:6: installing './missing'
Makefile.am: installing './INSTALL'
Makefile.am: error: required file './NEWS' not found
Makefile.am: error: required file './README' not found
Makefile.am: error: required file './AUTHORS' not found
Makefile.am: error: required file './ChangeLog' not found
Makefile.am: installing './COPYING' using GNU General Public License v3 file
Makefile.am: Consider adding the COPYING file to the version control system
Makefile.am: for your code, to avoid questions about which license your project uses
Makefile.am: installing './depcomp'
rice@rice:~/rice-autotools$ touch NEWS
rice@rice:~/rice-autotools$ touch README
rice@rice:~/rice-autotools$ touch AUTHORS
rice@rice:~/rice-autotools$ touch ChangeLog
rice@rice:~/rice-autotools$ ls
aclocal.m4 autom4te.cache ChangeLog config.h.in configure.ac depcomp install-sh Makefile.am NEWS
AUTHORS autoscan.log compile configure COPYING INSTALL main.c missing README
rice@rice:~/rice-autotools$ automake --add-missing
configure.ac:6: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see:
configure.ac:6: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
rice@rice:~/rice-autotools$
- configure命令: 执行./configure脚本。把Makefile.in变成最终的Makefile文件。configure会把一些配置参数配置到Makefile文件里面。
rice@rice:~/rice-autotools$ ./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 whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
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 whether gcc understands -c and -o together... yes
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
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
rice@rice:~/rice-autotools$ ls
aclocal.m4 autoscan.log config.h config.status COPYING install-sh Makefile.am NEWS
AUTHORS ChangeLog config.h.in configure depcomp main.c Makefile.in README
autom4te.cache compile config.log configure.ac INSTALL Makefile missing stamp-h1
rice@rice:~/rice-autotools$
- make命令: 执行make命令。生成可执行文件rice。并执行可执行文件,查看结果。
rice@rice:~/rice-autotools$ make
make all-am
make[1]: Entering directory '/home/tym/rice-autotools/temp'
gcc -DHAVE_CONFIG_H -I. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
mv -f .deps/main.Tpo .deps/main.Po
gcc -g -O2 -o rice main.o
make[1]: Leaving directory '/home/tym/rice-autotools/temp'
rice@rice:~/rice-autotools$ ./rice
Rice Autotools!!!
rice@rice:~/rice-autotools$
上述的内容是在ubuntu上进行操作的,接下来我们说说如何在arm架构的板子进行运行。由于我目前的系统构建环境是基于Yocto上的。所以我这里直接以Yocto进行说明。
在Yocto工程创建自己的recipe。这里我随便找了一个地方放我的recipe进行演示。创建files目录和rice-autotools_git.bb文件。然后将上面我们利用autotools工具得到的内容拷贝到files目录下。如下:
代码语言:javascript复制rice@rice:~/yocto/poky/meta-sdk/recipes-connectivity/rice-autotools$ tree
.
├── files
│ ├── AUTHORS
│ ├── ChangeLog
│ ├── configure.ac
│ ├── main.c
│ ├── Makefile.am
│ ├── NEWS
│ └── README
└── rice-autotools_git.bb
1 directory, 9 files
ice@rice:~/yocto/poky/meta-sdk/recipes-connectivity/rice-autotools$
为了方便我们操作,我们将files文件的内容进行压缩。如下:
代码语言:javascript复制rice@rice:~/yocto/poky/meta-sdk/recipes-connectivity/rice-autotools$ tar -cvzf rice-autotools.tgz .
./
./.deps/
./.deps/main.Po
./ChangeLog
./NEWS
./AUTHORS
./Makefile.am
./main.c
./README
./configure.ac
tar: .: file changed as we read it
rice@rice:~/yocto/poky/meta-sdk/recipes-connectivity/rice-autotools$ ls
AUTHORS ChangeLog configure.ac main.c Makefile.am NEWS README rice-autotools.tgz
rice@rice:~/yocto/poky/meta-sdk/recipes-connectivity/rice-autotools$
rice-autotools_git.bb文件:内容如下:
代码语言:javascript复制SMMARY = "Rice Autotools Test"
LICENSE = "CLOSED"
SRC_URI = "file://rice-autotools.tgz"
S = "${WORKDIR}"
do_install() {
install -d ${D}/usr/bin
install -m 0755 ${WORKDIR}/rice -D ${D}/usr/bin/
}
inherit autotools
- SRC_URI:源包下载URI,其中我们这里指向files目录的rice-autotools.tgz。这也就是我们上面为什么要压缩的原因。不然你要一个文件一个文件的指向。
- S:到Bitbake放置以解压文件所在目录的完整路径。
- do_install():将我们编译完的源文件放进板子的根文件系统目录中。
- inherit:继承。这里继承autotools。
然后我们在Yocto进行编译,然后将镜像烧录到板子上。运行结果:
代码语言:javascript复制/ # rice
Rice Autotools!!!
/ #