You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

392 lines
15 KiB

@node Contributing
@chapter Contributing
This project is a cooperative effort, and we need your help to make it
grow! Please get in touch with us on @email{} and
@code{#guix} on the Freenode IRC network. We welcome ideas, bug
reports, patches, and anything that may be helpful to the project. We
particularly welcome help on packaging (@pxref{Packaging Guidelines}).
@cindex code of conduct, of contributors
@cindex contributor covenant
We want to provide a warm, friendly, and harassment-free environment, so
that anyone can contribute to the best of their abilities. To this end
our project uses a ``Contributor Covenant'', which was adapted from
@url{}. You can find a local version in
the @file{CODE-OF-CONDUCT} file in the source tree.
Contributors are not required to use their legal name in patches and
on-line communication; they can use any name or pseudonym of their
* Building from Git:: The latest and greatest.
* Running Guix Before It Is Installed:: Hacker tricks.
* The Perfect Setup:: The right tools.
* Coding Style:: Hygiene of the contributor.
* Submitting Patches:: Share your work.
@end menu
@node Building from Git
@section Building from Git
If you want to hack Guix itself, it is recommended to use the latest
version from the Git repository. When building Guix from a checkout,
the following packages are required in addition to those mentioned in
the installation instructions (@pxref{Requirements}).
@item @url{, GNU Autoconf};
@item @url{, GNU Automake};
@item @url{, GNU Gettext};
@item @url{, GNU Texinfo};
@item @url{, Graphviz};
@item @url{, GNU Help2man (optional)}.
@end itemize
The easiest way to set up a development environment for Guix is, of
course, by using Guix! The following command starts a new shell where
all the dependencies and appropriate environment variables are set up to
hack on Guix:
guix environment guix
@end example
@xref{Invoking guix environment}, for more information on that command.
Extra dependencies can be added with @option{--ad-hoc}:
guix environment guix --ad-hoc help2man git strace
@end example
Run @command{./bootstrap} to generate the build system infrastructure
using Autoconf and Automake. If you get an error like this one:
@example error: possibly undefined macro: PKG_CHECK_MODULES
@end example
it probably means that Autoconf couldn’t find @file{pkg.m4}, which is
provided by pkg-config. Make sure that @file{pkg.m4} is available. The
same holds for the @file{guile.m4} set of macros provided by Guile. For
instance, if you installed Automake in @file{/usr/local}, it wouldn’t
look for @file{.m4} files in @file{/usr/share}. In that case, you have
to invoke the following command:
export ACLOCAL_PATH=/usr/share/aclocal
@end example
@xref{Macro Search Path,,, automake, The GNU Automake Manual}, for
more information.
Then, run @command{./configure} as usual. Make sure to pass
@code{--localstatedir=@var{directory}} where @var{directory} is the
@code{localstatedir} value used by your current installation (@pxref{The
Store}, for information about this).
Finally, you have to invoke @code{make check} to run tests
(@pxref{Running the Test Suite}). If anything
fails, take a look at installation instructions (@pxref{Installation})
or send a message to the @email{, mailing list}.
@node Running Guix Before It Is Installed
@section Running Guix Before It Is Installed
In order to keep a sane working environment, you will find it useful to
test the changes made in your local source tree checkout without
actually installing them. So that you can distinguish between your
``end-user'' hat and your ``motley'' costume.
To that end, all the command-line tools can be used even if you have not
run @code{make install}. To do that, prefix each command with
@command{./pre-inst-env} (the @file{pre-inst-env} script lives in the
top build tree of Guix), as in:
$ sudo ./pre-inst-env guix-daemon --build-users-group=guixbuild
$ ./pre-inst-env guix build hello
@end example
Similarly, for a Guile session using the Guix modules:
$ ./pre-inst-env guile -c '(use-modules (guix utils)) (pk (%current-system))'
;;; ("x86_64-linux")
@end example
@cindex REPL
@cindex read-eval-print loop
@dots{} and for a REPL (@pxref{Using Guile Interactively,,, guile, Guile
Reference Manual}):
$ ./pre-inst-env guile
scheme@@(guile-user)> ,use(guix)
scheme@@(guile-user)> ,use(gnu)
scheme@@(guile-user)> (define snakes
(lambda (package lst)
(if (string-prefix? "python"
(package-name package))
(cons package lst)
scheme@@(guile-user)> (length snakes)
$1 = 361
@end example
The @command{pre-inst-env} script sets up all the environment variables
necessary to support this, including @env{PATH} and @env{GUILE_LOAD_PATH}.
Note that @command{./pre-inst-env guix pull} does @emph{not} upgrade the
local source tree; it simply updates the @file{~/.config/guix/latest}
symlink (@pxref{Invoking guix pull}). Run @command{git pull} instead if
you want to upgrade your local source tree.@footnote{If you would like
to set up @command{guix} to use your Git checkout, you can point the
@file{~/.config/guix/latest} symlink to your Git checkout directory.
If you are the sole user of your system, you may also consider pointing
the @file{/root/.config/guix/latest} symlink to point to
@file{~/.config/guix/latest}; this way it will always use the same
@command{guix} as your user does.}
@node The Perfect Setup
@section The Perfect Setup
The Perfect Setup to hack on Guix is basically the perfect setup used
for Guile hacking (@pxref{Using Guile in Emacs,,, guile, Guile Reference
Manual}). First, you need more than an editor, you need
@url{, Emacs}, empowered by the
wonderful @url{, Geiser}.
Geiser allows for interactive and incremental development from within
Emacs: code compilation and evaluation from within buffers, access to
on-line documentation (docstrings), context-sensitive completion,
@kbd{M-.} to jump to an object definition, a REPL to try out your code,
and more (@pxref{Introduction,,, geiser, Geiser User Manual}). For
convenient Guix development, make sure to augment Guile’s load path so
that it finds source files from your checkout:
;; @r{Assuming the Guix checkout is in ~/src/guix.}
(with-eval-after-load 'geiser-guile
(add-to-list 'geiser-guile-load-path "~/src/guix"))
@end lisp
To actually edit the code, Emacs already has a neat Scheme mode. But in
addition to that, you must not miss
@url{, Paredit}. It provides
facilities to directly operate on the syntax tree, such as raising an
s-expression or wrapping it, swallowing or rejecting the following
s-expression, etc.
@node Coding Style
@section Coding Style
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.
* 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 Guile’s @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{, Riastradh's Lisp
Style Rules}. This document happens to describe the conventions mostly
used in Guile’s 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.
@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:
./etc/indent-code.el gnu/packages/@var{file}.scm @var{package}
@end example
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:
./etc/indent-code.el gnu/services/@var{file}.scm
@end example
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 Submitting Patches
@section Submitting Patches
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{, mailing list}.
Please write commit logs in the ChangeLog format (@pxref{Change Logs,,,
standards, GNU Coding Standards}); you can check the commit history for
Before submitting a patch that adds or modifies a package definition,
please run through this check list:
Take some time to provide an adequate synopsis and description for the
package. @xref{Synopses and Descriptions}, for some guidelines.
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}).
Make sure the package builds on your platform, using @code{guix build
@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.
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.
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}).
Packages with roughly 100 dependents or more usually have to be
committed to a separate branch. That branch can then be built
separately by our build farm, and later 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.
@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}):
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{} 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.
When writing documentation, please use gender-neutral wording when
referring to people, such as
@uref{, singular
``they''@comma{} ``their''@comma{} ``them''}, and so forth.
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.
Please follow our code formatting rules, possibly running the
@command{etc/indent-code.el} script to do that automatically for you
(@pxref{Formatting Code}).
@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. 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.