guix-devel/doc/contributing.zh_CN.texi

898 lines
38 KiB
Plaintext
Raw Normal View History

@node 贡献
@chapter 贡献
这个项目是大家合作的成果,我们需要你的帮助以更好地发展。请通过
@email{guix-devel@@gnu.org} 和 Freenode IRC 上的 @code{#guix} 联系我们。我们欢迎
您的想法、bug反馈、补丁以及任何可能对项目有帮助的贡献。我们特别欢迎帮助我们打
包(@pxref{打包指导})。
@cindex 行为准则和贡献者
@cindex 贡献者契约
我们希望提供一个温暖、友好,并且没有骚扰的的环境,这样每个人都能尽最大努力贡献。
为了这个目的,我们的项目遵循“贡献者契约”,这个契约是根据
@url{http://contributor-covenant.org/}制定的。你可以在源代码目录里的
@file{CODE-OF-CONDUCT}文件里找到一份本地版。
贡献者在提交补丁和网上交流时不需要使用法律认可的名字。他们可以使用任何名字或者假
名。
@menu
* 从Git编译:: 最新的并且最好的.
* 在安装之前运行Guix:: 黑客技巧。
* 完美的配置:: 正确的工具。
* 打包指导:: Growing the distribution.
* 代码风格:: 开发者的卫生情况
* 提交补丁:: 分享你的工作。
@end menu
@node 从Git编译
@section 从Git编译
如果你想折腾Guix本身建议使用Git仓库里最新的版本
@example
git clone https://git.savannah.gnu.org/git/guix.git
@end example
当从Git检出构建Guix时除安装指导@pxref{Requirements})里提及的软件包之外还需
要这些包。
@itemize
@item @url{http://gnu.org/software/autoconf/, GNU Autoconf};
@item @url{http://gnu.org/software/automake/, GNU Automake};
@item @url{http://gnu.org/software/gettext/, GNU Gettext};
@item @url{http://gnu.org/software/texinfo/, GNU Texinfo};
@item @url{http://www.graphviz.org/, Graphviz};
@item @url{http://www.gnu.org/software/help2man/, GNU Help2man (可选)}。
@end itemize
设置Guix开发环境的最简单的方式当然是使用Guix下面这些命令启动一个shell所有的
依赖和环境变量都为折腾Guix设置好了
@example
guix environment guix
@end example
这个命令更多的信息请参考@xref{Invoking guix environment}。额外的依赖可以通过
@option{--ad-hoc}选项添加:
@example
guix environment guix --ad-hoc help2man git strace
@end example
运行 @command{./bootstrap} 以使用Autoconf和Automake生成编译系统的基础框架。如果
你的得到这样的错误:
@example
configure.ac:46: error: possibly undefined macro: PKG_CHECK_MODULES
@end example
@noindent
它可能意味着Autoconf无法找到由pkg-config提供的@file{pkg.m4}。请确保@file{pkg.m4}
可用。由Guile提供的@file{guile.m4}宏也类似。假如你的Automake安装在
@file{/usr/local},那么它不会从@file{/usr/share}里寻找@file{.m4}文件。这种情况下,
你必须执行下面这个命令:
@example
export ACLOCAL_PATH=/usr/share/aclocal
@end example
参考@xref{Macro Search Path,,, automake, The GNU Automake Manual}.
然后,像正常一样运行@command{./configure}。确保提供
@code{--localstatedir=@var{directory}}参数,@var{directory}是你当前系统的
@code{localstatedir}的值。(@pxref{The Store}
最后,用@code{make check}执行测试(@pxref{Running the Test Suite})。如果遇到任
何错误,请参考“安装指导”(@pxref{Installation})或者给
@email{guix-devel@@gnu.org, 邮件列表}发邮件。
@node 在安装之前运行Guix
@section 在安装之前运行Guix
为了保持一个合适的工作环境,你会发现在你的本地代码树里测试修改而不用安装它们会很
有用。TODO: So that you can distinguish between your ``end-user'' hat and your
``motley'' costume.
这样,即使你没有运行@code{make install},所有的命令行工具都可以使用。为此,你先
要有一个包含全部依赖的环境(@pxref{从Git编译}),然后,为所有的命令添加
前缀@command{./pre-inst-env}@file{pre-inst-env}脚本在Guix编译树的最顶层它由
@command{./configure}生成),如@footnote{@command{sudo}命令的@option{-E}参数
确保@code{GUILE_LOAD_PATH}被正确设置,从而@command{guix-daemon}和它使用的工具可
以找到它们需要的Guile模块。}
@example
$ sudo -E ./pre-inst-env guix-daemon --build-users-group=guixbuild
$ ./pre-inst-env guix build hello
@end example
@noindent
类似的对于使用Guix模块的Guile会话
@example
$ ./pre-inst-env guile -c '(use-modules (guix utils)) (pk (%current-system))'
;;; ("x86_64-linux")
@end example
@noindent
@cindex REPL
@cindex read-eval-print loop
@dots{} and for a REPL (@pxref{Using Guile Interactively,,, guile, Guile
Reference Manual}):
@example
$ ./pre-inst-env guile
scheme@@(guile-user)> ,use(guix)
scheme@@(guile-user)> ,use(gnu)
scheme@@(guile-user)> (define snakes
(fold-packages
(lambda (package lst)
(if (string-prefix? "python"
(package-name package))
(cons package lst)
lst))
'()))
scheme@@(guile-user)> (length snakes)
$1 = 361
@end example
@command{pre-inst-env}脚本设置为此好了所有必要的的环境变量,包括@env{PATH}和
@env{GUILE_LOAD_PATH}。
@command{./pre-inst-env guix pull} @emph{不} 会更新本地源代码树,它只更新符号链
接@file{~/.config/guix/current} (@pxref{Invoking guix pull})。如果你想更新本地源
代码树,请运行@command{git pull}。
@node 完美的配置
@section 完美的配置
折腾Guix的完美配置也是折腾Guile的完美配置@pxref{Using Guile in Emacs,,, guile,
Guile Reference Manual})。首先,你需要的不仅是一个编辑器,你需要
@url{http://www.gnu.org/software/emacs, Emacs},以及美妙的
@url{http://nongnu.org/geiser/, Geiser}。为此,请运行:
@example
guix package -i emacs guile emacs-geiser
@end example
Geiser允许在Emacs里进行交互式的、增长式的开发buffer里的代码补全和执行获取一
行的文档docstrings上下文敏感的补全@kbd{M-.}跳转到对象定义,测试代码的
REPL及更多@pxref{Introduction,,, geiser, Geiser User Manual})。为了方便的
Guix开发请确保修改Guile的加载路径load path以使其能从你的项目里找到源代码文
件。
@lisp
;; @r{假设Guix项目在 ~/src/guix.}
(with-eval-after-load 'geiser-guile
(add-to-list 'geiser-guile-load-path "~/src/guix"))
@end lisp
真正编辑代码时别忘了Emacs自带了方便的Scheme模式。而且一定不要错过
@url{http://www.emacswiki.org/emacs/ParEdit, Paredit}。它提供了直接操作语法树的
的功能例如用S-表达式替换父节点为S-表达式添加、删除前后的括号删除后面的S-
表达式,等等。
@cindex 代码片段
@cindex 模板
@cindex reducing boilerplate
在@file{etc/snippets}文件夹里我们还为普通的git commit信息和软件包定义提供模板。
这些模板可以通过@url{http://joaotavora.github.io/yasnippet/, YASnippet}使用,它
可以把短的触发字符串扩展成交互式的文字片段。你可能希望将这个文件夹添加到Emacs的
@var{yas-snippet-dirs}变量里。
@lisp
;; @r{假设Guix项目在 ~/src/guix.}
(with-eval-after-load 'yasnippet
(add-to-list 'yas-snippet-dirs "~/src/guix/etc/snippets"))
@end lisp
commit信息片段显示staged文件需要依赖@url{https://magit.vc/, Magit}。编辑commit信
息时,输入@code{add},然后按@kbd{TAB}就可以插入一段用于新增软件包的模板;输入
@code{update},然后按@kbd{TAB}可以插入一段更新软件包的模板;输入@code{https}然后
按@kbd{TAB}可以插入一段修改主页URI为HTTPS的模板。
@code{scheme-mode}最重要的模板可以通过输入@code{package...},然后按@kbd{TAB}触发。
这个片段还插入了触发字符串@code{origin...},以进一步展开。@code{origin}片段更进
一步的可能插入其它以@code{...}结尾的触发字符串,它们可以被继续展开。
@node 打包指导
@section 打包指导
@cindex 软件包, 创建
这个GNU发行版正在开发的早期阶段可能缺少一些你喜欢的软件。这个章节介绍你可以怎
样帮助这个发行版成长。
自由软件通常以@dfn{源代码包}的形式分发,通常是包含完整代码的@file{tar.gz}包。添
加软件包到这个发行版意味着两件事:添加描述如何编译包的@dfn{配方}和一系列依赖软件,
以及添加配方之外的@dfn{软件包元数据},如一段文字描述和证书信息。
在Guix里所有这些信息都包含在@dfn{软件包定义}里。软件包定义提供了软件包的高层视角。
它们使用Scheme编程语言编写事实上对每个软件包我们都定义一个绑定到软件包定义的
的变量,并且从模块(@pxref{Package Modules}中导出那个变量。然而深入的Scheme
知识@emph{不}是创建软件包的前提条件。若要了解软件包的更多信息,@pxref{Defining
Packages}。
一旦软件包定义准备好了并且包存在Guix代码树的一个文件里你可以用@command{guix
build} (@pxref{Invoking guix build})命令测试它。假设这个新软件包的名字叫做
@code{gnew}你可以在Guix编译树里运行这个命令(@pxref{在安装之前运行Guix})
@example
./pre-inst-env guix build gnew --keep-failed
@end example
使用@code{--keep-failed}参数会保留失败的编译树,这可以使调试编译错误更容易。
@code{--log-file}也是一个调试时很有用的参数,它可以用来访问编译日志。
如果@command{guix}命令找不到这个软件包,那可能是因为源文件包含语法错误,或者缺少
导出软件包的@code{define-public}语句。为了查找错误你可以用Guile导入这个模块以
了解这个错误的详情:
@example
./pre-inst-env guile -c '(use-modules (gnu packages gnew))'
@end example
一旦你的软件包可以正确编译,请给我们发送补丁(@pxref{提交补丁})。当然,
如果你需要帮助我们也会很乐意帮助你。一旦补丁被提交到Guix仓库里这个新的软件包
会被自动地在支持的平台上编译@url{http://hydra.gnu.org/jobset/gnu/master, our
continuous integration system}。
@cindex substituter
用户可以通过运行@command{guix pull}命令获取最新的软件包定义(@pxref{Invoking
guix pull})。当@code{@value{SUBSTITUTE-SERVER}}编译好这些软件包之后,安装这些软
件包时会自动从服务器(@pxref{Substitutes})上下载编译好的二进制包。唯一需要人工
干预的地方是评审和应用代码补丁。
@menu
* 软件自由:: 什么可以进入这个发行版。
* 软件包命名:: 名字里包含什么?
* 版本号:: 当名字不够时
* 简介和描述:: 帮助用户寻找合适的软件包
* Python模块:: 接触英式的喜剧
* Perl模块:: 小珍珠。
* Java包:: 喝咖啡休息。
* 字体:: 字体的乐趣。
@end menu
@node 软件自由
@subsection 软件自由
@c ===========================================================================
@c
@c This file was generated with po4a. Translate the source file.
@c
@c ===========================================================================
@c Adapted from http://www.gnu.org/philosophy/philosophy.html.
@cindex 自由软件
开发GNU操作系统是为了用户拥有计算的自由。GNU是@dfn{自由软件},这意味着它有
@url{http://www.gnu.org/philosophy/free-sw.html,四项重要的自由}:运行程序的自由,
以源代码形式学习和修改程序的自由,原样重新分发副本的自由,和分发修改后的版本的自
由。GNU发行版里包含的软件包只提供遵守这四项自由的软件。
此外GNU发行版遵循
@url{http://www.gnu.org/distros/free-system-distribution-guidelines.html,自由软
件发行版准则}。这些准则拒绝非自由的固件和对非自由软件的推荐,并讨论解决商标和专
利的方法。
某些上游的软件包源代码包含一小部分违反上述准则的可选的子集,比如这个子集本身就是
非自由代码。这时,这些讨厌的代码需要用合适的补丁或者软件包定义(@pxref{Defining
Packages})里的@code{origin}里的代码片段移除。这样,@code{guix build --source}就
可以返回自由的源代码而不是未经修改的上游源代码。
@node 软件包命名
@subsection 软件包命名
@cindex 软件包名字
一个软件包事实上有两个名字:第一个是@emph{Scheme变量}的名字,即用
@code{define-public}定义的名字。通过这个名字软件包可以被Scheme代码找到如用作
其它软件包的输入。第二个名字是软件包定义里的@code{name}属性的字符串值。这个名字
用于软件包管理命令,如:@command{guix package}@command{guix build}
两个名字通常是相同的,常是上游项目名字转成小写字母并把下划线替换成连字符的结果。
比如GNUnet转成@code{gnunet}SDL_net转成@code{sdl-net}。
我们不给库软件包添加@code{lib}前缀,除非它是项目官方名字的一部分。但是
@pxref{Python模块}和@ref{Perl模块}有关于Python和Perl语言的特殊规则。
字体软件包的名字处理起来不同,@pxref{字体}.
@node 版本号
@subsection 版本号
@cindex 软件包版本
我们通常只为每个自由软件的最新版本打包。但是有时候,比如对于版本不兼容的库,需要
有同一个软件包的两个或更多版本。它们需要使用不同的Scheme变量名。我们为最新的版本
使用@ref{软件包命名}里规定的名字,旧的版本使用加上后缀的名字,后缀是@code{-}
和可以区分开版本号的版本号的最小前缀。
软件包定义里的名字对于同一个软件包的所有版本都是相同的,并且不含有版本号。
例如GTK+的2.24.20和3.9.12两个版本可以这样打包:
@example
(define-public gtk+
(package
(name "gtk+")
(version "3.9.12")
...))
(define-public gtk+-2
(package
(name "gtk+")
(version "2.24.20")
...))
@end example
如果我们还需要GTK+ 3.8.2,就这样打包
@example
(define-public gtk+-3.8
(package
(name "gtk+")
(version "3.8.2")
...))
@end example
@c See <https://lists.gnu.org/archive/html/guix-devel/2016-01/msg00425.html>,
@c for a discussion of what follows.
@cindex 用于版本控制快照的版本号
有时候我们为软件包上游的版本控制系统VCS的快照而不是正式发布版打包。这是特
殊情况,因为决定哪个是稳定版的权力应该属于上游开发者。然而,有时候这是必须的。那
么,我们该如何决定写在@code{version}里的版本号呢?
显然我们需要让VCS快照的commit ID在版本号中体现出来但是我们也需要确保版本号单
调递增,以便@command{guix package --upgrade}决定哪个版本号更新。由于commit ID
尤其是Git的commit ID不是单调递增的我们添加一个每次升级快照时都手动增长的
revision数字。最后的版本号字符串看起来是这样
@example
2.0.11-3.cabba9e
^ ^ ^
| | `-- 上游的commit ID
| |
| `--- Guix软件包的revision
|
最新的上游版本号
@end example
把@code{版本号}里的commit ID截短比如只取7个数字是一个好主意。它避免了美学上
的烦恼假设美学在这里很重要以及操作系统限制引起的问题比如Linux内核的127字
节)。尽管如此,在@code{origin}里最好使用完整的commit ID以避免混淆。
@example
(define my-package
(let ((commit "c3f29bc928d5900971f65965feaae59e1272a3f7")
(revision "1")) ;Guix软件包的revision
(package
(version (git-version "0.9" revision commit))
(source (origin
(method git-fetch)
(uri (git-reference
(url "git://example.org/my-package.git")
(commit commit)))
(sha256 (base32 "1mbikn@dots{}"))
(file-name (git-file-name name version))))
;; @dots{}
)))
@end example
@node 简介和描述
@subsection 简介和描述
@cindex 软件包描述
@cindex 软件包简介
我们已经看到GNU@tie{}Guix里的每个软件包都包含一个简介synopsis和一个描述
description@pxref{Defining Packages})。简介和描述很重要:它们是
@command{guix package --search}搜索的信息,并且是帮助用户决定一个软件包是否符合
自己需求的重要信息。因此,打包的人应该关注怎样写它们的内容。
简介必须以大写字母开头,并且不能以句号结尾。它们不能以 ``a'' 或者 ``the'' 等没有
意义的词开头。例如 ``File-frobbing tool'' 要比 ``A tool that frobs files'' 更好。
简介需要说明软件包是什么--如 ``Core GNU utilities (file, text, shell)'',或者
它的用途--如 GNU@tie{}grep 的简介是 ``Print lines matching a pattern''。
Keep in mind that the synopsis must be meaningful for a very wide audience.
For example, ``Manipulate alignments in the SAM format'' might make sense
for a seasoned bioinformatics researcher, but might be fairly unhelpful or
even misleading to a non-specialized audience. It is a good idea to come up
with a synopsis that gives an idea of the application domain of the
package. In this example, this might give something like ``Manipulate
nucleotide sequence alignments'', which hopefully gives the user a better
idea of whether this is what they are looking for.
Descriptions should take between five and ten lines. Use full sentences,
and avoid using acronyms without first introducing them. Please avoid
marketing phrases such as ``world-leading'', ``industrial-strength'', and
``next-generation'', and avoid superlatives like ``the most
advanced''---they are not helpful to users looking for a package and may
even sound suspicious. Instead, try to be factual, mentioning use cases and
features.
@cindex Texinfo markup, in package descriptions
Descriptions can include Texinfo markup, which is useful to introduce
ornaments such as @code{@@code} or @code{@@dfn}, bullet lists, or hyperlinks
(@pxref{Overview,,, texinfo, GNU Texinfo}). However you should be careful
when using some characters for example @samp{@@} and curly braces which are
the basic special characters in Texinfo (@pxref{Special Characters,,,
texinfo, GNU Texinfo}). User interfaces such as @command{guix package
--show} take care of rendering it appropriately.
Synopses and descriptions are translated by volunteers
@uref{http://translationproject.org/domain/guix-packages.html, at the
Translation Project} so that as many users as possible can read them in
their native language. User interfaces search them and display them in the
language specified by the current locale.
To allow @command{xgettext} to extract them as translatable strings,
synopses and descriptions @emph{must be literal strings}. This means that
you cannot use @code{string-append} or @code{format} to construct these
strings:
@lisp
(package
;; @dots{}
(synopsis "This is translatable")
(description (string-append "This is " "*not*" " translatable.")))
@end lisp
Translation is a lot of work so, as a packager, please pay even more
attention to your synopses and descriptions as every change may entail
additional work for translators. In order to help them, it is possible to
make recommendations or instructions visible to them by inserting special
comments like this (@pxref{xgettext Invocation,,, gettext, GNU Gettext}):
@example
;; TRANSLATORS: "X11 resize-and-rotate" should not be translated.
(description "ARandR is designed to provide a simple visual front end
for the X11 resize-and-rotate (RandR) extension. @dots{}")
@end example
@node Python模块
@subsection Python模块
@cindex python
We currently package Python 2 and Python 3, under the Scheme variable names
@code{python-2} and @code{python} as explained in @ref{版本号}. To
avoid confusion and naming clashes with other programming languages, it
seems desirable that the name of a package for a Python module contains the
word @code{python}.
Some modules are compatible with only one version of Python, others with
both. If the package Foo compiles only with Python 3, we name it
@code{python-foo}; if it compiles only with Python 2, we name it
@code{python2-foo}. If it is compatible with both versions, we create two
packages with the corresponding names.
If a project already contains the word @code{python}, we drop this; for
instance, the module python-dateutil is packaged under the names
@code{python-dateutil} and @code{python2-dateutil}. If the project name
starts with @code{py} (e.g.@: @code{pytz}), we keep it and prefix it as
described above.
@subsubsection Specifying Dependencies
@cindex inputs, for Python packages
Dependency information for Python packages is usually available in the
package source tree, with varying degrees of accuracy: in the
@file{setup.py} file, in @file{requirements.txt}, or in @file{tox.ini}.
Your mission, when writing a recipe for a Python package, is to map these
dependencies to the appropriate type of ``input'' (@pxref{package Reference,
inputs}). Although the @code{pypi} importer normally does a good job
(@pxref{Invoking guix import}), you may want to check the following check
list to determine which dependency goes where.
@itemize
@item
We currently package Python 2 with @code{setuptools} and @code{pip}
installed like Python 3.4 has per default. Thus you don't need to specify
either of these as an input. @command{guix lint} will warn you if you do.
@item
Python dependencies required at run time go into @code{propagated-inputs}.
They are typically defined with the @code{install_requires} keyword in
@file{setup.py}, or in the @file{requirements.txt} file.
@item
Python packages required only at build time---e.g., those listed with the
@code{setup_requires} keyword in @file{setup.py}---or only for
testing---e.g., those in @code{tests_require}---go into
@code{native-inputs}. The rationale is that (1) they do not need to be
propagated because they are not needed at run time, and (2) in a
cross-compilation context, it's the ``native'' input that we'd want.
Examples are the @code{pytest}, @code{mock}, and @code{nose} test
frameworks. Of course if any of these packages is also required at
run-time, it needs to go to @code{propagated-inputs}.
@item
Anything that does not fall in the previous categories goes to
@code{inputs}, for example programs or C libraries required for building
Python packages containing C extensions.
@item
If a Python package has optional dependencies (@code{extras_require}), it is
up to you to decide whether to add them or not, based on their
usefulness/overhead ratio (@pxref{提交补丁, @command{guix size}}).
@end itemize
@node Perl模块
@subsection Perl模块
@cindex perl
Perl programs standing for themselves are named as any other package, using
the lowercase upstream name. For Perl packages containing a single class,
we use the lowercase class name, replace all occurrences of @code{::} by
dashes and prepend the prefix @code{perl-}. So the class @code{XML::Parser}
becomes @code{perl-xml-parser}. Modules containing several classes keep
their lowercase upstream name and are also prepended by @code{perl-}. Such
modules tend to have the word @code{perl} somewhere in their name, which
gets dropped in favor of the prefix. For instance, @code{libwww-perl}
becomes @code{perl-libwww}.
@node Java包
@subsection Java包
@cindex java
Java programs standing for themselves are named as any other package, using
the lowercase upstream name.
To avoid confusion and naming clashes with other programming languages, it
is desirable that the name of a package for a Java package is prefixed with
@code{java-}. If a project already contains the word @code{java}, we drop
this; for instance, the package @code{ngsjava} is packaged under the name
@code{java-ngs}.
For Java packages containing a single class or a small class hierarchy, we
use the lowercase class name, replace all occurrences of @code{.} by dashes
and prepend the prefix @code{java-}. So the class @code{apache.commons.cli}
becomes package @code{java-apache-commons-cli}.
@node 字体
@subsection 字体
@cindex fonts
For fonts that are in general not installed by a user for typesetting
purposes, or that are distributed as part of a larger software package, we
rely on the general packaging rules for software; for instance, this applies
to the fonts delivered as part of the X.Org system or fonts that are part of
TeX Live.
To make it easier for a user to search for fonts, names for other packages
containing only fonts are constructed as follows, independently of the
upstream package name.
The name of a package containing only one font family starts with
@code{font-}; it is followed by the foundry name and a dash @code{-} if the
foundry is known, and the font family name, in which spaces are replaced by
dashes (and as usual, all upper case letters are transformed to lower
case). For example, the Gentium font family by SIL is packaged under the
name @code{font-sil-gentium}.
For a package containing several font families, the name of the collection
is used in the place of the font family name. For instance, the Liberation
fonts consist of three families, Liberation Sans, Liberation Serif and
Liberation Mono. These could be packaged separately under the names
@code{font-liberation-sans} and so on; but as they are distributed together
under a common name, we prefer to package them together as
@code{font-liberation}.
In the case where several formats of the same font family or font collection
are packaged separately, a short form of the format, prepended by a dash, is
added to the package name. We use @code{-ttf} for TrueType fonts,
@code{-otf} for OpenType fonts and @code{-type1} for PostScript Type 1
fonts.
@node 代码风格
@section 代码风格
In general our code follows the GNU Coding Standards (@pxref{Top,,,
standards, GNU Coding Standards}). However, they do not say much about
Scheme, so here are some additional rules.
@menu
* Programming Paradigm:: How to compose your elements.
* Modules:: Where to store your code?
* Data Types and Pattern Matching:: Implementing data structures.
* Formatting Code:: Writing conventions.
@end menu
@node Programming Paradigm
@subsection Programming Paradigm
Scheme code in Guix is written in a purely functional style. One exception
is code that involves input/output, and procedures that implement low-level
concepts, such as the @code{memoize} procedure.
@node Modules
@subsection Modules
Guile modules that are meant to be used on the builder side must live in the
@code{(guix build @dots{})} name space. They must not refer to other Guix
or GNU modules. However, it is OK for a ``host-side'' module to use a
build-side module.
Modules that deal with the broader GNU system should be in the @code{(gnu
@dots{})} name space rather than @code{(guix @dots{})}.
@node Data Types and Pattern Matching
@subsection Data Types and Pattern Matching
The tendency in classical Lisp is to use lists to represent everything, and
then to browse them ``by hand'' using @code{car}, @code{cdr}, @code{cadr},
and co. There are several problems with that style, notably the fact that
it is hard to read, error-prone, and a hindrance to proper type error
reports.
Guix code should define appropriate data types (for instance, using
@code{define-record-type*}) rather than abuse lists. In addition, it should
use pattern matching, via Guiles @code{(ice-9 match)} module, especially
when matching lists.
@node Formatting Code
@subsection Formatting Code
@cindex formatting code
@cindex coding style
When writing Scheme code, we follow common wisdom among Scheme programmers.
In general, we follow the @url{http://mumble.net/~campbell/scheme/style.txt,
Riastradh's Lisp Style Rules}. This document happens to describe the
conventions mostly used in Guiles code too. It is very thoughtful and well
written, so please do read it.
Some special forms introduced in Guix, such as the @code{substitute*} macro,
have special indentation rules. These are defined in the
@file{.dir-locals.el} file, which Emacs automatically uses. Also note that
Emacs-Guix provides @code{guix-devel-mode} mode that indents and highlights
Guix code properly (@pxref{Development,,, emacs-guix, The Emacs-Guix
Reference Manual}).
@cindex indentation, of code
@cindex formatting, of code
If you do not use Emacs, please make sure to let your editor knows these
rules. To automatically indent a package definition, you can also run:
@example
./etc/indent-code.el gnu/packages/@var{file}.scm @var{package}
@end example
@noindent
This automatically indents the definition of @var{package} in
@file{gnu/packages/@var{file}.scm} by running Emacs in batch mode. To
indent a whole file, omit the second argument:
@example
./etc/indent-code.el gnu/services/@var{file}.scm
@end example
@cindex Vim, Scheme code editing
If you are editing code with Vim, we recommend that you run @code{:set
autoindent} so that your code is automatically indented as you type.
Additionally, @uref{https://www.vim.org/scripts/script.php?script_id=3998,
@code{paredit.vim}} may help you deal with all these parentheses.
We require all top-level procedures to carry a docstring. This requirement
can be relaxed for simple private procedures in the @code{(guix build
@dots{})} name space, though.
Procedures should not have more than four positional parameters. Use
keyword parameters for procedures that take more than four parameters.
@node 提交补丁
@section 提交补丁
Development is done using the Git distributed version control system. Thus,
access to the repository is not strictly necessary. We welcome
contributions in the form of patches as produced by @code{git format-patch}
sent to the @email{guix-patches@@gnu.org} mailing list.
This mailing list is backed by a Debbugs instance accessible at
@uref{https://bugs.gnu.org/guix-patches}, which allows us to keep track of
submissions. Each message sent to that mailing list gets a new tracking
number assigned; people can then follow up on the submission by sending
email to @code{@var{NNN}@@debbugs.gnu.org}, where @var{NNN} is the tracking
number (@pxref{Sending a Patch Series}).
Please write commit logs in the ChangeLog format (@pxref{Change Logs,,,
standards, GNU Coding Standards}); you can check the commit history for
examples.
Before submitting a patch that adds or modifies a package definition, please
run through this check list:
@enumerate
@item
If the authors of the packaged software provide a cryptographic signature
for the release tarball, make an effort to verify the authenticity of the
archive. For a detached GPG signature file this would be done with the
@code{gpg --verify} command.
@item
Take some time to provide an adequate synopsis and description for the
package. @xref{简介和描述}, for some guidelines.
@item
Run @code{guix lint @var{package}}, where @var{package} is the name of the
new or modified package, and fix any errors it reports (@pxref{Invoking guix
lint}).
@item
Make sure the package builds on your platform, using @code{guix build
@var{package}}.
@item
We recommend you also try building the package on other supported
platforms. As you may not have access to actual hardware platforms, we
recommend using the @code{qemu-binfmt-service-type} to emulate them. In
order to enable it, add the following service to the list of services in
your @code{operating-system} configuration:
@example
(service qemu-binfmt-service-type
(qemu-binfmt-configuration
(platforms (lookup-qemu-platforms "arm" "aarch64" "mips64el"))
(guix-support? #t)))
@end example
Then reconfigure your system.
You can then build packages for different platforms by specifying the
@code{--system} option. For example, to build the "hello" package for the
armhf, aarch64, or mips64 architectures, you would run the following
commands, respectively:
@example
guix build --system=armhf-linux --rounds=2 hello
guix build --system=aarch64-linux --rounds=2 hello
guix build --system=mips64el-linux --rounds=2 hello
@end example
@item
@cindex bundling
Make sure the package does not use bundled copies of software already
available as separate packages.
Sometimes, packages include copies of the source code of their dependencies
as a convenience for users. However, as a distribution, we want to make
sure that such packages end up using the copy we already have in the
distribution, if there is one. This improves resource usage (the dependency
is built and stored only once), and allows the distribution to make
transverse changes such as applying security updates for a given software
package in a single place and have them affect the whole system---something
that bundled copies prevent.
@item
Take a look at the profile reported by @command{guix size} (@pxref{Invoking
guix size}). This will allow you to notice references to other packages
unwillingly retained. It may also help determine whether to split the
package (@pxref{Packages with Multiple Outputs}), and which optional
dependencies should be used. In particular, avoid adding @code{texlive} as
a dependency: because of its extreme size, use @code{texlive-tiny} or
@code{texlive-union} instead.
@item
For important changes, check that dependent package (if applicable) are not
affected by the change; @code{guix refresh --list-dependent @var{package}}
will help you do that (@pxref{Invoking guix refresh}).
@c See <https://lists.gnu.org/archive/html/guix-devel/2016-10/msg00933.html>.
@cindex branching strategy
@cindex rebuild scheduling strategy
Depending on the number of dependent packages and thus the amount of
rebuilding induced, commits go to different branches, along these lines:
@table @asis
@item 300 dependent packages or less
@code{master} branch (non-disruptive changes).
@item between 300 and 1,200 dependent packages
@code{staging} branch (non-disruptive changes). This branch is intended to
be merged in @code{master} every 3 weeks or so. Topical changes (e.g., an
update of the GNOME stack) can instead go to a specific branch (say,
@code{gnome-updates}).
@item more than 1,200 dependent packages
@code{core-updates} branch (may include major and potentially disruptive
changes). This branch is intended to be merged in @code{master} every 2.5
months or so.
@end table
All these branches are @uref{https://hydra.gnu.org/project/gnu, tracked by
our build farm} and merged into @code{master} once everything has been
successfully built. This allows us to fix issues before they hit users, and
to reduce the window during which pre-built binaries are not available.
@c TODO: It would be good with badges on the website that tracks these
@c branches. Or maybe even a status page.
Generally, branches other than @code{master} are considered @emph{frozen} if
there has been a recent evaluation, or there is a corresponding @code{-next}
branch. Please ask on the mailing list or IRC if unsure where to place a
patch.
@item
@cindex determinism, of build processes
@cindex reproducible builds, checking
Check whether the package's build process is deterministic. This typically
means checking whether an independent build of the package yields the exact
same result that you obtained, bit for bit.
A simple way to do that is by building the same package several times in a
row on your machine (@pxref{Invoking guix build}):
@example
guix build --rounds=2 my-package
@end example
This is enough to catch a class of common non-determinism issues, such as
timestamps or randomly-generated output in the build result.
Another option is to use @command{guix challenge} (@pxref{Invoking guix
challenge}). You may run it once the package has been committed and built
by @code{@value{SUBSTITUTE-SERVER}} to check whether it obtains the same
result as you did. Better yet: Find another machine that can build it and
run @command{guix publish}. Since the remote build machine is likely
different from yours, this can catch non-determinism issues related to the
hardware---e.g., use of different instruction set extensions---or to the
operating system kernel---e.g., reliance on @code{uname} or @file{/proc}
files.
@item
When writing documentation, please use gender-neutral wording when referring
to people, such as @uref{https://en.wikipedia.org/wiki/Singular_they,
singular ``they''@comma{} ``their''@comma{} ``them''}, and so forth.
@item
Verify that your patch contains only one set of related changes. Bundling
unrelated changes together makes reviewing harder and slower.
Examples of unrelated changes include the addition of several packages, or a
package update along with fixes to that package.
@item
Please follow our code formatting rules, possibly running the
@command{etc/indent-code.el} script to do that automatically for you
(@pxref{Formatting Code}).
@item
When possible, use mirrors in the source URL (@pxref{Invoking guix
download}). Use reliable URLs, not generated ones. For instance, GitHub
archives are not necessarily identical from one generation to the next, so
in this case it's often better to clone the repository. Don't use the
@command{name} field in the URL: it is not very useful and if the name
changes, the URL will probably be wrong.
@end enumerate
When posting a patch to the mailing list, use @samp{[PATCH] @dots{}} as a
subject. You may use your email client or the @command{git send-email}
command (@pxref{Sending a Patch Series}). We prefer to get patches in plain
text messages, either inline or as MIME attachments. You are advised to pay
attention if your email client changes anything like line breaks or
indentation which could potentially break the patches.
When a bug is resolved, please close the thread by sending an email to
@email{@var{NNN}-done@@debbugs.gnu.org}.
@unnumberedsubsec Sending a Patch Series
@anchor{Sending a Patch Series}
@cindex patch series
@cindex @code{git send-email}
@cindex @code{git-send-email}
@c Debbugs bug: https://debbugs.gnu.org/db/15/15361.html
When sending a patch series (e.g., using @code{git send-email}), please
first send one message to @email{guix-patches@@gnu.org}, and then send
subsequent patches to @email{@var{NNN}@@debbugs.gnu.org} to make sure they
are kept together. See @uref{https://debbugs.gnu.org/Advanced.html, the
Debbugs documentation} for more information.