0%

GNU Automake 版本(version 1.16.1, 26 February 2018)

Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
Version 1.3 or any later version published by the Free Software
Foundation; with no Invariant Sections, with no Front-Cover texts,
and with no Back-Cover Texts. A copy of the license is included in
the section entitled “GNU Free Documentation License.”

3 Automake的设计理念


本节主要讲讲Automake是如何工作的。

3.1 一般操作


Automake 读取Makefile.am 并生成文件Makefile.in

Makefile.am定义的变量和规则会指导Automake生成相关的代码。

比如bin_PROGRAMS 变量定义了如何编译连接的规则。

Makefile.am 大部分定义的变量和规则会拷贝到生成的文件。

GNU make支持追加操作符 +=

Automake在解析时并不是特别聪明,所以最好不要编写一些奇形怪状的语句。

特别是最好不要使用 <TAB> ,如果使用很多复杂的宏也会引起诸多问题:

 % cat Makefile.am
 $(FOO:=x): bar
 % automake
 Makefile.am:1: bad characters in variable name '$(FOO'
 Makefile.am:1: ':='-style assignments are not portable

Automake 也支持下面的书写方法:

 xs = a.c b.c
 foo_SOURCES = c.c $(xs)

它将使用 a.c, b.cc.c 来代替foo_SOURCES.

Automake 也支持#开头的注释,如果以 ##开头,那么将被Automake忽略,不显示在输出中。

比如一般Makefile.am的第一行可以写成:

1
## Process this file with automake to produce Makefile.in

3.2 限定级别


Automake用于 GNU packages的维护,所以可能根据不同的需求有了一些标准,有些标准可能并不适合所有的开发人员,这里说一下三种限定级别:

foreign
Automake只检查一些必须的文件,比如标准的GNU是需要 NEWS 文件的,而这个选项就不强制,建议新手使用。

gnu
​ Automake的默认级别,会尽可能多地检查,建议极大程度上匹配GNU标准的高手使用。

gnits
​ Automake检查是否与Gnits标准一致,虽然该标准还没有定下来,所以这个暂时没有必要。

3.3 统一的命名方案


Automake变量遵循一个统一的命名方案是的很容易决定程序是如何编译和安装的。

决定 automake 什么需要编译的通常称为primary,比如称为 PROGRAMSprimary决定了一系列将编译和链接的程序。

primary 还有一个前缀,用于决定安装到什么路径。这个可以参考GNU的编码标准,比如bindir简写为bin,其中的dir省略掉。

所有应该写成bin_PROGRAMS,而不是bindir_PROGRAMS

标准目录并不一定满足我们的需求,这时就可以通过自定义参数来解决,比如:我们将把 file.xml 安装到
$(datadir)/xml.

 xmldir = $(datadir)/xml
 xml_DATA = file.xml

前缀 noinst_ 将编译但是不安装,这个参数多用于编译其他包需要目标文件的时候,比如编译创建静态库或者帮助脚本。

前缀 check_ 只有在 make check 的时候才编译,但是不安装。

目前的 primary 由: PROGRAMS, LIBRARIES, LTLIBRARIES,LISP, PYTHON, JAVA, SCRIPTS, DATA, HEADERS, MANSTEXINFOS

一些primaries 还有一些附加前缀用于控制 automake 的行为,比如:dist_, nodist_, nobase_notrans_

3.4 命令行长度不要过长


大部分的类unix系统对命令行参数和环境变量都有长度限制,详细的可以参考http://www.in-ulm.de/~mascheck/various/argmax/ ,这个在 make的时候也存在,所以我们可以采用下述策略:

 data_DATA = file1 ... fileN fileN+1 ... file2N

改写为:

 data_DATA = file1 ... fileN
 data2dir = $(datadir)
 data2_DATA = fileN+1 ... file2N

3.5 变量是如何命名的


命名中除了字母、数组和@符号,其他的都会转换为下划线。比如程序命名为 sniff-glue,最后的变量名为 sniff_glue_PROGRAMS,而不是 sniff-glue_PROGRAMS,再比如一个库 libmumble++.a将被更改为 libmumble___a_SOURCES

其中@符号的保留主要是为了防止后续Autoconf在变量替换时出现问题。

3.6 Variables reserved for the user


Some Makefile variables are reserved by the GNU Coding Standards for
the use of the “user”—the person building the package. For instance,
CFLAGS is one such variable.

Sometimes package developers are tempted to set user variables such
as CFLAGS because it appears to make their job easier. However, the
package itself should never set a user variable, particularly not to
include switches that are required for proper compilation of the
package. Since these variables are documented as being for the package
builder, that person rightfully expects to be able to override any of
these variables at build time.

To get around this problem, Automake introduces an automake-specific
shadow variable for each user flag variable. (Shadow variables are not
introduced for variables like CC, where they would make no sense.)
The shadow variable is named by prepending AM_ to the user variable’s
name. For instance, the shadow variable for YFLAGS is AM_YFLAGS.
The package maintainer—that is, the author(s) of the Makefile.am and
configure.ac files—may adjust these shadow variables however
necessary.

3.7 automake可能需要的一些软件包


Automake在生成Makefile 的时候并非单兵作战,它在为了支持多个操作系统的路上需要一帮好朋友软件来支持。如下:

ar-lib:提供给微软的一个lib归档包装器

compile 方便不能同时接受参数选项 -c 和​ -o 的编辑器,

config.guess
config.sub
​ These two programs compute the canonical triplets for the given
​ build, host, or target architecture. These programs are updated
​ regularly to support new architectures and fix probes broken by
​ changes in new kernel versions. Each new release of Automake comes
​ with up-to-date copies of these programs. If your copy of Automake
​ is getting old, you are encouraged to fetch the latest versions of
​ these files from https://savannah.gnu.org/git/?group=config
​ before making a release.

depcomp
​ This program understands how to run a compiler so that it will
​ generate not only the desired output but also dependency
​ information that is then used by the automatic dependency tracking
​ feature

install-sh
​ This is a replacement for the install program that works on
​ platforms where install is unavailable or unusable.

mdate-sh
​ This script is used to generate a version.texi file. It examines
​ a file and prints some date information about it.

missing
​ This wraps a number of programs that are typically only required by
​ maintainers. If the program in question does not exist, or seems to
​ old, missing will print an informative warning before failing
​ out, to provide the user with more context and information.

mkinstalldirs
​ This script used to be a wrapper around mkdir -p, which is not
​ portable. Now we prefer to use install-sh -d when configure
​ finds that mkdir -p does not work, this makes one less script to
​ distribute.
​ For backward compatibility mkinstalldirs is still used and
​ distributed when automake finds it in a package. But it is no
​ longer installed automatically, and it should be safe to remove it.

py-compile
​ This is used to byte-compile Python scripts.

test-driver
​ This implements the default test driver offered by the parallel
​ testsuite harness.

texinfo.tex
​ Not a program, this file is required for make dvi, make ps and
make pdf to work when Texinfo sources are in the package. The
​ latest version can be downloaded from
https://www.gnu.org/software/texinfo/.

ylwrap
​ This program wraps lex and yacc to rename their output files.
​ It also ensures that, for instance, multiple yacc instances can
​ be invoked in a single directory in parallel.

解压命令之一 gzip

.. _linux-beginner-gzip:

:ref:unzip<linux-beginner-unzip>

gzip用于对后缀为gz文件进行解压:

1
$ gzip -d data.gz

这个命令将解压examplefile.gz,并且在当前目录下生成一个名为data的解压后的文件。

但特别需要留意的是,这个操作会删除源文件,会删除源文件,会删除源文件

所以如果你想保留原始压缩文件,一定记得使用-k选项:

1
$ gzip -dk data.gz

这会保留原始的data.gz文件,并生成一个解压后的data文件。

linux 之uname命令

Linux uname命令用于打印系统信息。

uname 可显示电脑、操作系统、发行版本等等信息。

官方的定义为:

uname - print system information

使用的方法为:

1
$ uname [OPTION]...

常用的一些选项为:

  • -a, --all:打印全部的信息
  • -s, --kernel-name:打印内核名
  • -n, --nodename:打印网络节点hostnme,即主机名
  • -r, --kernel-release:打印内核发行版
  • -v, --kernel-version:打印内核版本
  • -m, --machine:打印机器的硬件名字
  • -p, --processor:打印processor或者unknown
  • -i, --hardware-platform:打印硬件平台或者“unknown”
  • -o, --operating-system:打印操作系统

一些实例

显示系统信息,这个基本足矣

1
2
$ uname -a
Linux localdomain 3.10.0-1160.36.2.el7.x86_64 #1 SMP Wed Jul 21 11:57:15 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

显示计算机类型:

1
2
$ uname -m
x86_64

显示计算机名:

1
2
$ uname -n
locaodomain

显示操作系统发行编号:

1
2
$ uname -r
3.10.0-1160.36.2.el7.x86_64

显示操作系统名称:

1
2
$ uname -s
Linux

显示系统版本与时间:

1
2
$ uname -v
#1 SMP Wed Jul 21 11:57:15 UTC 2020

SEE ALSO
arch(1), uname(2)

linux 之uname命令

Linux uname命令用于打印系统信息。

uname 可显示电脑、操作系统、发行版本等等信息。

官方的定义为:

uname - print system information

使用的方法为:

1
$ uname [OPTION]...

