Skip to main content

autotools, deb 和 PPA 不完全攻略

最近在给自己的GameConqueror折腾 PPA, 那少不了折腾标题里的三样东西。下决心看了一遍三个东西的文档,整理如下

链接
autotools:
AutoconfAutomake

deb packaging:
Debian New Maintainers' Guide
Ubuntu Packaging Guide
Building Package for PPA

PPA stuff
PPA Overview
Uploading


那么一个一个说:
注意: 本篇系个人总结而非教程,如有疑问请参阅上述链接。


1. AUTOTOOLS
autotools 的精髓是让开发者免于手写繁琐的Makefile,同时又让最后生成的源码包符合GNU的一套标准。然而autotools本身也很难用。。。入门门槛比较高。当然难用是相对的,掌握了基本要领就可以了

需要手写的文件一般是一个configure.ac和若干个Makefile.am, ac和am分别是autoconf和automake的缩写

configure.ac定义了源码包整体信息,如名称,版本,编译环境等,最后根据configure.ac输出configure,而configure可以判断编译环境是否满足需要,这就是著名的./configure && make 的前一半

Makefile.am则是Makefile的另一种格式,由于绝大多数C/C++或一些其他语言的程序编译,打包,安装等等都是同一模式,所以才有了automake,Makefile.am的作用是决定程序的编译方式,还有各个文件的类型,是否打包,安装位置等等,这些由automake生成许多Makefile.in一起打包,等到编译时./configure会把Makefile.in再变成Makefile

关于configure.ac, 最开始可以用autoscan生成一个模板,自己慢慢改,有许多宏,都可以在autoconf的网页上查到

一般(我看到的)分为两个部分,前一半检查编译环境,后一半把检查的结果输出,一般就是进行宏替换等等。

检查编译环境,一般无非是编译器(是否存在,编译选项,特性支持),库(是否存在,版本),条件编译(是否启用的某个功能,或其他编译时指定的参数),这一部分去查AC_CHECK*,AM_CONDITIONAL这些宏好了,很好用

第二部分是宏替换,相关的宏是AC_CONFIG_FILES和AC_OUTPUT。Makefile.in是自动生成的,也会自动被替换,不用管它。我遇到的情况是需要写一个脚本,里面有个路径是安装路径,这样的话,我需要写一个script.in:

DATAPATH=@INSTALLPATH@

# do anything with $DATAPATH

然后在configure.ac里加上AC_CONFIG_FILES([script])

以及AS_AC_EXPAND(INSTALLPATH, "some path")

这样到时候configure的时候就会生成一个script,里面是DATAPATH=some path

其中AS_AC_EXPAND不是autotools里的宏,我是从ubuntu-tweak包里抄来的,再往上就找不到确切出处了

把这段放configure.ac里就好了
dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
dnl
dnl example
dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local

AC_DEFUN([AS_AC_EXPAND],
[
EXP_VAR=[$1]
FROM_VAR=[$2]

dnl first expand prefix and exec_prefix if necessary
prefix_save=$prefix
exec_prefix_save=$exec_prefix

dnl if no prefix given, then use /usr/local, the default prefix
if test "x$prefix" = "xNONE"; then
prefix=$ac_default_prefix
fi
dnl if no exec_prefix given, then use prefix
if test "x$exec_prefix" = "xNONE"; then
exec_prefix=$prefix
fi

full_var="$FROM_VAR"
dnl loop until it doesn't change anymore
while true; do
new_full_var="`eval echo $full_var`"
if test "x$new_full_var" = "x$full_var"; then break; fi
full_var=$new_full_var
done

dnl clean up
full_var=$new_full_var
AC_SUBST([$1], "$full_var")

dnl restore prefix and exec_prefix
prefix=$prefix_save
exec_prefix=$exec_prefix_save
])

另外需要看看AC_SUBST这个宏以及一些标准路径定义,如datadir等等

那么configure.ac基本就这么回事了,下面是Makefile.am

网上的很多教程上来就说“对于一个简单的hello程序,我们可以写如此一个Makefile.am”,但是再往下就没有了。但是像我每次看到Makefile.am里面的bin_PROGRAMS, xxx_SOURCES等等,我会想bin是啥玩意, PROGRAMS又是啥 -- 基本没查到,只能看文档。

