automake详解

合集下载

automake的教程

automake的教程

转一个automake的教程2008年06月24日星期二下午 03:03使用 GNU autotools 改造一个软件项目本文不是一篇规范的教程,而是用一个软件项目作为例子,演示使用 GNU autotools 进行软件管理的思路和过程目录· 示例项目· 软件布局· Makefile 分析· GNU 的软件风格· 准备 autotools· 改造文件布局· autoscan· configure.ac 的基本结构· Makefile 文件的产生· 编写 Makefile.am软件根目录 Makefile.amsrc/Makefile.amdata/Makefile.amdocs/Makefile.amfonts/Makefile.amimages/Makefile.ammusic/Makefile.amsound/Makefile.am· 运行 autotools· SDL 库的侦测· 软件使用的数据文件· configure 选项· autotools 脚本· 使用 configure 产生的 Makefile· 最终的 configure.ac 文件· 结束语示例项目这里借用了 Wei Mingzhi <whistler_wmz@> 开发的麻将游戏来进行演示,在此,先对他表示感谢!示例软件下载:软件布局将下载的软件包解压到一个目录$ cd ~/work$ tar xjf mahjong.tar.bz2可以看到这是一个典型的 Windows 风格的软件项目布局,在 mahjong 目录下放着程序的源码,程序运行时使用的数据文件放在子目录下面作者还提供了一个 Makefile,一个 DOS 风格的 !play.bat 批处理文件,一个编译好的mj.exe 可执行文件在 Win32 平台上运行 !play.bat 就可以直接运行程序在Unix/Linux 系统上,进入 mahjong 目录,键入 make 命令,如果一切顺利的话,将生成 mj 可执行文件,然后在命令行上运行 ./mj 程序,也可以启动麻将游戏对于一个 Windows 程序来讲,该软件布局可以说非常清晰明了但在 Unix/Linux 系统上,执行 make 命令就可能遇到问题:编译找不到头文件,或者连接找不到库文件而在make 成功以后,运行麻将程序必须先进入该 majiong 目录,才能执行程序如果要像其他的程序一样,可以在任意目录使用,就要专门为这一个程序修改 PATH 环境变量,或者再写一个启动脚本,并将它复制到 /usr/bin 这样的目录下Makefile 分析1 #2 # Copyright (c) 2005, Wei Mingzhi. All rights reserved.3 #4 # Use, redistributions and modifications of this file is5 # unrestricted provided the above copyright notice is6 # preserved.7 #89 OBJ = \10 bot.o config.o game.o general.o hand.o ini.o main.o \11 player.o text.o tile.o util.o1213 HEADERS = \14 bot.h game.h general.h hand.h ini.h main.h player.h \15 tile.h1617 CC = gcc18 CXX = g++1920 TARGET = mj2122 BASEFLAGS = -g3 -D_DEBUG=123 #BASEFLAGS = -s -O32425 CFLAGS = ${BASEFLAGS} `sdl-config --cflags`26 LDFLAGS = ${BASEFLAGS} `sdl-config --libs` -lSDL_image -lSDL_mixer -lSDL_ttf2728 all: ${TARGET}2930 ${TARGET}: ${OBJ}31 ${CXX} ${LDFLAGS} -o ${TARGET} ${OBJ}3233 clean:34 rm -f *.o ${TARGET}3536 distclean:37 rm -f *.o ${TARGET}3839 %.o: %.cpp ${HEADERS}40 ${CXX} ${CFLAGS} -c $< -o $@4142 %.o: %.c ${HEADERS}43 ${CC} ${CFLAGS} -c $< -o $@Makefile 很清楚:第 20 行定义 TARGET 变量为 mj,第 28 行表明 make 默认的 target也就是生成 `mj';第 22 行加入编译时的调试信息;第 2526 行使用了sdl-config 工具侦测 SDL 开发库编译链接信息,在 26 行还指明需要连接SDL_imageSDL_mixser 和SDL_ttf 库GNU 的软件风格一个标准的 GNU 软件,编译安装都是使用下面三个步骤:$ ./configure$ make$ make installconfigure 脚本运行时可以侦测系统的环境,确定软件安装目录,然后生成Makefile 文件make 调用系统中的编译器进行编译和连接make install 将软件安装到设定的目录用户执行 configure 时可以通过它的命令行参数指定自己所需的编译选项,比如安装目录通过 --prefix=PREFIX 设置,如果不指定,缺省情况下 PREFIX 是 /usr/local 默认安装时,执行文件安装到 /usr/local/bin 目录,库安装到 /usr/local/lib 目录,数据文件安装到 /usr/local/share 目录由于 GNU 的软件风格方便易用,通用性好,可移植性高,现在大多数 Unix/Linux 系统上的自由软件都采用这种方式分发软件准备 autotoolsGNU autotools 主要包含三个软件: autoconf,automake 和 libtool当前流行的有新旧两个版本,本例采用的是新版本,分别对应的是: autoconf 2.59, automake 1.9.6和 libtool 1.5.18很多 linux 发行版都会默认安装这几个工具本例是在 NetBSD 下进行操作,安装这几个软件包是通过 pkgsrc,它们在 pkgsrc 目录为 devel/autoconfdevel/automake 和devel/libtool改造文件布局原来软件的根目录下面放的是程序的源码,按照 GNU 的习惯,将它们放到 src 子目录,根目录留给 configure 这类文件使用,其他的数据文件保持不变,仍然放在各自的子目录先创建一个目录 majiang,然后根据需要将 mahjong 目录下的文件复制过来由于是为Unix/Linux 系统进行改写,原目录里的 win32 相关文件就不用复制到新目录$ cd ~/work/majiang$ lsdata/ docs/ fonts/ images/ music/ sound/ src/autoscanautoconf 软件包里面的 autoscan 工具可以扫描工作目录,生成一个configure.ac 的模板文件 configure.scan$ cd ~/work/majiang$ autoscanautoscan 命令在当前目录生成的 configure.scan 文件内容为:1 # -*- Autoconf -*-2 # Process this file with autoconf to produce a configure script. 34 AC_PREREQ(2.59)5 AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)6 AC_CONFIG_SRCDIR([src/bot.h])7 AC_CONFIG_HEADER([config.h])89 # Checks for programs.10 AC_PROG_CXX11 AC_PROG_CC1213 # Checks for libraries.1415 # Checks for header files.16 AC_HEADER_STDC17 AC_CHECK_HEADERS([limits.h malloc.h stdlib.h string.h unistd.h])1819 # Checks for typedefs, structures, and compiler characteristics.20 AC_HEADER_STDBOOL21 AC_C_CONST22 AC_C_INLINE2324 # Checks for library functions.25 AC_FUNC_MALLOC26 AC_FUNC_REALLOC27 AC_CHECK_FUNCS([memset strcasecmp strchr strdup])28 AC_OUTPUT# 号开始的行是注释,其他都是 m4 宏命令将它改名为 configure.ac,然后在此基础上进行修改configure.ac 的基本结构configure.ac 文件是 autoconf 的输入文件,经过 autoconf 处理,展开里面的 m4 宏,输出的是 configure 脚本第 4 行声明本文件要求的 autoconf 版本,因为本例使用了新版本 2.59,所以在此注明第 5 行 AC_INIT 宏用来定义软件的名称和版本等信息,本例写成:AC_INIT(majiang, 1.0)这里省略了 BUG-REPORT-ADDRESS 参数,它是可选项,一般写成作者的邮件地址第 6 行 AC_CONFIG_SRCDIR 宏通过侦测所指定的源码文件是否存在,来确定源码目录的有效性可以选择源码目录中的任何一个文件作为代表,比如将 autoscan 选择的bot.h文件改成 main.cpp:AC_CONFIG_SRCDIR([src/main.cpp])宏参数中使用 `[ ]',是为了表明其中的字符串是一个整体第 7 行的 AC_CONFIG_HEADER 宏用于生成 config.h 文件,里面存放configure 脚本侦测到的信息如果程序需要使用其中的定义,就在源码中加入#include <config.h>其他的一些宏是标准的侦测过程,可以保留不动configure.ac 文件要求 AC_INIT 宏必须放在开头位置,AC_OUTPUT 放在文件末,中间用来检测编译环境的各种宏没有特别的先后次序要求,由宏之间相互关系决定Makefile 文件的产生前面 configure.ac 里面的宏,主要作用是侦测系统,并没有编译相关的设置因为这些信息是写在 Makefile.am 里面,然后用 automake 工具转换成 Makefile.in,configure脚本执行时再读取 Makefile.in,并与侦测信息一起写到 Makefile 文件在 autotools 的命名习惯中,后缀 ac 的文件是 autoconf 的输入文件,后缀am 的文件是 automake 的输入文件,后缀 in 的文件是 configure 的输入文件autoconf 旧版本中 configure.in 等同于 configure.ac,虽然新版本也可以识别,但它不符合命名规则,所以新版本的文件应该使用 ac 后缀简单的 Makefile.in 可以手动编写,如果使用 automake 产生,需要在configure.ac里面加入 AM_INIT_AUTOMAKE 宏进行声明要输出 Makefile,还需要在 configure.ac 中使用 AC_CONFIG_FILES 宏指明该宏并不是只处理 Makefile,而是将 FILE.in 文件转换为 FILE 文件因为 make 可以遍历子目录,如果子目录中存在 Makefile,也将同时处理在本例中 src 目录下是源码,其他是数据文件,可以使用单独一个 Makefile 放在根目录下面,也可以用多个Makefile由于每个子目录的 Makefile 只处理本目录的文件,分工明确,是模块化的方法,推荐使用因此在 configure.ac 里面增加下面的宏,表示软件根目录和子目录中都需要生成Makefile 文件:AC_CONFIG_FILES([Makefilesrc/Makefiledata/Makefiledocs/Makefilefonts/Makefileimages/Makefilemusic/Makefilesound/Makefile])编写 Makefile.am软件根目录 Makefile.am由于该目录下面保存的是与 autotools 相关的文件,没有需要编译安装的文件,所以只注明需要进一步处理的子目录信息:SUBDIRS = src data docs fonts images music soundsrc/Makefile.am此目录里是源代码,最终生成 mj 可执行文件,在其 Makefile.am 中写入bin_PROGRAMS = mjmj_SOURCES = bot.h \bot.cpp \config.cpp \game.h \game.cpp \general.h \general.cpp \hand.h \hand.cpp \ini.h \ini.cpp \main.h \main.cpp \player.h \player.cpp \text.cpp \tile.h \tile.cpp \util.cppam 文件里变量通过命名判断其含义,保留的字符串间用下划线分隔bin_PROGRAMS 表示列出二进制的程序,值为多个空格分开的程序列表,这里仅有一个 mjmj_SOURCES 列出的是组成 mj 程序的文件,文件比较多的时候,每个文件写成一行容易看清楚data/Makefile.am本目录的文件是 mj 运行时读取的数据,它的 Makefile.am 可以这样写mjdatadir = $(pkgdatadir)/datamjdata_DATA = mj.ini titles.txtEXTRA_DIST = $(mjdata_DATA)因为 datadir 是保留的关键字,所以用 mjdatadir 代替,pkgdatadir 指向$prefix/share/FULL-PACKAGE-NAME 目录,因为在 AC_INIT 中已经声明FULL-PACKAGE-NAME 为majiang,pkgdatadir 就等于 $prefix/share/majiang 目录其中 mjdatadir 让 data 目录下的文件安装到 $prefix/share/majiang/data 目录里面mjdata_DATA 列出此目录下需要安装的文件,然后用 EXTRA_DIST 变量注明余下几个子目录都与 data 目录类似docs/Makefile.amdocsdir = $(pkgdatadir)/docsdocs_DATA = gkai00mp.txt gpl.html readme.txtEXTRA_DIST = $(docs_DATA)fonts/Makefile.amfontsdir = $(pkgdatadir)/fontsfonts_DATA = brush.ttf gkai00mp.ttfEXTRA_DIST = $(fonts_DATA)images/Makefile.amimagesdir = $(pkgdatadir)/imagesimages_DATA = bgame.jpg \mjgirl1a.jpg \mjgirl2a.jpg \mjgirl3a.jpg \mjgirl4a.jpg \tiles.jpg \electron.jpg \mjgirl1b.jpg \mjgirl2b.jpg \mjgirl3b.jpg \mjgirl4b.jpg \gameover.jpg \mjgirl1c.jpg \mjgirl2c.jpg \mjgirl3c.jpg \mjgirl4c.jpgEXTRA_DIST = $(images_DATA) music/Makefile.ammusicdir = $(pkgdatadir)/music music_DATA = bet.ogg \ bonus.ogg \music.ogg \musicb.ogg \musice.ogg \win.ogg \bgame.ogg \gameover.ogg \music1.ogg \musicc.ogg \musicp.oggEXTRA_DIST = $(music_DATA) sound/Makefile.amsounddir = $(pkgdatadir)/sound sound_DATA = boom.wav \ding.wav \discard.wav \discard2.wav \flash.wav \snd1.wav \snd2.wav \snd3.wav \EXTRA_DIST = $(sound_DATA)运行 autotools准备好 configure.ac 和 Makefile.am,就可以用 autotools 的命令处理这些文件开始可能会出现错误,不过没关系,可以按照错误信息的提示逐步进行修正首先要使用的是 aclocal 命令,它根据 configure.ac 的定义,将需要使用的m4 宏定义复制到 aclocal.m4 里面缺省时,搜索 m4 宏是从 autoconf 的安装目录和系统的aclocal 目录如果需要使用其他路径下的宏,可以通过命令行的 -I 选项指定接着使用 autoheader 命令,它负责生成 config.h.in 文件,这里面的 C 语言宏定义也是通过解析 configure.ac 产生下来运行 automake 命令处理 Makefile.am,生成 Makefile.inGNU 对自己发布的软件有严格的规范,比如必须附带许可证声明文件 COPYING 等等,否则 automake 执行时会报错automake 提供了三种软件等级: foreigngnu 和 gnits,让用户选择采用,默认等级为 gnu本例使用 foreign 等级,它只检测必须的文件有一些必需的脚本文件可以从 automake 软件包里复制过来,在执行时使用 --add-missing 选项可以让automake 自动添加,默认方式是采用符号链接,如加上 --copy 选项则可以使用复制方式本例中,automake 的命令如下:$ automake --foreign --add-missing --copy最后,使用 autoconf 命令生成 configure 脚本文件SDL 库的侦测这个麻将游戏是基于 SDL 库开发的,一般系统默认不会安装,因此 configure 脚本的一个任务就是检查用户的系统中是否有该软件包autoconf 提供了很多宏可以实现侦测功能,但首先应该查看 SDL 软件包是否已应的宏通过 pkgsrc 的工具可以看到:$ pkg_info -L SDL|grep m4/usr/pkg/share/aclocal/sdl.m4即 SDL 软件包提供了一个 sdl.m4 宏,放在系统的 aclocal 目录下在这个宏文件的注释中说明了使用的方法:dnlAM_PATH_SDL([MINIMUM-VERSION,[ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]] )dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS也就是说在 configure.ac 里面调用 AM_PATH_SDL 宏,就可以侦测 SDL找到SDL 库以后,该宏还输出 SDL_CFLAGS 和 SDL_LIBS 编译连接选项,它们实际上就是调用`sdl-config --cflags` 和 `sdl-config --libs`于是在 configure.ac 里面加入 AM_PATH_SDL 宏# Checks for libraries.SDL_VERSION=1.2.0AM_PATH_SDL($SDL_VERSION,:,AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]))当前 SDL 的版本为 1.2.9,于是 MINIMUM-VERSION 就设为 1.2.0如果在系统中侦测到需要的库,没什么额外的操作,假如没有找到,则给出错误信息AM_PATH_SDL 输出 SDL_CFLAGS 和 SDL_LIBS 编译参数,需要添加到src/Makefile.am 里面:mj_CPPFLAGS = @SDL_CFLAGS@mj_LDFLAGS = @SDL_LIBS@用 `@' 包围的变量会在 configure 执行时被替换从 mahjong 的 Makefile 中看到,这个软件还要使用 SDL_imageSDL_mixser 和SDL_ttf 库,但它们不属于 SDL 软件包,需要另外安装由于这些库在 sdl.m4 中也没有进行侦测,所以自己要写一些脚本autotools 提供了一个 AC_CHECK_LIB 宏可以用来检测库,现在就使用它来检测这几个SDL 库该宏的语法为:AC_CHECK_LIB (LIBRARY, FUNCTION, [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], [OTHER-LIBRARIES])第一个参数是库名,第二个参数是库中的一个函数,第三个参数是检测到以后进行的动作,第四个参数是未检测到以后的动作,第五个参数是其他的库对于 SDL_imageSDL_mixer 和 SDL_ttf 对应的使用方法如下:# Check for SDL_image libraryAC_CHECK_LIB(SDL_image, IMG_LoadPNG_RW, , AC_MSG_ERROR([*** Unable to find SDL_image libary with PNG support(/projects/SDL_image/)]), `sdl-config --libs`)# Check for SDL_mixer libraryAC_CHECK_LIB(SDL_mixer, Mix_LoadOGG_RW, , AC_MSG_ERROR([*** Unable to find SDL_mixer libary with OGG support(/projects/SDL_mixer/)]), `sdl-config --libs`)# Check for SDL_ttf libraryAC_CHECK_LIB(SDL_ttf, TTF_OpenFont, , AC_MSG_ERROR([*** Unable to find SDL_ttf libary(/projects/SDL_ttf/)]), `sdl-config --libs`)软件使用的数据文件原来 mj 读取数据是从执行时目录的子目录中读取,但现在将数据放到$prefix/share/majiang 目录下,需要通过一种途径让程序可以知道数据文件被安放的位置要达到这个目的有很多方法,这里采用最直接的一种:将数据文件安装目录变量通过CPPFLAGS 编译参数传递给程序于是修改 src/Makefile.am 的 CPPFLAGS:mj_CPPFLAGS = @SDL_CFLAGS@ -DDATA_DIR=\"${datadir}/majiang\"相应地修改 src 目录下的源码,在读取数据文件的地方,将读取的路径改成DATA_DIR里对应的子目录例如,原先 config.cpp 中是:void LoadCfg(){cfg.Load("data/mj.ini");}现改成:void LoadCfg(){char ini_file[260];sprintf(ini_file, "%s/data/mj.ini", DATA_DIR);cfg.Load(ini_file);}configure 选项原来 mahjong 的 Makefile 第 22 行定义了 debug 调试选项,虽然也可以照样放到 src/Makefile.am 的 CPPFLAGS 里面实现,但 autotools 提供了一种更灵活的机制configure 脚本可以通过选项来设置编译参数,现增加一个 --enable-debug 选项,需要DEBUG 时,在命令行上加上它来打开,默认则关闭这项功能是使用 AC_ARG_ENABLE 宏实现:AC_ARG_ENABLE (FEATURE, HELP-STRING, [ACTION-IF-GIVEN],[ACTION-IF-NOT-GIVEN])其中 FEATURE 是名称,HELP_STRING 为说明信息,在使用 ./configure --help 时可以看到最后两个分别对应打开和关闭时的操作现在将 DEBUG 功能加入 configure.ac:AC_ARG_ENABLE(debug,[ --enable-debug turn on debug],CXXFLAGS="$CXXFLAGS -g3 -D_DEBUG=1")autotools 脚本每次修改了 configure.ac 或 Makefile.am 等 autotools 输入文件后都需要再次运行aclocalautomakeautoconf 这些命令,为了方便起见,可以将他们放到一个shell脚本里面,例如:#! /bin/shset -xaclocalautoheaderautomake --foreign --add-missing --copyautoconf将上面内容保存到 autogen.sh 文件,并修改文件属性为 755每次需要重新生成configure 脚本时,执行 ./autogen.sh 即可使用 configure 产生的 Makefile现在执行 ./autogen.sh 得到的 configure 脚本已经可以正常工作了,进入~/work/majiang 目录,执行 ./configure,可以看到它检查系统的过程,包括 SDL 和SDL_image 等库的侦测结果使用 ./configure --help 可以看到 autotools 提供的帮助信息configure 执行的完毕,输出软件根目录和几个子目录下面的 Makefile 文件这些Makefile 有几个常用的 target:· make all不加任何 target,默认就是 all,作用是编译软件· make install安装软件包,如果安装到系统目录,需要 root 权限· make clean清除编译产生的目标文件· make distclean可以同时清除编译的结果和 configure 输出的文件· make tags生成 etags 使用的 TAGS 文件· make dist生成软件发布包,为 tar.gz 格式的压缩包,文件名由软件包名和版本组成最终的 configure.ac 文件# -*- Autoconf -*-# Process this file with autoconf to produce a configure script.AC_PREREQ(2.59)AC_INIT([majiang], [1.0])AC_CONFIG_SRCDIR([src/main.cpp])AC_CONFIG_HEADER([config.h])AC_CANONICAL_HOSTAC_CANONICAL_TARGETAM_INIT_AUTOMAKE# Checks for programs.AC_PROG_CXXAC_PROG_CCAC_LANG(C++)# Checks for libraries.SDL_VERSION=1.2.0AM_PATH_SDL($SDL_VERSION,:,AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]))# Check for SDL_image libraryAC_CHECK_LIB(SDL_image, IMG_LoadPNG_RW, , AC_MSG_ERROR([*** Unable to find SDL_image libary with PNG support(/projects/SDL_image/)]), `sdl-config --libs`)# Check for SDL_mixer libraryAC_CHECK_LIB(SDL_mixer, Mix_LoadOGG_RW, , AC_MSG_ERROR([*** Unable to find SDL_mixer libary with OGG support(/projects/SDL_mixer/)]), `sdl-config --libs`)# Check for SDL_ttf libraryAC_CHECK_LIB(SDL_ttf, TTF_OpenFont, , AC_MSG_ERROR([*** Unable to find SDL_ttf libary(/projects/SDL_ttf/)]), `sdl-config --libs`)# Checks for header files.AC_HEADER_STDCAC_CHECK_HEADERS([limits.h malloc.h stdlib.h string.h unistd.h])# Checks for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOLAC_C_CONSTAC_C_INLINE# Checks for library functions.AC_FUNC_MALLOCAC_FUNC_REALLOCAC_CHECK_FUNCS([memset strcasecmp strchr strdup])AC_ARG_ENABLE(debug,[ --enable-debug turn on debug],CXXFLAGS="$CXXFLAGS -g3 -D_DEBUG=1")AC_CONFIG_FILES([Makefilesrc/Makefiledata/Makefiledocs/Makefilefonts/Makefileimages/Makefilemusic/Makefilesound/Makefile])AC_OUTPUT结束语GNU 的很多工具经常给人一种感觉: 功能很强大,但也很难学autotools 可以说是这类工具的一个典型,它需要用户对 shellmake软件编译m4 宏语言,以及Unix/Linux操作系统各方面知识都有一定的了解使用时又要 autoconf automakelibtool 多个工具相互配合^1,如果要给软件增加国际化功能,还要再了解和掌握 gettextpo 等工具和规则与学习其他知识一样,所谓难,其实是不了解,不熟悉本文通过一个范例演示使用autotools 的过程,是让不了解的人熟悉这个工具但真正的理解,还需要将它运用到自己的软件项目当中,不断地实践,不断地思考和总结脚注... 多个工具相互配合^1由于本例软件中没有生成库文件,所以没有涉及 libtool 工具的使用。

