Autoconf 配置文件
Autoconf
是一个用于生成 shell 脚本的工具,可自动配置源码包以适应多种类 Posix 的系统, 产生的配置脚本通常叫做 configure
。 对于与 Autoconf
一起使用的每个软件包,它会从模板文件创建一个配置脚本, 其中列出了该软件包需要或可以使用的系统功能。
使用 automake
工具,程序开发人员只需要写一些简单的含有预定义宏的文件, 便可由 autoconf
根据该文件生成 configure
文件, 由 automake
工具根据另一个宏文件生成 Makefile.in
文件, 再使用 configure
文件依据 Makefile.in
来生成一个符合惯例的 Makefile
文件。
使用 autoconf
工具的最终目的是生成能够根据不同系统生成 Makefile
所需的 configure
文件。 一般情况下我们需要准备如下内容:
- 软件源代码
- configure.ac
- Makefile.am
然后通过如下一系列命令可以生成 configure
文件:
aclocal; autoconf; autoheadr; automake --add-missing
在调用上述命令前,应先使用 autoscan
扫描源码目录寻找一般的可移植性问题, 生成 configure.scan
文件。 经过人工确认并修改后缀后,形成 configure.ac
文件。 其中包含对 Autoconf
内置宏的调用,这些宏用于测试软件包需要或可以使用的系统功能。 对于大多数功能,Autoconf
模板宏会生成自定义检查规则; 对于一些无法自动检查的特殊功能,configure.ac
需要包含一些手工检查配置。
configure.ac
脚本还需要一些关于如何进行初始化的指导性信息, 诸如如何寻找包的源文件信息、如何获得 configure
的输入、输出信息。
configure.ac
在做任何其他事情之前需要调用 AC_INIT
宏,来处理所有命令参数并且寻找源代码目录。
对于需要手工配置的项目来说,需要通过调用 AC_CONFIG_AUX_DIR
来告诉 configure.ac
到哪里去寻找一些其他的 shell 脚本。
Autoconf
生成的配置脚本 configure
可以根据系统类型或目标三元组的规范名称确定软件包的目标硬件架构平台, 其格式为:cpu-vendor-os
。 configure
通常可以通过运行一个名为 config.guess
的脚本文件来推测目标架构类型的规范名称。
用户也可以使用自定义的命令行参数指定系统类型:
--build=build-type
:目标架构类型。默认值为config.guess
脚本的运行结果。 指定不同于宿主机的架构类型将启用交叉编译模式。如果指定了该参数,则会覆盖config.guess
的推测结果, 取而代之的是用户给出的信息,并会调用config.sub
对用户给出的信息进行规范化,规范化结果为cpu-vendor-os
的形式。--host=host-type
:宿主机的架构类型。默认情况下,它与正在编译构建软件包的设备架构相同。--target=target-type
:目标架构类型(通常不使用)。默认情况下,它与宿主机的架构类型相同。
宏 AC_CONFIG_AUX_DIR(dir)
的目录 dir
中使用 config.guess
、config.sub
、 install.sh
、pkg.m4
配置脚本,他们是配置中使用的辅助文件。
config.guess
:configure 通过该脚本推测出它正在运行的系统类型的规范名, 该脚本使用uname
或者预定义的 C 预处理器符号来推断系统类型的规范名。config.sub
:configure 通过该脚本对用户给出的关于主机、目标等任何别名进行规范化。
因此,autoconf 配置文件中与架构相关的原因可以归为以下两类:
推断系统类型的规范名列表是否已包含目标架构
推断系统类型的规范名主要有两个步骤:
- 通过
uname
获取UNAME_MACHINE
(主机硬件架构名称)、UNAME_RELEASE
(操作系统发行版本)、UNAME_SYSTEM
(操作系统名称)、UNAME_VERSION
(操作系统版本号)。 - 根据以上四个信息用 switch-case 语句推断系统类型规范名
示例 openjdk-1.8.0 推断系统类型的规范名
- 项目名称:openjdk-1.8.0
- 项目版本:git#2805c1c367878ef4fea8e909367d64cd166258f6
- 相关文件:
- 简介:openjdk-1.8.0 通过
autoconf-config.guess
和config.guess
两个文件共同推断系统类型的规范名, 其中config.guess
对autoconf-config.guess
推断的规范名结果进行进一步的筛选。
通过 uname
系统命令获取系统架构相关信息:
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
推断系统类型规范名示例:
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
...
# other systems with GNU libc and userland
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
...
为了适配 RISC-V 架构,需要增加以下获取规范名的代码:
riscv64:Linux:*:*)
echo riscv64-unknown-linux-gnu
exit ;;
是否支持规范化目标架构的任何别名
规范化用户给出的主机、目标等信息的任何别名主要有以下两个步骤:
- 分析命令行参数,从参数中提取出用户给出的包含主机信息的参数
- 从指定的参数值中,筛选出操作系统、架构信息,并对信息进行规范化处理
示例 openjdk-1.8.0 规范化用户给出的主机、目标等信息的任何别名
- 项目名称:openjdk-1.8.0
- 项目版本:git#2805c1c367878ef4fea8e909367d64cd166258f6
- 相关文件:
- 简介:openjdk-1.8.0 通过
autoconf-config.sub
和config.sub
两个文件共同规范化信息, 其中config.sub
对autoconf-config.sub
规范化的结果进行进一步的筛选。
分析命令行指令:
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help"
exit 1 ;;
*local*)
# First pass through any local machine types.
echo $1
exit ;;
* )
break ;;
esac
done
提取出用户给出的包含 KERNEL-OS
格式的信息:
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
then os=`echo $1 | sed 's/.*-/-/'`
else os=; fi
;;
esac
识别架构类型并规范化处理:
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| bfin \
...
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
| z8k)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-unknown
;;
在此部分添加对 RISC-V 架构判断的代码:
| riscv32 | riscv64 \
| riscv32-* | riscv64-* \