实际是这样的
bin_PROGRAMS: bin是安装路径,即${prefix}/bin, 而prefix就是configure时指定的那个--prefix
_PROGRAMS: 是autotools里预设的宏,好比说,我想到了LaTeX里的\documentclass,基本就是一回事,其他还有_SCRIPTS, _DATA, _LIBRARIES,具体去查文档

如果定义了bin_PROGRAMS = scanmem # scanmem就是我正在搞的那个包
那么下面就会有scanmem_SOURCES = xxx.c yyy.c 这种,scanmem_XXX就是指定scanmem的具体内容了,除了_SOURCES还有_CFLAGS等等

类似的例子是dist_doc_DATA = AAA BBB, 这样 AAA BBB 会被安装到 docdir 里去,这也是个标准定义,一般是${prefix}/share/doc/$PACKAGE。 dist_则是前缀,为了将来把AAA BBB一起打包, make dist 默认是不把_DATA的内容放到包里

另外你可以可以自己写scanmem_PROGRAMS这种,但是要注意定义scanmemdir,就是对应的安装目录

还有一些:
EXTRA_DIST: 这种是强制把某些内容放到源码包里
SUBDIRS: 表示make的时候需要光顾的目录,如果 SUBDIRS = aaa . bbb, 那么就分别到aaa, 当前目录和bbb去make一番

常用的就这些把,记得把每个目录的Makefile.am都加到configure.ac里去,如
AC_CONFIG_FILES([Makefile
src/Makefile
xxx/Makefile
])

所有东西都搞完以后打个autoreconf (如果缺文件可能需要加--install)就齐活了,这时候已经可以./configure && make 了,如果想打包就make dist,这时候才终于发现了autotools的好用。。。

关于autotools的感想就这么多,总之还是看文档最有效,说的已经很清楚了。

2. DEB 打包
首先需要装一堆脚本,我也忘了有哪些了
主要需要的是debian这个目录,里面必要的文件是control copyright changelog rules这几个文件,如果没有的话可以用dh_make -e 这个命令生成一些基本的,但是我还是建议对照着一个现有的deb包看

control最简单了,照猫画虎就好了,第一大段是源码包信息,下面若干段是deb包信息,这个源码包最后打出几个deb包来就写几段

changelog需要一定格式,用dch命令,非常好用

dch:在最新的changelog entry加一段文字
dch -i: 新建一个changeleog entry,版本修订号加1
dch -v :新建一个changelog entry, 指定版本号为version

另外,最后的deb包的版本是由changelog最新一项决定的

rules:这个是打包用的Makefile,对于简单的包,可以用cdbs,虽然一听新名词显得很麻烦,但是实际上只需要如下几行

#!/usr/bin/make -f

include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/autotools.mk

DEB_CONFIGURE_EXTRA_FLAGS := --enable-gui

就行了,最下面是自定义的configure参数,还有一些其他的类似的变量

另外务必在control的Build-Depends里加上cdbs

copyright:最“没用”也是最难搞的,说明这个包是谁整的,原来作者是谁,原来的文件分别的版权和协议(由于我的包是多作者多协议,所以很麻烦),最后是这个包的协议。 这个文件对照着说明慢慢整好了。。。

这些文件都搞定以后,用debuild或者dpkg-buildpackage就好了

具体操作是这样:

首先搞来源码包,如scanmem-0.09.tar.gz,把它改名为scanmem_0.09.orig.tar.gz,注意包和版本号中间的-改为_,另外就是加个.orig
然后解压,进入scanmem-0.09目录,建立debian目录,写需要的东西。(可以用dh_make或者copy一份)
然后debuild,等会儿就好了

其他说明
1.debuild是编译成.dsc .orig.tar.gz .diff.gz这三个文件,还有个.changes 而dpkg-buildpackages则是最终搞若干个.deb

2.我的另一个需求是一个源码包搞出两个deb package出来,这个我搜了好久,现在似乎唯一可用的资源是ubuntu packaing guide以及这个链接http://www.miriamruiz.es/weblog/?p=42,我再整理一下,大致是这个样子

我现在是想编译两个包,分别是scanmem和gameconqueror,那么control文件里自然要分别写一套信息,而另一方面在debian目录里建立scanmem.install gameconqueror.install两个文件,分别是需要的文件列表,可以用通配符,例如
#scanmem.install
usr/bin/scanmem

#gameconqueror.install
usr/bin/gameconqueror
usr/share/gameconqueror/*

这样就可以了。

另外就是,默认rules是把需要的内容安装到debian/tmp/下,而如果用dh_make按照single binary的设置输出,rules文件会设成安装到debian/scanmem,需要改成tmp,否则报错

由于我主要是给PPA打包,所以用到的是debuild, dpkg-buildpackage以前自己编译内核是用过

3.我看了Debian的打包说明,发现了svn-buildpackage这个好东西,适合我这种直接在svn里搞的人。

直接在svn里建立debian目录和相关文件,然后svn-buildpackage --svn-builder=debuild -S -sa -k就搞定了,最后的东西到../build-area里去找,另外--svn-builder后面这堆参数是为PPA用的

3. PPA
ubuntu 社区的PPA确实是个好东西,装了很多PPA很是羡慕,现在也终于有一个自己的PPA了

激活PPA的大致流程是:

注册Launchpad帐号
建立一个PPA,设置名称,说明等等
创建一个自己的OpenPGP密钥,发布到Ubuntu Key Server, 再导入到Launchpad
签署Ubuntu Codes of Conduct,就是拿自己的私钥加密一个文件再上传

所有步骤在上面所述的PPA Overview链接都有说明,界面简介,高效,甚至有趣,我在操作过程中笑了好几次。倒不是多幽默,主要是确实好用,也是第一次实际操作公钥私钥这种东西。

然后就是上传了,按照Uploading Guide 慢慢来就好了。如果编译没问题,这一步很简单。只是注意要导入自己的公钥,以及签署Ubuntu Codes of Conduct。



基本就这些了,再一次跟开源世界亲密接触,真爽!

Comments

Popular posts from this blog

[转] UTF-8 and Unicode FAQ for Unix/Linux

这几天,这个东西把我搞得很头疼 而且这篇文章好像太大了,blogger自己的发布系统不能发 只好用mail了 //原文 http://www.cl.cam.ac.uk/~mgk25/unicode.html UTF-8 and Unicode FAQ for Unix/Linux by Markus Kuhn This text is a very comprehensive one-stop information resource on how you can use Unicode/UTF-8 on POSIX systems (Linux, Unix). You will find here both introductory information for every user, as well as detailed references for the experienced developer. Unicode has started to replace ASCII, ISO 8859 and EUC at all levels. It enables users to handle not only practically any script and language used on this planet, it also supports a comprehensive set of mathematical and technical symbols to simplify scientific information exchange. With the UTF-8 encoding, Unicode can be used in a convenient and backwards compatible way in environments that were designed entirely around ASCII, like Unix. UTF-8 is the way in which Unicode is used under Unix, Linux, and similar systems. It is now time to make sure that you are well familiar

Determine Perspective Lines With Off-page Vanishing Point

In perspective drawing, a vanishing point represents a group of parallel lines, in other words, a direction. For any point on the paper, if we want a line towards the same direction (in the 3d space), we simply draw a line through it and the vanishing point. But sometimes the vanishing point is too far away, such that it is outside the paper/canvas. In this example, we have a point P and two perspective lines L1 and L2. The vanishing point VP is naturally the intersection of L1 and L2. The task is to draw a line through P and VP, without having VP on the paper. I am aware of a few traditional solutions: 1. Use extra pieces of paper such that we can extend L1 and L2 until we see VP. 2. Draw everything in a smaller scale, such that we can see both P and VP on the paper. Draw the line and scale everything back. 3. Draw a perspective grid using the Brewer Method. #1 and #2 might be quite practical. #3 may not guarantee a solution, unless we can measure distances/p

Moving Items Along Bezier Curves with CSS Animation (Part 2: Time Warp)

This is a follow-up of my earlier article.  I realized that there is another way of achieving the same effect. This article has lots of nice examples and explanations, the basic idea is to make very simple @keyframe rules, usually just a linear movement, then use timing function to distort the time, such that the motion path becomes the desired curve. I'd like to call it the "time warp" hack. Demo See the Pen Interactive cubic Bezier curve + CSS animation by Lu Wang ( @coolwanglu ) on CodePen . How does it work? Recall that a cubic Bezier curve is defined by this formula : \[B(t) = (1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\ 0 \le t \le 1.\] In the 2D case, \(B(t)\) has two coordinates, \(x(t)\) and \(y(t)\). Define \(x_i\) to the be x coordinate of \(P_i\), then we have: \[x(t) = (1-t)^3x_0+3(1-t)^2tx_1+3(1-t)t^2x_2+t^3x_3,\ 0 \le t \le 1.\] So, for our animated element, we want to make sure that the x coordiante (i.e. the "left" CSS property) is \(