提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
由于本人在参与测试工作中发现GUN autotool工具集在不少项目中出现如LTP (linux test project),所以决定做个分享对自己来说也是笔记。
一、autotools是什么?
GNU Autotools 是 Linux/Unix 世界中最经典的构建系统生成工具。它的核心目的是让你的代码可以在不同的 Unix 类系统上(Linux, BSD, macOS 等)自动配置并编译,在大型项目中有不少应用的案例,简而言之就是一个帮助跨平台且自动生成makefie的工具集合(注意是集合)。
1,工作流程
Developer writes
┌───────────────────────────────┐
│ configure.ac Makefile.am │
└───────────────┬───────────────┘
│
▼
(autoconf / automake)
│
┌─────────────────────────┐
│ configure Makefile.in │
└───────────────┬─────────┘
│
▼
./configure
│
▼
Generates:
┌──────────────┐
│ Makefile │
└──────────────┘
│
▼
make
如上流程图,
开发者写:configure.ac Makefile.am
|
执行 automake/autoconf(或执行 autoreconf -i)生成:
|
aclocal.m4 configure Makefile.in
|
用户执行:./configure --prefix=/usr
|
它会根据系统环境把 Makefile.in → MakefileMakefile.in → Makefile
然后make 执行器就根据makefile 执行编译操作。
二、作用
1:跨平台适配
很多项目在开发的时候往往是针对某一个平台比如arm,x86。但是类似LTP这样的大型项目往往是跨平台的各个平台的用例会上传到同一个仓库,这样会产生一些问题,比如某些测试程序(用例)往往只针对x86 这些程序在非x86平台无法运行如下:
#include <syscall.h>
pid_t tid = syscall(SYS_gettid);
SYS_gettid这个宏在非x86的头文件根本不存在,也没有必要编译。autotools工具集可以通过设置的头文件进行检查如果头文件不存在就跳过编译。还有别的一些类似的作用比如检测库版本、路径、函数是否存在、编译器语法、shell 功能等。
2,自动生成makefile
很多大型的项目,比如有个项目需要写非常多少程序,那他每添加一个文件夹和程序都需要手写makefile虽然可能大部分的内容是一样的,大部分是复制粘贴然后对应修改,累加起来也是不小的工作量,可以自动生成就节省人工成本。
3,检测功能
他拥有一些环境检测和文件检测的语法举例如下:
AC_CONFIG_SRCDIR([src/main.c])
上面的基本是检测文件是否纯在,并且在运行的时候能提示是否在当前项目的根目录。
总结如上autotool 工具集合其实就是makefile的一个二次封装基础上增加一些检测功能的动态生成器即可以根据环境自动生成makefile。
三,ac文件的基础语法
ac文件基本就是用与生成配置即选配检测项目(头文件、函数、结构体),生成config.h头文件。
am文件基本就用于生成makefile指定编译规则(不参与检测)。
1.ac初始化项目
在 M4 中,所有的字符串参数建议都用 [] 包裹,如下面案例
%%初始化项目宏
# 必须第一个调用
AC_INIT([myapp], [1.0], [bug@example.com])
这些简而言之是设置宏即固定变量的初始化,
AC_INIT(PACKAGE_NAME, PACKAGE_VERSION, BUG_REPORT) 即设置声明包名、版本、错误报告地址。
%%初始化码源
# 指定源码根文件(用于校验)
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_SRCDIR([src/main.c]) 检查文件是否存在,附带是否在项目文件夹执行config文件的检测。
2.函数和头文件等检查
%%库和头文件检查
AC_CONFIG_HEADERS([config.h]):显示指定配置文件,就是自动生成该文件,如上配置后大概有两种使用情况。
第一种情况判断是否编译整个文件,如下检测头文件等,然后转化为自定义的宏语句
某个项目config.ac文件
#检测头文件
AC_CHECK_HEADERS([sys/epoll.h])
AM_CONDITIONAL([HAVE_EPOLL], [test "x$ac_cv_header_sys_epoll_h" = "xyes"])
#检查函数
AC_CHECK_FUNCS([gettimeofday syscall])
...
# 配置文件头
AC_CONFIG_HEADERS([config.h])
AM_CONDITIONAL([HAVE_EPOLL], [test “x a c c v h e a d e r s y s e p o l l h " = " x y e s " ] ) : H A V E E P O L L 是自定义的宏名称,要与 a m 文件对应, t e s t " x ac_cv_header_sys_epoll_h" = "xyes"]) :HAVE_EPOLL是自定义的宏名称,要与am文件对应,test "x accvheadersysepollh"="xyes"]):HAVEEPOLL是自定义的宏名称,要与am文件对应,test"xac_cv_header_sys_epoll_h” = "xyes"指 shell的判断语句,格式是"x… = x…"等于if [ “x” = “xyes” ] ,转化后差不多是HAVE_EPOLL 1或者0变成一个shell的变量让make可以识别的到,am文件大致内容如下:
if HAVE_EPOLL
bin_PROGRAMS += test_syscall
test_syscall_SOURCES = test_syscall.c
endif
这样就可以通过这样方式判断这个文件是否需要编译,很多代码是为了跨平台可能需要编译不同源码这样就可以不需要手动修改makefile通过设置的头文件和函数来智能判断,如果对于动辄几百上千程序的项目非常友好,否者只能单独项目。
第二种情况是判断是否编译某些源码里面的内容。
如果同一个平台但是配置不同只是几个函数的区别,完全不必要用多个文件,这种情况无需AM_CONDITIONAL设置shell的宏变量,他会根据检测的文件名生成config.h的文件内容如下案例:
AC_CHECK_HEADERS([aaa/bbb.h])
#生成的宏:
HAVE_AAA_BBB_H
大致规则如下:
*** 将字符串全部转换为大写
*** /变成_
*** .会删除
然后源码上可以使用这些宏根据环境编译:
incloude <config.h>
#ifdef HAVE_AAA_BBB_H
#include <unistd.h>
#endif
int main() {
#ifdef HAVE_GETTIMEOFDAY
gettimeofday(...);
#else
printf("no gettimeofday\n");
#endif
}
一般要incloude<config.h>或者在am文件强制包含效果一致:
AM_CPPFLAGS = -include config.h
%% 程序检查宏
# 检查编译器
AC_PROG_CC # C 编译器
AC_PROG_CXX # C++ 编译器
AC_PROG_LEX # lex 词法分析器
AC_PROG_YACC # yacc 语法分析器
# 检查工具
AC_CHECK_PROG([PYTHON], [python3], [python3], [no])
AC_CHECK_PROGS([TAR], [gtar tar], [tar])
如果当前系统没有设置就会报错。
3.定义变量与输出 (AC_SUBST)
# 1. 定义 shell 变量
MY_CFLAGS="-O2 -g"
# 2. 导出变量,使其在 Makefile 中变成 $(MY_CFLAGS)
AC_SUBST([MY_CFLAGS])
类似AM_CONDITIONAL 转化为shell 命令,这样makefile可以使用
总结
如上大概是我对autotool工具集的理解和ac 语法的部分理解分享
1262

被折叠的 条评论
为什么被折叠?



