LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 7436|回复: 18

翻译:如何写 SlackBuild 脚本

[复制链接]
发表于 2009-3-1 23:37:23 | 显示全部楼层 |阅读模式
利用周末时间翻译的,当时写的 html 文件,上传到 googlepages 了。

链接:http://cn.fyodor.googlepages.com/SlackBuild.html
原文链接:http://slackwiki.org/Writing_A_SlackBuild_Script

翻译有不当的,望诸位不吝赐教。谢。


edit: 用 firefox 的打印到 pdf 功能,转换成 pdf 文件了,上传。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
发表于 2009-3-2 00:04:29 | 显示全部楼层
support the good translation.
回复 支持 反对

使用道具 举报

发表于 2009-3-2 08:13:54 | 显示全部楼层
相当不错的翻译!

对于那个 ./configure --prefix=$PKG/usr 的问题,好像 slackbuilds.org 上出过问题的。就是虽然这样打出来的包结构是对的,但是里面的程序还是有可能去 $PKG/usr 下面找自己的库,安装的过程某种意义上说是 $PKG/usr => /usr 的过程,库的路径变了,安装之后的程序就没法启动了……

忽然又想到,咱们要不要有一个合作翻译 slackwiki 的计划(或者是项目)?
回复 支持 反对

使用道具 举报

发表于 2009-3-2 09:06:23 | 显示全部楼层
如何写 SlackBuild 脚本

-- 来自 SlackWiki

介绍

原作者:Florian Mueller (jjdm at jjdm.org)
增删者:Robby Workman (rworkman)
翻译者:aBiNg (cn.fyodor at gmail.com) @ 2009.03.01

如果你把 slackware 作为你的主操作系统,你很可能需要安装一些官方网 (slackware.com) 上所没有的应用程序,或者来自第三方源(例如 linuxpackages.net),或者你不想用第三方包。后一种情况下,你有几个安装应用程序的途径:


  • ./configure && make && make install
  • 使用 checkinstall
  • 使用 installwatch
  • 编译并使用 makepkg 打包
  • 写 SlackBuild 脚本


我将讨论最后一个选择:写 SlackBuild 脚本,它包含了前述几种方式的所有优点。你可以通过 SlackBuild 脚本自动地完成所有编译任务,并且以后升级或者打补丁也很方便。SlackBuild 脚本也是 Patrick Volkerding 编译 Slackware 所有官方程序包的方式。如果看到不同源代码的大量脚本,你会发现它们通常包括两部分:独立于程序的部分和依赖于程序的部分。

我无法教给你写一个"完美"的脚本,因为达到这个目标需要对 Slackware 系统有较深入的理解。你得综合考虑你所提交的包与发行版的其它包之间的关系,二者必须"亲密无间"。我所能教的是以 "Slackware Way" 编译一个能运行的包。

"But it takes so much time!"

我将用大概 30 分钟讨论这篇指南,用 15 分钟去创建每个文件(实际编译过程略),但相比以后节省的时间,开始花点时间是值得的。

Slackware 包的结构

见 SlackWiki http://www.slackwiki.org/Packages#Slackware_Package_Layout

设置编译环境

见 SlackWiki http://www.slackwiki.org/Build_Environment

准备工作

但愿你对 Slackware 包的结构现在已经清楚了,并且你已设置了一个干净的编译环境,我们开始经由 SlackBuild 脚本的编译之旅吧。

我们拿 latex2html 作为创建包的一个例子 -- 我在我的主页上已创建过这个包。