常用的一些选项为:

  • -a, --all:打印全部的信息
  • -s, --kernel-name:打印内核名
  • -n, --nodename:打印网络节点hostnme,即主机名
  • -r, --kernel-release:打印内核发行版
  • -v, --kernel-version:打印内核版本
  • -m, --machine:打印机器的硬件名字
  • -p, --processor:打印processor或者unknown
  • -i, --hardware-platform:打印硬件平台或者“unknown”
  • -o, --operating-system:打印操作系统

一些实例

显示系统信息,这个基本足矣

1
2
$ uname -a
Linux localdomain 3.10.0-1160.36.2.el7.x86_64 #1 SMP Wed Jul 21 11:57:15 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

显示计算机类型:

1
2
$ uname -m
x86_64

显示计算机名:

1
2
$ uname -n
locaodomain

显示操作系统发行编号:

1
2
$ uname -r
3.10.0-1160.36.2.el7.x86_64

显示操作系统名称:

1
2
$ uname -s
Linux

显示系统版本与时间:

1
2
$ uname -v
#1 SMP Wed Jul 21 11:57:15 UTC 2020

SEE ALSO
arch(1), uname(2)

解压命令之一 unzip

.. _linux-beginner-unzip:

Linux unzip命令用于解压缩zip文件。

官方的定义为:

unzip - list, test and extract compressed files in a ZIP archive

基本命令

1
$ unzip file.zip

unzip 只需在命令后跟上要解压的文件名,如 file.zip,将该压缩文件解压缩到当前目录。

指定目录解压

如果需要指定解压缩的目标目录,可以使用 -d 参数:

1
$ unzip archive.zip -d /path/where/to/extract

这样就会把压缩文件解压到指定的目录中。

不解压某些文件

如果压缩的文件巨大,而不想解压其中的某些,可以用下面的命令

1
$ unzip file.zip -x data

这个命令的意思为,解压file.zip,但是不把里面的data解压。

解压方法之一 zip

.. _linux-beginner-zip:

:ref:unzip<linux-beginner-unzip>

.. note::
林花谢了春红,太匆匆。无奈朝来寒雨,晚来风。
李煜《相见欢·林花谢了春红》

Linux zip命令的功能是用于压缩文件,解压命令为unzip

通过zip命令可以将很多文件打包成.zip格式的压缩包,里面会包含文件的名称、路径、创建时间、上次修改时间、权限等信息,与tar命令相似。

对于类似文本文件而言,压缩比基本可以达到2:1到3:1.

官方的定义为:

zip - package and compress (archive) files

语法

zip的参数超级的多,各种设置也是很巧妙,不过常用的就几个,其他的放在后面再说。

1
$ zip  [-aABcdDeEfFghjklLmoqrRSTuvVwXyz!@$] [--longoption ...]  [-b path] [-n suffixes] [-t date] [-tt date] [zipfile [file ...]]  [-xi list]

参数

  • -r--recurse-paths :遍历整个目录 for example:
  • -j--junk-paths: 仅保存文件名,而不保存路径。默认情况下zip将保存整个路径

参考实例

将指定目录及其内全部文件都打包成zip格式压缩包文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ zip -r backuptest.zip /etc
adding: etc/resolv.conf (stored 0%)
adding: etc/fonts/ (stored 0%)
adding: etc/fonts/conf.d/ (stored 0%)
adding: etc/fonts/conf.d/65-0-wqy-zenhei-sharp.conf (deflated 88%)
adding: etc/fonts/conf.d/59-liberation-mono.conf (deflated 57%)
adding: etc/fonts/conf.d/57-paratype-pt-sans.conf (deflated 66%)
adding: etc/fonts/conf.d/59-liberation-sans.conf (deflated 74%)
adding: etc/fonts/conf.d/65-0-ttf-arphic-uming.conf (deflated 87%)
adding: etc/fonts/conf.d/65-1-vlgothic-gothic.conf (deflated 74%)
adding: etc/fonts/conf.d/65-0-lohit-nepali.conf (deflated 57%)
adding: etc/fonts/conf.d/20-unhint-small-dejavu-sans.conf (deflated 43%)
adding: etc/fonts/conf.d/61-urw-d050000l.conf (deflated 71%)
adding: etc/fonts/conf.d/57-dejavu-sans.conf (deflated 77%)
...

zip还支持通配符的表达,比如将当前工作目录内所有以.jpg为后缀的文件打包:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ zip -r backuptest.zip *.jpg
adding: test0.jpg (deflated 56%)
adding: test10.jpg (deflated 56%)
adding: test12.jpg (deflated 56%)
adding: test14.jpg (deflated 56%)
adding: test16.jpg (deflated 56%)
adding: test18.jpg (deflated 56%)
adding: test20.jpg (deflated 56%)
adding: test2.jpg (deflated 56%)
adding: test22.jpg (deflated 56%)
adding: test24.jpg (deflated 56%)
adding: test26.jpg (deflated 56%)
adding: test28.jpg (deflated 56%)