AutoMake

AutoMake

AutoMakeAutoMake版本问题Auto Make 例子步骤总述新版的automake变化autotools系列工具作用怎么能让automake生成的makefile里面包含有我指定的库制作 configure 脚本使用 automakeautoconf手册利用libtool自动生成动态库的Makefile的生成方法autoconf 和automake生成Makefile文件引子模拟需求工具简介生成 Makefile 的来龙去脉Configure.in的八股文实战Makefile.am几个重要的宏三种一般需求版本问题不同的automake,autoconf,autoscan之间存在着一定的不兼容性。

这里推荐autoscan 2.59和automake 1.9配合使用。

如果你是debian或者ubuntu,那么可你可以简单按照下面的方式安装apt-get install autoconf apt-get remove automake1.4 apt-get install automake1.9Auto Make 例子现在google Makefile 和 automake就能找到一些文章。

以一个Hello 程序描述为一个project生成Makefile的过程。

这个例子其实在 Info automake 里能看到。

大家把它翻成中文的,不错。

但实际上按照这个例子来做的话,步骤都对,就是太简单,一些常用的设置需要写进去,但是没有提到,还是要自己info, google, try. 步骤总述•autoscan 生成configure.scan .•在configure.scan基础上手动编辑,主要要添加的:AM_INIT_AUTOMAKE(myprojectname , version) AC_OUTPUT( 最后要生成的Makefile , 包括子目录中的,中间用空格隔开) , 例如AC_OUTPUT(Makefile subdir/Makefile subdir1/Makefile) AC_PROG_RANLIB (意义见第四条末尾)•aclocal•autoconf 生成configure脚本。

