update ZIM

This commit is contained in:
geekard
2013-01-19 17:16:59 +08:00
parent d94d414d18
commit ac6326ab22
20 changed files with 413 additions and 469 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*~
auto/

View File

@@ -1,4 +1 @@
* GCC 与 Glibc的关系
GCC与Glibc是相互依赖的关系部分链接的GCC在加载时需要Glibc提供的目标对象符号。
GCC运行时库文件也需要Glibc提供的符号。同时Glibc提供的crt1.o,crti.o,crtn.o等也
依赖GCC的crtbegin.o, crtend.o等提供的符号。

BIN
Org/Tool-Chain.pdf Normal file

Binary file not shown.

42
Org/Tool-Chain.tex Normal file
View File

@@ -0,0 +1,42 @@
% Created 2013-01-07 Mon 12:24
\documentclass[11pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{fixltx2e}
\usepackage{graphicx}
\usepackage{longtable}
\usepackage{float}
\usepackage{wrapfig}
\usepackage{soul}
\usepackage{textcomp}
\usepackage{marvosym}
\usepackage{wasysym}
\usepackage{latexsym}
\usepackage{amssymb}
\usepackage{hyperref}
\tolerance=1000
\providecommand{\alert}[1]{\textbf{#1}}
\title{Tool-Chain}
\author{}
\date{\today}
\hypersetup{
pdfkeywords={},
pdfsubject={},
pdfcreator={Emacs Org-mode version 7.8.11}}
\begin{document}
\maketitle
\setcounter{tocdepth}{3}
\tableofcontents
\vspace*{1cm}
\section{GCC 与 Glibc的关系}
\label{sec-1}
GCC与Glibc是相互依赖的关系部分链接的GCC在加载时需要Glibc提供的目标对象符号。
GCC运行时库文件也需要Glibc提供的符号。同时Glibc提供的crt1.o,crti.o,crtn.o等也
依赖GCC的crtbegin.o, crtend.o等提供的符号。
\end{document}

Binary file not shown.

View File

@@ -1,7 +1,7 @@
[History]
list=[["Utils:\u5de5\u5177\u94fe:autoconf---automake:Autoconf\u5b66\u4e60\u7b14\u8bb0",7575,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b",849,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake",3328,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b",1475,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake",3328,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b",3346,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake",3328,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b",65,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b:demo.c",40,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b:foo.c",39,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b:demo.c",1314,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b:foo.c",135,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b:demo.c",1314,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b",5599,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake",3328,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b",10803,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:Autoconf\u5b66\u4e60\u7b14\u8bb0",7575,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b:foo.c",135,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b:autoreconf",2682,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:Autoconf\u5b66\u4e60\u7b14\u8bb0",7731,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:autoconf\u8f6f\u4ef6\u5305",698,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:Autoconf\u5b66\u4e60\u7b14\u8bb0",7731,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:autoconf\u8f6f\u4ef6\u5305",130,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:Autoconf\u5b66\u4e60\u7b14\u8bb0",873,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:Autotools\u4e0a\u624b\u6307\u5357",276,null]]
list=[["Utils:\u5de5\u5177\u94fe:libtool:libtool\u7684\u4f5c\u7528\u53ca\u5e94\u7528",164,null],["Utils:\u5de5\u5177\u94fe:autotut-Using GNU autoconf-automake-autoheader",57108,null],["Utils:\u5de5\u5177\u94fe:pkgconfig",0,null],["Utils:\u5de5\u5177\u94fe:pkgconfig:linux\u91cc\u547d\u4ee4pkg-config\u5de5\u5177\u7684\u4f7f\u7528",0,null],["Utils:\u5de5\u5177\u94fe:pkgconfig",5545,null],["Utils:\u5de5\u5177\u94fe:pkgconfig:Makefile\u597d\u52a9\u624b\uff1apkgconfig",1740,null],["Utils:\u5de5\u5177\u94fe:pkgconfig",5545,null],["Utils:\u5de5\u5177\u94fe:autotut-Using GNU autoconf-automake-autoheader",57108,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:Is your build environment sane \uff1f",162,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:Autotools\u4e0a\u624b\u6307\u5357",7212,null],["Utils:\u5de5\u5177\u94fe:gcc&g++",0,null],["Utils:\u5de5\u5177\u94fe:libtool",6567,null],["Utils:\u5de5\u5177\u94fe:libtool:libtool\u7684\u4f5c\u7528\u53ca\u5e94\u7528",164,null],["Utils:\u5de5\u5177\u94fe:\u4f7f\u7528GNU Autotools\u81ea\u52d5\u7de8\u8b6f\u9805\u76ee",155,null],["Utils:\u5de5\u5177\u94fe:libtool:libtool\u7684\u4f5c\u7528\u53ca\u5e94\u7528",164,null],["Utils:\u5de5\u5177\u94fe:libtool",6350,null],["Utils:\u5de5\u5177\u94fe:libtool:libtool\u7684\u4f5c\u7528\u53ca\u5e94\u7528",315,null],["Utils:emacs:dired",3523,null],["Research:Error Notes:\u7f16\u8bd1\u9519\u8bef:libnl",4258,null],["Utils:Graphviz",0,null],["Utils:Graphviz:Graphviz\u4ecb\u7ecd",0,null],["Utils:emacs:gnus",3181,null],["Research:Error Notes:\u7f16\u8bd1\u9519\u8bef",0,null],["Research:Error Notes:\u7f16\u8bd1\u9519\u8bef:libnl",4528,null],["Research:Error Notes:\u7f16\u8bd1\u9519\u8bef:busybox",2449,null]]
current=24
recent=[["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u56fe\u89e3autoscan\u3001aclocal\u3001autoheader\u3001automake\u3001autoconf\u3001configure\u3001make",0,null],["Utils:\u5de5\u5177\u94fe:automake\u53d8\u91cf",0,null],["Utils:\u5de5\u5177\u94fe:autotut-Using GNU autoconf-automake-autoheader",0,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b:demo.c",1314,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake",3328,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b",10803,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b:foo.c",135,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:\u5b9e\u4f8b:autoreconf",2682,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:Autoconf\u5b66\u4e60\u7b14\u8bb0",873,null],["Utils:\u5de5\u5177\u94fe:autoconf---automake:Autotools\u4e0a\u624b\u6307\u5357",276,null]]
recent=[["Utils:\u5de5\u5177\u94fe:\u4f7f\u7528GNU Autotools\u81ea\u52d5\u7de8\u8b6f\u9805\u76ee",155,null],["Utils:\u5de5\u5177\u94fe:libtool",6350,null],["Utils:\u5de5\u5177\u94fe:libtool:libtool\u7684\u4f5c\u7528\u53ca\u5e94\u7528",315,null],["Utils:emacs:dired",3523,null],["Utils:Graphviz",0,null],["Utils:Graphviz:Graphviz\u4ecb\u7ecd",0,null],["Utils:emacs:gnus",3181,null],["Research:Error Notes:\u7f16\u8bd1\u9519\u8bef",0,null],["Research:Error Notes:\u7f16\u8bd1\u9519\u8bef:libnl",1365,null],["Research:Error Notes:\u7f16\u8bd1\u9519\u8bef:busybox",2449,null]]
[MainWindow]
windowsize=[1278,779]
@@ -50,7 +50,7 @@ calendar_expanded=False
[InsertImageDialog]
windowsize=[1280,749]
attach_inserted_images=False
last_image_folder=/home/geekard/Notes/Zim/Utils/gdb/gdb_debugging
last_image_folder=/home/geekard/Notes/Zim/Utils/\u5de5\u5177\u94fe/\u4f7f\u7528GNU_Autotools\u81ea\u52d5\u7de8\u8b6f\u9805\u76ee
[InsertLinkDialog]
windowsize=[328,156]

View File

@@ -9,11 +9,10 @@ dired 是 Emacs 自带的文件管理器,操作非常方便,再加上一些
===== Mark & Flag =====
dired 最方便的一点就是可以**对许多文件进行标记,并进行批量操作**。标记的方法有很多,最普通的标记就是 __d __为当前文件贴上删除标签之后可以使用 __x__ 来真正删除所有贴上删除标签的文件。
dired 还提供了许多预定义的方便的标记操作(当使用__ C-u 传递一个前缀参数时他们执行相反操作__即去掉标记),例如:
通常这些命令可以方便地帮你清理垃圾如果还不满意可以使用__ % d __REGEXP <RET> 来输入自己的正则表达式,匹配到的文件会被贴上删除标签。
当然,能用的标签并不止是 __D (即删除标签)__几乎任何一个字符都可以使用(但需要通过转换默认的为D和*标签)不过__最常用的还是 *__ m 命令即是以 * 标记当前文件。同样dired 提供了很多方便的标记操作(这些命令在传递一个前缀参数的时候都会执行相反的操作,例如 C-u * * 会去掉所有可执行文件的标记)
当然,能用的标签并不止是 __D (即删除标签)__几乎任何一个字符都可以使用(但需要通过转换默认的为D和*标签)不过__最常用的还是 *__ m 命令即是以 * 标记当前文件。同样dired 提供了很多方便的标记操作(这些命令在传递一个前缀参数C-u的时候都会执行__相反__的操作,例如 C-u * * 会去掉所有可执行文件的标记)
dired 可以使用更多的字符进行标记,只是没有提供相应的快捷键操作而已,你可以先以 * 标记,然后使用 * c OLD-MARKCHAR NEW-MARKCHAR 来把 * 标记变换成其他标记,几乎任何字符(当然不包括中文这种多字节的字符)都可以作为标记,不过空格被特殊对待,用于表示所有未标记的文件。
@@ -34,9 +33,9 @@ dired 还提供了许多预定义的方便的标记操作(当使用__ C-u 传递
dired 内建了很多文件操作,对于操作的文件有一个统一的约定,按照顺序是:
__如果你通过 C-u 传递一个前缀参数 N ,那么它对从当前行开始的 N 行执行操作( N 也可以是负数)。__
__ 如果有被标记为 * 的文件则以这些文件为操作对象。__
__ 只对当前光标所在的文件进行操作。__
* __如果你通过 C-u 传递一个前缀参数 N ,那么它对从当前行开始的 N 行执行操作( N 也可以是负数)。__
* __如果有被标记为 * 的文件则以这些文件为操作对象。__
* __只对当前光标所在的文件进行操作。__
这些命令全部__绑定到大写字母__上记忆也非常方便
@@ -65,7 +64,7 @@ __ 只对当前光标所在的文件进行操作。__
以上命令的标记为D
a 在当前buffer打开目录(默认是在新的buffer打开目录)
i 在当前buffer尾部打开目录并设置标记
k 隐藏标记为*的文件
k 隐藏标记为__*__的文件
o 在新buffer中打开当前文件并将光标移到其中
q 关闭当前窗口(不是文件编辑窗口)
n 下移一行
@@ -89,41 +88,35 @@ __ 只对当前光标所在的文件进行操作。__
__w 复制文件名,如果通过 C-u 传递一个前缀参数 0 ,则复制决定路径名,如果只是 C-u 则复制相对于 dired 当前目录的相对路径。__
I 把当前文件以 info 文档的格式打开。
N 把当前文件以 man 格式打开(使用 WoMan)。
Y 为所有标记的文件创建一个到指定目录的相对符号连接(即使用相对路径进行引用,而不是绝对路径)。
===== *命令 =====
** 标记所有可执行文件
*@ 标记所有符号链接文件
*/ 标记所有目录文件
*s 标记所有文件为*
*. 标记具有给定扩展名的文件
* % REGEXP <RET>标记所有__文件名__匹配到给定的正则表达式的文件
*s 标记__所有文件__为*
* % REGEXP <RET>标记所有__文件名__匹配到给定的正则表达式的文件等效的命令为%m
*? MARKCHAR 或 M-<DEL> __去除所有以 MARKCHAR 标记的文件的标记__如果传递一个前缀参数则会对每一个文件要求你确认是否去除标记。
__* c OLD-MARKCHAR NEW-MARKCHAR__ 把 * 标记变换成其他标记
以上命令的标记为*
*! 去除所有文件的标记等效的命令为U
以上命令的标记为*它们为Dired其它命令的默认操作文件。
===== %命令(一般和正则表达式有关) =====
%d REGEXP <RET> 把__文件名__符合正则表达式的文件标记为删除D
% m REGEXP <RET> >标记所有__文件名__匹配到给定的正则表达式的文件
% g REGEXP <RET> 标记所有__文件 内容__ 匹配到给定的正则表达式的文件
% m REGEXP <RET> >标记所有__文件名__匹配到给定的正则表达式的文件
% g REGEXP <RET> 标记所有__文件内容__ 匹配到给定的正则表达式的文件
正则表达式语法为grep而非egrep
===== 强大的重命名功能 =====
dired 有一个文件名转换的理念,所以转换,并不一定是重命名,还可以是复制和创建链接。所以,除了 % u 和 % l 重命名原文件为大写、小写外,一个使用正则表达式进行转换的命令提供了四个选项: __% X 其中 X 可以是 R , C , H 和 S __分别代表重命名、复制、创建硬链接和创建软链接他们使用匹配和替换的机制这有点像 rename 这个程序,例如: % R \.[^.]*$ <RET> .1\& <RET> 给原来的文件名加个标号 1 ,把 foo.txt 变成 foo.1.txt 。
另外dired 还有一个叫做 __Wdired__ 的扩展可以直接在 dired 的 buffer 里面编辑文件名来达到重命名的效果。使用 __M-x wdired-change-to-wdired-mode__ 进入编辑模式,这个时候可以直接像编辑普通文本一样编辑文件名,还可以添加路径来实现把文件移动到其他目录(可以通过保存文件的方式来使更改生效)。除了文件名可以编辑以外,其他部分被标记为只读,但是如果把 __wdired-allow-to-change-permissions__ 设为 t 的话,还可以编辑文件的权限位。编辑完成之后使用 C-c C-c 来应用所做的编辑。非常方便。
===== 排序和过滤 =====
dired 有方便的排序功能,这里介绍了如何方便地使用排序功能。另外 dired 还有一个 __k__ 用于去掉不想显示出来的文件,它并不删除磁盘上的文件,只是临时从 dired 的 buffer 中去掉他们__ g __刷新一下它们又会显示出来这样首先用强大的标记功能进行标记然后使用 k 去掉,就实现了过滤的功能。
子目录操作
===== 同时操作当前目录和子目录 =====
dired 允许同时操作当前目录和子目录。在 dired-listing-switches 里面加入 R 选项就可以显示子目录如果只是想临时显示某个子目录的内容对该目录执行__ i __操作就会把该子目录的内容添加到 dired __当前 buffer 的末尾__并把光标移动到那里dired 在__移动之前会先设置一个 mark__ ,所以可以使用 C-u C-<SPC> (对于我来说,我把 set-mark-command 绑定到了 M-<SPC> 上,这里自然就是使用 C-u M-<SPC> 了)回到原来的位置。
还有一些方便的功能,我把几个常用的命令列在这里:

View File

@@ -10,37 +10,11 @@ ccmx 于 2011年 一月 7日 发表 | 最后修改于 2011年 一月 10日
要想弄懂Autotools并使用它必须先要了解一下M4这个怪物。那么何为M4呢M4的名称取自MacroM后面跟4个字母…。它和C预处理器里的宏是一个概念其实M4和C预处理器都K&R操刀设计的用来处理文本替换。也就是说M4是bash里的预处理器。
取自维基的例子:
divert(-1)
This `divert' discards this text. Note that I had to quote the `divert'
in the comment so it wouldn't get undiverted.
This starts the count at ONE as the incr is a preincrement.
define(`H2_COUNT', 0)
The define H2_COUNT is redefined every time the H2 macro is used.
The dnl deletes everything on the line after it in the output (ie this bit)
define(`H2', `define(`H2_COUNT', incr(H2_COUNT))'dnl
`<h2>H2_COUNT. $1</h2>')
divert(0)dnl diversion to 0 means back to normal dnl removes this line.
H2(First Section)
H2(Second Section)
H2(Conclusion)
这段M4宏用m4处理输出的结果就是
<h2>1. First Section</h2>
<h2>2. Second Section</h2>
<h2>3. Conclusion</h2>
简单说下:
1.M4的语法跟C里面宏的语法差不多都很像函数名字加括号。
2.M4里的参数即使声明了也是可以忽略的如果一个宏一个参数都不加的话括号都可以忽略。
懂了吧。就当你懂了。
autoconf就是基于M4这个工具来生成configure脚本的。
我们来看一个最简单的autoconf输入将下面代码存为configure.ac
autoconf就是基于M4这个工具来生成configure脚本的。我们来看一个最简单的autoconf输入将下面代码存为configure.ac
AC_INIT([test], [1.0])
AC_CONFIG_FILES([Makefile])
@@ -54,8 +28,6 @@ all: @PACKAGE_NAME@_bin
gcc -o @PACKAGE_NAME@_bin test.c
好,下面执行命令:
$ autoconf
$ ./configure
@@ -67,9 +39,9 @@ test_bin: test.c
中间发生了什么?停我慢慢道来。
首先autoconf读取configure.ac里的宏__调用M4处理这些宏__做些检查如果你很感兴趣这些宏的实现可以在__/usr/share/autoconf/autoconf__/*.m4里找到这些宏的定义看了不要发疯。检查完会生成两个文件configure。执行configure脚本生成__config.status和config.log__。config.log里面是执行的记录config.status是下一步执行的__脚本__用来生成Makefileconfigure生成完这个脚本会自动调用的。
首先autoconf读取configure.ac里的宏__调用M4处理这些宏__做些检查如果你很感兴趣这些宏的实现可以在__/usr/share/autoconf/autoconf/*.m4__里找到这些宏的定义看了不要发疯。检查完会生成两个文件configure。执行configure脚本生成__config.status和config.log__。config.log里面是执行的记录config.status是下一步执行的__脚本__用来生成Makefileconfigure生成完这个脚本会自动调用的。
那Makefile.in又是什么呢那是第二个宏AC_CONFIG_FILES([Makefile])执行时的默认输入。__方括号是用来表示参数的__。就像上面的`一样。Makefile.in就是一个模板用来生成Makefile。执行configure脚本时实际上是config.status脚本里面的%变量%会被替换成相应的内容。有哪些变量看看config.log就知道了。
那Makefile.in又是什么呢那是第二个宏AC_CONFIG_FILES([Makefile])执行时的默认输入。__方括号是用来表示参数的__。就像上面的`一样。Makefile.in就是一个模板用来生成Makefile。执行configure脚本时实际上是config.status脚本里面的__@变量@__会被替换成相应的内容。有哪些变量看看config.log就知道了。
前面说了autotools的基本原理将configure.ac里的宏展开运行生成Makefile。其实对于大多数项目来说configure.ac里的内容基本框架都差不多。既然都差不多那么有没有什么工具可以帮我们做这些基本的事情呢别忘了你在linux下
@@ -83,7 +55,6 @@ test
└── server.c
在test目录下运行autoscan看看。是不是生成了如下的configure.scan呢autoscan.log被我们无情的忽略了
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
@@ -102,7 +73,7 @@ AC_PROG_CC
**AC_CHECK_HEADERS**([netinet/in.h stdlib.h strings.h sys/socket.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
**AC_TYPE_PID_T**
AC_TYPE_PID_T
# Checks for library functions.
AC_FUNC_FORK
@@ -117,9 +88,7 @@ AC_CHECK_FUNCS([bzero socket])
我们解释一下这个文件里的一些宏。
首先是AC_PREREQ([2.68])这个宏用来检查你__机器上的autoconf版本__的。这里是我机器上的版本号2.68。
然后AC_INIT宏这里你要将里面的内容改改里面的提示你懂的。我们改成下面这样
AC_INIT([test], [0.1], [dccmx@test.com])
紧跟着是AC_CONFIG_SRCDIR([src/server.c])__这是autoconf用来定位自己的所在目录的宏里面的内容是所在目录下的任意一个文件就可以了__你可以改成一个更能代表你项目的文件这样不会更其他项目冲突也可以不动。
@@ -165,8 +134,6 @@ config.h.in呢我们写一个吧从上面autoscan生成的configure.ac来
所有存在的头文件都被define成了1__不存在的被注释掉__。好吧在你的程序里尽情的include吧生活真美好。现在可以make生成可执行文件了。test_client和test_server是不是如愿生成了呢应该是的
现在我们项目中仍然有两个.in文件要我们自己写config.h.in和Makefile.in关于这两个文件的工具我们后面再谈。
前面提到config.h.in和Makefile.in还要手写现在我们就来看看Autotools里有那些工具帮助我们完成这些体力活。
首先是config.h.in。这个非常简单弄好configure.ac后直接在项目根目录运行下面命令
@@ -174,8 +141,8 @@ __autoheader__
看看是不是生成了config.h.in了看看内容。真轻松啊__autoheader工具分析了configure.ac里面所有要检查的东西然后生成了相应的宏__好了可以用了。
Makefile.in的生成就比较复杂了毕竟Makefile是个复杂的东东。
我坦白要自动生成Makefile.in以便让configure自动生成Makefile你必须再手动写个Makefile.am文件这就是灵活的代价和unix的哲学
Makefile.in的生成就比较复杂了毕竟Makefile是个复杂的东东。我坦白要自动生成Makefile.in以便让configure自动生成Makefile你必须再手动写个Makefile.am文件这就是灵活的代价和unix的哲学
所谓Makefile.am其实就是__automake用来生成Makefile.in的模板__里面就像一般的Makefile只不过加了一些automake宏。
回顾前面的目录结构我们需要在根目录和所有源码目录添加Makefile.am文件如下
@@ -189,31 +156,25 @@ test
└── server.c
先来看根目录下的Makefile.am文件
SUBDIRS = src
灰常简单!
再看src目录下的Makefile.am文件
bin_PROGRAMS = client server
client_SOURCES = client.c
server_SOURCES = server.c
同样灰常简单,这个文件,不解释,你懂的。现在应该淡定些了。
现在我们还需要建一些文件AUTHORS、COPYING、NEWS、ChangeLog和README这些文件都是gnu项目的标准文件automake会检查这些文件的。所以如果不想要的话先建个空文件搪塞一下吧如果实在受不了也可以用__foreign__参数来禁止这个检查。
同样灰常简单,这个文件,不解释,你懂的。现在应该淡定些了。现在我们还需要建一些文件AUTHORS、COPYING、NEWS、ChangeLog和README这些文件都是gnu项目的标准文件automake会检查这些文件的。所以如果不想要的话先建个空文件搪塞一下吧如果实在受不了也可以用__foreign__参数来禁止这个检查。
最后一步__在configure.ac里面加上automake支持的宏__
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.68])
AC_INIT([test], [1.0], [test@dccmx.com])
AM_INIT_AUTOMAKE
**AM_INIT_AUTOMAKE**
AC_CONFIG_SRCDIR([src/server.c])
AC_CONFIG_HEADERS([config.h])
@@ -233,7 +194,7 @@ AC_FUNC_FORK
AC_FUNC_MALLOC
AC_CHECK_FUNCS([bzero socket])
AC_CONFIG_FILES([Makefile src/Makefile])
**AC_CONFIG_FILES([Makefile src/Makefile])**
AC_OUTPUT
看到了我们现在初始化部分__加了AM_INIT_AUTOMAKE 来初始化automake__在最后又改了AC_CONFIG_FILES([Makefile src/Makefile]) 来吧src目录下的Makefile也加入管理。
@@ -247,19 +208,21 @@ dccmx@~/projects/console/test$ automake a c
dccmx@~/projects/console/test$ make
神清气爽啊。在src目录里生成两个二进制文件了。make distclean看看一切恢复如初make dist看看自动打包发布。生活真是美好啊。
等等第一个命令是干什么的呢这个命令是用来生成automake依赖的宏的供autoconf调用因为automake其实不是autoconf的一部分只相当于插件。automake后面的两个参数又是干什么的呢因为automake生成的__Makefile需要一些外部脚本辅助__而项目里是没有的所以-a就是把这些文件__自动添加__就来-c就是指定用__复制的方式添加__否则是符号链接。
有了前面几篇文章介绍的几招,基本的构建系统就算完成了。开始离专业水平还有一定距离。我们现在看看一些后续的方法,让我们的构建脚本更加专业。
1.设置库依赖和预处理宏:
设置依赖库和宏的方法很简单只要维护gcc的参数就ok了。这些参数在Makefile.am里面维护。
设置依赖库和宏的方法很简单,只要维护__gcc的参数__就ok了。这些参数在**Makefile.am**里面维护。
先在configure.ac里面加上相关的宏__AM_PROG_CC_C_O__。
要添加预处理宏的话比如_GNU_SOURCE宏只要在Makefile.am里面添加__xxx_CFLAGS__ = -D_GNU_SOURCE。好了。重新configure吧。
依赖的库呢你猜对了在Makefile.am里面添加__xxx_LDFLAGS__ = -lssl -lidn -lz就ok了。生活。。。真美好
[[autoconf---automake]]
2.检查目标系统上的库:

View File

@@ -5,33 +5,6 @@ Creation-Date: 2012-06-14T10:05:55+08:00
====== GNU Automake ======
Created Thursday 14 June 2012
GNU Automake
For version 1.3, 3 April 1998
David MacKenzie and Tom Tromey
@dircategory GNU admin @direntry * automake: (automake). Making Makefile.in's
@dircategory Individual utilities @direntry * aclocal: (automake)Invoking aclocal. Generating aclocal.m4
Copyright (C) 1995, 96 Free Software Foundation, Inc.
这是GNU Automake文档的第一版
并且是针对GNU Automake 1.3的。
自由软件基金会出版
59 Temple Place - Suite 330,
Boston, MA 02111-1307 USA
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the Free Software Foundation.
只要版权声明和本许可声明保留在所有副本中,您就被授权制作和发行本手册的 原文副本。
只要整个最终派生工作按照与本手册相同的许可声明发行,您就被授权按照与 发行原文相同的条件复制和发行本手册的修改版本。
除了本许可声明应该使用由基金会批准的译文之外,您被授权按照与上述修改 版本相同的条件复制和发行本手册的其它语言的译文。
本文档由王立翻译。 1999.12.17
译者在此声明:不对任何由译文错误或者对译文的误解承担任何责任。
===== 介绍 =====
__Automake是一个从文件`Makefile.am'自动生成`Makefile.in' 的工具__。每个`Makefile.am'基本上是__一系列make的宏定义__ make规则也会偶尔出现。生成的`Makefile.in's服从GNU Makefile标准。
@@ -60,13 +33,14 @@ Automake不能识别GNU对make的扩展。在`Makefile.am'中使用这些扩展
Automake试图明智地把注释和相邻的目标或者变量定义关联起来。
在`Makefile.am'中定义的目标通常覆盖了所有由automake 自动生成的拥有相似名字的目标。虽然Automake提供了这一功能但最好避免使用它 因为有些时候生成的规则将是十分特别的。
在`Makefile.am'中定义的目标通常__覆盖了__所有由automake 自动生成的拥有相似名字的目标。虽然Automake提供了这一功能但最好避免使用它 因为有些时候生成的规则将是十分特别的。
类似地__在`Makefile.am'中定义的变量将覆盖任何通常由automake 创建的变量定义__。该功能比覆盖目标定义的功能要常用得多。需要警告的是许多由 automake生成的变量都被认为是内部使用的并且它们的名字可能在未来 的版本中改变。
类似地__在`Makefile.am'中定义的变量将覆盖任何通常由automake 创建的变量定义__。该功能比覆盖目标定义的功能要常用得多。需要警告的是许多由 automake生成的变量都被认为是内部使用的并且它们的名字可能在未来的版本中改变。
在检验变量定义的时候Automake将递归地检验定义中的变量引用。例如如果Automake 在如下片断中搜索`foo_SOURCES'的内容。
xs = a.c b.c foo_SOURCES = c.c $(xs)
xs = a.c b.c
foo_SOURCES = c.c $(xs)
它将把文件`a.c'、 `b.c'和 `c.c'作为`foo_SOURCES' 的内容。
@@ -80,7 +54,7 @@ Automake还允许给出不被复制到输出中的注释所有以`##'开头
automake支持三种目录层次 “flat”、“shallow”和“deep”。
* 一个flat包指的是__所有文件__都在一个目录中的包。为这类包提供的`Makefile.am' 缺少宏SUBDIRS。这类包的一个例子是termutils。
* 一个flat包指的是__所有文件__都在一个目录中的包。为这类包提供的`Makefile.am' 缺少__宏SUBDIRS__。这类包的一个例子是termutils。
* 一个deep包指的是所有的源代码都被储存在子目录中的包顶层目录主要包含配置信息。GNU cpio 是这类包的一个很好的例子GNU tar也是。deep包的顶层`Makefile.am'将包括宏SUBDIRS但没有定义需要创建的对象的宏(**所有的对象如可执行程序和库文件都是在SUBDIRS中的makefle.am中定义的**)。
* 一个shallow包指的是主要的源代码储存在顶层目录中而各个部分典型的是库则储存在子目录中的包。Automake本身就是这类包GNU make也是如此它现在已经不使用automake。这样顶层的makefile.am既包括SUBDIRS宏__也包括__创建对象的宏定义使用的是顶层目录的源代码
@@ -115,7 +89,7 @@ EXTRA_PROGRAMS = mt rmt
bin_PROGRAMS = cpio pax
sbin_PROGRAMS = @PROGRAMS@
定义没有前缀的主变量比如说PROGRAMS是错误的。
定义没有__前缀__的主变量比如说PROGRAMS是错误的。
在构造变量名的时候,通常省略后缀`dir';因此我们使用 `bin_PROGRAMS'而不是`bindir_PROGRAMS'.

View File

@@ -7,7 +7,6 @@ Created Thursday 14 June 2012
http://railsmonkey.net/2010/05/is-your-build-environment-sane/
Is your build environment sane…?
By Matthew Savage
Ive been testing a Varnish reverse-proxy/cache setup this weekend to try to resolve the 80% of the problems Ive been dealing with across our websites.

View File

@@ -1,125 +0,0 @@
Content-Type: text/x-zim-wiki
Wiki-Format: zim 0.4
Creation-Date: 2012-06-14T10:36:42+08:00
====== 图解autoscan、aclocal、autoheader、automake、autoconf、configure、make ======
Created Thursday 14 June 2012
http://hi.baidu.com/yzkuang/blog/item/557e4f24423d8136c9955908.html
1.autoscan (autoconf): 扫描源代码以搜寻普通的__可移植性问题__比如检查编译器头文件等生成文件configure.scan,它是configure.ac的一个雏形。
your source files --> [autoscan*] --> [configure.scan] --> configure.ac
2.aclocal (automake):根据已经安装的宏用户定义宏和__acinclude.m4__文件中的宏将configure.ac文件所需要的宏集中定义到文件 aclocal.m4中。aclocal是一个perl 脚本程序它的定义是“aclocal - create aclocal.m4 by scanning configure.ac”
user input files optional input process output files
================ ============== ======= ============
acinclude.m4 - - - - -.
V
.-------,
configure.ac ------------------------>|aclocal|
{user macro files} ->| |------> aclocal.m4
`-------'
3.autoheader(autoconf): 根据configure.ac中的某些宏比如cpp宏定义运行m4生成config.h.in
user input files optional input process output files
================ ============== ======= ============
aclocal.m4 - - - - - - - .
|
V
.----------,
configure.ac ----------------------->|autoheader|----> autoconfig.h.in
`----------'
4.automake: automake将Makefile.am中定义的结构建立Makefile.in然后configure脚本将生成的Makefile.in文件转换为Makefile。如果在configure.ac中定义了一些特殊的宏比如__AC_PROG_LIBTOOL__它会调用__libtoolize__否则它会自己产生config.guess和config.sub
user input files optional input processes output files
================ ============== ========= ============
.--------,
| | - - -> COPYING
| | - - -> INSTALL
| |------> install-sh
| |------> missing
|automake|------> mkinstalldirs
configure.ac ----------------------->| |
Makefile.am ----------------------->| |------> Makefile.in
| |------> stamp-h.in
.---+ | - - -> config.guess
| | | - - -> config.sub
| `------+-'
| | - - - -> config.guess
|libtoolize| - - - -> config.sub
| |--------> ltmain.sh
| |--------> ltconfig
`----------'
The `libtoolize' program __provides a standard way to add libtool support to your package__. In the future, it may implement better usage
checking, or other features to make libtool even easier to use.
5.autoconf:将configure.ac中的宏展开生成configure脚本。这个过程可能要用到aclocal.m4中定义的宏。
user input files optional input processes output files
================ ============== ========= ============
aclocal.m4 ,autoconfig.h.in - - - - - - -.
V
.--------,
configure.ac ----------------------->|autoconf|------> configure
6. ./configure的过程
.-------------> [config.cache]
configure* --------------------------+-------------> config.log
|
[config.h.in] -. v .--> [autoconfig.h]
+-------> config.status* -+
Makefile.in ---' `--> Makefile
7. make过程
[autoconfig.h] -.
+--> make* ---> 程序
Makefile ---'
.---------,
config.site - - ->| |
config.cache - - ->| | - - -> config.cache
| +-,
`-+-------' |
| |----> config.status
config.h.in ------->|config- |----> config.h
Makefile.in ------->| .status|----> Makefile
| |----> stamp-h
| +--,
.-+ | |
| `------+--' |
ltmain.sh ------->|ltconfig|-------> libtool
| | |
`-+------' |
|config.guess|
| config.sub |
`------------'
.--------,
Makefile ------>| |
config.h ------>| |
{project sources} ---------------->| |--------> {project targets}
.-+ +--,
| `--------' |
| libtool |
| missing |
| install-sh |
|mkinstalldirs|
`-------------'

View File

@@ -1,40 +0,0 @@
Content-Type: text/x-zim-wiki
Wiki-Format: zim 0.4
Creation-Date: 2012-06-14T09:19:47+08:00
====== automake变量 ======
Created Thursday 14 June 2012
http://www.delorie.com/gnu/docs/automake/automake_47.html
**9.6 Variables used when building a program**
Occasionally it is useful to know which `Makefile' variables Automake uses for compilations; for instance you might need to do your own compilation in some special cases.
Some variables are **inherited**// from Autoconf//; these are __CC, CFLAGS, CPPFLAGS, DEFS, LDFLAGS, and LIBS__.
There are some additional variables which Automake **itself** defines:
* **AM_CPPFLAGS**
The contents of this variable are passed to **every compilation** which invokes the C preprocessor; it is a list of arguments to the preprocessor. For instance, `-I' and `-D' options should be listed here.
Automake already provides some `-I' options automatically. In particular it generates __`-I$(srcdir)', `-I.'__, and a `-I' pointing to the directory holding `config.h' (if you've used AC_CONFIG_HEADERS or AM_CONFIG_HEADER). You can disable the default `-I' options using the `nostdinc' option.
AM_CPPFLAGS is ignored in preference to a __per-executable (or per-library) _CPPFLAGS variable__ if it is defined.
* AM_CPPFLAGS是一个全局变量会传给每一个编译预处理命令。
* 我们也可以通过filename_CPPFLAGS的形式为每一个可执行程序或库文件指定编译预处理选项。当定义这个变量时AM_CPPFLAGS会被忽略。
* **INCLUDES** (将被弃用的变量)
This does the same job as `AM_CPPFLAGS'. It is an older name for the same functionality. This variable is __deprecated;__ we suggest using `AM_CPPFLAGS' instead.
* **AM_CFLAGS**
This is the variable which the `Makefile.am' author can use to pass in **additional C compiler flags**. It is more fully documented elsewhere. In some situations, this is not used, in preference to the __per-executable (or per-library) _CFLAGS__.
* **COMPILE**
This is the command used to actually compile a C source file. The filename is appended to form the complete command line.
* **AM_LDFLAGS**
This is the variable which the `Makefile.am' author can use to pass in **additional linker flags**. In some situations, this is not used, in preference to the __per-executable (or per-library) _LDFLAGS__.
* **LINK**
This is the command used to actually link a C program. It already includes `-o $@' and the usual variable references (for instance, CFLAGS); it takes as "arguments" the names of the object files and libraries to link in.

View File

@@ -33,10 +33,6 @@ Other formats
The widespread use of these configure scripts made building software from the sources easier. This document discusses the software packages used to generate the configure script and other associated files.
This document is aimed at developers intending to develop Free Software or already maintaining Free Software packages.
We assume the reader is already familiar with Makefiles.
===== 2. Who's who =====
The software packages we are dealing directly with here are: **GNU autoconf, GNU automake and GNU autoheader**. Indirectly, we are dealing with the **m4** macro processor, **make** (either GNU or BSD)**aclocal **and **libtool**. We talk about GNU libtool too.
@@ -154,7 +150,7 @@ You should see an output like this
galadriel:~/autotut-ex1$
* configure.in是autoconf的输入文件autoconf展开其中的宏引用然后输出到configure脚本文件中。
* configure.in是autoconf的输入文件autoconf展开其中的宏引用然后输出到configure脚本文件中同时它也是个bash脚本
* configure.in中引用的宏定义一般是由aclocal扫描该文件后从系统宏库中提取出来然后写入到源代码目录中的aclocal.m4文件中的。
* makefile.in是configure脚本的输入文件configure脚本根据__配置参数和系统环境检查结果替换__makefile.in文件中包含在两@间的变量然后输出到makefile文件中。
* configure脚本检查哪些项目(头文件、库文件及其中函数等)读取和替换哪些makefile.in等是由configure.in中的各种宏决定的。
@@ -169,9 +165,10 @@ You should see an output like this
The configure.in file is processed by the __m4 macro processor__, but aside from the m4 macros, __it is a Bourne shell script__. Thus you can use if...then...fi, and constructs from Bourne shells. You can have some reference on shell programming by reading the bash or sh man pages (depending on the operating system you are on).
IMPORTANT! The square brackets have special meaning to the m4 processor, so if you want to use the test (see test (1)) command you must spell it out as **test** instead of using the Bourne shell [...] abbreviation.
IMPORTANT! The __square brackets__ have special meaning to the m4 processor, so if you want to use the test (see test (1)) command you must spell it out as **test** instead of using the Bourne shell [...] abbreviation.
configure.in是一个文本文件它__会被M4宏处理器和shell读取执行__因此其中可以包含M4能够识别并展看的__以AC_或AM_开头的宏函数__也可以包含shell脚本语法内容。
注意configure.in中的__方括号对于M4而言有特殊含义__因此不在具有shell脚本中的测试功能如果要使用shell的判断功能可以使用test命令。
Also, **the shell variables** defined and modified within configure.in are NOT substituted automatically in the AC_OUTPUT files. You must explicitly call __AC_SUBST__ (as done with the VERSION variable in the first example) to request the substitution. However, when an internal autoconf macro says "sets variable NAME", it sets and AC_SUBSTs it, thus you must only worry about variables set on your own.
@@ -188,7 +185,8 @@ configure.in是一个文本文件它__会被M4宏处理器和shell读取执
this is parameter 3 which spans
along several lines. Now you
know why square brackets cannot
be used for the 'test' command.]) //M4宏的参数//如果以方括号开头,则可以分布在多个行中//。
be used for the 'test' command.])
//M4宏的参数//如果以方括号开头,则可以分布在多个行中。
Conventionally , all macros provided by //autoconf// start with __AC___. As we shall see later, //automake//'s macros start with __AM___.
@@ -198,15 +196,15 @@ configure.in是一个文本文件它__会被M4宏处理器和shell读取执
**Macro Prototype Comments**
AC_INIT(sourcefile) Initializes autoconf, should be __the first macro__ called in configure.in(第一个宏函数调用,但是在其前面**可以有变量定义**。). sourcefile is the name (relative to //current// directory) of a source file from your code.
AC_PROG_CC Determines a C compiler to use, sets the __CC__ variable. If this is GCC, set the __GCC__ variable to 'yes', otherwise 'no'. Initializes the __CFLAGS__ variable if it hasn't been set already (to override CFLAGS, do it in configure.in __BEFORE__ calling this macro) 如果CFLAGS变量没有定义则该宏会初始化它为默认值。CLFAGS的定义可以来自本文,也可来自命令行参数。
AC_PROG_CXX Determines a C++ compiler to use, sets the __CXX__ variable. If this is the GNU C++ compiler, set __GXX__ to 'yes', otherwise 'no'. Initializes the __CXXFLAGS__ variable if it hasn't been set already (to override CXXFLAGS, do it in configure.in BEFORE calling this macro)
AC_PROG_CC Determines a C compiler to use, sets the __CC__ variable. If this is GCC, set the __GCC__ variable to 'yes', otherwise 'no'. Initializes the __CFLAGS__ variable if it hasn't been set already (to override CFLAGS, do it in configure.ac __BEFORE__ calling this macro) 如果CFLAGS变量没有定义则该宏会初始化它为默认值。CLFAGS的定义可以来自本文,也可来自命令行参数。
AC_PROG_CXX Determines a C++ compiler to use, sets the __CXX__ variable. If this is the GNU C++ compiler, set __GXX__ to 'yes', otherwise 'no'. Initializes the __CXXFLAGS__ variable if it hasn't been set already (to override CXXFLAGS, do it in configure.ac BEFORE calling this macro)
AC_LANG_C Tests the C compiler //**测试C编译器能否正常工作**
AC_LANG_CPLUSPLUS Tests the C++ compiler
AC_PROG_INSTALL Set variable __INSTALL__ to the path of a BSD-compatible //install program// (see install (1)). If not found, set it to 'dir/install-sh -c' , looking in the directories specified to __AC_CONFIG_AUX_DIR__. Also sets __INSTALL_SCRIPT__ and __INSTALL_PROGRAM__ to $(INSTALL), and __INSTALL_DATA__ to '$(INSTALL) -m 644'. You must provide __a install-sh file__ in the current directory (unless you use AC_CONFIG_AUX_DIR -- the common practice is to provide a install-sh file) else autoconf will refuse to run. //install-sh为安装该程序的系统提供一个**install程序的候选版本**。
AC_PATH_X Try to locate the **X window system**'s includes and libraries, and sets the variables __x_includes__ and __x_libraries__ to their locations.
AC_PATH_XTRA Like the previous, but adds the required include flags to __X_CFLAGS__ and required linking flags to __X_LIBS__.
AC_PATH_PROG(a,b[,c[,d]])
AC_PATH_PROG(a,b[,c[,d]]) //在系统路径PATH中查找prog-to-check程序是否存在
a=variable-name
b=prog-to-check
c=value-if-not-found
@@ -214,23 +212,23 @@ configure.in是一个文本文件它__会被M4宏处理器和shell读取执
AC_PROG_MAKE_SET If make predefines the variable MAKE, define output variable __SET_MAKE__ to be empty. Otherwise, define SET_MAKE to contain `MAKE=make'. 如果是多级编译则MAKE环境变量必须要检查。
AC_OUTPUT(files [,a[,b]]) Create output files. __Perform substitutions on files__, which contains a list of files separated by **spaces**. (is writes, say, Makefile, from a Makefile__.in__ file, spec from spec__.in__, and so on. **The name given here is without the .in suffix.** The other 2 parameters are seldom used, consult the autoconf docs if needed. If AC_CONFIG_HEADER, AC_LINK_FILES or AC_CONFIG_SUBDIRS were called, the files named as their arguments are created too.
AC_OUTPUT(files [,a[,b]]) Create output files. __Perform substitutions on files__, which contains a list of files separated by **spaces**. (is writes, say, Makefile, from a Makefile__.in__ file, spec from spec__.in__, and so on. **The name given here is without the .in suffix.** The other 2 parameters are seldom used, consult the autoconf docs if needed. If __AC_CONFIG_HEADER__, __AC_LINK_FILES__ or __AC_CONFIG_SUBDIRS__ were called, the files named as their arguments are created too.
该宏一般位于configure.in的最后指明了替换其中的变量引用后生成的文件filename(可能带路径)同时也指出了需要替换的模板文件filename.in读入和输出都是由//将要生成的configure脚本//完成。
AC_CONFIG_HEADER(files) Make AC_OUTPUT create the headers listed in the files list (space-separated). Replaces @DEFS@ in generated files with -DHAVE_CONFIG_H. The usual name for the header is **config.h** (created from **config.h.in**. The __autoheader__ generates config.h.in files automatically for you (it is documented in the next sections).
AC_CONFIG_HEADER(files) Make AC_OUTPUT create the headers listed in the **files list **(space-separated, 外侧不需要加方括号). Replaces @DEFS@ in generated files with -DHAVE_CONFIG_H. The usual name for the header is **config.h** (created from **config.h.in**. The __autoheader__ generates config.h.in files automatically for you (it is documented in the next sections).
AC_CONFIG_SUBDIRS(dirs) run configure scripts in the subdirectories listed in dirs (space-separated). This is meant for when you __nest child packages__ to your program (like including libraries as subdirs). 该宏适用于nest类型的源代码目录结构dirs中的各目录**含有configure.in文件**。
**AC_CONFIG_SUBDIRS(dirs)** **run configure scripts** in the subdirectories listed in dirs (space-separated). This is meant for when you __nest child packages__ to your program (like including libraries as subdirs). 该宏适用于nest类型的源代码目录结构dirs中的各目录**含有configure.in文件**。
AC_CHECK_FUNC(a[,b[,c]])
a=function
b=action if found
c=action if not found checks if the given C function is available in the standard library (i.e., the libraries that are linked by default to any C program).
c=action if not found checks if the given C function is available in the __standard library__ (i.e., the libraries that are linked by default to any C program).
AC_CHECK_FUNCS(a[,b[,c]])
a=list of functions (space-separated)
b=action if found
c=action if not found similar to AC_CHECK_FUNC, but looks for many functions at once, setting HAVE_function for each function found (in the given set).
c=action if not found similar to AC_CHECK_FUNC, but looks for many functions at once, setting **HAVE_function** for each function found (in the given set).
AC_CHECK_LIB(a,b[,c[,d[,e]]])
a=library name
@@ -258,7 +256,8 @@ configure.in是一个文本文件它__会被M4宏处理器和shell读取执
There are many more autoconf macros. If these weren't already enough, you can supply **a macro library** with your own software distribution. To do this, place the macro definitions in a file called __aclocal.m4__ in the same directory as configure.in, all macros defined in aclocal can now be used in configure.in. The common use for this is to have **specific-library checking macros**, e.g. AC_REQUIRE_GTK(1,2,8) to require the GTK library version 1.2.8 or later. You may also place your macros in a file called __acinclude.m4__ if you are using the __aclocal__ program. aclocal will be presented later.
上面列出的以AC_开头的宏都是autoconf工具提供的标准宏可以直接调用。程序员也可以将自己定义的宏放在aclocal.m4或acinclude.m4文件中这样configure.in中就可以使用它们。
注意没当运行aclocal命令后aclocal.m4文件中的内容就会被覆盖为代码中使用的宏定义这样安装这个代码的系统如果没有安装这些宏也可以正常使用autoconf工具重新生成configure脚本configure脚本运行时就不在需要autoconfautomakeautoheader和aclocal等工具。程序员将自己定义的宏放在acinclude.m4文件中就可以避免被覆盖该文件会被acloacl自动读取。
注意每当运行aclocal命令后aclocal.m4文件中的内容就会被覆盖为代码中使用的宏定义这样安装这个代码的系统如果没有安装这些宏也可以正常使用autoconf工具重新生成configure脚本configure脚本运行时就不在需要autoconfautomakeautoheader和aclocal等工具。程序员将自己定义的宏放在acinclude.m4文件中就可以避免被覆盖该文件会被acloacl自动读取。
And don't be tempted to have configure.in for each directory in your source tree. Multiple configure.in's are only desirable when you integrate different software packages in a common source tree (such as my program and the 3000 libraries it requires).
@@ -281,6 +280,15 @@ configure.in是一个文本文件它__会被M4宏处理器和shell读取执
__The solution is to put all the definitions in a header file.__ You can do that in autoconf with the __AC_CONFIG_HEADER__ macro. The conventional name for this header is __config.h__. However, you must supply a __.in header__ (config.h.in) with all the possible definitions spelled out, so that autoconf will just change #undef to #define or add a value to the #define. Here comes autoheader. Just run **autoheader** on a directory with a configure.in that contains a AC_CONFIG_HEADER macro call, and it will write the __.in file__.
当程序员在编写程序时可能需要一些特性或变量而且这些特性和变量是程序的最终用户__在运行configure脚本时才配置或指定的__。
为了利用这些变量或开关特性程序员通常的做法是在代码中定义一些宏变量以及条件编译语句然后用户在编译时的__gcc命令行__上用-DMarco-name=value的形式为这些宏赋值。把宏定义及其值在gcc的命令行上指定的最大缺点是
1. gcc命令行过长可读性降低。
2. 相同的宏需要在使用的每个gcc命令行上指定非常繁琐。
解决的方法是将相关的宏定义放在一个众所周知的头文件中(如config.h)然后使用这些宏的代码文件只需include该头文件即可。
config.h来源于一个模板文件config.h.in默认其中的各宏都是#undef的用户在执行的configure脚本在收集到相关系统和配置信息
后会替换config.h.in中的相关宏定义然后将结果写入到config.h中。
Let's use the same pi.c program we did before to show the work of autoheader. You can get the files in a tarball too: autotut-ex2.tar.gz. I won't list all files again, just configure.in.
**Example 2: configure.in**
@@ -295,7 +303,7 @@ configure.in是一个文本文件它__会被M4宏处理器和shell读取执
AC_PROG_MAKE_SET
AC_HEADER_STDC
AC_CHECK_FUNCS(atol atoi strtod)
AC_CHECK_FUNCS(atol atoi strtod) //从标准C库中检查是否穿在这些函数
VERSION="0.0.1-rc2"
AC_SUBST(VERSION)
@@ -323,7 +331,7 @@ configure.in是一个文本文件它__会被M4宏处理器和shell读取执
/* Define if you have the strtod function. */
#undef HAVE_STRTOD
And now you run configure as usual. It will write a config.h based on this template. Let's see what it generates:
And now you run //configure// as usual. It will write a config.h based on this template. Let's see what it generates:
**Example 2: config.h**
@@ -347,7 +355,8 @@ configure.in是一个文本文件它__会被M4宏处理器和shell读取执
Also, autoheader only copies definitions from the /usr/share/autoconf/acconfig.h file. If some macro you used needs a different entry in config.h.in, write it in a file called **acconfig.h** in the same directory as configure.in, and it will be included in config.h.in by autoheader.
autoheader工具分析了configure.ac里面所有要检查的东西然后生成了相应的编译预处理宏定义到config.h.in文件中然后configure脚本根据检测到的结果修改该文件并输出到config.h文件中。
程序代码可以包含该config.h文件根据其中的宏定义条件包含一些代码。
程序代码应该包含该config.h文件可以引用其中的宏定义只进行条件编译。
===== 6. Automake =====
@@ -381,7 +390,7 @@ autoheader工具分析了configure.ac里面所有要检查的东西然后生
In the next sections we present __GNU automake, which generates a Makefile.in file based on a Makefile.am file__.
Makefile.am只是定义一些automake可以识别的并且会包含到生成的makefile文件中的__变量automake工具会根据这些变量自动创建相关编译规则然后写入到makefile.in文件中__而且auomake还会向最终生成的Makefile.in文件中添加一些标准目标规则。configure脚本会更改Makefile.in中的变量引用。
Makefile.am只是定义一些automake可以识别的并且会包含到生成的makefile文件中的__变量automake工具会根据这些变量自动创建相关编译规则然后写入到makefile.in文件中__而且auomake还会向最终生成的Makefile.in文件中添加一些标准目标规则。configure脚本会更改Makefile.in中的变量引用。 makefile.in与makefile的唯一区别就是其中的@xxx@变量被configure脚本替换为实际值(可以通过config.log文件查看这些变量值)。
Automake will also look for missing files that may cause your users to be confused if they are not present. Automake will either place a standard one in the package directory or complain about the missing file. (The rule is that universal files are copied from automake's distribution, and package-dependent files like AUTHORS, ChangeLog, etc. aren't).
@@ -402,10 +411,8 @@ Makefile.am中定义的只是一些符合makefile语法的__变量__。
===== Create an empty directory for the project =====
mkdir gdu
===== Place source files =====
For gdu, the source is consists of 2 C++ source files (.cc), 1 C++ header (.h), 6 pixmap pictures for the toolbar (.xpm) and a man page for the program (gdu.1x).
@@ -419,7 +426,9 @@ Makefile.am中定义的只是一些符合makefile语法的__变量__。
===== 3. Write configure.in(该文件同时被autoconf和autoheader检查) =====
Write a configure.in file for autoconf. Notice that some automake macros (AM_) come in, and **some autoconf macros are replaced by automake macros**. You must call AM_INIT_AUTOMAKE(package,version) right after AC_INIT, use AM_CONFIG_HEADER instead of AC_CONFIG_HEADER.
Write a configure.in file for autoconf. Notice that some automake macros (AM_) come in, and **some autoconf macros are replaced by automake macros**. 这意味着在运行automake前必须要准备好configure.in文件。
You must call AM_INIT_AUTOMAKE(package,version) right after AC_INIT, use AM_CONFIG_HEADER instead of AC_CONFIG_HEADER.
This is our configure.in:
@@ -429,7 +438,7 @@ Makefile.am中定义的只是一些符合makefile语法的__变量__。
__AM_INIT_AUTOMAKE(__gdu,0.0.1) //由于使用了AM_宏因此该宏必须放在AC_INIT宏的后面。
__AM_CONFIG_HEADER__(config.h)
CXXFLAGS=
CXXFLAGS= //这里定义了CXXFLAGS变量会覆盖autoconf自动产生的值。
AC_PROG_CC # for AM_PROG_GTK only
AC_PROG_CXX
@@ -440,7 +449,7 @@ Makefile.am中定义的只是一些符合makefile语法的__变量__。
# it will define GTK_CFLAGS and GTK_LIBS for us,
# comes from gtk.m4 (aclocal will find it for us)
AM_PATH_GTK(1.2.6)
AM_PATH_GTK(1.2.6) //系统预定义宏
AC_LANG_CPLUSPLUS # else AM_PATH_GTK blows up
@@ -452,21 +461,20 @@ Makefile.am中定义的只是一些符合makefile语法的__变量__。
AC_OUTPUT(Makefile)
If you use macros from system aclocal files (usually in /usr/share/aclocal), as we did here (the AM_PROG_GTK macro is in /usr/share/aclocal/gtk.m4, and some automake macros must be imported too), you must run the **aclocal** program to create an __aclocal.m4__ file with all needed macros. This file is overwritten every time aclocal is run, so if you want to have your own macros written locally, place them in __acinclude.m4__, aclocal will include these in the generated aclocal.m4.
If you use macros from system aclocal files (usually in /usr/share/aclocal), as we did here (the AM_PROG_GTK macro is in /usr/share/aclocal/gtk.m4, and some automake macros must be imported too), you must run the **aclocal** program to create an __aclocal.m4__ file with all needed macros. This file is __overwritten__ every time aclocal is run, so if you want to have your own macros written locally, place them in __acinclude.m4__, aclocal will include these in the generated aclocal.m4.
===== Run aclocal, autoconf, autoheader =====
Now you can already generate some of the files. You must run aclocal, autoheader and autoconf; **aclocal must run first**. In a Bourne shell you can run all three in a row with
Now you can already generate some of the files. You must run aclocal, autoheader and autoconf; **aclocal **__must run first__. In a Bourne shell you can run all three in a row with
//aclocal && autoheader && autoconf//
* aclocal will generate an aclocal.m4 file (getting information from **configure.in** [needed] and **acinclude.m4** [optional]).
* autoheader will read **configure.in** and produce a __config.h.in__ file (or whatever you named it in the AM_CONFIG_HEADER macro).
* autoconf will read **configure.in** and **aclocal.m4** and produce a __configure__ script.
* autoconf需要利用aclocal.m4中的宏定义来展开configure.in中的宏函数调用这个过程中需要调用系统的M4工具。但是一旦生成了configure脚本aclocal.m4和M4工具不在是必需的了(除非
用户在配置前修改了configure.in中的宏调用这样需要重新调用autoconf工具生成cofigure脚本)。
autoconf需要利用aclocal.m4中的宏定义来展开configure.in中的宏函数调用这个过程中需要调用系统的M4工具。但是一旦生成了configure脚本aclocal.m4和M4工具不在是必需的了(除非用户在配置前修改了configure.in中的宏调用这样需要重新调用autoconf工具生成cofigure脚本)。
===== Write a Makefile.am =====
@@ -475,7 +483,7 @@ Makefile.am中定义的只是一些符合makefile语法的__变量__。
**GDU (Example 3): Makefile.am**
AUTOMAKE_OPTIONS = __gnu__
AUTOMAKE_OPTIONS = gnu
LDADD = @GTK_LIBS@
CPPFLAGS = @GTK_CFLAGS@ //这两个变量是由configure.in中的AM_PATH_GTK(1.2.6)宏引入。
bin_PROGRAMS = gdu //生成一个可执行文件gdu
@@ -486,7 +494,7 @@ Makefile.am中定义的只是一些符合makefile语法的__变量__。
# man page
man_MANS = gdu.1x
# we want these **in the dist tarball**
# we want these in the dist tarball
EXTRA_DIST = back.xpm reload.xpm root.xpm \
home.xpm stop.xpm about.xpm gdu.1x
@@ -494,7 +502,7 @@ Makefile.am中定义的只是一些符合makefile语法的__变量__。
AUTOMAKE_OPTIONS = gnu could be achieved by running //automake// with the __--gnu__ command-line option. See 'automake --help' for all command-line options.
__LDADD__ and __CPPFLAGS__ (CFLAGS for C programs) specify flags used for **linking and compiling**);
__LDADD__ and __CPPFLAGS__ (CFLAGS for C programs) specify flags used for **linking and compiling**;
bin_PROGRAMS is a (**space-separated**) __list of all binaries__ that will be built and installed by your package. We'll build just gdu here.
@@ -502,12 +510,11 @@ Makefile.am中定义的只是一些符合makefile语法的__变量__。
* 如果需要编译和安装多个可执行文件则将它们的名称作为bin_PROGRAMS宏的参数。
* 每个可执行文件都要用name_SOURCES宏定义它所依赖的源文件automake会自动生成规则来编译和链接这些文件最终生成一个可执行程序。
* automake在读取makefile.am文件后根据其中的变量设置会生成一个makefile.in文件该文件采用了makefile语法规则与最终的makefile的__唯一区别__是含有将被configure脚本
替换的变量。除了可执行程序或库目标(程序员在configure.in中相关变量指定的)automake还会安装GNU惯例在makefile.in中添加一些标准规则。
* automake在读取makefile.am文件后根据其中的变量设置会生成一个makefile.in文件该文件采用了makefile语法规则与最终的makefile的__唯一区别__是含有将被configure脚本 替换的变量。除了可执行程序或库目标(程序员在configure.in中相关变量指定的)automake还会安装GNU惯例在makefile.in中添加一些标准规则。
man_MANS lists the man pages installed.
__noinst___HEADERS is the list of headers that **must go into a distribution** (a distribution is the .tar.gz file you distribute you program) **but are NOT installed** to @prefix@/include in the install step.
__noinst___HEADERS is the list of headers that **must go into a distribution** (a distribution is the .tar.gz file you distribute you program) **but are NOT in**stalled to @prefix@/include in the install step.
EXTRA_DIST lists //additional files// that must be included in the distribution. The xpm files could be listed under noinst_HEADERS, it really makes no difference here.
@@ -516,7 +523,7 @@ Makefile.am中定义的只是一些符合makefile语法的__变量__。
Now we are ready to run automake (maybe). There some files missing, but automake will tell us about them, so relax. Run this (the **--add-missing** will add default files from the automake distribution when possible, complain about missing files when not)
automake --add-missing #--add-missing会从automake的安装文件中符号链接一些标准通用的文件到当前代码树中但是有些项目特定的文件还需要自己创建。
automake --add-missing #--add-missing会从automake的安装文件中符号链接一些标准通用的文件到当前代码树中但是有些项目特定的文件还需要自己创建(NEWS README AUTHORS COPYING ChangeLog)
we obtain
@@ -533,9 +540,11 @@ we obtain
automake: Makefile.am: required file `./AUTHORS' not found
automake: Makefile.am: required file `./ChangeLog' not found #上面5个与具体项目相关需要自己创建。
__install-sh__ is the shell replacement for the BSD **install** program, triggered by AC_PROG_INSTALL. __mkinstalldirs__ and __missing__ are similar shell scripts triggered by the AM_ macros in configure.in.
__install-sh__ is the shell replacement for the BSD **install** program, triggered by **AC_PROG_INSTALL**. __mkinstalldirs__ and __missing__ are similar shell scripts triggered by the AM_ macros in configure.in.
INSTALL is the **automake standard installation instructions text**. COPYING is the GNU General Public License. COPYING was "needed" because we specified AUTOMAKE_OPTIONS = __gnu__. To work with bare requirements use AUTOMAKE_OPTIONS = __foreign__. In our example we stick with gnu, this is GPL'd program anyway.
INSTALL is the **automake standard installation instructions text**. COPYING is the GNU General Public License. COPYING was "needed" because we specified AUTOMAKE_OPTIONS = __gnu__.
To work with bare requirements use AUTOMAKE_OPTIONS = __foreign__. In our example we stick with gnu, this is GPL'd program anyway.
However, the other required files couldn't be resolved. Because they are **package-specific**. To keep the gnu option, we have to write each of those files.
@@ -545,7 +554,7 @@ we obtain
Having written the missing files, we run automake again (no --add-missing required, all it could add has already been added), and it runs swiftly without errors.
You'll notice that the added files are symlinks to files in /usr/share/automake. This is fine for some people, since the make dist step that creates the distribution tarball packs as files, but if you will import you source tree into CVS (Concurrent Versioning System -- not needed but widely used, don't worry if you don't use it) you probably want to run automake with automake --add-missing __--copy__ to force file copying (if you want to do it now, you'll have to remove the symlinks first).
You'll notice that the added files are **symlinks** to files in /usr/share/automake. This is fine for some people, since the make dist step that creates the distribution tarball packs as files, but if you will import you source tree into CVS (Concurrent Versioning System -- not needed but widely used, don't worry if you don't use it) you probably want to run automake with __automake --add-missing --copy__ to force file copying (if you want to do it now, you'll have to remove the symlinks first).
===== Phew! Test it. =====
@@ -558,20 +567,24 @@ we obtain
make clean
make distclean
The first one will compile the package. The dist target will create a __dist__ribution tarball -- the one you'll distribute to your users -- in our case it will create a tarball named **gdu-0.0.1.tar.gz**, __name and version are taken from the AM_INIT_AUTOMAKE macro__ in configure.in. This tarball complies with what users expect: it unpacks into a fresh directory of the same name (without the .tar.gz suffix).
The first one will compile the package. The dist target will create a distribution tarball -- the one you'll distribute to your users -- in our case it will create a tarball named **gdu-0.0.1.tar.gz**, __name and version are taken from the AM_INIT_AUTOMAKE macro__ in configure.in. This tarball complies with what users expect: it unpacks into a fresh directory of the same name (without the .tar.gz suffix).
IMPORTANT! You should __always test__ the distribution tarball (by unpacking, compiling and installing), for it is usual to have files left out because you forgot to add graphic files, program headers or other needed files in the EXTRA_DIST or noinst_HEADERS variables in Makefile.am. Some files (README, INSTALL, etc.) are automatically included in the distribution if found, and running automake with 'automake --help' will show a list of all included-if-found filenames.
The clean target removes binaries and object files (.o).
The distclean target removes not only the binaries, but __all the configuration results__ created by the configure script. If you think your changes to configure.in or Makefile.am are not taking effect after running autoconf and automake, do a make distclean to clean any **cached** results. Also, you should do make distclean before importing your source tree into a CVS repository.
The **distclean** target removes not only the binaries, but __all the configuration results__ created by the configure script. If you think your changes to configure.in or Makefile.am are not taking effect after running autoconf and automake, do a make distclean to clean any **cached** results. Also, you should do make distclean before importing your source tree into a CVS repository.
Other targets are install, uninstall and test.
===== 8. Makefile.am =====
__SUBDIRS__
Automake'd projects can vary in directory topology. __Flat topologies__ include all source files in the project's top directory, like gdu. __Shallow topologies__ includes the sources in some subdirectories. The most common situation is having the source go inside a //src// directory instead of the top directory. __Deep topologies__ is what happens when you include your source in the top directory and libraries in subdirectories.
Automake'd projects can vary in directory topology.
* __Flat topologies__ include all source files in the project's top directory, like gdu.
* __Shallow topologies__ includes the sources in some subdirectories. The most common situation is having the source go inside a //src// directory instead of the top directory.
* __Deep topologies__ is what happens when you include your source in the top directory and libraries in subdirectories.
To have a //multi-directory source tree//, specify all child directories in __the SUBDIRS variable__. Example:
@@ -580,12 +593,11 @@ we obtain
Each subdirectory must have __its own Makefile.am__.
* Flat topologies: 所有的源文件(可执行文件和库文件的头文件C/C++文件等)都放在项目的顶层目录中configure.in, makefile.am, makefile.in等也放在该目录中。
* Shallow topologies: 顶层目录只放配置文件(如整个项目的configure.in和makefile.am文件)和数据文件。所有的可执行文件和库文件源代码都按放在不同的目录中目录中有自己的makefile.am文件这些目录由上层
的makefile.am中的SUBDIRS变量指定。
* Shallow topologies: 顶层目录只放配置文件(如整个项目的configure.in和makefile.am文件)和数据文件。所有的可执行文件和库文件源代码都按放在不同的目录中目录中有自己的makefile.am文件这些目录由上层的makefile.am中的SUBDIRS变量指定。
* Deep topologies: 可执行程序的源代码在当前目录,库文件源代码在单独的子目录中。
PROGRAMS
__the *_PROGRAMS variables__ specify programs to be built. __bin___PROGRAMS list programs to be built and installed to @prefix@/bin, __sbin___PROGRAMS are built and installed to @prefix@/sbin; EXTRA_PROGRAMS are built but not installed.
the *_PROGRAMS variables specify programs to be built. bin_PROGRAMS list programs to be built and installed to @prefix@/bin, sbin_PROGRAMS are built and installed to @prefix@/sbin; EXTRA_PROGRAMS are built but not installed.
Where Files Go ?
For each program listed, __program_SOURCES__ lists the source files. __include_HEADERS__ lists headers that are installed to @prefix@/include. __EXTRA_DIST__ and __noinst_HEADERS__ files are included in the distribution but not installed.
@@ -601,15 +613,18 @@ we obtain
===== 9. Building Libraries: libtool =====
In this section we show a very short example of **a shared library package**. __Automake will write a Makefile.in file that uses libtool to build it in a portable way__. Libtool is the way to build libraries. It will prevent you from dealing with arcane system idiosyncrasies by selecting **compiler and linker flags** and running system utilities as needed to integrate libraries seamlessly into the system.
libtool是一种在不同系统间可移植性地编译、安装和使用__库文件__的脚本工具。libtool本质上是GCC的封装程序它的mode参数如compile/link/install分别和GCC的编译/链接/安装阶段相对应automake会在需要时自动调用libtool脚本并向其传入合适的mode参数。libtool在编译库文件时会自动添加适合安装平台的参数如-c/-fPIC/-fpic等。libtool是个脚本文件一般由automake自动地将其调用方法写入到生成的makefile中__该脚本通常会放到源代码树中__所以编译和安装该代码的系统不需要安装它。
不同于M4和auto-系列工具libtool对于使用了该方法的软件包而言在编译和安装软件包的过程中是必需的
* libtool是一种在不同系统间可移植性地编译、安装和使用__库文件__的脚本工具。
* libtool本质上是GCC的封装程序它的mode参数如compile/link/install分别和GCC的编译/链接/安装阶段相对应automake会在需要时自动调用libtool脚本并向其传入合适的mode参数
* libtool在编译库文件时会自动添加适合安装平台的参数如-c/-fPIC/-fpic等。
* libtool是个脚本文件一般由automake自动地将其调用方法写入到生成的makefile中__该脚本通常会放到源代码树中__所以编译和安装该代码的系统不需要安装它。
* 不同于M4和auto-系列工具libtool对于使用了该方法的软件包而言在编译和安装软件包的过程中是必需的。
The example for this section is a set of 4 programs, one of which is a shared library. We'll use this same set of programs as an example for the next section.
The four programs are: dinnerd, libdinner, hungryhacker and vdinner.
* **dinnerd** is a daemon that acts as a server for the Dining Hackers protocol (this is an unofficial protocol, mostly useless, that I created for this example -- for a deeper explanation of protocol check the documentation in the dinnerd package). It manages a round table with at most 256 places, and waits for hackers (clients) to sit around. There are always N Chinese food boxes and N chop-sticks on the table, where N is the current number of hackers. Hackers need 2 chop-sticks to eat, so they all cannot eat at the same time. Competition for chop-sticks occurs, and hackers get angry and may beat each other if they can't get a chop-stick, and even die of starvation if they can't eat for too long. dinnerd provides two sub-protocols: one for hackers to connect and interact (request chop-sticks, etc.) and another for observers to watch the whole scene. Download source: dinnerd-1.0.0.tar.gz
* **vdinner** screen-shot libdinner is a library that provides a set of functions to access a dinnerd server without the need to code directly with the Unix network API -- you don't need to know what bytes come and go in the connection, the library wraps the ugly things for you. Download source: libdinner-0.0.1.tar.gz
* **libdinner** screen-shot libdinner is a library that provides a set of functions to access a dinnerd server without the need to code directly with the Unix network API -- you don't need to know what bytes come and go in the connection, the library wraps the ugly things for you. Download source: libdinner-0.0.1.tar.gz
* **hungryhacke**r implements a client for the first sub-protocol. It implements a hacker that sleeps (in the sense of the Unix sleep() call, not human sleep) for a random amount of time, try to acquire chop-sticks, eat for a random amount of time, repeat. Download source: hungryhacker-0.0.1.tar.gz
* **vdinner** implements a client for the second sub-protocol, it grabbing information about the status of the table from dinnerd using the library functions of libdinner and renders everything animated in 3D with the aid of the Mesa graphics library, as the screen-shot at the right shows. Download source: vdinner-0.0.1.tar.gz
@@ -617,7 +632,7 @@ libtool是一种在不同系统间可移植性地编译、安装和使用__库
The library source code is contained on two files: libdinner.c and dinner.h. The later will be installed under @prefix@/include and applications that link with the library will need to include it.
The first step to build a library is including the AM_PROG_LIBTOOL macro in configure.in. This is libdinner's configure.in file:
The first step to build a library is including the **AM_PROG_LIBTOOL** macro in configure.in. This is libdinner's configure.in file:
**libdinner (Example 4): configure.in**
@@ -646,7 +661,10 @@ And this is libdinner's Makefile.am file:
**libdinner (Example 4): Makefile.am**
AUTOMAKE_OPTIONS = __gnu__
lib___LT__LIBRARIES = libdinner.__la #类似的还有安装到@prefix@/libexec的libexec_LTLIBRARIES__。libname.la是libtool的生成的库文件在生成它的同时还会生成libname.so和libname.a等库文件而libname.la是记录它们**实际安装位置的文本文件**。
lib___LT__LIBRARIES = libdinner.la
#类似的还有安装到@prefix@/libexec的libexec_LTLIBRARIES__。
#libname.la是libtool使用的**文本文件**在生成它的同时__还会生成__libname.so和libname.a等库文件。
#libname.la文本文件记录了与name相关的所有库文件的名称及版本依赖关系等。
__libdinner_la___SOURCES = libdinner.c #目标文件名中的点号必须用下划线代替该宏一般只列出C/C++源文件__不需要列出头文件__。头文件可以由CFLAGS标志给出。
@@ -654,8 +672,7 @@ And this is libdinner's Makefile.am file:
libdinner_la___LDFLAGS__ = **-version-info 0:0:0**
As usual, automake variable names have two parts. The lib in lib_LTLIBRARIES means the target will be installed to @prefix@/lib.
And the __LT__ in LTLIBRARIES is from LibTool. **When target names have dashes (-) or dots (.), they're substituted for underscores, so we have libdinner_la_SOURCES instead of libdinner.la_SOURCES.**
As usual, automake variable names have two parts. The lib in **lib_LTLIBRARIES** means the target will be installed to @prefix@/lib. And the __LT__ in LTLIBRARIES is from LibTool. **When target names have dashes (-) or dots (.), they're substituted for underscores, so we have libdinner_la_SOURCES instead of libdinner.la_SOURCES.**
We're using for the first time the include_HEADERS variable. It will place dinner.h in @prefix@/include.
@@ -668,10 +685,11 @@ And this is libdinner's Makefile.am file:
* Current is the version of the **interface** the library implements. Whenever a new function is added, or its name changed, or the number or type of its parameters (the prototype -- in libraries we call this the function signature), this number goes up. And it goes up exactly by one.
* Revision is the revision of the **implementation** of this interface, i.e., when you change the library by only modifying code inside the functions (fixing bugs, optimizing internal behavior, or adding/removing/changing signatures of functions that are private to the library -- used only internally) you raise the revision number only.
* Age is the difference between the newest and oldest interface the library currently implements. Let's say you had 8 versions of your library's interface, 0 through 7. You are now on the 4th revision of the 8th interface, that is, 7:3:X (remember we start counting on zero). And when you had to make choices for what old interfaces you would keep support -- for backward compatibility purposes, you chose to keep support for interfaces 5, 6 and (obviously) the current, 7. The libtool version of your library would be 7:3:2 , because the Age is 7-5 = 2.
AGE表示该库保证interface一致性的距离CURRENT的距离如CURRENT=8, AGE=3则表示CURRENT为5,67,8的三个版本在interface级别是兼容的。
From the libtool documentation, verbatim:
**Never** try to set the interface numbers so that they correspond
**Never** try to set **the interface numbers** so that they correspond
to the release number of your package. This is an abuse that only
fosters misunderstanding of the purpose of library versions. Instead,
use the `-release' flag (*note Release numbers::.), but be warned that
@@ -689,10 +707,9 @@ And this is libdinner's Makefile.am file:
The major difference between __shallow and deep is that in shallow packages you have only one configure.in, located in the top directory, and it will check everything that everything in the subdirectories need. Deep packages have a configure.in in each subdirectory, and it looks very much like an aggregate of programs which just happen to be distributed together.__
flat style 是将所有的源代码放到同一个目录下整个工程只有一个configure.in和makefile.am文件。
shallow style 有多个源代码目录每个目录中都有makefile.am文件整个工程只有一个位于顶层目录的configure.in文件它负责检查__所有目录中__的源代码
需要的系统特性
deep style 更像是将多个独立的工程目录添加到某个工程的顶层目录中整个工程由多个configure.in文件它们由顶层的configure.in控制。
* flat style 是将所有的源代码放到同一个目录下整个工程只有一个configure.in和makefile.am文件。
* shallow style 有多个源代码目录每个目录中都有makefile.am文件整个工程只有一个位于顶层目录的configure.in文件它负责检查系统环境并替换相应目录中的Makefile.in文件。
* deep style 更像是将多个独立的工程目录添加到某个工程的顶层目录中整个工程由多个configure.in文件它们由顶层的configure.in控制
**Shallow Example**
Our shallow example is vdinner (Source code: vdinner-0.0.1.tar.gz). It has three important requirements: X, Mesa and libdinner. All the code is contained in the __src__ subdirectory. For shallow topologies, we write **a top-level configure.in** just like in a flat topology, except that __we must remember to AC_OUTPUT Makefiles for all subdirectories__ and __references to files may need directory prefixes__, such as src/vdinner.c. This is vdinner's configure.in:
@@ -786,10 +803,10 @@ And this is the Makefile.am file in src:
It also has nothing different from what we discussed in the previous sections.
Automake must be **run from the top-level directory only**. __It will automatically descend into all SUBDIRS and create the associated Makefile.in files__. If you try running automake from an inner directory it will complain about the //lack of a configure.in there//, but you don't need one.
Automake __must be__ run from the top-level directory only. __It will automatically descend into all SUBDIRS and create the associated Makefile.in files__. If you try running automake from an inner directory it will complain about the //lack of a configure.in there//, but you don't need one.
shallow style的package 必须在顶层目录运行automake工具因为它需要读取configure.in文件中的信息而该文件只单一地存在与顶层目录。
shallow style的package的顶层makefile.am一般是比较简单的因为该目录一般没有源代码文件。通过makefile.am中的SUBDIRS变量参数automake会自动切换到该目录将其中的makefile.am转换为makefile.in文件。__automake最终会搜集所有子目录中的makefile.in目标信息将其写入顶层目录的makefile.in中(当然具体如何编译各个目标还要依赖相应目录中的makefile文件。)。configure脚本将检测到的值替换AC_OUT中列出的所有makefile.in文件然后生成makefile文件。__
* shallow style的package 必须在顶层目录运行automake工具因为它需要读取configure.in文件中的信息而该文件只单一地存在与顶层目录。
* shallow style的package的顶层makefile.am一般是比较简单的因为该目录一般没有源代码文件。通过makefile.am中的SUBDIRS变量参数automake会自动切换到该目录将其中的makefile.am转换为makefile.in文件。__automake最终会搜集所有子目录中的makefile.in目标信息将其写入顶层目录的makefile.in中(当然具体如何编译各个目标还要依赖相应目录中的makefile文件。)。configure脚本将检测到的值替换AC_OUT中列出的所有makefile.in文件然后生成makefile文件。__
**Deep Example**
As an example of a deep topology, we'll put all four programs (dinnerd, libdinner, hungryhacker and vdinner) in one package. We'll call this all-in-one package the dinnersuite. First we create a dinnersuite directory and unpack the distribution tarballs into it. I'll also rename the unpacked directories to remove the version string from the name, but it's not needed. Now we have this directory tree:
@@ -861,7 +878,8 @@ dinnersuite (Example 6): hungryhacker/configure.in
AC_CHECK_HEADERS(assert.h errno.h unistd.h time.h,,AC_MSG_ERROR([
required header missing]))
#删除了对libdinner库的检查。
#删除了对libdinner库的检查。
AC_OUTPUT(Makefile)
@@ -880,7 +898,7 @@ dinnersuite (Example 6): hungryhacker/configure.in
(a) Install your software in standard places. If you're using automake you're probably doing so already. Placing your binary under /var/coolstuff/lib/etc/boing/bin is much like not placing it anywhere at all. Doing a find / -name "foo" isn't practical and can take hours or even days to complete on systems that mount directories from a network (NFS is sooo transparent...)
(b) **Provide version information**. The standard is to print a version string and exit without further action when the __-v or --version__ options are given in the command line. If you want to provide the version information in a different way, it's ok, but you must document it somewhere. A man page is probably the best place.
(c) For libraries, __the most common way to check for presence is trying to link a small program(链接的目的只是检查该文件是否可以找到,而不是生成的程序是否可以正常工作)__. Document in the library changelogs the API changes. This way, if you introduced a float foo_bar(int,int) call in version X.Y.Z, users can detect versions >= X.Y.Z by trying to link a program that calls that function.
(d) Many software packages (usually large ones) provide a __programname-config__ script that is installed together with the program, that will provide information on version, include file paths, library paths, features, etc. Examples are GTK+ (gtk-config), Gimp (gimp-config), XMMS (xmms-config) and Gnome (gnome-config). Below we show an example of output for the gtk-config script.
(d) Many software packages (usually large ones) provide a __programname-config script __that is installed together with the program, that will provide information on version, include file paths, library paths, features, etc. Examples are GTK+ (gtk-config), Gimp (gimp-config), XMMS (xmms-config) and Gnome (gnome-config). Below we show an example of output for the gtk-config script.
//galadriel:~$ gtk-config//
Usage: gtk-config [OPTIONS] [LIBRARIES]
@@ -904,7 +922,7 @@ dinnersuite (Example 6): hungryhacker/configure.in
实际上是使用[[../pkgconfig.txt|pkg-config机制]]。
(e) Provide m4 macros to perform checks and tests on/for your software. The best behavior is to install these to the @prefix@/share/aclocal directory with the name yourpackage.m4. This way other developers may use the macros in their configure.in input files and aclocal will automatically look for the missing macros and place them in the aclocal.m4 of the distribution of the package that depends on yours.
(e) Provide __m4 macros__ to perform checks and tests on/for your software. The best behavior is to install these to the @prefix@/share/aclocal directory with the name yourpackage.m4. This way other developers may use the macros in their configure.in input files and aclocal will automatically look for the missing macros and place them in the aclocal.m4 of the distribution of the package that depends on yours.
Compatibility. Make your software usable by the widest range of people possible. For example: when writing a library, it is quite easy to turn down C++ programmers by not enclosing the function prototypes in the public header files in extern "C" blocks. A way to do this in a portable manner is shown in the dinner.h header of libdinner, the example library of the libtool section.

View File

@@ -91,6 +91,7 @@ Libtool 库可以是一个静态链接库,可以是一个动态链接库,也
}
这个文件实现了一个函数 compress_file(),它接收一个文件名作为参数,然后对文件进行压缩,生成一个 .z结尾的压缩文件。在这个文件中使用了 compress()函数,这个函数是有由 libz 提供的。
从源文件建立 Libtool 库需要经过两个步骤,先建立 Libtool 对象文件,再建立 Libtool 库。
===== 建立 Libtool 对象文件 =====
@@ -103,8 +104,7 @@ Libtool 库可以是一个静态链接库,可以是一个动态链接库,也
$ libtool --mode=compile gcc -c foo.c
可以看到,**使用 Libtool 只需要将“传统”的命令 (gcc -c foo.c) 作为参数传递给 Libtool 即可**。
在上面的命令中libtool 使用 compile模式 (--mode=compile 选项 )这是建立对象文件的模式Libtool 还有其它的模式,后面将介绍。
上面的命令输出如下 :
在上面的命令中libtool 使用 compile模式 (--mode=compile 选项 )这是建立对象文件的模式Libtool 还有其它的模式,后面将介绍。上面的命令输出如下 :
mkdir .libs
gcc -c compress.c -fPIC -DPIC -o __.libs__/compress.o
@@ -138,7 +138,7 @@ gcc -shared .libs/compress.o **-lz** -Wl,-soname -Wl,libcompress.so.0
可以看到Libtool 自动的插入了**建立动态链接库需要的编译选项** -shared。并且它也建立了**静态链接库** .libs/libcompress.a后面我们将会介绍如何控制 Libtool 只建立需要的库。
你可能会奇怪为什么建立的动态链接库有 .0 和 .0.0.0 这样的后缀,这里先不用理会它,后面在介绍 **Libtool 库版本信息**时将会解释这点。
值得注意的是Libtool 希望以后系统程序在链接时使用 libcompress.la 文件而不是直接使用 libcompress.a 和 libcompress.so 文件,如果你这样做,虽然可以,但会破坏 Libtool 库的可移植性。
值得注意的是Libtool 希望__以后系统程序在链接时使用 libcompress.la 文件__而不是直接使用 libcompress.a 和 libcompress.so 文件,如果你这样做,虽然可以,但会破坏 Libtool 库的可移植性。
===== 安装 Libtool 库 =====
如果打算发布建立好的 Libtool 库,可以使用下面的命令安装它 :
@@ -162,8 +162,7 @@ gcc -shared .libs/compress.o **-lz** -Wl,-soname -Wl,libcompress.so.0
ranlib /tmp/libcompress.a
...
可以看到它安装了真实的动态链接库和静态链接库,**同时也安装了 Libtool 库文件 libcompress.la**,这个文件可以被后续的 Libtool 命令使用。
在安装完成之后可能还需要做一些配置才能正确使用Libtool 的 finish 模式可以在这方面给我们一些提示 :
可以看到它安装了真实的动态链接库和静态链接库,**同时也安装了 Libtool 库文件 libcompress.la**,这个文件可以被后续的 Libtool 命令使用。在安装完成之后可能还需要做一些配置才能正确使用Libtool 的 finish 模式可以在这方面给我们一些提示 :
$ libtool -n --mode=finish /tmp

View File

@@ -6,10 +6,9 @@ Creation-Date: 2012-06-13T14:56:25+08:00
Created Wednesday 13 June 2012
http://blog.csdn.net/larntin2002/article/details/1821430
libtool常见于autoconf/automake单独用的例子很少,所以我想仔细研究一下,为将来兄弟们看起来方便。
libtool常见于autoconf/automake单独用的例子很少
==== 一libtool的作用 ====
==== 一 libtool的作用 ====
offer a standard procedure for __creating__ shared libraries on different platforms
libtool 是一个通用库支持__脚本__将创建动态库的复杂性隐藏在统一、可移植的接口中也就是说你可以通过如下所示的标准方法在不同平台上创建并调用动态库我们可以认为libtool是gcc的一个抽象也就是说它包装了gcc或者其他的任何编译器用户无需知道细节只要告诉libtool说我需要要编译哪些库即可并且它只与libtool文件打交道例如lo、la为后缀的文件。
@@ -63,7 +62,7 @@ libtool --mode=install install -c libhello.la /usr/local/lib/libhello.la
/lib/ld-linux.so.2 (0x40000000)
===== 5.install executable file =====
===== 5.install executable file =====
#libtool --mode=install cp hello /usr/local/bin/hello
安装可执行程序。

View File

@@ -5,3 +5,123 @@ Creation-Date: 2012-06-13T14:30:22+08:00
====== pkgconfig ======
Created Wednesday 13 June 2012
====== linux里命令pkg-config工具的使用 ======
Created Wednesday 13 June 2012
http://www.91linux.com/html/article/program/cpp/20071207/8934.html
===== 一、编译和连接 =====
一般来说,如果库的头文件不在 /usr/include 目录中,那么在编译的时候需要用 -I 参数指定其路径。由于同一个库在不同系统上可能位于不同的目录下,用户安装库的时候也可以将库安装在不同的目录下,所以即使使用同一个库,由于库的路径的不同,造成了用 -I 参数指定的头文件的路径也可能不同其结果就是造成了__编译命令界面的不统一__。如果使用 -L 参数也会造成连接界面的不统一。__编译和连接界面不统一__会为库的使用带来麻烦。
为了解决编译和连接界面不统一的问题,人们找到了一些解决办法。**其基本思想就是:**__事先把库的位置信息等保存起来__**,需要的时候再通过特定的工具将其中有用的信息提取出来供编译和连接使用。这样,就可以做到编译和连接界面的一致性。**其中目前最为常用的__库信息提取工具__就是下面介绍的 pkg-config。
pkg-config 是__通过库提供的一个 .pc 文件__获得库的各种必要信息的包括版本信息、编译和连接需要的参数等。这些信息可以通过 pkg-config 提供的参数单独提取出来直接供编译器和连接器使用。
The pkgconfig package contains tools for passing the **include path and/or library paths** to build tools during the make file execution.
pkg-config is a function that returns **meta information** for the specified library.
The default setting for __PKG_CONFIG_PATH__ is **/usr/lib/pkgconfig** because of the prefix we use to install pkgconfig. You may add to PKG_CONFIG_PATH by exporting additional paths on your system where pkgconfig files are installed. Note that PKG_CONFIG_PATH is **only needed when compiling packages**, not during run-time.
在默认情况下,每个支持 pkg-config 的库对应的 .pc 文件在安装后都位于**安装目录中的 lib/pkgconfig 目录**下。例如,我们在上面已经将 Glib 安装在 /opt/gtk 目录下了,那么这个 Glib 库对应的 .pc 文件是 /opt/gtk/lib/pkgconfig 目录下一个叫 glib-2.0.pc 的文件:
prefix=/opt/gtk/
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
glib_genmarshal=glib-genmarshal
gobject_query=gobject-query
glib_mkenums=glib-mkenums
Name: GLib
Description: C Utility Library
Version: 2.12.13
Libs: -L${libdir} -lglib-2.0
Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib-2.0/include
在利用源代码中提供的configure脚本配置该库时.pc文件中的变量会被实际值所代替针对提供.pc文件公其它软件包使用的当前源代码而言如${prefix}会被该库的实际安装位置所代替。
使用 pkg-config 的 __--cflags__ 参数可以给出在编译时所需要的选项,而 __--libs 参数__可以给出连接时的选项。例如假设一个 sample.c 的程序用到了 Glib 库,就可以这样编译:
$ gcc -c `pkg-config --cflags **glib-2.0**` sample.c
然后这样连接:
$ gcc sample.o -o sample `pkg-config --libs glib-2.0`
或者上面两步也可以合并为以下一步:
$ gcc sample.c -o sample `pkg-config --cflags --libs glib-2.0`
可以看到:**由于使用了 pkg-config 工具来获得库的选项,所以不论库安装在什么目录下,都可以使用相同的编译和连接命令,带来了编译和连接界面的统一**。
使用 pkg-config 工具提取库的编译和连接参数有两个基本的前提:
* 库本身在安装的时候必须提供一个相应的 .pc 文件。不这样做的库说明不支持 pkg-config 工具的使用。
* pkg-config 工具必须知道要到哪里去寻找此 .pc 文件。
**GTK+ 及其依赖库支持使用 pkg-config 工具**,所以剩下的问题就是如何告诉 pkg-config 到哪里去寻找库对应的 .pc 文件这也是通过设置__搜索路径__来解决的。
对于支持 pkg-config 工具的 GTK+ 及其依赖库来说,库的头文件的搜索路径的设置变成了对 .pc 文件搜索路径的设置。.pc 文件的搜索路径是通过环境变量 __PKG_CONFIG_PATH__ 来设置的pkg-config 将按照设置路径的先后顺序进行搜索,直到找到指定的 .pc 文件为止。
安装完 Glib 后,在 bash 中应该进行如下设置:
$ export PKG_CONFIG_PATH=**/opt/gtk/lib/pkgconfig**:$PKG_CONFIG_PATH
可以执行下面的命令检查是否 /opt/gtk/lib/pkgconfig 路径已经设置在 PKG_CONFIG_PATH 环境变量中:
$ echo $PKG_CONFIG_PATH
这样设置之后,使用 Glib 库的其它程序或库__在编译的时候__ pkg-config 就知道首先要到 /opt/gtk/lib/pkgconfig 这个目录中去寻找 glib-2.0.pc 了GTK+ 和其它的依赖库的 .pc 文件也将拷贝到这里,也会首先到这里搜索它们对应的 .pc 文件)。之后,通过 pkg-config 就可以把其中库的编译和连接参数提取出来供程序在编译和连接时使用。另外还需要注意的是环境变量的设置只对当前的终端窗口有效。如果到了没有进行上述设置的终端窗口中pkg-config 将找不到新安装的 glib-2.0.pc 文件、从而可能使后面进行的安装(如 Glib 之后的 Atk 的安装)无法进行。
在我们采用的安装方案中,由于是使用环境变量对 GTK+ 及其依赖库进行的设置,所以当系统重新启动、或者新开一个终端窗口之后,如果想使用新安装的 GTK+ 库,需要如上面那样重新设置 PKG_CONFIG_PATH 和 LD_LIBRARY_PATH 环境变量。
这种使用 GTK+ 的方法,在使用之前多了一个对库进行设置的过程。虽然显得稍微繁琐了一些,但却是一种最安全的使用 GTK+ 库的方式,不会对系统上已经存在的使用了 GTK+ 库的程序(比如 GNOME 桌面)带来任何冲击。
为了使库的设置变得简单一些,可以把下面的这两句设置保存到一个文件中(比如 set_gtk-2.10 文件):
export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig:$PKG_CONFIG_PATH
export **LD_LIBRARY_PATH**=/opt/gtk/lib:$LD_LIBRARY_PATH
之后,就可以用下面的方法进行库的设置了(其中的 source 命令也可以用 . 代替):
$ source set_gtk-2.10
只有在用新版的 GTK+ 库开发应用程序、或者运行使用了新版 GTK+ 库的程序的时候,才有必要进行上述设置。
如果想避免使用 GTK+ 库之前上述设置的麻烦,可以把上面两个环境变量的设置在系统的配置文件中(如 /etc/profile或者自己的用户配置文件中如 ~/.bash_profile ;库的搜索路径也可以设置在 /etc/ld.so.conf 文件中,等等。这种设置在系统启动时会生效,从而会导致使用 GTK+ 的程序使用新版的 GTK+ 运行库,这有可能会带来一些问题。当然,如果你发现用新版的 GTK+ 代替旧版没有什么问题的话,使用这种设置方式是比较方便的。加入到~/.bashrc中例如
PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig
重启之后:
[root@localhost ~]# echo $PKG_CONFIG_PATH
/opt/gtk/lib/pkgconfig
===== 二、运行时 =====
库文件在连接静态库和共享库和运行__仅限于使用共享库的程序__时被使用其搜索路径是在系统中进行设置的。一般 Linux 系统把 /lib 和 /usr/lib 两个目录作为默认的库搜索路径,所以使用这两个目录中的库时不需要进行设置搜索路径即可直接使用。对于处于默认库搜索路径之外的库,需要将库的位置添加到 库的搜索路径之中。设置库文件的搜索路径有下列两种方式,可任选其一使用:
* 在环境变量 LD_LIBRARY_PATH 中指明库的搜索路径。
* 在 /etc/ld.so.conf 文件中添加库的搜索路径。
将自己可能存放库文件的路径都加入到/etc/ld.so.conf中是明智的选择 ^_^
添加方法也极其简单将库文件的绝对路径直接写进去就OK了一行一个。例如
/usr/X11R6/lib
/usr/local/lib
/opt/lib
需要注意的是:第二种搜索路径的设置方式对于程序连接时的库(包括共享库和静态库)的定位已经足够了,但是对于使用了共享库的程序的执行还是不够的。这是 因为为了加快程序执行时对共享库的定位速度,避免使用搜索路径查找共享库的低效率,所以是直接读取库列表文件 __/etc/ld.so.cache__ 从中进行搜索的。/etc/ld.so.cache 是一个非文本的数据文件,不能直接编辑,它是根据 /etc/ld.so.conf 中设置的搜索路径由 __/sbin/ldconfig__ 命令将这些搜索路径下的共享库文件集中在一起而生成的ldconfig 命令要以 root 权限执行)。
因此,为了保证程序执行时对库的定位,在 /etc/ld.so.conf 中进行了库搜索路径的设置之后还必须__要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache__ 文件之后才可以。ldconfig ,简单的说,它的作用就是将/etc/ld.so.conf列出的路径下的库文件 缓存到/etc/ld.so.cache 以供使用。因此当安装完一些库文件,(例如刚安装好glib)或者修改ld.so.conf增加新的库路径后需要运行一下 /sbin/ldconfig使所有的库文件都被缓存到ld.so.cache中如果没做即使库文件明明就在/usr/lib下的也是不会被使用 的结果编译过程中抱错缺少xxx库去查看发现明明就在那放着搞的想大骂computer蠢猪一个。 ^_^
在程序连接时,对于库文件(静态库和共享库)的搜索路径,除了上面的设置方式之外,还可以通过 -L 参数显式指定。因为用 -L 设置的路径将被优先搜索,所以在连接的时候通常都会以这种方式直接指定要连接的库的路径。
前面已经说明过了,库搜索路径的设置有两种方式:在环境变量 LD_LIBRARY_PATH 中设置以及在 /etc/ld.so.conf 文件中设置。其中,第二种设置方式需要 root 权限,以改变 /etc/ld.so.conf 文件并执行 /sbin/ldconfig 命令。而且,当系统重新启动后,所有的基于 GTK2 的程序在运行时都将使用新安装的 GTK+ 库。不幸的是,由于 GTK+ 版本的改变,这有时会给应用程序带来兼容性的问题,造成某些程序运行不正常。为了避免出现上面的这些情况,在 GTK+ 及其依赖库的安装过程中对于库的搜索路径的设置将采用第一种方式进行。这种设置方式不需要 root 权限,设置也简单:
$ export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH
可以用下面的命令查看 LD_LIBRAY_PATH 的设置内容:
$ echo $LD_LIBRARY_PATH
至此,库的两种设置就完成了。

View File

@@ -18,7 +18,6 @@ http://blog.csdn.net/absurd/article/details/599813
以上的场景并非虚构,我都经历过好几次,明明在本机上好好的,在别人的机器上连编译都过不去。可能两人的操作系统一模一样,需要的库都安装上,只是由于个人喜好不同,安装在不同的目录而已。遇到这种情况,每次都技巧性的绕过去了,用的补丁型的方法,心里老惦记其它地方能不能工作。
今天我们要介绍的pkgconfig为解决以上问题提供了一个优美方案。从此你再也不为此担忧了。Pkgconfig提供了下面几个功能
1. 检查库的版本号。如果所需要的库的版本不满足要求,它会打印出错误信息,避免链接错误版本的库文件。

View File

@@ -1,123 +0,0 @@
Content-Type: text/x-zim-wiki
Wiki-Format: zim 0.4
Creation-Date: 2012-06-13T14:41:11+08:00
====== linux里命令pkg-config工具的使用 ======
Created Wednesday 13 June 2012
http://www.91linux.com/html/article/program/cpp/20071207/8934.html
===== 一、编译和连接 =====
一般来说,如果库的头文件不在 /usr/include 目录中,那么在编译的时候需要用 -I 参数指定其路径。由于同一个库在不同系统上可能位于不同的目录下,用户安装库的时候也可以将库安装在不同的目录下,所以即使使用同一个库,由于库的路径的不同,造成了用 -I 参数指定的头文件的路径也可能不同其结果就是造成了__编译命令界面的不统一__。如果使用 -L 参数也会造成连接界面的不统一。__编译和连接界面不统一__会为库的使用带来麻烦。
为了解决编译和连接界面不统一的问题,人们找到了一些解决办法。**其基本思想就是:**__事先把库的位置信息等保存起来__**,需要的时候再通过特定的工具将其中有用的 信息提取出来供编译和连接使用。这样,就可以做到编译和连接界面的一致性。**其中目前最为常用的__库信息提取工具__就是下面介绍的 pkg-config。
pkg-config 是通过__库提供的一个 .pc 文件__获得库的各种必要信息的包括版本信息、编译和连接需要的参数等。这些信息可以通过 pkg-config 提供的参数单独提取出来直接供编译器和连接器使用。
The pkgconfig package contains tools for passing the **include path and/or library paths** to build tools during the make file execution.
pkg-config is a function that returns **meta information** for the specified library.
The default setting for __PKG_CONFIG_PATH__ is **/usr/lib/pkgconfig** because of the prefix we use to install pkgconfig. You may add to PKG_CONFIG_PATH by exporting additional paths on your system where pkgconfig files are installed. Note that PKG_CONFIG_PATH is **only needed when compiling packages**, not during run-time.
在默认情况下,每个支持 pkg-config 的库对应的 .pc 文件在安装后都位于安装目录中的 lib/pkgconfig 目录下。例如,我们在上面已经将 Glib 安装在 /opt/gtk 目录下了,那么这个 Glib 库对应的 .pc 文件是 /opt/gtk/lib/pkgconfig 目录下一个叫 glib-2.0.pc 的文件:
prefix=/opt/gtk/
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
glib_genmarshal=glib-genmarshal
gobject_query=gobject-query
glib_mkenums=glib-mkenums
Name: GLib
Description: C Utility Library
Version: 2.12.13
Libs: -L${libdir} -lglib-2.0
Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib-2.0/include
在利用源代码中提供的configure脚本配置该库时.pc文件中的变量会被实际值所代替如${prefix}会被该库的实际安装位置所代替。
使用 pkg-config 的 __--cflags__ 参数可以给出在编译时所需要的选项,而 __--libs 参数__可以给出连接时的选项。例如假设一个 sample.c 的程序用到了 Glib 库,就可以这样编译:
$ gcc -c `pkg-config --cflags **glib-2.0**` sample.c
然后这样连接:
$ gcc sample.o -o sample `pkg-config --libs glib-2.0`
或者上面两步也可以合并为以下一步:
$ gcc sample.c -o sample `pkg-config --cflags --libs glib-2.0`
可以看到:**由于使用了 pkg-config 工具来获得库的选项,所以不论库安装在什么目录下,都可以使用相同的编译和连接命令,带来了编译和连接界面的统一**。
使用 pkg-config 工具提取库的编译和连接参数有两个基本的前提:
* 库本身在安装的时候必须提供一个相应的 .pc 文件。不这样做的库说明不支持 pkg-config 工具的使用。
* pkg-config 工具必须知道要到哪里去寻找此 .pc 文件。
**GTK+ 及其依赖库支持使用 pkg-config 工具**,所以剩下的问题就是如何告诉 pkg-config 到哪里去寻找库对应的 .pc 文件这也是通过设置__搜索路径__来解决的。
对于支持 pkg-config 工具的 GTK+ 及其依赖库来说,库的头文件的搜索路径的设置变成了对 .pc 文件搜索路径的设置。.pc 文件的搜索路径是通过环境变量 __PKG_CONFIG_PATH__ 来设置的pkg-config 将按照设置路径的先后顺序进行搜索,直到找到指定的 .pc 文件为止。
安装完 Glib 后,在 bash 中应该进行如下设置:
$ export PKG_CONFIG_PATH=**/opt/gtk/lib/pkgconfig**:$PKG_CONFIG_PATH
可以执行下面的命令检查是否 /opt/gtk/lib/pkgconfig 路径已经设置在 PKG_CONFIG_PATH 环境变量中:
$ echo $PKG_CONFIG_PATH
这样设置之后,使用 Glib 库的其它程序或库__在编译的时候__ pkg-config 就知道首先要到 /opt/gtk/lib/pkgconfig 这个目录中去寻找 glib-2.0.pc 了GTK+ 和其它的依赖库的 .pc 文件也将拷贝到这里,也会首先到这里搜索它们对应的 .pc 文件)。之后,通过 pkg-config 就可以把其中库的编译和连接参数提取出来供程序在编译和连接时使用。另外还需要注意的是环境变量的设置只对当前的终端窗口有效。如果到了没有进行上述设置的终端窗口中pkg-config 将找不到新安装的 glib-2.0.pc 文件、从而可能使后面进行的安装(如 Glib 之后的 Atk 的安装)无法进行。
在我们采用的安装方案中,由于是使用环境变量对 GTK+ 及其依赖库进行的设置,所以当系统重新启动、或者新开一个终端窗口之后,如果想使用新安装的 GTK+ 库,需要如上面那样重新设置 PKG_CONFIG_PATH 和 LD_LIBRARY_PATH 环境变量。
这种使用 GTK+ 的方法,在使用之前多了一个对库进行设置的过程。虽然显得稍微繁琐了一些,但却是一种最安全的使用 GTK+ 库的方式,不会对系统上已经存在的使用了 GTK+ 库的程序(比如 GNOME 桌面)带来任何冲击。
为了使库的设置变得简单一些,可以把下面的这两句设置保存到一个文件中(比如 set_gtk-2.10 文件):
export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig:$PKG_CONFIG_PATH
export **LD_LIBRARY_PATH**=/opt/gtk/lib:$LD_LIBRARY_PATH
之后,就可以用下面的方法进行库的设置了(其中的 source 命令也可以用 . 代替):
$ source set_gtk-2.10
只有在用新版的 GTK+ 库开发应用程序、或者运行使用了新版 GTK+ 库的程序的时候,才有必要进行上述设置。
如果想避免使用 GTK+ 库之前上述设置的麻烦,可以把上面两个环境变量的设置在系统的配置文件中(如 /etc/profile或者自己的用户配置文件中如 ~/.bash_profile ;库的搜索路径也可以设置在 /etc/ld.so.conf 文件中,等等。这种设置在系统启动时会生效,从而会导致使用 GTK+ 的程序使用新版的 GTK+ 运行库,这有可能会带来一些问题。当然,如果你发现用新版的 GTK+ 代替旧版没有什么问题的话,使用这种设置方式是比较方便的。加入到~/.bashrc中例如
PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig
重启之后:
[root@localhost ~]# echo $PKG_CONFIG_PATH
/opt/gtk/lib/pkgconfig
===== 二、运行时 =====
库文件在连接静态库和共享库和运行__仅限于使用共享库的程序__时被使用其搜索路径是在系统中进行设置的。一般 Linux 系统把 /lib 和 /usr/lib 两个目录作为默认的库搜索路径,所以使用这两个目录中的库时不需要进行设置搜索路径即可直接使用。对于处于默认库搜索路径之外的库,需要将库的位置添加到 库的搜索路径之中。设置库文件的搜索路径有下列两种方式,可任选其一使用:
* 在环境变量 LD_LIBRARY_PATH 中指明库的搜索路径。
* 在 /etc/ld.so.conf 文件中添加库的搜索路径。
将自己可能存放库文件的路径都加入到/etc/ld.so.conf中是明智的选择 ^_^
添加方法也极其简单将库文件的绝对路径直接写进去就OK了一行一个。例如
/usr/X11R6/lib
/usr/local/lib
/opt/lib
需要注意的是:第二种搜索路径的设置方式对于程序连接时的库(包括共享库和静态库)的定位已经足够了,但是对于使用了共享库的程序的执行还是不够的。这是 因为为了加快程序执行时对共享库的定位速度,避免使用搜索路径查找共享库的低效率,所以是直接读取库列表文件 __/etc/ld.so.cache__ 从中进行搜索的。/etc/ld.so.cache 是一个非文本的数据文件,不能直接编辑,它是根据 /etc/ld.so.conf 中设置的搜索路径由 __/sbin/ldconfig__ 命令将这些搜索路径下的共享库文件集中在一起而生成的ldconfig 命令要以 root 权限执行)。
因此,为了保证程序执行时对库的定位,在 /etc/ld.so.conf 中进行了库搜索路径的设置之后还必须__要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache__ 文件之后才可以。ldconfig ,简单的说,它的作用就是将/etc/ld.so.conf列出的路径下的库文件 缓存到/etc/ld.so.cache 以供使用。因此当安装完一些库文件,(例如刚安装好glib)或者修改ld.so.conf增加新的库路径后需要运行一下 /sbin/ldconfig使所有的库文件都被缓存到ld.so.cache中如果没做即使库文件明明就在/usr/lib下的也是不会被使用 的结果编译过程中抱错缺少xxx库去查看发现明明就在那放着搞的想大骂computer蠢猪一个。 ^_^
在程序连接时,对于库文件(静态库和共享库)的搜索路径,除了上面的设置方式之外,还可以通过 -L 参数显式指定。因为用 -L 设置的路径将被优先搜索,所以在连接的时候通常都会以这种方式直接指定要连接的库的路径。
前面已经说明过了,库搜索路径的设置有两种方式:在环境变量 LD_LIBRARY_PATH 中设置以及在 /etc/ld.so.conf 文件中设置。其中,第二种设置方式需要 root 权限,以改变 /etc/ld.so.conf 文件并执行 /sbin/ldconfig 命令。而且,当系统重新启动后,所有的基于 GTK2 的程序在运行时都将使用新安装的 GTK+ 库。不幸的是,由于 GTK+ 版本的改变,这有时会给应用程序带来兼容性的问题,造成某些程序运行不正常。为了避免出现上面的这些情况,在 GTK+ 及其依赖库的安装过程中对于库的搜索路径的设置将采用第一种方式进行。这种设置方式不需要 root 权限,设置也简单:
$ export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH
可以用下面的命令查看 LD_LIBRAY_PATH 的设置内容:
$ echo $LD_LIBRARY_PATH
至此,库的两种设置就完成了。

View File

@@ -0,0 +1,127 @@
Content-Type: text/x-zim-wiki
Wiki-Format: zim 0.4
Creation-Date: 2012-12-31T19:53:42+08:00
====== 使用GNU Autotools自動編譯項目 ======
Created Monday 31 December 2012
http://www.cnblogs.com/crazyhack/archive/2011/12/17/2291410.html
為了駕馭GNU Autotools這頭猛獸我們先來驗明它的真身:
{{./1.png}}
圖中橢圓形狀的就是gnu autotools里的主要工具了包括autoscanaclocalautoheaderautomakeautoconf等.而方形形狀只有Makefile.am和configure.ac是需要我們寫的别的方框里除了Makefile是最終的配置文件其它都是中間文件。(Makefile文件是由configure生成的)
整體流程紀錄如下:
0.添加src目錄,將項目源碼放入該目錄中
1.進入項目根目錄執行命令,以生成configure.scan文件:
autoscan
2.修改configure.scan文件為configure.ac文件,編輯configure.ac文件:
mv configure.scan configure.ac
vim configure.ac
3.編輯根目錄下的Makefile.am文件
vim Makefile.am
4.建立autogen.sh文件,將aclocal、autoheader、automake、autoconf等命令添加到腳本中。
5.在根目錄執行
./autogen.sh
6.用[./configure](執行後生成Makefile文件 )、[make]、[sudo make install]安裝並運行執行檔.
PS:其中0~5為開發人員執行的步驟6為測試人員和用戶執行的步驟。
0.在項目根目錄建立src文件夾內容如下:
image
1.在項目根目錄運行autoscan命令:
image
可以看到生成了autoscan.logautom4te.cache目錄以及我們需要的configure.scan文件
2.修改configure.scan文件為configure.ac執行:
mv configure.scan configure.ac
vim configure.ac
為了方便我已經事先寫好了configure.ac文件使用vimdiff命令對比一下修改的部分:
image
修改的部分一目了然:)
3.在根目錄添加Makefile.am文件:
vim Makefile.am
image
其中bin_PROGRAMS後面是需要生成的執行文件如有多個可以用空格隔開而xxx_SOURCES後面的就是編譯時需要的源文件了直接指定源碼在src目錄中這樣configure.ac的AC_CONFIG_FILES參數就可以寫成AC_CONFIG_FILES([Makefile])了而不需要在參數中添加更多目錄下的Makefile。否則就要寫成:
image
4.建立autogen.sh文件添加我們需要後續執行的命令aclocal、autoheader、automake、autocon:
vim autogen.sh
image
下面解釋一下各命令:
1)aclocal:根據configure.ac的定義將需要使用的m4宏定義複製到aclocal.m4裡面。缺省時搜索m4宏是從autoconf的安裝目錄和系統的aclocal目錄。
2)autoheader:負責生成config.h.in文件這裡面的C語言宏定義通過解析configure.ac生成。
3)automake:處理Makefile.am從而生成Makefile.in。automake提供了三個軟件等級:foreign、gnu和gnits。默認等級是gnu這裡我們使用foreign等級它只檢測必須的文件。在執行時使用—add-missing選項可以讓automake自動添加(默認採用符號連結)如加上—copy選項可以使用複製方式本例中automake的命令如下:
automake foreign add-missing copy
4)autoconf:生成configure文件configure是一個shell script,可以自動設定原始程式以符合不同平台上Unix系統的特性並且根據系統參數及環境產生合適的Makefile文件或C的頭文件讓源代碼可以在這些不同的平台上被編譯出來。
5.退回根目錄,在終端執行
./autogen.sh
PS:如果看到下面的提示是正常的因為我們的項目只是用於測試所以不要求按照GNU的標準來添加所有需要的文件
Makefile.am: required file `./NEWS' not found
Makefile.am: required file `./README' not found
Makefile.am: required file `./AUTHORS' not found
Makefile.am: required file `./ChangeLog' not found
6.用三部曲生成需要的執行檔:
1)./configure:
image
image
看到Makefile文件就說明配置項目成功了
2)make:
image
出現很多錯誤不要管它因為我只在testgenfilemap.c中輸入了打印hello world!的源碼,再用tree命令可以看到生成了testgenfilemap.o文件和二進制文件testgenfilemap
image
再輸入./testgenfilemap呢?
image
哈哈,恭喜你,成功了!
3)如果需要安裝到系統目錄請運行sudo make install
參考文章:
1.http://www.ibm.com/developerworks/cn/linux/l-makefile/
2.http://tetralet.luna.com.tw/index.php?op=ViewArticle&articleId=200&blogId=1
3.http://blog.csdn.net/zhbaoq/article/details/750199

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB