本文将介绍如何使用autotools生成一个Makefile文件,并在此基础上使用dh-make和debuild生成一个可发布的deb程序包,这也是咱们在Linux下开发应用程序以及想要发布应用程序须要作的。
html
不管是在Linux仍是在Unix环境中,make都是一个很是重要的编译命令。无论是本身进行项目开发仍是安装应用软件,咱们都常常要用到make或 make install。利用make工具,咱们能够将大型的开发项目分解成为多个更易于管理的模块,对于一个包括几百个源文件的应用程序,使用make和 Makefile工具就能够垂手可得的理顺各个源文件之间纷繁复杂的相互关系。其中 Makefile 文件是用于自动编译和连接的,一个工程有不少文件组成,每个文件的改变都会致使工程的从新连接,可是不是全部的文件都须要从新编译,Makefile中纪录有文件的信息,在make时会决定在连接的时候须要从新编译哪些文件。linux
Makefile的基本结构不是很复杂,但当一个程序开发人员开始写Makefile时,常常会怀疑本身写的是否符合惯例,并且本身写的Makefile常常和本身的开发环境相关联,当系统环境变量或路径发生了变化后,Makefile可能还要跟着修改。因此手动编写Makefile,对任何程序员都是一场挑战。幸而有GNU 提供的Autoconf及Automake这两套工具能够然咱们自动生成Makefile。
git
使用automake,程序开发人员只须要写一些简单的含有预约义宏的文件,由autoconf根据这个宏文件生成configure,由automake根据另外一个宏文件生成Makefile.in,再使用configure依据Makefile.in来生成一个符合惯例的Makefile。本文将介绍如何利用 GNU Autotools工具来协助咱们自动产生 Makefile文件,生成Makefile文件后,咱们将接着介绍如何使用dh-make和debuild建立一个Debian的安装包文件(deb)。这个deb文件能够拷贝到别的电脑上使用dpkg安装使用(若是足够好,能够发布!)。程序员
这是使用autotools生成Makefile文件的大致步骤。redis
我使用的是Ubuntu 13.04(32bit),使用apt-get 安装如下工具: automake,dh-make ,devscripts。
使用apt-get install automake 将安装 autoconf{a} automake autotools-dev{a} 三个包。
使用apt-get install dh-make 将安装 debhelper dh-make html2text三个包。
使用apt-get install devscripts ,这个是使用debuild所须要的。
数据库
在当前目录下建立一个名为hello的子目录。进入文件夹并新建一个标准的Hello World的C代码hello.c
#include <stdio.h>
int main(int argc, char ** argv){
printf("hello,world\n");
return 0;
}
此时,文件夹下只有一个hello.c文件,
vim
automake根据configure.in中的宏并在perl的帮助下把Makefile.am转成Makefile.in文件。Makefile.am 文件定义所要产生的目标。咱们要填写的 Makefile.am 内容为如下两句:
bin_PROGRAMS=beep // bin_PROGRAMS:定义要产生的可执行程序的文件名
beep_SOURCES=hello.c // beep_SOURCES:定义“beep”这个可执行程序所须要的原始文件。若是“beep”这个程序是由多个原始文件产生的,必须把它所用到的全部原始文件都列出来,并以空白符隔开。假设“beep”还须要“hello.c”、“main.c”、“hello.h”3个文件,则定义beep_SOURCES= hello.c main.c hello.h。若是定义多个可执行文件,则对每一个可执行程序都要定义相应的filename_SOURCES,其中filename为要生成的可执行程序的文件名。
因此,beep 能够替换为你想要生成的二进制可执行文件名(后面生成deb文件也是同样的名称),若是我最终咱们生成的应用名为long.deb,上面两句就写成:
bin_PROGRAMS=long
long_SOURCES=hello.c
当前咱们目录下只有:hello.c Makefile.am 两个文件
zhouyl@zhouyl:/tmp/hello$ vim Makefile.am
zhouyl@zhouyl:/tmp/hello$ ls
hello.c Makefile.am
安全
执行autoscan命令,会生成一个configure.scan文件,将configure.scan更名为configure.in
zhouyl@zhouyl:/tmp/hello$ autoscan
zhouyl@zhouyl:/tmp/hello$ ls
autoscan.log configure.scan hello.c Makefile.am
zhouyl@zhouyl:/tmp/hello$ mv configure.scan configure.in
zhouyl@zhouyl:/tmp/hello$ lsbash
autoscan.log configure.in hello.c Makefile.am架构
configure.in 文件的内容是一系列GNU m4 的宏,这些宏经autoconf处理后会变成检查系统特性的Shell脚本。configure.in文件中宏的顺序并无特别的规定,可是每个configure.in 文件必须以宏AC_INIT开头,以宏AC_OUTPUT结束。
打开configure.in文件咱们会看到自动生成的configure.in(scan)包括如下内容:
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69]) // 此行是描述须要的工具兼容性,如咱们使用的是autotools工具版本是2.69,这个自动生成不要修改!
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS]) // 此行是描述咱们要生成的应用的信息,包括:应用名,版本号以及维护人邮箱(直译为反馈bug地址)。好比咱们须要将此行修改为 AC_INIT([beep], [0.1], [reaper888@yeah.net])
//下面两行形容的是软件包的地址和名称,以便autotools开始工做
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])
// 在这咱们须要加入一行“ AM_INIT_AUTOMAKE ”,若是没有此行,在部分系统生成Makefile时会报错并且生成不了Makefile文件。
# Checks for programs.
AC_PROG_CC//这句高速autotools使用默认的编译器和binutils,固然你也能够传入相似于“ AC_PROG_CC([gcc gcc-4.7]) ”的参数,咱们不传参,使用默认便可
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
// 下面不变
AC_CONFIG_FILES([Makefile])// 设置configure命令所要产生的文件。咱们最终指望产生Makefile
AC_OUTPUT
因此,通过修改后,咱们的configure.in文件是:
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([beep], [0.1], [reaper888@yeah.net])
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
autoheader是用来映射头文件,aclocal用来设置全部的宏(执行aclocal会产生aclocal.m4文件,若是没有特别的要求,无需修改它。用 aclocal产生的宏将会提示automake如何动做。)。
zhouyl@zhouyl:/tmp/hello$ ls
autoscan.log configure.in hello.c Makefile.am
zhouyl@zhouyl:/tmp/hello$ autoheader
zhouyl@zhouyl:/tmp/hello$ ls
autom4te.cache autoscan.log config.h.in configure.in hello.c Makefile.am
zhouyl@zhouyl:/tmp/hello$ aclocal
zhouyl@zhouyl:/tmp/hello$ ls
aclocal.m4 autom4te.cache autoscan.log config.h.in configure.in hello.c Makefile.am
zhouyl@zhouyl:/tmp/hello$
zhouyl@zhouyl:/tmp/hello$ automake
configure.in:8: required file `./install-sh' not found
configure.in:8: `automake --add-missing' can install `install-sh'
configure.in:8: required file `./missing' not found
configure.in:8: `automake --add-missing' can install `missing'
Makefile.am: required file `./INSTALL' not found
Makefile.am: `automake --add-missing' can install `INSTALL'
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
Makefile.am: required file `./COPYING' not found
Makefile.am: `automake --add-missing' can install `COPYING'
因此,根据提示,咱们缺乏 NEWS、README、AUTHORS、ChangeLog和COPYING,而使用automake --add-missing会生成COPYING,因此在此以前咱们须要手动添加这几个文件:
zhouyl@zhouyl:/tmp/hello$ touch NEWS README AUTHORS ChangeLog
zhouyl@zhouyl:/tmp/hello$ ls
aclocal.m4 autom4te.cache ChangeLog configure.in Makefile.am README
AUTHORS autoscan.log config.h.in hello.c NEWS
注:这是我在演示如何使用autotools,若是是你真得要发布软件,请仔细填写这几个文件,而不是使用touch生成一个空文件。
如今咱们可使用automake --add-missing:
zhouyl@zhouyl:/tmp/hello$ automake --add-missing
configure.in:8: installing `./install-sh'
configure.in:8: installing `./missing'
Makefile.am: installing `./INSTALL'
Makefile.am: installing `./COPYING' using GNU General Public License v3 file
Makefile.am: Consider adding the COPYING file to the version control system
Makefile.am: for your code, to avoid questions about which license your project uses.
zhouyl@zhouyl:/tmp/hello$ ls
aclocal.m4 autom4te.cache ChangeLog configure.in hello.c install-sh Makefile.in NEWS
AUTHORS autoscan.log config.h.in COPYING INSTALL Makefile.am missing README
会发现,如今使用automake很顺利,并且生成了INSTALL、COPYING等文件。
zhouyl@zhouyl:/tmp/hello$ ls
aclocal.m4 autom4te.cache ChangeLog configure.in hello.c install-sh Makefile.in NEWS
AUTHORS autoscan.log config.h.in COPYING INSTALL Makefile.am missing README
zhouyl@zhouyl:/tmp/hello$ autoconf
zhouyl@zhouyl:/tmp/hello$ ls
aclocal.m4 autom4te.cache ChangeLog configure COPYING INSTALL Makefile.am missing README
AUTHORS autoscan.log config.h.in configure.in hello.c install-sh Makefile.in NEWS
因此,咱们能够看到,使用autoconf命令生成了configure。
接下来的工做无非就是使用configure,生成make文件:
zhouyl@zhouyl:/tmp/hello$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
……(a lot of cheaking)
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
zhouyl@zhouyl:/tmp/hello$ls
aclocal.m4 autoscan.log config.h.in configure depcomp install-sh Makefile.in README
AUTHORS ChangeLog config.log configure.in hello.c Makefile missing stamp-h1
autom4te.cache config.h config.status COPYING INSTALL Makefile.am NEWS
因此,使用./configure生成了Makefile、config.h和其余一些文件。
由于此时Makefile文件已经生成,因此咱们可使用make命令了:
zhouyl@zhouyl:/tmp/hello$ make
(CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/bash /tmp/hello/missing --run autoheader)
rm -f stamp-h1
touch config.h.in
cd . && /bin/bash ./config.status config.h
config.status: creating config.h
make all-am
make[1]: 正在进入目录 `/tmp/hello'
gcc -DHAVE_CONFIG_H -I. -g -O2 -MT hello.o -MD -MP -MF .deps/hello.Tpo -c -o hello.o hello.c
mv -f .deps/hello.Tpo .deps/hello.Po
gcc -g -O2 -o beep hello.o
make[1]:正在离开目录 `/tmp/hello'
zhouyl@zhouyl:/tmp/hello$ ls // 使用make命令后,生成了二进制可执行文件,由于咱们在上面已经指定,因此生成的可执行文件名不是hello而是beep
aclocal.m4 autoscan.log config.h config.log configure.in hello.c install-sh Makefile.in README
AUTHORS beep config.h.in config.status COPYING hello.o Makefile missing stamp-h1
autom4te.cache ChangeLog config.h.in~ configure depcomp INSTALL Makefile.am NEWS
dslab@Raring-Ringtail:/tmp/hello$ ./beep // 运行二进制可执行文件,得正确的执行结果
hello,world
分析一下能够发现,咱们这一步的步骤大体是这样的:
Makefile.in -----+ +-> Makefile -----+-> make -> binary
src/Makefile.in -+-> ./configure -+-> src/Makefile -+
config.h.in -----+ +-> config.h -----+
其实此时,在当前目录下有Makefile文件,咱们能够作的工做有:
* make all:产生设定的目标,即生成全部的可执行文件。使用make也能够达到此目的。
* make clean:删除以前编译时生成的可执行文件及目标文件(形如*.o的中间文件)。
* make distclean:除了删除可执行文件和目标文件之外,把configure所产生的 Makefile文件也清除掉。一般在发布软件前执行该命令。
* make install:将使用make all或make命令产生的可执行文件以软件的形式安装到系统中。若使用bin_PROGRAMS宏,程序将会被安装到 /usr/local/bin下,不然安装到预约义的目录下。
* make dist:将程序和相关的文档包装为一个压缩文档以供发布。执行完该命令,在当前目录下会产生一个名为PACKAGE-VERSION.tar.gz的文件。PACKAGE 和 VERSION 这两个参数是来自configure.in文件中的AM_INIT_AUTOMAKE(PACKAGE,
VERSION)。如在上个例子中执行make dist命令,会产生名为“hello-1.0.tar.gz”的文件。
* make distcheck:与make dist相似,可是加入了检查包装之后的压缩文件是否正常。
======================= 下面步骤是生成deb程序包,Debian系专属 ==================================
下面,咱们作的但是高端大气上档次的工做 -- 生成可发布的Debian应用包 -- deb文件。(Debian系Linux专属哦)
首先,咱们使用“ make dist ”命令,make dist将程序和相关的文档包装为一个压缩文档以供发布。今后,你将不再想手动写Makefile!!
zhouyl@zhouyl:/tmp/hello$ make dist
if test -d "beep-0.1"; then find "beep-0.1" -type d ! -perm -200 -exec chmod u+w {} ';' && rm -rf "beep-0.1" || { sleep 5 && rm -rf "beep-0.1"; }; else :; fi
test -d "beep-0.1" || mkdir "beep-0.1"
test -n "" \
|| find "beep-0.1" -type d ! -perm -755 \
-exec chmod u+rwx,go+rx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec /bin/bash /tmp/hello/install-sh -c -m a+r {} {} \; \
|| chmod -R a+r "beep-0.1"
tardir=beep-0.1 && ${TAR-tar} chof - "$tardir" | GZIP=--best gzip -c >beep-0.1.tar.gz
if test -d "beep-0.1"; then find "beep-0.1" -type d ! -perm -200 -exec chmod u+w {} ';' && rm -rf "beep-0.1" || { sleep 5 && rm -rf "beep-0.1"; }; else :; fi
zhouyl@zhouyl:/tmp/hello$ ls
aclocal.m4 autoscan.log config.h config.status COPYING install-sh Makefile.in README
AUTHORS beep-0.1.tar.gz config.h.in configure hello.c Makefile missing stamp-h1
autom4te.cache ChangeLog config.log configure.in INSTALL Makefile.am NEWS
咱们能够看到,目录里多了个beep-0.1.tar.gz文件。这就是咱们后续工做的核心
zhouyl@zhouyl:/tmp/hello$ mkdir ../hello_deb
zhouyl@zhouyl:/tmp/hello$ cd ../hello_deb/
zhouyl@zhouyl:/tmp/hello_deb$ cp ../hello/beep-0.1.tar.gz ./
zhouyl@zhouyl:/tmp/hello_deb$ ls
beep-0.1.tar.gz
zhouyl@zhouyl:/tmp/hello_deb$ tar -xzf beep-0.1.tar.gz
zhouyl@zhouyl:/tmp/hello_deb$ ls
beep-0.1 beep-0.1.tar.gz
zhouyl@zhouyl:/tmp/hello_deb$ cd beep-0.1/
zhouyl@zhouyl:/tmp/hello_deb/beep-0.1$ ls
aclocal.m4 ChangeLog configure COPYING install-sh Makefile.in NEWS
AUTHORS config.h.in configure.in INSTALL Makefile.am missing README
为了建立一个Debian包,咱们首先要建立一个Debian控制文件,因此咱们须要先配置dh_make,最基本的咱们须要先配置以下两个选项(固然,还有其余更多的选项,如今咱们就配置最简单的):
export DEBFULLNAME="your name"
export DEBEMAIL="a@b.com"
在此咱们须要配置Debian包的维护人名称和邮箱,好比我就能够写:
export DEBFULLNAME="Zhouyl"
export DEBEMAIL="reaper888@yeah.net"
作好上述步骤后,咱们可使用“ dh_make --single -copyright=gpl3 -f ../beep-0.1.tar.gz ” ,会提示一些确认信息,其中须要选择"single" (s)型包。
zhouyl@zhouyl:/tmp/hello_deb/beep-0.1$ export DEBFULLNAME="Zhouyl"
zhouyl@zhouyl:/tmp/hello_deb/beep-0.1$ export DEBEMAIL="reaper888@yeah.net"
zhouyl@zhouyl:/tmp/hello_deb/beep-0.1$ dh_make --single -copyright=gpl3 -f ../beep-0.1.tar.gz
Maintainer name : Zhouyl
Email-Address : reaper888@yeah.net
Date : Mon, 14 Oct 2013 10:03:41 +0800
Package Name : beep
Version : 0.1
License : gpl3
Type of Package : Single
Hit <enter> to confirm:
Done. Please edit the files in the debian/ subdirectory now. beep
uses a configure script, so you probably don't have to edit the Makefiles.
如今咱们ls下当前目录,会发现当前目录下多了一个debian目录,咱们cd进debian目录,打开control文件:
zhouyl@zhouyl:/tmp/hello_deb/beep-0.1$ cd debian/
zhouyl@zhouyl:/tmp/hello_deb/beep-0.1/debian$ vim control
----- 下面是control内容
Source: beep // 程序包名
Section: unknown // 使用 unknown 或者misc 均可以,建议使用 misc
Priority: extra
Maintainer: Zhouyl <reaper888@yeah.net>
Build-Depends: debhelper (>= 8.0.0), autotools-dev
Standards-Version: 3.9.4
Homepage: <insert the upstream URL, if relevant> // 若是你的程序有官方网站,在此编辑上网站地址
#Vcs-Git: git://git.debian.org/collab-maint/beep.git
#Vcs-Browser: http://git.debian.org/?p=collab-maint/beep.git;a=summary
Package: beep
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: <insert up to 60 chars description>
<insert long description, indented with spaces>
cd ..进入beep-0.1目录,使用debuild命令
dslab@Raring-Ringtail:/tmp/hello_deb/beep-0.1/debian$ cd ..
dslab@Raring-Ringtail:/tmp/hello_deb/beep-0.1$ debuild
dpkg-buildpackage -rfakeroot -D -us -uc
dpkg-buildpackage: 源码包 beep
dpkg-buildpackage: 源码版本 0.1-1
dpkg-buildpackage: 源码修改者 Zhouyl <reaper888@yeah.net>
dpkg-source --before-build beep-0.1
dpkg-buildpackage: 主机架构 i386
……
gpg: “Zhouyl <reaper888@yeah.net>”已跳过:私钥不可用
gpg: /tmp/debsign.rFNS3UeK/beep_0.1-1.dsc: clearsign failed: 私钥不可用
debsign: gpg error occurred! Aborting....
debuild: fatal error at line 1278:
running debsign failed
因此,此时由于须要gpg密钥,而当前还没设置(为不可用的),因此遇到错误并退出,咱们使用 gpg --gen-key 命令:
zhouyl@zhouyl:/tmp/hello_deb/beep-0.1$ gpg --gen-key
gpg (GnuPG) 1.4.12; Copyright (C) 2012 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
请选择您要使用的密钥种类:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (仅用于签名)
(4) RSA (仅用于签名)
您的选择?
RSA 密钥长度应在 1024 位与 4096 位之间。
您想要用多大的密钥尺寸?(2048)
您所要求的密钥尺寸是 2048 位
请设定这把密钥的有效期限。
0 = 密钥永不过时
<n> = 密钥在 n 天后过时
<n>w = 密钥在 n 周后过时
<n>m = 密钥在 n 月后过时
<n>y = 密钥在 n 年后过时
密钥的有效期限是?(0)
密钥永远不会过时
以上正确吗?(y/n) y
您须要一个用户标识来辨识您的密钥;本软件会用真实姓名、注释和电子邮件地址组合
成用户标识,以下所示:
“Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>”
真实姓名: Zhouyl
电子邮件地址: reaper888@yeah.net
注释: hello for test
您选定了这个用户标识:
“Zhouyl (hello for test) <reaper888@yeah.net>”
更改姓名(N)、注释(C)、电子邮件地址(E)或肯定(O)/退出(Q)? O
您须要一个密码来保护您的私钥。
咱们须要生成大量的随机字节。这个时候您能够多作些杂事(像是敲打键盘、移动
鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会得到足够的熵数。
随机字节不够多。请再作一些其余的杂事,以使操做系统能搜集到更多的熵!
(还须要278字节)
^[[A^[[A^[[B+++++
...+++++
咱们须要生成大量的随机字节。这个时候您能够多作些杂事(像是敲打键盘、移动
鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会得到足够的熵数。
........+++++
...+++++
gpg: /home/dslab/.gnupg/trustdb.gpg:创建了信任度数据库
gpg: 密钥 A5318445 被标记为绝对信任
公钥和私钥已经生成并经签名。
gpg: 正在检查信任度数据库
gpg: 须要 3 份勉强信任和 1 份彻底信任,PGP 信任模型
gpg: 深度:0 有效性: 1 已签名: 0 信任度:0-,0q,0n,0m,0f,1u
pub 2048R/A5318445 2013-10-14
密钥指纹 = CD58 76C8 BE9C 242E ADEA F277 FE5D 11BB A531 8445
uid Zhouyl (hello for test) <reaper888@yeah.net>
sub 2048R/0FCA8EE0 2013-10-14
zhouyl@zhouyl:/tmp/hello_deb/beep-0.1$
在使用gpg --gen-key建立密钥时,使用默认便可,在须要传入姓名邮箱时你输入本身的信息便可,若是在下面运行时遇到我上述错误时“ 咱们须要生成大量的随机字节。这个时候您能够多作些杂事(像是敲打键盘、移动鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会得到足够的熵数。 ”(英文系统为:Not enough random bytes available. Please do some other work to give the OS a chance to collect more entropy! (Need 284 more bytes)),不要惊慌,由于建立密钥时为了提升安全等级,会须要从系统中的随机数熵池中选择随机数熵从而生成足够好的密钥,从而达到更好的加密效果(咱们的Linux中使用全部的操做做为随机数熵的源,好比说键盘输入、鼠标移动以及网卡收包等,这些都是很随机的,因此当前报错随机熵不够,咱们只须要手动添加随机熵便可,好比说多移动鼠标,多敲打键盘,最有效的方法是:打开另外一个终端,使用“ find / ” 命令(多开几个会更快),这些会很快的添加随机数熵池,上面建立密钥会很快就继续进行)。
此时,咱们继续使用debuild建立deb程序包便可。
zhouyl@zhouyl:/tmp/hello_deb/$ ls
beep-0.1 beep_0.1-1.dsc beep_0.1-1_i386.changes beep_0.1.orig.tar.gz
beep_0.1-1.debian.tar.gz beep_0.1-1_i386.build beep_0.1-1_i386.deb beep-0.1.tar.gz
=====================部分引用自:【1】http://www.cnblogs.com/phinecos/archive/2008/11/27/1342381.html【2】http://www.ibm.com/developerworks/cn/linux/l-makefile/【3】http://www.yesky.com/120/1865620.shtml