教你如何使用automake生成Makefile文件

教你如何使用automake生成Makefile文件

教你如何使用automake生成Makefile文件引言总所周知,Makefile主要用来组织源码的编译,其语法在此不再迭述。

经分析可发现,源码的组织结构通常有以下3种形式:①、flat:所有文件都处在同一目录所有源文件、头文件以及相关的库文件都处在当前的目录中,不存在任何子目录。

②、shallow:主要源代码处在顶层目录,其他各部分处在子目录主要源文件在当前目录中,而其它一些实现各部分功能的源文件位于各自不同的目录。

③、deep:所有源代码处在子目录,顶层目录存放配置信息所有源文件及自己写的头文件位于当前目录的一个子目录中,而当前目录里没有任何源文件。

使用automake对以上3种源码组织结构的编译过程在某些细节上存在一些差异,但是大概流程是一致的,如下图所示:图1生成Makefile的过程编译过程2.1flat根据引言中对flat源码结构的描述“所有源文件、头文件以及相关的库文件都处在当前的目录中,不存在任何子目录”可知其目录结构如下图所示:图2flat源码结构目录说明:add.c:实现加法运算int my_add(int a,int b){return(a+b);}sub.c:实现减法运算int my_sub(int a,int b){return(a-b);}mul.c:实现乘法运算int my_mul(int a,int b){return(a*b);}div.c:实现除法运算int my_div(int a,int b){return(a/b);}algo.h:头文件声明源码中实现的函数test.c:在主函数中调用以上源文件实现的函数,并展示运算结果编译步骤:①、执行autoscan在目录中执行autoscan命令,会生成文件configure.scan,再将其重命名为configure.in,最后还需要做如下修改。

#autoscan#mv configure.scan configure.in#vim configure.in修改前:图3configure.scan①、将AC_CONFIG_SRCDIR([sub.c])改为AC_CONFIG_SRCDIR([test.c])注:使用有主函数main()的源文件test.c取代sub.c②、将AC_CONFIG_HEADER([config.h])改为AM_CONFIG_HEADER([config.h])③、新增AM_INIT_AUTOMAKE(math, 1.0):其中math是希望生成的可执行程序的名字,1.0表示版本号④、将AC_OUTPUT改为AC_OUTPUT(Makefile):表示要创建的Makefile名修改后:图4configure.in②、配置Makefile.am在当前目录中新建Makefile.am文件,生成可执行文件math,因此其配置内容为:图5Makefile.am③、新建文件在当前目录下新建文件NEWS、README、ChangeLog、AUTHORS文件,内容为空;#touch NEWS#touch README#touch ChangeLog#touch AUTHORS④、生成configure#aclocal——该命令将以configure.in为输入文件,生成aclocal.m4#autoconf——该命令将以configure.in和aclocal.m4为输入文件,生成文件configure#autoheader⑤、生成Makefile.in#automake-a(该命令将以configure.in和Makefile.am为输入文件,生成文件Makefile.in)⑥、执行./configure配置安装程序,并生成Makefile⑦、编译源码经过以上步骤,已经生成了Makefile,此时只需执行make,便可以编译源码,并生成可执行程序了;⑧、运行结果完成以上所有操作之后,在当前目录下就生成了可执行程序math,其最终的运行结果如下图所示:图6flat结果2.2shallow根据引言中对shallow源码结构的描述“主要源文件在当前目录中,而其它一些实现各部分功能的源文件位于各自不同的目录”可知其目录结构如下图所示:图7shallow源码结构目录说明:add/add.c:实现加法运算int my_add(int a,int b){return(a+b);} sub/sub.c:实现减法运算int my_sub(int a,int b){return(a-b);} mul/mul.c:实现乘法运算int my_mul(int a,int b){return(a*b);} div/div.c:实现除法运算int my_div(int a,int b){return(a/b);} incl/algo.h:头文件声明源码中实现的函数test.c:在主函数中调用以上源文件实现的函数,并展示运算结果编译步骤:①、执行autoscan在目录中执行autoscan命令,会生成文件configure.scan,再将其重命名为configure.in,最后还需要做如下修改。