首先,建立文件夹 <build_environment>/latex2html/。获取 latex2html 最新源码包并放到此文件夹中。需要注意的是,下面使用 wget 下载源码的方式是可选的 -- 你完全可以用自己最喜欢的浏览器打开并下载它,然后再放到正确的目录中。
  1. $ cd
  2. $ mkdir latex2html
  3. $ cd latex2html
  4. $ wget [url=http://saftsack.fs.uni-bayreuth.de/%7Elatex2ht/current/latex2html-2002-2-1.tar.gz]http://saftsack.fs.uni-bayreuth.de/~latex2ht/current/latex2html-2002-2-1.tar.gz[/url] # 05.02.2005
复制代码

下一步,使用 touch 命令创建一些必要的文件。如果你对 touch 不熟悉,见:
  1. man touch
复制代码

特别注意,*.SlackBuild 文件必须总是匹配应用程序名的;例如,gaim 包将创建 gaim.SlackBuild 文件。
  1. $ touch latex2html.SlackBuild
  2. $ touch slack-desc
复制代码
解包,因为你需要查看下 configure 脚本以便后面决定哪些选项该传递给它。
  1. $ tar -xzf latex2html-2002-2-1.tar.gz || exit 1
复制代码

写 Slack-desc 文件

见 Slackwiki.org 上面的页面 Slack-desc,从中你会学到如何写一个合适的 slack-desc 文件。

写 SlackBuild 脚本

这是最占时间的部分,我将一步步来讨论。当你编译更多包的时候,你只需要复制现有 SlackBuild 脚本,然后再自定义它。首先我得提醒你,你可以用任何一种方式来写你的 SlackBuild 脚本,只要它能创建一个能正常运行包即可。现在所讲述的大概就是 Pat Volkerding 创建包的方式,但是即便是 Pat 本人也有几种写官方 SlackBuild 脚本的方式。因此,倘若你觉得应该以不同方式写,尽情去发挥吧。没有问题。

初始化脚本

用自己喜欢的编译器打开 latex2html.SlackBuild 文件。下面所要做的就是一点点地充实脚本了。你当然可以完全粘贴这些内容,但在笔者看来,自己动手将会使你更加理解其中的意思。

首先,你须设定你的 shell 解释器。这个应该是 /bin/sh,因为所有 Slackware 系统肯定都装有它,它会使脚本移植性更好。同此,你应该特别注意一下其它 shell(bash, zsh等) 的语法与 sh 的兼容性,它们不一定都通用。
  1. #!/bin/sh
复制代码

你可以把一些许可协议之类的加到你的 SlackBuild 脚本中(可能有,GPL 或 BSD-style 许可等),但至少你应该写上这个:
  1. #<your name> revision date yyyy/mm/dd
复制代码

下面几行通常用于给脚本全局变量赋值。首当其冲是 "CWD" 变量;本例,CWD 为 <build_environment>/latex2html/。如果 TMP 变量为空,还要给它赋值。
  1. #Set initial variables:
  2. CWD=$(pwd)
  3. if [ "$TMP" = "" ]; then
  4.    TMP=/tmp
  5. fi
复制代码

可能有些人喜欢在 /tmp 的子目录中编译(例如 /tmp/build),这个完全取决于你了。
  1. # 程序名的出现的版本号
  2. VERSION=2002-2-1
  3. # 如果版本与 Slackware 包冲突
  4. # 符号 - 允许在 VERSION 中使用
  5. # 你可以设置 PKG_VERSION 成不同于 VERSION 的值。 PKG_VERSION=2002.2.1 # 包名中出现的版本号
  6. ARCH=${ARCH:-i486}
  7. # 首数字是编译次数
  8. # 其次字符为作者的名字缩写,一般为三字符
  9. BUILD=${BUILD:-1_rlw}
  10. # 应用程序名
  11. APP=latex2html
  12. # 程序安装路径(真正的目录结构创建处)
  13. PKG=$TMP/package-$APP
复制代码
设定 SLKCFLAGS (它用于 CFLAGS 和 CXXFLAGS)。如果你在 gcc 版本早于 3.4.x 的系统上编译,下面一段用 "-mcpu" 代替 "-mtune"吧。
  1. if [ "$ARCH" = "i486" ]; then
  2.    SLKCFLAGS="-O2 -march=i486 -mtune=i686"
  3. elif [ "$ARCH" = "x86_64" ]; then
  4.    SLKCFLAGS="-O2 -fPIC"
  5. fi
复制代码
这段完成了依赖于程序的变量。你创建别的包的时候,只要改变相应的变量即可,后面大部分步骤将自动完成。

解包
  1. # 删除之前遗留的目录(可能以前编译过),并重新创建
  2. rm -rf $PKG
  3. mkdir -p $TMP $PKG
  4. rm -rf $TMP/$APP-$VERSION
  5. # cd 到 TMP 目录
  6. cd $TMP || exit 1
  7. # 在 TMP 目录中解包
  8. # 注意点:如果程序包以 tar.bz2 结尾,当执行 tar -jxvf
  9. tar -zxvf $CWD/$APP-$VERSION.tar.gz || exit 1
  10. # 转到程序源代码目录
  11. cd $APP-$VERSION || exit 1
  12. # 改所有者以及权限如果必要
  13. # 也许并不一定所有包都这样做,但没有坏处
  14. chown -R root:root .
  15. chmod -R u+w,go+r-w,a-s .
复制代码

编译源代码
  1. # 设置 configure 选项 # 如果程序用 C++ 语言写的,须给 CXXFLAGS 加一行
  2. CFLAGS="$SLKCFLAGS" \
  3. ./configure \
  4.    --prefix=/usr \
  5.    --sysconfdir=/etc \
  6.    --localstatedir=/var \
  7.    --with-perl=/usr/bin/perl \
  8.    --enable-eps \
  9.    --enable-gif \
  10.    --enable-png \
  11.    --build=$ARCH-slackware-linux \
  12.    --host=$ARCH-slackware-linux
  13. # 编译,有错退出
  14. make || exit
  15. # 安装所有文档到包目录,有错退出
  16. make install DESTDIR=$PKG || exit
复制代码

其中有三个 configure 选项我总会设定:


  • --prefix=/usr
  • --sysconfdir=/etc
  • --localstatedir=/var


设置文件会到 /etc 目录,状态文件(例如 log 文件)会到 /var 目录,其它都到 /usr 目录。

这就是通常意义上的 Slackware 方式,但你的系统你做主,你完全可以将所有资源装到 /usr/local 或其它目录。详情参见Unix 文件系统的继承标准

你意识到可能还有别的选项传递给 configure 脚本,对每个要编译的应该程序来说,你必须理解这些选项的意义 -- 这也是之前解压源代码的原因。直接 cd 到源代码目录运行:
  1. ./confiugre --help
复制代码

便会显示一到两页(即使有时会更多)的选项信息。通读这些帮助文档并弄明白你所需要的选项(我喜欢用管道再 lpr 得到一份复印件,你也可以使用别的:
  1. ./configure --help | lpr
  2. ./configure --help | less
复制代码

DESTDIR 变量在脚本中至关重要,因为它指定了文件安装目录。这同样也是程序包的目录($PKG)。不幸的是,有些程序的 Makefiles 文件不包括 DESTDIR 变量,因此你不能这样用。源代码目录中执行:
  1. grep DESTDIR Makefile*
复制代码

这将会告诉你程序包支不支持 DESTDIR 变量。如果输出一些包含 $DESTDIR 的行,没有问题。如果没有输出,Makefile 就不支持 DESTDIR 变量了。

顺便提个建议:在你执行 SlackBuild 脚本之前,记得一定要手动以普通用户身份执行一遍 ".configure && make && make install DESTDIR=/somedir"。它会输出程序在安装过程中究竟做了哪些"趣事"。

例如,apcupsd 会试图给 /etc/rc.d/rc.6 打补丁。嗯,这可以经由 configure 脚本选项避免掉,但在你读懂所有 Makefiles(或者检查安装过程) 之前你并不清楚。

不管怎样,如果你以普通用户身份执行这些步骤,安装程序尝试写不被允许的地方时将会有 "ermission Denied" 的提示。

安装帮助文档
  1. # 创建帮助文档目录
  2. mkdir -p $PKG/usr/doc/$APP-$VERSION
  3. # 复制文档到指定目录,并设置权限
  4. cp -a BUGS Changes FAQ INSTALL LICENSE MANIFEST README TODO docs/ $PKG/usr/doc/$APP-$VERSION
  5. find $PKG/usr/doc/$APP-$VERSION -type f -exec chmod 644 {} \;
复制代码
我(rworkman)通常也会复制一份 SlackBuild 脚本到这个目录:
  1. cat $CWD/$APP.SlackBuild > $PKG/usr/doc/$APP-$VERSION/$APP.SlackBuild
复制代码

确认你检查过源代码包中的文档,因为有些程序对于以上指定的文档并不一定都提供,有些程序还会有别的文档。换句话讲,不要只是简单地复制粘贴这些代码到你的 SlackBuild 脚本 -- 你必须为每个包自定义这部分。

最后一步
  1. # 创建 ./install 目录,并复制 slack-desc 到该目录
  2. mkdir -p $PKG/install
  3. cat $CWD/slack-desc > $PKG/install/slack-desc
复制代码

注意:有些情况下,程序安装之后可能会加一些额外的设置命令 -- 要完成它,你得添加一个被称为 "doinst.sh" 的文件,此文件包括了必要的命令,然后再用 gzip 压缩该文件。SlackBuild 脚本将 zcat(意思是 gunzip,然后再 cat 内容) 该文件,并将内容写入到 $PKG/install 目录下的 doinst.sh 文件。
  1. # 如果有 doinst.sh,添加之
  2. if [ -e $CWD/doinst.sh.gz ]; then
  3.    zcat $CWD/doinst.sh.gz > $PKG/install/doinst.sh
  4. fi
复制代码

尽可能地减少空间利用;去除库文件和二进制文件,压缩帮助文档。需要注意的是上面代码中你可以使用 "make install-strip" 代替 "make install" 以取得达到相同的目的。
  1. # 去除不必要的库文件以及二进制文件
  2. ( cd $PKG
  3.    find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
  4.    find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
  5. )
  6. # 如果有 man pages,压缩之
  7. if [ -d $PKG/usr/man ]; then
  8.    ( cd $PKG/usr/man
  9.    find . -type f -exec gzip -9 {} \;
  10.    for i in $(find . -type l) ; do ln -s $(readlink $i).gz $i.gz ; rm $i ; done
  11.    )
  12. fi
  13. # 如果有 info pages,压缩之(同时删除 dir 文件)
  14. if [ -d $PKG/usr/info ]; then
  15.    gzip -9 $PKG/usr/info/*.info
  16.    rm -f $PKG/usr/info/dir
  17. fi
复制代码

打包
  1. # 打包
  2. cd $PKG
  3. /sbin/makepkg -l y -c n $TMP/$APP-$PKG_VERSION-$ARCH-$BUILD.tgz
复制代码

相关问题

DESTDIR 变量不可用

正如上面所提到的,有些程序的 Makefiles 文件不支持 DESTDIR 选项。还有一些 DESTDIR 变量在 Makefiles 中用了别的名称。例如,Qt 程序中有些是使用 INSTLL_ROOT 变量代替的。如果你懂 Makefiles,值得你花点时间精读一下它的内容并努力搞懂安装规则中的具体执行操作。糟糕的是,有时根本没有 DESTDIR 类似的变量。最好的办法就是给 Makefile.in 打补丁或类似的操作,并发送给开发者完美代码,但我知道不是所有都有能力这么做。退而求其次的就是写信给开发者,并请求在后来的版本中加入该功能。同时,现在有些变通的方法。

例1

连同别的选项这样执行 configure 脚本:
  1. ./configure --prefix=$PKG/usr
复制代码

这会把包安装到那个指定目录。如果程序包创建 $PKG/usr/etc 和 $PKG/usr/var 目录(或者别的什么目录),你只需将它们移动到包目录树的正确位置即可。因此,你可能要尝试这样编译:
  1. ./configure --prefix=$PKG/usr \
  2.    --sysconfdir=$PKG/etc \
  3.    --localstatedir=$PKG/var
复制代码

尽管如此,还有一些程序,它们的"硬编码"配置文件是基于 configure/Makefile 参数的(译注:没懂)。这种情况,你得在打包之前找到打补丁的方法,或者至少应该为用户添加一个说明文档,用于解释如何做些必要的修改。

例2

这个例子将使用一种覆盖 Makefile 变量的方法,该方法在 Makefile 词条学中被称为 "macro",只基于命令行,故不必担心为了添加 DESTDIR 宏而给 Makefile 打补丁,而且还给那些不熟悉 Makefiles 语法的人带有便利。

如果 Makefile 文件中 'make install' 命令不带 DESTDIR,你可以改变预定义宏,这样:
  1. make prefix=$PKG/usr install
复制代码

这将覆写 Makefile 中的 $(prefix) 变量,并安装到该命令所指定目录。这样一来,你便可以使用标准的 ./configure --prefix=/usr(或 ./configure --prefix=/usr/local) 语法,并且还能通过给 'make install' 命令传递 DESTDIR=$PKG/usr 参数实现安装到不同目录的目的。

重点:宏名称是分大小写的(至少 GNU make 是这样)。有些 Makefiles 使用 "REFIX =" 宏替代通常的 "prefix =",因而 'make intall' 命令应该像这样写:
  1. make PREFIX=$PKG/usr install
复制代码

因此,检查 Makefile 文件中使用哪种形式是非常必要的。一般地,对于复杂的 makefiles 文件,最简单的是 'grep' 一下 Makefile,像这样:
  1. grep -i '^prefix \?=' Makefile{,.in}
复制代码

'-i' 参数指不分大小查找,'{,.in}' 部分将查找 "Makefile" 以及 "Makefile.in" 文件,后者是 "configure" 脚本的模板。Grep 查找内容是基本的正则表达式,因此空格加转义问号是用来匹配一个或零个空格的。

你正处理的 Makefile 文件中一旦有未定义的 "REFIX =",这种情况下就可以使用 /usr(或 /usr/local)了,再 'make PREFIX=$PKG/usr install' 安装到程序的编译位置。

给源代码打补丁

总有一些原因,迟早会让你在编译之前给源代码打补丁,并且你应该能够自动完成它。

获取补丁

大多数情况下,补丁由代码作者提供,所以我们不必在这儿讨论写补丁的问题。下载并将它放到与 SlackBuild 脚本,slack-desc 文件,以及别的相关文件相同的目录(即 $CWD)。
  1. $ wget [URL]http://someapplication.org/files/patches/bigsecuritypatch.diff[/URL]
复制代码

下面的步骤也许不必做,但开发者们通常尽可能地节约空间,故:
  1. $ gzip -9 bigsecuritypatch.diff
复制代码

这将产生一个新的名为 bigsecuritypatch.diff.gz 的文件 -- 我们一会在 SlackBuild 脚本中使用到它。

打补丁

现在编译 .SlackBuild 脚本,在 'configure, make, make install' 之前打好补丁。类似这样在 configure 脚本运行之前运行:
  1. zcat $CWD/bigsecuritypatch.diff.gz | patch -p1 || exit
复制代码

但在解压之后,根据补丁创建方式不同,可能使用不同的 patchlevel,像这样:
  1. zcat $CWD/bigsecuritypatch.diff.gz | patch -p0 || exit
复制代码

这有点超出这篇 HOWTO 范围了,但从原理上讲,'-p#' 指定了在搜索要打补丁的文件路径时截去路径中目录的个数。通常最高目录(译注:指 '/',见 man patch)都要截去,但实际情况并不总是这样(此处的 '-p0')。

参考

回复 支持 反对

使用道具 举报

发表于 2009-3-2 09:41:07 | 显示全部楼层
翻译的好!!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-3-2 10:12:07 | 显示全部楼层
to grimssion:
开发者不按 configure 规则来,怕是要麻烦包维护者了。
SlackWiki 词条不很多,但是,国内 Slacker 更不是很多,我觉得可以先着手重要部分,合作完成。
话说回来,国内 Slacker 估计不精通英文的怕是不多,我都觉得这篇翻译有点多余了似乎。

to windrose:
html 中有用了 <xmp></xmp> tag,论坛不支持吧?代码引用格式有的已乱了。谁熟悉 tex,帮做成 pdf,或者我自己学去吧,还是个未入门者呢。
回复 支持 反对

使用道具 举报

发表于 2009-3-2 11:42:22 | 显示全部楼层
不错的slackbuild翻译哦

slackbuild是针对slackware构建,所以最好所有包都用slackbuild构建,不然可能会出现grimssion的问题,我觉得是这样的
回复 支持 反对

使用道具 举报

发表于 2009-3-2 13:33:25 | 显示全部楼层
学习了,感谢lz的工作!
回复 支持 反对

使用道具 举报

发表于 2009-3-2 13:41:43 | 显示全部楼层
Post by helo_aBiNg;1954925
to grimssion:
开发者不按 configure 规则来,怕是要麻烦包维护者了。
SlackWiki 词条不很多,但是,国内 Slacker 更不是很多,我觉得可以先着手重要部分,合作完成。
话说回来,国内 Slacker 估计不精通英文的怕是不多,我都觉得这篇翻译有点多余了似乎。

to windrose:
html 中有用了 <xmp></xmp> tag,论坛不支持吧?代码引用格式有的已乱了。谁熟悉 tex,帮做成 pdf,或者我自己学去吧,还是个未入门者呢。


其实貌似不按 configure 规则来的人比较少了,所以一般不会有什么问题~ 感觉上虽然英语能看,但是母语还是快一些,如果要是有谁牵头合作的话我就跟;)

tex 谈不上熟悉但是会用一点~ 我抽空做下看?;)
回复 支持 反对

使用道具 举报

发表于 2009-3-2 14:59:03 | 显示全部楼层
非常好的资料,受益了。感谢译者。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表