前言
最近正在学习C++,在Linux下进行开发(没有图形界面)。手头没有了像Eclipse[JavaIDE]般好用的工具之后感觉寸步难行,写完程序之后还要费半天劲搞个Makefile去编译链接。开始程序代码少的时候还好,可是当目录和源码变多之后,维护Makefile变成了一个比较痛苦的事情。不仅仅是因为源码和目录的管理,还有Makefile所需的各种配置,所使用的各种变量和参数也是越来越复杂。要能有个工具帮我把Makefile都搞定该多好啊!于是盯上了GNU的自动化Makefile生成工具。大概读了一下automake和autoconf的手册之后,觉得这手册实在就是个手册,当教程恐怕就.....于是自己上网上搜索加上自己动手实践,大概弄清了这一套工具的基本用法,应付普通的编译工作应该是没问题了。不过需要注意的是,虽然是(半)自动化的工具,操作起来还是需要花些时间的,如果您的程序结构不是很复杂的话就用不着了,用了反倒会感觉繁琐。
1. 准备知识
一般来说,一个新事物的诞生都是需求驱动的,Autotools也不例外。据手册上描述,是1991年一个叫做David J. MacKenzie的牛人对于在20个平台上调Makefile感到十分厌倦,就手写了一个名为“configure”的叫本来自动调整不同平台上的Makefile。虽然不知道他为啥需要在20个平台上编译同样的代码,但是其行为还是十分值得敬仰。后来这个工具被不断完善,最终形成了现在的Autotools工具集。它用来为我们的工程代码生成一个GNU Build System,这个所谓的System可以理解为符合GUN源码编写规范的工程。其中最重要的两个工具是autoconf和automake,前者主要用于生“configure”脚本(进行变量定义、测试及编译环境的设定等功能),而后者主要用户自动生成Makefile文件,这些工具需要配合使用才能达到最终目的。
(1)主要步骤及意义
对于一个带有源码的项目来说,要为其自动生成Makefile需要经历一下几个步骤
[1]在工程目录下运行autoscan命令,生成configure.scan文件
[2]将configure.scan改名为configure.ac,并手动修改其中的内容。该文件主要用于定义程序的基本信息(名字、版本号等)、在进行编译之前需
要进行的测试、需要在哪些目录生成Makefile文件等等
[3]在每个要生成Makefile的目录下创建Makefile.am文件,该文件用于生成创建Makefile的规则和变量。也就是说最终的Makefile文件是根据它
来生成的,虽然也需要手动在里面写入一些内容,但是比写Makefile要简单许多。
[4]在工程根目录下建立NEWS、 README、 ChangeLog 、AUTHORS这几个文件,这些文件和其他几个文件(如INSTALL等)都是GNU Build System规
范要求的,里面的内容可以自己写,不想写空着也行,但文件必须得存在。
[5]运行aclocal,这一步的作用是把各个地方定义的宏[就不去管到底有哪些宏了]集中到aclocal.m4里面
[6]运行autoconf命令,将configure.ac中的宏展开,生成configure脚本,中间可能会用到上一步生成的aclocal.m4脚本
[7]运行automake -a命令,作用是将我们自己定义的Makefile.am转换成Makefile.in,该文件会被configure脚本用来生成最终的Makefile文件。
此外,还会把automake安装目录下的一些文件,如果INSTALL,install-sh等作为软连接连到工程根目录(如果工程根目录本身没有这些文件的话)
[8]运行./configure --prefix /you/project/path。进行预定义的测试和生成Makefile文件。注意由于prefix变量用于指定工程目录的前缀,例如项目在/usr/local/app/MyProj,那么这个变量的值就应该设为/usr/local/app。因为很多其他有关于目录的变量(如bindir,srcdird等)的值都是用这个变量定义的(bindir=${prefix}/bin等),所以最好在运行configure脚本时指定一下,不指定将会使用默认值/usr/local
[9]运行make编译,make install进行安装,make clean是清理,这些都已经是定义好的了,不用再手动搞了。
(2)重要变量及宏定义的含义
[1]变量
CC [C代码编译的命令]
CFLAGS [C编译器的Flag]
CXX [C++代码编译的命令]
CXXFLAGS [C++编译器的Flag]
LDFLAGS [linker flags]
CPPFLAGS [C/C++ preprocessor flags]
例如,如果想要编译的时候指定gcc-3编译器,在编译时使用“~/usr/include”目录下的头文件,以及在连接时“~/usr/lib”目录下的库文件的话就可是使用如下命令:./configure --prefix ~/usr CC=gcc-3 CPPFLAGS=-I$HOME/usr/include LDFLAGS=-L$HOME/usr/lib
[2]预定义目录变量及其缺省值
prefix /usr/local
exec_prefix ${prefix}
bindir ${exec_prefix}/bin
libdir ${exec_prefix}/lib
. . .
includedir ${prefix}/include
datarootdir ${prefix}/share
datadir ${datarootdir}
mandir ${datarootdir}/man
infodir ${datarootdir}/info
docdir ${datarootdir}/doc/${PACKAGE}
[3]automake后缀
automake缺省定义了几个后缀,如_PROGRAMS,_SCRIPTS, _DATA, _LIBRARIES,分别代表程序可执行文件,脚本,数据和库。他们的作用是可以与上面提到的目录变量的定义结合起来,作为文件安装的依据。例如,假设我们知道目录变量bindir=${prefix}/bin,该目录一般用于存放生成好的可执行程序文件。如果我们想要把编译生成好的程序文件MyApp最终复制到bindir所指向的目录,我们需要在Makefile.am中定义:bin_PROGRAMS=MyApp。这句话告诉automake把生成好的MyApp文件复制到bindir[注意命名时去掉dir]所指向的目录中去。再例如myappdocdir = ${prefix}/projdir和myappdoc_DATA =README,表示安装时要把README这个文件copy到myappdocdir所指定的目录中去。
2.实战演练
我们的目标是编译如下目录结构的工程,其中src是源码目录,server里面是server的实现代码,也就是需要用这里的代码生成可执行程序;wbl是我们内部的一个库的源码,最后要生成一个名为libwbl.a的库文件供server里的代码使用,子目录及其作用下面有提示。sgi_stl目录里面是sgi stl3.3的源码,本想不用系统自带的stl而使用自己下载的源码,可惜最后没成功。
httpsvr
|
+-- src
| |-- server
| | |
| | `-- httpsvr_main.cpp
| |-- wbl
| | |
| | +-- src[wbl库实现源码]
| | |
| | `-- wbl[wbl库header]
| |
| `- sgi_stl[里面是sgi stl3.3源码]
|
+-- bin
|
+-- conf
|
+-- logs
|
`-- scripts
第一阶段,起步!!
(1)起始设置
我们初始的目录设定如下,httpsvr是指工程根目录,此时除了svr目录之外其他目录都是空的。这一阶段先不管其他目录,只把目光聚焦src/server目录。
httpsvr
|
+-- src
| |-- server
| | |
| | `-- httpsvr_main.cpp
| |-- wbl
| |
| `- sgi_stl
|
+-- bin
|
+-- conf
|
+-- logs
|
`-- scripts
此时server目录下只有一个源文件,我们需要做的是把httpsvr_main.cpp编译成httpsvr_main.o,然后生成可执行文件httpsvr。下面的行动按照本文一开始的步骤进行即可。在程序根目录运行autoconf扫描一遍目录,得到两个文件:autoscan.log和configure.scan运行结束出现两行提示,对于后续操作没有影响忽略即可。
autom4te: configure.ac: no such file or directory
autoscan: /usr/bin/autom4te failed with exit status: 1
(2)生成configure.ac
将configure.scan更名为configure.ac,然后编辑一下其内容,主要添加以下内容
AM_INIT_AUTOMAKE(httpsvr,0.0.1) #指定应用程序名和版本号
AC_PROG_RANLIB #因为需要链接wbl代码生成的库,所以需要加上这个
#指定要生成的Makefile文件,根据我的程序结构,需要如下3个Makefile
AC_OUTPUT([Makefile #在最外层,作为所谓的“总控”Makefile,除了编译之外还可以做一些其他操作,如文件复制、移动等等
src/Makefile #负责编译src目录下的所有源码,也可以成为“源码总控”的Makefile。其实没有也行,只看个人喜好。
src/server/Makefile #负责编译server的实现源码
src/wbl/Makefile]) #负责编译wbl库源码
(3)撰写Makefile.am
对于automake来说,一个Makfile.am就对应一个Makefile,只不过我们可以在Makefile.am里定义一些远比复杂的Makefile本身简单许多的rules。
httpsvr/Makefile.am:
#目前只需要一条语句足矣,主要是告诉automake先去编译src目录下的东东
SUBDIRS=src
httpsvr/src/Makefile.am
#暂时也只有一条,指定先编译wbl下的源码,然后再编译server下的源码
SUBDIRS=wbl server
httpsvr/src/wbl/Makefile.am
#暂空
httpsvr/src/server/Makefile.am
#定义一下bin目录,其实bindir是预定义变量,这里只是为了清晰重新设置一下。
#这里的目的是通过httpsvr_SOURCES源码生成可执行文件httpsvr,在运行make install的时候会把这个可执行文件放到bin目录下
bindir = ${prefix}/bin
bin_PROGRAMS=httpsvr
httpsvr_SOURCES=httpsvr_main.cpp
然后在工程根目录创建:NEWS,README,ChangeLog,AUTHORS,其他文件可以通过automake -a来自动添加。
(4)编译连接
这些工作完成之后就可以aclocal,autoconf,automake -a了,此时已经生成了Makefile.in.
接下来就是执行./configure --prefix /usr/local/app/httpsvr(注意最后不要带“/”),这一步主要是执行各种测试命令并生成Makefile文件
最后几句执行输出是:
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating src/server/Makefile
config.status: creating src/wbl/Makefile
config.status: executing depfiles commands
看着没?生成好了我们在configure.ac中所希望的输出文件
下面就简单了,在工程根目录下执行make,然后再make install。我们就可以在输出目录bin下看到可执行文件httpsvr了,初期目标大功告成!
第二阶段,编译wbl!!
httpsvr
|
+-- src
| |-- server
| | |
| | `-- httpsvr_main.cpp
| |-- wbl
| | |
| | +-- src
| | |
| | `-- wbl
| |
| `- sgi_stl
|
`-- etc....
(1)Makefile.am定义
wbl/wbl下是接口定义的头文件,src里面是实现代码。具体功能和内容忽略,只需要知道目录结构即可。
wbl/Makefile.am的定义如下:
#定义Flag
AM_CFLAGS = -I wbl
AM_CXXFLAGS = -I wbl $(EXPAT_CFLAGS)
#标识wbl的源码将会生成一个名为libwbl.a的库文件,该库文件仅用于编译链接而不是安装
noinst_LIBRARIES = libwbl.a
#定义生成wbl库所需要的源码,注意名字
libwbl_a_SOURCES = \
wbl/atomic_count.h\
下略...
#生成库文件所需要的flags
libwbl_a_LIBFLAGS = $(EXPAT_LDFLAGS) $(EXPAT_LIBS)
【EXPAT_CFLAGS、EXPAT_LDFLAGS和EXPAT_LIBS这三个变量的意义还有待挖掘】
(2)编译时引用libwbl.a库文件
在编译src/server/下源码的时候,如果要引用刚刚生成的wbl库,需要在src/server/Makefile.am中加入:
AM_CXXFLAGS = -I $(top_srcdir)/src/wbl -I .
这句的意思是编译的时候要引入httpsvr/src/wbl目录
httpsvr_LDADD=$(top_srcdir)/src/wbl/libwbl.a
这个意思是说链接的时候需要引入httpsvr/svc/wbl/libwbl.a库文件,后面还需要引入库文件的话可以用空格分隔即可。注意top_srcdir是一个预定义变量,指代源码的根目录,缺省值是${prefix}/src
【AM_CXXFLAGS的作用】
if g++ -DPACKAGE_NAME=\"httpsvr\" -DPACKAGE_TARNAME=\"httpsvr\" -DPACKAGE_VERSION=\"0.0.1\" -DPACKAGE_STRING=\"httpsvr\ 0.0.1\" -
DPACKAGE_BUGREPORT=\"eddiexue@tencent.com\" -DPACKAGE=\"httpsvr\" -DVERSION=\"0.0.1\" -I. -I. -I /usr/local/app/httpsvr/src/wbl -I. -g -O2 -MT httpsvr_main.o -MD -MP -MF ".deps/httpsvr_main.Tpo" -c -o httpsvr_main.o httpsvr_main.cpp; then mv -f".deps/httpsvr_main.Tpo" ".deps/httpsvr_main.Po"; else rm -f ".deps/httpsvr_main.Tpo"; exit 1; fi
【httpsvr_LDADD设定的作用】
g++ -I /usr/local/app/httpsvr/src/wbl -I . -g -O2 -o httpsvr httpsvr_main.o /usr/local/app/httpsvr/src/wbl/libwbl.a
第二阶段,编译sgi_stl 3.3!!
经过各种方法尝试之后发现似乎没办法用自带的stl源码覆盖系统的stl,当我在INCLUDE中定义-I${prefix}/src/sgi_stl之后,程序里无论是使用#include <vector>、#include "include" 还是#include "sgi_stl/vector"都会导致错误,看起来貌似是定义冲突之类的问题,难道系统的stl和程序里自带的stl不能共存吗?那stl源码是怎么测试的?这个问题问了无所不知的google也没找到答案。
后记
对于最后一个问题各位谁有这方面的经验可以不吝指教。有其他想法也可以通过jxuedi@gmail.com或留言,期待与各位交流。
分享到:
相关推荐
在Linux环境中,Autotools是一套工具集合,用于自动化软件构建过程,包括autoconf、automake、libtool等。这些工具使得开发者能够编写出可以在多种操作系统和硬件平台编译的源代码,尤其对于进行交叉编译时,其作用...
3. 实战案例:通过实际项目示例展示如何在项目中集成和使用autoTools。 4. 跨平台编译策略:如何利用autoTools确保软件在多种操作系统上运行。 通过阅读这些电子书,开发者不仅可以提升构建工具的使用技能,还能更...
GNU autotools 入门指南 GNU autotools 是一个强大且功能丰富的构建工具,广泛应用于开源软件的构建和安装过程中。在本文中,我们将深入探讨 GNU autotools 的基本概念、组件和使用方法,以便帮助读者更好地理解和...
自己写的autotools工具链:ws作为自动编译工具,只要在写好程序的目录下运行ws便可得到经过autotools处理的可执行文件和安装包,并且会生成在arm板上运行的二进制文件 arm.bin .ws是一个别名,在.bashrc文件中定义,...
**GNU Autotools 多级目录构建详解** 在软件开发中,尤其是在Unix-like系统中,GNU Autotools是一套强大的工具链,它包括Autoconf、Automake和Libtool等组件,用于生成可移植的Makefile,使项目能够在不同的平台上...
### Autotools 入门详解 #### 一、前言 Autotools 是一组用于辅助在 Unix 和类 Unix 操作系统上构建软件包的工具集。这套工具包括 Autoconf、Automake、Libtool 和 Gettext 等。它们主要用于帮助开发者创建可移植...
### 使用GNU Autotools改造一个软件项目的知识点梳理 #### 一、示例项目介绍 - **项目背景**:本文档采用Wei Mingzhi开发的一款麻将游戏作为示例,旨在通过实际项目来展示如何使用GNU Autotools进行软件项目管理。...
通过两天的学习,基本掌握了autotools(autoconf/automake)工具的使用。然后把这两天学习用到的资料整理了下,全是干货,能以最快的速度学会用autotools来产生符合GNU标准的小型项目,从而满足自己平时发布开源代码的...
标题中的“自己写的autotools工具”指的是作者利用Autotools这一开源构建系统自定义创建的一个脚本。Autotools是一套在Unix/Linux系统中广泛使用的自动化构建工具,包括Autoconf、Automake和Libtool等组件,它们可以...
Autotools是一组用于生成makefile的工具,它们包括autoscan、autoconf、autoheader、aclocal、automake和configure等。使用Autotools可以帮助开发者自动化生成配置和编译文件的过程。以下是使用Autotools制作...
### 五、实战应用 以一个简单的C语言项目为例,我们创建`configure.ac`,定义项目信息和依赖;编写`src/Makefile.am`,设置源文件和目标文件;然后运行`autoreconf -i`来生成所有必要的文件,接着执行`./configure`...
### Linux Autotools 讲稿知识点总结 #### 一、前言 - **目标受众**:这份演示文稿的目标读者是对Unix开发工具(如shell、make、编译器等)有所了解并希望学习Autotools的开发者。 - **最新版本获取**:读者可以从...
使用autotools工具包中的autoconf, automake, 以及libtool组织的一个包含多个原码目录的helloworld工程。工程比较简单, 就不具体说明了, 供初学autotools的同学参考。 解压原码包之后按序执行./configure, make...
autotools-dev_20100122.1_all 交叉工具链编译是需要。
### Autotools 使用详解——Linux Makefile 自动生成工具 #### 一、引言 在 Linux 开发领域,Autotools 可谓是不可或缺的工具之一。它不仅极大地简化了软件包的构建过程,还使得跨平台编译变得轻而易举。通过使用 ...
《GNU Autotools详解》 GNU Autotools是开源软件开发中的一个重要工具集,它包括了autoconf、automake和libtool等组件,主要用于构建跨平台的C/C++项目。这些工具帮助开发者创建出能够在不同操作系统和硬件架构上...
这使得开发者可以利用Autotools(Autoconf、Automake和Libtool)等自动化构建工具来配置、编译和打包开源软件。 Autoconf是一个自动配置脚本生成器,它检查主机系统上的特性,然后生成一个configure脚本,这个脚本...
autotools使用说明文档、配套的hello源码操作指南。 linux 下c/c++使用autotools工具自动生成makefile 操作说明。 指令:autoscan、aclocal、autoheader、autoconf、automake 创建:makefile.am等
标题 "测试autotools的源码" 涉及到的是使用GNU Autotools构建开源软件项目的实践。Autotools是一套工具集合,包括autoconf、automake、autoheader和aclocal,它们主要用来帮助开发者在不同的操作系统和编译器环境下...
### Autotools:实践者的指南—GNU Autoconf、Automake与Libtool #### 知识点一:Autotools概述 - **定义**:Autotools是一套用于辅助跨平台软件构建过程的工具集合,主要由GNU Autoconf、Automake与Libtool组成。...