Automake中文文档

Automake中文文档

bin_PROGRAMS = zardoz zardoz_SOURCES = main.c head.c float.c vortex9.c gun.c zardoz_LDADD = @LIBOBJS@
info_TEXINFOS = zardoz.texi
现在你运行automake --add-missing以生成你的`Makefile.in' 并且得到任何你可能需要的附加文件,现在你完成了你的任 务!
无标题 -------------------------------------------------------------------------------介绍 Automake是一个从文件`Makefile.am'自动生成`Makefile.in' 的工具。每个`Makefile.am'基本上是一系列make的宏定义( make规则也会偶尔出现)。生成的`Makefile.in's服从GNU Makefile标准。 GNU Makefile标准文档(参见GNU编码标准中的‘Makefile惯例’节)长、复杂,而且会发生改变。Automake的目的就是解除 个人GNU维护者维护Makefile的负担(并且让Automake的维护者来承担这个负担)。 典型的Automake输入文件是一系列简单的宏定义。处理所有这样的文件以创建 `Makefile.in'。在一个项目(project)的每 个目录中通常包含一个 `Makefile.am'。 Automake在几个方面对一个项目做了限制;例如它假定项目使用Autoconf (参见Autoconf手册),并且对`configure.in'的 内容施加了某些限制。 为生成`Makefile.in',Automake需要perl。但是由Automake创建的发布完全服从GNU标准,并且在创建中不需要perl。 请把关于Automake的建议和bug发送到 automake-bugs@。 通用性概念 一些基本概念将有助于理解Automake是如何工作的。 通用操作 Automake读入`Makefile.am'并且生成`Makefile.in'。在`Makefile.am'中定义的一些宏和目标(targets)指挥automake生 成更多特定的代码;例如一个`bin_PROGRAMS'宏定义将生成一个需要被编译、连接的目标。 `Makefile.am'中的宏定义和目标被复制到生成的文件中。这使得你可以把任何代码添加到生成的`Makefile.in'文件中。例 如,Automake的发布包含了非标准的cvs-dist目标,Automake的维护者用它从他的版本控制系统中创建发布版本。 Automake不能识别GNU对make的扩展。在`Makefile.am'中使用这些扩展将导致错误或者令人不解的行为。 Automake试图明智地把注释和相邻的目标(或者变量定义)关联起来。 在`Makefile.am'中定义的目标通常覆盖了所有由automake 自动生成的拥有相似名字的目标。虽然Automake提供了这一功 能,但最好避免使用它,因为有些时候生成的规则将是十分特别的。 类似地,在`Makefile.am'中定义的变量将覆盖任何通常由automake 创建的变量定义。该功能比覆盖目标定义的功能要常用 得多。需要警告的是许多由 automake生成的变量都被认为是内部使用的,并且它们的名字可能在未来的版本中改变。 在检验变量定义的时候,Automake将递归地检验定义中的变量引用。例如,如果Automake 在如下片断中搜索`foo_SOURCES' 的内容。 xs = a.c b.c foo_SOURCES = c.c $(xs) 它将把文件`a.c'、 `b.c'和 `c.c'作为`foo_SOURCES' 的内容。 Automake还允许给出不被复制到输出中的注释;所有以`##'开头的行将被Automake彻底忽略。 作为惯例,`Makefile.am'的第一行是: ## Process this file with automake to produce Makefile.in 深度 automake支持三种目录层次: “flat”、“shallow”和“deep”。 一个flat(平)包指的是所有文件都在一个目录中的包。为这类包提供的`Makefile.am' 缺少宏SUBDIRS。这类包的一个例子 是termutils。 一个deep(深)包指的是所有的源代码都被储存在子目录中的包;顶层目录主要包含配置信息。GNU cpio 是这类包的一个很 好的例子,GNU tar也是。deep包的顶层`Makefile.am'将包括宏SUBDIRS,但没有其它定义需要创建的对象的宏。 一个shallow(浅)包指的是主要的源代码储存在顶层目录中,而各个部分(典型的是库)则储存在子目录中的包。Automake 本身就是这类包(GNU make也是如此,它现在已经不使用automake)。 严格性 Automake的目的是用于维护GNU包,它为适应那些希望使用它的人做出了一些努力,但并不指望应用所有的GNU惯例。 按照这个目标,Automake支持三级严格性---严格性指的是Automake 将如何检查包所服从的标准。