仅保存文件名

zip默认情况下会保存路径信息,如果加上-j将不保存路径信息,而仅仅保存文件。
这个情况可以在希望把同一类文件放在一起时比较有用。

1
$ zip -j foo foo/*

GNU Automake 版本(version 1.16.1, 26 February 2018)

Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
Version 1.3 or any later version published by the Free Software
Foundation; with no Invariant Sections, with no Front-Cover texts,
and with no Back-Cover Texts. A copy of the license is included in
the section entitled “GNU Free Documentation License.”

2 Autotools 简介


如果以前没有接触过Automake,你可能大概也许知道它是 Autotools 工具集的一部分。

如果你已经开始研究诸如 configure,configure.ac,Makefile.in,Makefile.am,aclocal.m等,那么你可能已经看到他们被声明为 generated by Autoconf or Automake。

整套生成过程异常复杂,本章准备一点点介绍讲解出来。

Alexandre Duret-Lutz 的 Autotools 教程特别好,供参考
(http://www.lrde.epita.fr/~adl/autotools.html)。

2.1 GNU Build System 简介


作为一个开发人员,有一套构建系统是相当有必要的。

在Unix的世界里,一般使用make。所有的规则都在文件Makefile中描述。

比如程序prog链接到文件 main.o,foo.o,bar.o,文件 main.omain.c编译而成。

每次执行 make的时候,它都会读取Makefile,检查文件的修改日期,来决定哪些文件需要重新构建。

在不同的平台上进行编译的时候,Makefile 可能需要微调。

1991年David J. MacKenzie在厌倦反复修改 Makefile后,编写了一个支持20个平台的脚本。
这个脚本的文件称为 configure,可以自动调整 Makefile

现在编译软件包简化为 ./configure && make.

目前GNU项目已经标准化这个过程,安装只需要解压软件包,然后执行 ./configure && make && make install,即可安装。

Autotools 工具可以帮助我们构建自己的工具包。

Autoconf 主要完成configure, Automake 完成Makefile

2.2 GNU Build System的用例


随automake发布的还有一个示例程序 amhello-1.0.tar.gz ,一般位于
PREFIX/share/doc/automake/amhello-1.0.tar.gz,其中PREFIX为安装路径的前缀,

默认为/usr/local,还有一些发行版位于/usr

2.2.1 基本安装


最常见的安装如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
~ % tar zxf amhello-1.0.tar.gz
~ % cd amhello-1.0
~/amhello-1.0 % ./configure
...
config.status: creating Makefile
config.status: creating src/Makefile
...
~/amhello-1.0 % make
...
~/amhello-1.0 % make check
...
~/amhello-1.0 % su
Password:
/home/adl/amhello-1.0 # make install
...
/home/adl/amhello-1.0 # exit
~/amhello-1.0 % make installcheck
...

我们首先解压文件,然后执行configure,将会创建Makefile文件,此时就可以执行make命令了。

make命令将编译程序、库和相关脚本。

make check会测试程序是否运行,不过需要编写测试用例。

当一切完成后,我们就可以使用make install来安装程序的,默认情况下降安装在目录/usr/local,比如:

  • 可执行程序在 /usr/local/bin,
  • 库文件在 /usr/local/lib

2.2.2 标准的 Makefile目标


前面我们接触了 make, make check, make install, 和 make installcheck.
这里的 check, installinstallcheck称为目标,而 make本身是 make all的缩写。
下面是一些常用的make命令:

  • make all :编译程序、库、文档等
  • make install :安装并拷贝相关文件到系统目录
  • make uninstall:清除安装的文件(需要在同一个目录执行)
  • make clean:清除由make生产的编译文件
  • make distclean:清除由configure创建的文件
  • make check:运行测试用例
  • make installcheck:检查安装的程序或库
  • make dist:从源码制作发布归档文件PACKAGE-VERSION.tar.gz

2.2.3 标准目录变量


GNU的编码标准也指定了安装的目录层,如下所示:

目录变量 默认值
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}

安装的时候,安装的文件就会按照到上述变量的一个目录中。比如示例 amhello-1.0,可执行程序 hello将安装到BINDIRREADME安装到DOCDIR,默认路径为
/usr/local/share/doc/amhello.

如果希望安装到自己的目录,可以使用以下参数:

1
2
3
4
5
6
~/amhello-1.0 % ./configure --prefix ~/usr
...
~/amhello-1.0 % make
...
~/amhello-1.0 % make install
...

将安装为 ~/usr/bin/hello~/usr/share/doc/amhello/README.

更多参数可以使用 ./configure --help.

2.2.4 标准配置变量


GNU的编码标准也指定了编译中一系列的配置变量,如下所示:

变量 含义
CC C编译器
CFLAGS C编译器参数
CXX C++编译器
CXXFLAGS C++编译器参数
LDFLAGS 链接参数
CPPFLAGS C/C++预处理参数

configure一本都会设定好默认的参数值,不过如果希望覆盖默认参数,就需要修改这些值了比如通过 configure强制设定 gcc-3作为C编译器,使用 ~/usr/include的头文件编译,使用 ~/usr/lib的库进行连接。

1
~/amhello-1.0 % ./configure --prefix ~/usr CC=gcc-3 CPPFLAGS=-I$HOME/usr/include LDFLAGS=-L$HOME/usr/lib

这些变量均可以通过./configure --help查看

2.2.5 使用文件config.site重置默认的配置


在安装多个文件的时候,如果配置参数一致,那么创建一个通用的文件将十分简便。如果文件PREFIX/share/config.site存在,在configure的时候将自动导入这些参数。

重新调用上一节的命令:

1
2
~/amhello-1.0 % ./configure --prefix ~/usr CC=gcc-3 \
CPPFLAGS=-I$HOME/usr/include LDFLAGS=-L$HOME/usr/lib

此时我们就可以把下面的内容写入文件 ~/usr/share/config.site

 test -z "$CC" && CC=gcc-3
 test -z "$CPPFLAGS" && CPPFLAGS=-I$HOME/usr/include
 test -z "$LDFLAGS" && LDFLAGS=-L$HOME/usr/lib

然后,每次执行 configure都会load这个文件

1
2
3
~/amhello-1.0 % ./configure --prefix ~/usr
configure: loading site script /home/adl/usr/share/config.site
...

2.2.6 并行编译树(Parallel Build Trees) (又名VPATH Builds)


GNU Build System区分两个目录树:源码树和编译树。

源码树包含文件 configure及源码,编译树位于 configure运行的目录。一般编译树的布局与源码树类似。

正常情况下,我们可能会在源码树目录直接执行 configure命令,还有一种情况是如果希望保持源码树的整洁,在其他目录来进行编译,如下所示:

1
2
3
4
5
6
7
~ % tar zxf ~/amhello-1.0.tar.gz
~ % cd amhello-1.0
~/amhello-1.0 % mkdir build && cd build
~/amhello-1.0/build % ../configure
...
~/amhello-1.0/build % make
...

源码树与编译树的目录不同即被称为“parallel builds” 或 “VPATH builds”。

这个源码与编译不在同一个目录的方式对不同的配置参数进行编译特别方便,比如我们通过不同的配置参数来分别编译:

1
2
3
4
5
6
7
8
9
10
11
12
~ % tar zxf ~/amhello-1.0.tar.gz
~ % cd amhello-1.0
~/amhello-1.0 % mkdir debug optim && cd debug
~/amhello-1.0/debug % ../configure CFLAGS='-g -O0'
...
~/amhello-1.0/debug % make
...
~/amhello-1.0/debug % cd ../optim
~/amhello-1.0/optim % ../configure CFLAGS='-O3 -fomit-frame-pointer'
...
~/amhello-1.0/optim % make
...

对于网络文件系统,这种方式更方便了,比如我们在两个主机 HOST1HOST2上分别编译,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
~ % cd /nfs/src
/nfs/src % tar zxf ~/amhello-1.0.tar.gz
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[HOST1] ~ % mkdir /tmp/amh && cd /tmp/amh
[HOST1] /tmp/amh % /nfs/src/amhello-1.0/configure
...
[HOST1] /tmp/amh % make && sudo make install
...
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[HOST2] ~ % mkdir /tmp/amh && cd /tmp/amh
[HOST2] /tmp/amh % /nfs/src/amhello-1.0/configure
...
[HOST2] /tmp/amh % make && sudo make install
...

这种情况下,不会对源码目录有任何特殊需求,就算是只读也可编译,这个功能最开始主要是因为当时FSF使用CD-ROM发布,而CD只能读取。

2.2.7 两步安装


GNU编译系统还支持两步安装,什么意思的,也就是区分两种类型的文件,架构相关的和架构无关的,可以通过不同的 Makefile 来完成相关安装。

其实对于我们平时使用的make install是由两部分组成的:

  • 架构相关的 install-exec
  • 架构无关的install-data

从GNU编译系统的角度来看,架构相关与架构无关主要是安装环境及变量不同。所以架构相关的我们使用 make install-exec来安装,架构无关的直接使用make install-data来安装。

举个例子来看看:有两台主机需要安装,假定 (1) 程序安装到 /usr, (2) 目录 /usr/share共享。

在第一台host上,执行On the first host we would run

1
2
3
4
5
[HOST1] ~ % mkdir /tmp/amh && cd /tmp/amh
[HOST1] /tmp/amh % /nfs/src/amhello-1.0/configure --prefix /usr
...
[HOST1] /tmp/amh % make && sudo make install
...

On the second host, however, we need only install the
architecture-specific files.

1
2
3
4
5
[HOST2] ~ % mkdir /tmp/amh && cd /tmp/amh
[HOST2] /tmp/amh % /nfs/src/amhello-1.0/configure --prefix /usr
...
[HOST2] /tmp/amh % make && sudo make install-exec
...

In packages that have installation checks, it would make sense to run
make installcheck to verify that the
package works correctly despite the apparent partial installation.

2.2.8 交叉编译


这个功能特别有用,我们可以在一个平台编译,而在另外一个平台运行。

其中参数为:

  • --build=BUILD:软件包的编译系统
  • --host=HOST:软件和库将要运行的系统

再加上 --host参数的时候, configure就会搜索这个平台的交叉编译套件。交叉编译工具一般在名字前有目标架构作为前缀,比如 MinGW32 编译环境被称为i586-mingw32msvc-gcc, i586-mingw32msvc-ld, i586-mingw32msvc-as等。

接下来的操作介绍如何在GNU/Linux上为 i586-mingw32msvc编译 amhello-1.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
~/amhello-1.0 % ./configure --build i686-pc-linux-gnu --host i586-mingw32msvc
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for i586-mingw32msvc-strip... i586-mingw32msvc-strip
checking for i586-mingw32msvc-gcc... i586-mingw32msvc-gcc
checking for C compiler default output file name... a.exe
checking whether the C compiler works... yes
checking whether we are cross compiling... yes
checking for suffix of executables... .exe
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether i586-mingw32msvc-gcc accepts -g... yes
checking for i586-mingw32msvc-gcc option to accept ANSI C...
...
~/amhello-1.0 % make
...
~/amhello-1.0 % cd src; file hello.exe
hello.exe: MS Windows PE 32-bit Intel 80386 console executable not relocatable

2.2.9 安装时重命名程序


可以使用 configure的编译选项,在安装之前加上特定的前缀或后缀来避免与系统程序冲突。

  • --program-prefix=PREFIX:增加前缀
  • --program-suffix=SUFFIX:增加后缀
  • --program-transform-name=PROGRAM:安装时运行sed PROGRAM

比如下面的例子将安装 hello/usr/local/bin/test-hello

1
2
3
4
5
6
~/amhello-1.0 % ./configure --program-prefix test-
...
~/amhello-1.0 % make
...
~/amhello-1.0 % sudo make install
...

2.2.10 使用DESTDIR编译二进制包


单纯的GNU Build System的 make installmake uninstall接口并不能完全满足系统管理员的部署,比如我们希望在编译的时候安装指定路径,而在make的时候因为可能没有root权限暂时放在一个临时目录,然后再部署到其他机器。

比如像下面这个例子就很好的诠释了这个方法。

1
2
3
4
5
6
7
8
9
10
11
~/amhello-1.0 % ./configure --prefix /usr
...
~/amhello-1.0 % make
...
~/amhello-1.0 % make DESTDIR=$HOME/inst install
...
~/amhello-1.0 % cd ~/inst
~/inst % find . -type f -print > ../files.lst
~/inst % tar zcvf ~/amhello-1.0-i686.tar.gz `cat ../files.lst`
./usr/bin/hello
./usr/share/doc/amhello/README

然后,我们就可以把 amhello-1.0-i686.tar.gz解压到大部分主机的 /目录了。

注意使用cat ../files.lst而不是.是为了避免子目录的归档问题,保证在解压的时候按照预定的目录进行解压。

2.2.11 准备发布


make dist收集源码及必须的文件创建一个压缩包,名为 PACKAGE-VERSION.tar.gz

虽然也能满足大部分的功能,但是还有一个更有用的命令 make distcheck,这个命令也会像 make dist一样创建压缩包 PACKAGE-VERSION.tar.gz,并会做各种各样的检查以确保压缩包没有问题:

• 将运行所有的软件包命令,比如 make, make check, make installmake installcheck, 甚至是 make dist,来确保软件发布没有问题
• 测试只读源码树的VPATH编译
• 确保 make clean, make distclean, and make uninstall不忽略任何文件
• 检查 DESTDIR安装是否工作

所有的这些操作都在一个临时目录进行,所以并不需要root权限。

如果 make distcheck失败了,意味着其中的一个场景没有满足,可能不会影响程序的使用,不过最好根据失败的提示进一步改进得到一个完美的发布包。

2.2.12 自动依赖跟踪


Automake自动生成代码来解决依赖的问题。

configure执行的时候,我们可以看到这个过程:

1
2
3
4
~/amhello-1.0 % ./configure --prefix /usr
...
checking dependency style of gcc... gcc3
...

可以通过下面两个选项来使能或禁用依赖跟踪:

  • --disable-dependency-tracking :Speed up one-time builds.
  • --enable-dependency-tracking:Do not reject slow dependency extractors.

2.2.13 嵌套包


虽然并不推荐刚开始接触Autotools的时候就了解嵌套包,但是最为一个极具特性的功能还是需要了解一下的。

使用Autotools或者相关工具开发的时候可以任意潜逃子模块,比如包A的发布将需要字幕了的一个库,库B拥有自己的一套构建系统,那么包A的 configure脚本将先运行库B的 configure脚本,所以安装编译包A的同时也安装编译了库B。生成的包A的发型版也将包含库B。

当然还可以收集更多的包,GCC重度使用这个功能,这样就可以保证每个子模块均可以独立的开发了。

可以使用命令 configure --help=recursive来显示所有包含包的选项。

2.3 Autotools大有裨益


或许你只是希望完成一些可以通过自行编写 configure和 Makefile来完成的功能:

• 不需要特别多的功能
• 需要考虑移植的代价
• 随着GNU Coding Standards的改变需要及时升级配置文件

而 GNU Autotools 就把这些工作自己悄悄的做掉了,只需要关注你的代码即可。

2.4 经典Hello World小程序


本节中我们首先重新从头创建 amhello-1.0软件包,然后介绍下configure.acMakefile.am的含义。

2.4.1 创建 amhello-1.0.tar.gz


接下来我们从头创建 amhello-1.0.tar.gz ,这个压缩包很简单,我们只需要准备5个文件即可。
在一个空目录中创建以下文件:

src/main.c:程序 hello的源文件,我们把这个文件保存在 src/子目录,这样方便以后添加诸如man/data/的文件夹。

1
2
3
4
5
6
7
8
9
10
~/amhello % cat src/main.c
#include <config.h>
#include <stdio.h>
int
main (void)
{
puts ("Hello World!");
puts ("This is " PACKAGE_STRING ".");
return 0;
}

README:包含一些说明文档

1
2
3
~/amhello % cat README
This is a demonstration package for GNU Automake.
Type 'info Automake' to read the Automake manual.

Makefile.amsrc/Makefile.am包含Automake的指令

1
2
3
4
5
6
7
~/amhello % cat src/Makefile.am
bin_PROGRAMS = hello
hello_SOURCES = main.c
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
~/amhello % cat Makefile.am
SUBDIRS = src
dist_doc_DATA = README

configure.ac包含创建 configure脚本的Autoconf指令

1
2
3
4
5
6
7
8
9
10
~/amhello % cat configure.ac
AC_INIT([amhello], [1.0], [bug-automake@gnu.org])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CC
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([
Makefile
src/Makefile
])
AC_OUTPUT

准备好这些文件就可以运行 Autotools 了,使用 autoreconf指令:

1
2
3
4
5
~/amhello % autoreconf --install
configure.ac: installing './install-sh'
configure.ac: installing './missing'
configure.ac: installing './compile'
src/Makefile.am: installing './depcomp'

搞定,此时就完成了编译工作。

除了提示的添加的文件, autoreconf还会创建另外4个文件: configure, config.h.in,
Makefile.insrc/Makefile.in. configure将使用后面的3个文件来创建 config.h, Makefilesrc/Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
~/amhello % ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating config.h
config.status: executing depfiles commands

此时我们就可以看到已经创建了 Makefile, src/Makefileconfig.h

1
2
3
4
5
6
7
8
9
10
11
~/amhello % make
...
~/amhello % src/hello
Hello World!
This is amhello 1.0.
~/amhello % make distcheck
...
=============================================
amhello-1.0 archives ready for distribution:
amhello-1.0.tar.gz
=============================================

autoreconf只需要运行一次即可,在构建后环境,后续更改了 Makefile.amconfigure.ac,在 make的时候会自动重建需要的依赖。

autoreconfautoconf, automake等一些列命令的集合

其中 autoconf负责从configure.ac创建 configure

automakeconfigure.acMakefile.am创建 Makefile.in

2.4.2 configure.ac 配置详解


看看文件 configure.ac

 AC_INIT([amhello], [1.0], [bug-automake@gnu.org])
 AM_INIT_AUTOMAKE([-Wall -Werror foreign])
 AC_PROG_CC
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_FILES([
  Makefile
  src/Makefile
 ])
 AC_OUTPUT

这个文件被 autoconf(创建 configure) 和automake(创建 Makefile.ins)读取。这个文件包含一系列的M4宏。

AC_开头的是Autoconf 宏,以 AM_开头的是Automake 宏。

configure.ac的前两行用于初始化 Autoconf 和Automake。 AC_INIT的参数为软件包,版本及联系邮箱(可以使用 ./configure --help来看到)。

记得邮箱要使用自己的

AM_INIT_AUTOMAKE的参数为automake的选项,比如 -Wall-Werror为打开所有的警告和错误报告。 foreign选项告诉Automake这个包不遵从GNU标准。GNU包需要包含ChangeLog, AUTHORS等文件。如果我们不希望
automake抱怨就需要加上这个选项。

AC_PROG_CC可以指定 configure脚本的C编译器。文件src/Makefile.in将使用这里定义的编译器来编译生成hello,当 configuresrc/Makefile.in创建src/Makefile的时候会用到。

选项 AC_CONFIG_HEADERS([config.h])将使 configure脚本创建一个文件config.h用于汇总configure.ac文件中所有定义的宏。在我们的例子中国呢,AC_INIT宏已经定义了一部分了。比如下面这个例子:

1
2
3
4
5
6
7
...
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "bug-automake@gnu.org"

/* Define to the full name and version of this package. */
#define PACKAGE_STRING "amhello 1.0"
...

我们可能注意到文件src/main.c 包含头文件config.h,这样就可以使用 PACKAGE_STRING

AC_CONFIG_FILES宏定义了configure需要从 *.in模版生成的文件。Automake将遍历需要的 Makefile.am文件,所以如果新增了一个文件夹,一定要记得添加 Makefile到这个列表。

AC_OUTPUT行为结束命令。

2.4.3 amhelloMakefile.am配置详解


接下来我们看看文件 src/Makefile.am,这个文件包含Automake编译安装 hello的指令。

bin_PROGRAMS = hello
hello_SOURCES = main.c

Makefile.amMakefile有相同的语法。automake在处理Makefile.am的时候,会拷贝整个文件到 Makefile.in

_PROGRAMS结尾的变量为 Makefiles将要编译的程序。还有其他后缀变量,比如 _SCRIPTS, _DATA, _LIBRARIES等,参考后面的章节。

bin_PROGRAMSbin部分表示 automake将把该程序安装到BINDIR。

注意此处省略了dir

程序需要从源码编译,所以对于每一个以 _PROGRAMS结尾的PROG都需要有一个变量为 PROG_SOURCES,后面将列出所有编译时需要的源文件。

Automake也会通过这个源码文件在打包 make dist的时候一起发布。

最后我们看看顶层目录的文件Makefile.am