autoconf与automake的完整例程

autoconf与automake的完整例程

autoconf与automake的完整例程一、 automake 的用途automake 和 autoconf 可以自动生成 GNU 的 Makefile ,虽然我们也可以手工写 Makefile ,但是考虑到在多硬件平台上运行,编译环境差异,依赖关系,静态和动态库的生成,等一系列的问题,对于复杂的代码树,用 automake 工具就成了更好的选择。

在下面的例程中,将介绍树型源码包的 Makefile 生成,其中包括生成库文件和可执行文件。

二、完整例程1.建立目录树a) 生成目录树$ mkdir lib$ mkdir src$ mkdir include$ touch include/xy.h$ touch lib/xy1.cpp$ touch lib/xy2.cpp$ touch src/main.cppb) 编辑源代码文件i. include/xy.h 内容如下:void xytest1();void xytest2();ii. lib/xy1.cpp 内容如下:#include <stdio.h>void xytest1(){ printf(“xytest1/n”); }iii. lib/xy2.cpp 内容如下:#include <stdio.h>void xytest2(){ printf(“xytest2/n”); }iv. src/main.cpp 内容如下:#include <xy.h>main(){xytest1();xytest2();}2. autoconfa) 生成默认的 configure.in$ autoscan此时目录下生成 configure.scan$ mv configure.scan configure.inb) 编辑 configure.in (为了书写简单,去掉了所有注释)AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)AM_INIT_AUTOMAKE(xytest, 1.0) # 此处是软件名和版本号AC_PROG_CXX # 自动检测编译器AC_PROG_CCAC_PROG_LIBTOOL # 生成动态/ 静态库需要LIBTOOL AC_OUTPUT(Makefile lib/Makefile src/Makefile) # 此处是输出的文件c) 自动生成 configure$ aclocal 它是一个perl 脚本,根据configure.in 产生aclocal.m4$ libtoolize –force它会生成 libtool 所需要的工具,主要为生成库做准备$ autoconf 通过 aclocal.m4 产生 configure3. automakea) Makefile.am 项层写法,编辑 ./Makefile.am 如下AUTOMAKE_OPTIONS=foreignSUBDIRS = lib srcb) Makefile.am 编译库文件的写法,编辑 lib/Makefile.am 如下DEFAULT_INCLUDES=-I../includelib_LTLIBRARIES = libxy_la_SOURCES =xy1.cpp xy2.cppc) Makefile.am 编译开执行程序的写法,编辑src/Makefile.am 如下DEFAULT_INCLUDES=-I../includebin_PROGRAMS = mainmain_SOURCES = main.cppmain_LDADD= -L../lib/.libs/ -lxyd) 生成 Makefile.in$ automake –add-missing4.编译运行(以 arm 为示例)$ ./configure –host=arm-linux 此时机器上需要有arm-linux-gcc 系统的编译工具$ make$ make install5.总结a) 需要手动编译的只有 configure.in, Makefile.am, 和源代码三处i. Makefile.am 中的常用设置项AM_CXXFLAGS= 编译 C++ 程序时所带的 FLAGSAM_CFLAGS= 编译C 程序时所带的FLAGSDEFAULT_INCLUDES= 编译时加入的include 目录DEFS= 编译时定义的DEFIND 值b) 注意看执行过程中有无错误提示。

使用Automake生成Makefile及动态库和静态库的创建-BriverSong...

使用Automake生成Makefile及动态库和静态库的创建-BriverSong...

使用Automake生成Makefile及动态库和静态库的创建-BriverSong...使用Automake生成Makefile及动态库和静态库的创建收藏使用Automake 创建和使用静态库1. 目录结构如下:view plaincopy to clipboardprint?example|——src 目录(存放源代码文件)|——hello.c|——lib 目录(存放用来生成库的文件)|——test.c 用来生成静态库libhello.a|——include 目录(存放程序中使用的头文件)|——hello.hexample|——src 目录(存放源代码文件)|——hello.c|——lib 目录(存放用来生成库的文件)|——test.c 用来生成静态库libhello.a|——include 目录(存放程序中使用的头文件)|——hello.h2. 编写的各个目录下的源文件view plaincopy to clipboardprint?hello.h 文件extern void print(char *);test.c 文件#include<stdio.h>void print(char *msg){print(“%s\n”, msg);}hello.c 文件#include “hello.h”int main(){print(“Hello static library!”);//这里用到的是静态库中的函数return 0;}hello.h 文件extern void print(char *);test.c 文件#include<stdio.h>void print(char *msg){print(“%s\n”, msg);}hello.c 文件#include “hello.h”int main(){print(“Hello static library!”);//这里用到的是静态库中的函数return 0;}3. 编写lib/Makefile.am 文件view plaincopy to clipboardprint?noinst_LIBRARIES=libhello.alibhello_a_SOURCES=test.cAUTOMAKE_OPTIONS=foreignnoinst_LIBRARIES=libhello.alibhello_a_SOURCES=test.cAUTOMAKE_OPTIONS=foreign第一行noinst 表示生成的是静态库,不需要make install ,直接制定它的位置和名字就可以使用。

automake详解

automake详解
2.6.1Autoconf/Automake工具组简介(1)
Autoconf/Automake工具组主要包括autoconf、automake、perl语言环境和m4。其中FC4默认安装的autoconf和automake软件包信息如下:
[root@localhost hello]# rpm -qa |grep autoconf //查看是否安装autoconf
使用Autoconf/Automake工具自动生成Makefile文件的流程图如图2-5所示。在此过程中使用的命令主要有aclocal、autoscan、autoconf、autoheader和automake。由图可知运行步骤如下:
(点击查看大图)图2-5自动创建Makefile文件流程
(1)创建源代码文件,使用"autoscan"生成configure.scan文件,将其重命名为configure.ac,并做适当修改,然后使用"aclocal"命令生成aclocal.m4文件,使用"autoconf"命令由configure.ac和aclocal.m4文件生成configure文件。
AC_PREREQ(2.59)
AC_INIT(hello,1.0,yangzongde@) //在此行内容中设置当前软件包信息
AM_INIT_AUTOMAKE(hello,1.0) //automake所必备的宏,必须添加
AC_CONFIG_SRCDIR([hello.c]) //源文件名
autoscan.log configure.ac configure.scan hello.c
[root@localhost hello]# cat configure.ac

Autotools使用指南

Autotools使用指南

Autotools使用指南Autotools使用指南一、功能&简介:Linux环境下,我们编译程序啥的都是一般用的GCC&&GDB等等工具,直接使用GCC命令进行编译操作。

这种方式一般是适用于程序文件比较少,组织结构比较简单的情况。

但是,当我们程序文件比较的多的时候,或者是程序文件组织结构比较的复杂(例如在程序文件夹中存在文件夹多层嵌套以及复杂引用等),此时我们如果是直接使用GCC一点一点的编译工作量会非常的大,而且万一程序修改了,还要重新的再工作一遍。

为此,我们有了make工具,依靠Makefile辅助文件,我们可以方便的进行工程的管理,以及编译操作。

当程序很复杂的时候,依靠我们去手工的建立、维护Makefile文件是非常的不现实的,不仅很复杂,而且费时费力,还容易出错。

为此,就有了我们的_Autotools_工具,只要输入工程中的目标文件、依赖文件、文件目录等信息就可以自动生成Makefile。

二、Autotools工具包:Autotools工具包的目标就是去方便的帮助我们得到我们需要的Makefile文件。

___Autotools使用流程:___<1>目录树的最高层运行autoscan,生成configure.scan文件;<2>运行aclocal,生成aclocal.m4文件;<3>运行autoconf,生成configure配置脚本;<4>运行autoheader,生成config.h.in文件;<5>手工编写Makefile.am文件;<6>运行automake,生成Makefile.in;<7>运行配置脚本configure,生成Makefile。

三、c源文件同一目录下Autotools的使用:如果你的源文件都放在同一个目录下面。

可以按照以下步骤来实现同一目录下的Autotools工具的使用:1、编写源代码:2、运行autoscan:第一步:我们需要在我们的<项目目录>下执行autoscan命令。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

无论是在Linux还是在Unix环境中,make都是一个非常重要的编译命令。

不管是自己进行项目开发还是安装应用软件,我们都经常要用到make或make install。

利用make工具,我们可以将大型的开发项目分解成为多个更易于管理的模块,对于一个包括几百个源文件的应用程序,使用make和makefile工具就可以轻而易举的理顺各个源文件之间纷繁复杂的相互关系。

但是如果通过查阅make的帮助文档来手工编写Makefile,对任何程序员都是一场挑战。

幸而有GNU 提供的Autoconf及Automake这两套工具使得编写makefile不再是一个难题。

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

回页首模拟需求假设源文件按如下目录存放,如图1所示,运用autoconf和automake生成makefile文件。

图1文件目录结构假设src是我们源文件目录,include目录存放其他库的头文件,lib目录存放用到的库文件,然后开始按模块存放,每个模块都有一个对应的目录,模块下再分子模块,如apple、orange。