SUBDIRS = src
dist_doc_DATA = README

SUBDIRS是一个特殊的变量,用来列出在处理当前目录之前 make需要遍历的目录。

dist_doc_DATA = README将会把文件 README发布和安装到DOCDIR。以 _DATA结尾的变量默认情况下在 make dist发布时是不包含的,所以我们新增了前缀dist_

GNU Automake 版本(version 1.16.1, 26 February 2018)

Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
Version 1.3 or any later version published by the Free Software
Foundation; with no Invariant Sections, with no Front-Cover texts,
and with no Back-Cover Texts. A copy of the license is included in
the section entitled “GNU Free Documentation License.”

简介

Automake从文件Makefile.am中自动生成Makefile.in

Makefile.am基本由make的一系列变量定义组成。

按照GNU Makefile的标准生成 ‘Makefile.in’十分复杂,而Automake就是希望解放这个工作。

linux服务器git pull/push时不输入密码

step1

先cd到根目录,执行git config –global credential.helper store命令

1
[root@iZ25mi9h7ayZ ~]# git config --global credential.helper store

step2

执行之后会在.gitconfig文件中多加红色字体项

1
2
3
4
5
[user]
name = shaoguangleo
email = xxxx@xxxx.com
[credential]
helper = store

step3

之后cd到项目目录,执行git pull命令,会提示输入账号密码。输完这一次以后就不再需要,并且会在根目录生成一个.git-credentials文件

1
2
3
4
5
[~/gittest]# git pull
Username for 'https://github.com': xxxx@xxxx.com
Password for 'https://shaoguangleo@github.com':
[~]# cat .git-credentials
https://Username:Password@github.com

step4

之后pull/push代码都不再需要输入账号密码了~

Linux查看内存信息(型号、大小、速率等)

安装工具dmidecode

1.查看内存槽及内存条

1
$ sudo dmidecode -t memory

2.查看内存的插槽数,已经使用多少插槽.每条内存多大

1
$ sudo dmidecode -t memory | grep Size

3.查看服务器型号、序列号

1
$ sudo dmidecode | grep "System Information" -A9 | egrep "Manufacturer|Product|Serial"