每个子目录下又分core,include,shell三个目录,其中core和shell目录存放.c文件,include 的存放.h文件,其他类似。

样例程序功能:基于多线程的数据读写保护(联系作者获取整个autoconf和automake生成的Makefile工程和源码,E-mail:normalnotebook@)。

回页首工具简介所必须的软件:autoconf/automake/m4/perl/libtool(其中libtool非必须)。

autoconf是一个用于生成可以自动地配置软件源码包,用以适应多种UNIX类系统的shell 脚本工具,其中autoconf需要用到m4,便于生成脚本。

automake是一个从Makefile.am文件自动生成Makefile.in的工具。

为了生成Makefile.in,automake还需用到perl,由于automake 创建的发布完全遵循GNU标准,所以在创建中不需要perl。

libtool是一款方便生成各种程序库的工具。

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

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

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

Termutils就是这一类。

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

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

automake本身就是这一类。

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

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

GNU cpio和GNU tar就是这一类。

flat类型是最简单的,deep类型是最复杂的。

不难看出,我们的模拟需求正是基于第三类deep 型,也就是说我们要做挑战性的事情:)。

注:我们的测试程序是基于多线程的简单程序。

回页首生成Makefile 的来龙去脉首先进入project 目录,在该目录下运行一系列命令,创建和修改几个文件,就可以生成符合该平台的Makefile文件,操作过程如下:1) 运行autoscan命令2) 将configure.scan 文件重命名为configure.in,并修改configure.in文件3) 在project目录下新建Makefile.am文件,并在core和shell目录下也新建makefile.am文件4) 在project目录下新建NEWS、README、ChangeLog 、AUTHORS文件5) 将/usr/share/automake-1.X/目录下的depcomp和complie文件拷贝到本目录下6) 运行aclocal命令7) 运行autoconf命令8) 运行automake -a命令9) 运行./confiugre脚本可以通过图2看出产生Makefile的流程,如图所示:图2生成Makefile流程图回页首Configure.in的八股文当我们利用autoscan工具生成confiugre.scan文件时,我们需要将confiugre.scan重命名为confiugre.in文件。

confiugre.in调用一系列autoconf宏来测试程序需要的或用到的特性是否存在,以及这些特性的功能。

下面我们就来目睹一下confiugre.scan的庐山真面目:# Process this file with autoconf to produce a configure script.AC_PREREQ(2.59)AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)AC_CONFIG_SRCDIR([config.h.in])AC_CONFIG_HEADER([config.h])# Checks for programs.AC_PROG_CC# Checks for libraries.# FIXME: Replace `main' with a function in `-lpthread':AC_CHECK_LIB([pthread], [main])# Checks for header files.# Checks for typedefs, structures, and compiler characteristics.# Checks for library functions.AC_OUTPUT每个configure.scan文件都是以AC_INIT开头,以AC_OUTPUT结束。

我们不难从文件中看出confiugre.in文件的一般布局:AC_INIT测试程序测试函数库测试头文件测试类型定义测试结构测试编译器特性测试库函数测试系统调用AC_OUTPUT上面的调用次序只是建议性质的,但我们还是强烈建议不要随意改变对宏调用的次序。

现在就开始修改该文件:$mv configure.scan configure.in$vim configure.in修改后的结果如下:# -*- Autoconf -*-# Process this file with autoconf to produce a configure script.AC_PREREQ(2.59)AC_INIT(test, 1.0, normalnotebook@)AC_CONFIG_SRCDIR([src/ModuleA/apple/core/test.c])AM_CONFIG_HEADER(config.h)AM_INIT_AUTOMAKE(test,1.0)# Checks for programs.AC_PROG_CC# Checks for libraries.# FIXME: Replace `main' with a function in `-lpthread':AC_CHECK_LIB([pthread], [pthread_rwlock_init])AC_PROG_RANLIB# Checks for header files.# Checks for typedefs, structures, and compiler characteristics.# Checks for library functions.AC_OUTPUT([Makefilesrc/lib/Makefilesrc/ModuleA/apple/core/Makefilesrc/ModuleA/apple/shell/Makefile])其中要将AC_CONFIG_HEADER([config.h])修改为:AM_CONFIG_HEADER(config.h), 并加入AM_INIT_AUTOMAKE(test,1.0)。

由于我们的测试程序是基于多线程的程序,所以要加入AC_PROG_RANLIB,不然运行automake命令时会出错。

在AC_OUTPUT输入要创建的Makefile文件名。

由于我们在程序中使用了读写锁,所以需要对库文件进行检查,即AC_CHECK_LIB([pthread], [main]),该宏的含义如下:其中,LIBS是link的一个选项,详细请参看后续的Makefile文件。

由于我们在程序中使用了读写锁,所以我们测试pthread库中是否存在pthread_rwlock_init函数。

由于我们是基于deep类型来创建makefile文件,所以我们需要在四处创建Makefile文件。

即:project目录下,lib目录下,core和shell目录下。

Autoconf提供了很多内置宏来做相关的检测,限于篇幅关系,我们在这里对其他宏不做详细的解释,具体请参看参考文献1和参考文献2,也可参看autoconf信息页。

回页首实战Makefile.amMakefile.am是一种比Makefile更高层次的规则。

只需指定要生成什么目标,它由什么源文件生成,要安装到什么目录等构成。

表一列出了可执行文件、静态库、头文件和数据文件,四种书写Makefile.am文件个一般格式。

表1Makefile.am一般格式对于可执行文件和静态库类型,如果只想编译,不想安装到系统中,可以用noinst_PROGRAMS代替bin_PROGRAMS,noinst_LIBRARIES代替lib_LIBRARIES。

Makefile.am还提供了一些全局变量供所有的目标体使用:表 2 Makefile.am中可用的全局变量在Makefile.am中尽量使用相对路径,系统预定义了两个基本路径:表3Makefile.am中可用的路径变量在上文中我们提到过安装路径,automake设置了默认的安装路径:1) 标准安装路径默认安装路径为:$(prefix) = /usr/local,可以通过./configure --prefix=<new_path>的方法来覆盖。

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

相关文档
最新文档