diff options
| -rw-r--r-- | .gitignore | 31 | ||||
| -rw-r--r-- | Makefile.am | 3 | ||||
| -rwxr-xr-x | bootstrap | 12 | ||||
| -rw-r--r-- | doc/guix-cookbook.texi | 821 | ||||
| -rw-r--r-- | doc/local.mk | 9 | ||||
| -rw-r--r-- | po/doc/local.mk | 33 |
6 files changed, 890 insertions, 19 deletions
diff --git a/.gitignore b/.gitignore index 93d2ec98019..38cde42fca0 100644 --- a/.gitignore +++ b/.gitignore | |||
| @@ -29,22 +29,23 @@ | |||
| 29 | /doc/*.1 | 29 | /doc/*.1 |
| 30 | /doc/.dirstamp | 30 | /doc/.dirstamp |
| 31 | /doc/contributing.*.texi | 31 | /doc/contributing.*.texi |
| 32 | /doc/guix.*.aux | 32 | /doc/guix*.aux |
| 33 | /doc/guix.*.cp | 33 | /doc/guix*.cp |
| 34 | /doc/guix.*.cps | 34 | /doc/guix*.cps |
| 35 | /doc/guix.*.fn | 35 | /doc/guix*.fn |
| 36 | /doc/guix.*.fns | 36 | /doc/guix*.fns |
| 37 | /doc/guix.*.html | 37 | /doc/guix*.html |
| 38 | /doc/guix.*.info | 38 | /doc/guix*.info |
| 39 | /doc/guix.*.info-[0-9] | 39 | /doc/guix*.info-[0-9] |
| 40 | /doc/guix.*.ky | 40 | /doc/guix*.ky |
| 41 | /doc/guix.*.pg | 41 | /doc/guix*.pg |
| 42 | /doc/guix.*.toc | 42 | /doc/guix*.toc |
| 43 | /doc/guix.*.t2p | 43 | /doc/guix*.t2p |
| 44 | /doc/guix.*.tp | 44 | /doc/guix*.tp |
| 45 | /doc/guix.*.vr | 45 | /doc/guix*.vr |
| 46 | /doc/guix.*.vrs | 46 | /doc/guix*.vrs |
| 47 | /doc/guix.*.texi | 47 | /doc/guix.*.texi |
| 48 | /doc/guix-cookbook.*.texi | ||
| 48 | /doc/guix.aux | 49 | /doc/guix.aux |
| 49 | /doc/guix.cp | 50 | /doc/guix.cp |
| 50 | /doc/guix.cps | 51 | /doc/guix.cps |
diff --git a/Makefile.am b/Makefile.am index 7e3b5c10703..93d18d7df6e 100644 --- a/Makefile.am +++ b/Makefile.am | |||
| @@ -814,7 +814,8 @@ assert-no-store-file-names: | |||
| 814 | $(AM_V_at)if grep -r --exclude=*.texi --exclude=*.info \ | 814 | $(AM_V_at)if grep -r --exclude=*.texi --exclude=*.info \ |
| 815 | --exclude=*.info-[0-9] --exclude=*.dot \ | 815 | --exclude=*.info-[0-9] --exclude=*.dot \ |
| 816 | --exclude=*.eps --exclude-dir=bootstrap \ | 816 | --exclude=*.eps --exclude-dir=bootstrap \ |
| 817 | --exclude=guix-manual.pot --exclude=guix-manual.*.po \ | 817 | --exclude=guix-manual.pot --exclude=guix-manual.*.po \ |
| 818 | --exclude=guix-cookbook.pot --exclude=guix-cookbook.*.po \ | ||
| 818 | --exclude=guix-prettify.el \ | 819 | --exclude=guix-prettify.el \ |
| 819 | --exclude=ChangeLog* \ | 820 | --exclude=ChangeLog* \ |
| 820 | -E "$(storedir)/[a-z0-9]{32}-" $(distdir) ; \ | 821 | -E "$(storedir)/[a-z0-9]{32}-" $(distdir) ; \ |
| @@ -4,7 +4,7 @@ | |||
| 4 | set -e -x | 4 | set -e -x |
| 5 | 5 | ||
| 6 | # Generate stubs for translations. | 6 | # Generate stubs for translations. |
| 7 | langs=`find po/doc -type f -name '*.po' \ | 7 | langs=`find po/doc -type f -name 'guix-manual*.po' \ |
| 8 | | sed -e 's,guix-manual\.,,' \ | 8 | | sed -e 's,guix-manual\.,,' \ |
| 9 | | xargs -n 1 -I{} basename {} .po` | 9 | | xargs -n 1 -I{} basename {} .po` |
| 10 | for lang in ${langs}; do | 10 | for lang in ${langs}; do |
| @@ -15,5 +15,15 @@ for lang in ${langs}; do | |||
| 15 | touch "po/doc/guix-manual.${lang}.po" | 15 | touch "po/doc/guix-manual.${lang}.po" |
| 16 | fi | 16 | fi |
| 17 | done | 17 | done |
| 18 | langs=`find po/doc -type f -name 'guix-cookbook*.po' \ | ||
| 19 | | sed -e 's,guix-manual\.,,' \ | ||
| 20 | | xargs -n 1 -I{} basename {} .po` | ||
| 21 | for lang in ${langs}; do | ||
| 22 | if [ ! -e "doc/guix-cookbook.${lang}.texi" ]; then | ||
| 23 | echo "@setfilename guix-cookbook.${lang}.info" > "doc/guix-cookbook.${lang}.texi" | ||
| 24 | # Ensure .po file is newer. | ||
| 25 | touch "po/doc/guix-cookbook.${lang}.po" | ||
| 26 | fi | ||
| 27 | done | ||
| 18 | 28 | ||
| 19 | exec autoreconf -vfi | 29 | exec autoreconf -vfi |
diff --git a/doc/guix-cookbook.texi b/doc/guix-cookbook.texi new file mode 100644 index 00000000000..66f94a0fe7c --- /dev/null +++ b/doc/guix-cookbook.texi | |||
| @@ -0,0 +1,821 @@ | |||
| 1 | \input texinfo | ||
| 2 | @c -*-texinfo-*- | ||
| 3 | |||
| 4 | @c %**start of header | ||
| 5 | @setfilename guix-cookbook.info | ||
| 6 | @documentencoding UTF-8 | ||
| 7 | @settitle GNU Guix Cookbook | ||
| 8 | @c %**end of header | ||
| 9 | |||
| 10 | @copying | ||
| 11 | Copyright @copyright{} 2019 Ricardo Wurmus@* | ||
| 12 | Copyright @copyright{} 2019 Efraim Flashner@* | ||
| 13 | Copyright @copyright{} 2019 Pierre Neidhardt@* | ||
| 14 | |||
| 15 | Permission is granted to copy, distribute and/or modify this document | ||
| 16 | under the terms of the GNU Free Documentation License, Version 1.3 or | ||
| 17 | any later version published by the Free Software Foundation; with no | ||
| 18 | Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A | ||
| 19 | copy of the license is included in the section entitled ``GNU Free | ||
| 20 | Documentation License''. | ||
| 21 | @end copying | ||
| 22 | |||
| 23 | @dircategory System administration | ||
| 24 | @direntry | ||
| 25 | * Guix cookbook: (guix-cookbook). Tutorials and examples for GNU Guix. | ||
| 26 | @end direntry | ||
| 27 | |||
| 28 | @titlepage | ||
| 29 | @title GNU Guix Cookbook | ||
| 30 | @subtitle Tutorials and examples for using the GNU Guix Functional Package Manager | ||
| 31 | @author The GNU Guix Developers | ||
| 32 | |||
| 33 | @page | ||
| 34 | @vskip 0pt plus 1filll | ||
| 35 | |||
| 36 | @insertcopying | ||
| 37 | @end titlepage | ||
| 38 | |||
| 39 | @contents | ||
| 40 | |||
| 41 | @c ********************************************************************* | ||
| 42 | @node Top | ||
| 43 | @top GNU Guix Cookbook | ||
| 44 | |||
| 45 | This document presents tutorials and detailed examples for GNU@tie{}Guix, a | ||
| 46 | functional package management tool written for the GNU system. Please | ||
| 47 | @pxref{Top,,, guix, GNU Guix reference manual} for details about the system, | ||
| 48 | its API, and related concepts. | ||
| 49 | |||
| 50 | @c TRANSLATORS: You can replace the following paragraph with information on | ||
| 51 | @c how to join your own translation team and how to report issues with the | ||
| 52 | @c translation. | ||
| 53 | If you would like to translate this document in your native language, consider | ||
| 54 | joining the @uref{https://translationproject.org/domain/guix-cookbook.html, | ||
| 55 | Translation Project}. | ||
| 56 | |||
| 57 | @menu | ||
| 58 | * Scheme tutorials:: Meet your new favorite language! | ||
| 59 | * Packaging:: Packaging tutorials | ||
| 60 | * System Configuration:: Customizing the GNU System | ||
| 61 | |||
| 62 | * Acknowledgments:: Thanks! | ||
| 63 | * GNU Free Documentation License:: The license of this document. | ||
| 64 | * Concept Index:: Concepts. | ||
| 65 | |||
| 66 | @detailmenu | ||
| 67 | --- The Detailed Node Listing --- | ||
| 68 | |||
| 69 | Scheme tutorials | ||
| 70 | |||
| 71 | * A Scheme Crash Course:: Learn the basics of Scheme | ||
| 72 | |||
| 73 | Packaging | ||
| 74 | |||
| 75 | * Packaging Tutorial:: Let's add a package to Guix! | ||
| 76 | |||
| 77 | System Configuration | ||
| 78 | |||
| 79 | * Customizing the Kernel:: Creating and using a custom Linux kernel | ||
| 80 | |||
| 81 | |||
| 82 | @end detailmenu | ||
| 83 | @end menu | ||
| 84 | |||
| 85 | @c ********************************************************************* | ||
| 86 | @node Scheme tutorials | ||
| 87 | @chapter Scheme tutorials | ||
| 88 | |||
| 89 | GNU@tie{}Guix is written in the general purpose programming language Scheme, | ||
| 90 | and many of its features can be accessed and manipulated programmatically. | ||
| 91 | You can use Scheme to generate package definitions, to modify them, to build | ||
| 92 | them, to deploy whole operating systems, etc. | ||
| 93 | |||
| 94 | Knowing the basics of how to program in Scheme will unlock many of the | ||
| 95 | advanced features Guix provides --- and you don't even need to be an | ||
| 96 | experienced programmer to use them! | ||
| 97 | |||
| 98 | Let's get started! | ||
| 99 | |||
| 100 | @node A Scheme Crash Course | ||
| 101 | @section A Scheme Crash Course | ||
| 102 | |||
| 103 | @cindex Scheme, crash course | ||
| 104 | |||
| 105 | Guix uses the Guile implementation of Scheme. To start playing with the | ||
| 106 | language, install it with @code{guix install guile} and start a | ||
| 107 | @uref{https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop, | ||
| 108 | REPL} by running @code{guile} from the command line. | ||
| 109 | |||
| 110 | Alternatively you can also run @code{guix environment --ad-hoc guile -- guile} | ||
| 111 | if you'd rather not have Guile installed in your user profile. | ||
| 112 | |||
| 113 | In the following examples we use the @code{>} symbol to denote the REPL | ||
| 114 | prompt, that is, the line reserved for user input. @xref{Using Guile | ||
| 115 | Interactively,,, guile, GNU Guile Reference Manual}) for more details on the | ||
| 116 | REPL. | ||
| 117 | |||
| 118 | @itemize | ||
| 119 | @item | ||
| 120 | Scheme syntax boils down to a tree of expressions (or @emph{s-expression} in | ||
| 121 | Lisp lingo). An expression can be a literal such as numbers and strings, or a | ||
| 122 | compound which is a parenthesized list of compounds and literals. @code{#t} | ||
| 123 | and @code{#f} stand for the booleans "true" and "false", respectively. | ||
| 124 | |||
| 125 | Examples of valid expressions: | ||
| 126 | |||
| 127 | @example scheme | ||
| 128 | > "Hello World!" | ||
| 129 | "Hello World!" | ||
| 130 | > 17 | ||
| 131 | 17 | ||
| 132 | > (display (string-append "Hello " "Guix" "\n")) | ||
| 133 | "Hello Guix!" | ||
| 134 | @end example | ||
| 135 | |||
| 136 | @item | ||
| 137 | This last example is a function call nested in another function call. When a | ||
| 138 | parenthesized expression is evaluated, the first term is the function and the | ||
| 139 | rest are the arguments passed to the function. Every function returns the | ||
| 140 | last evaluated expression as its return value. | ||
| 141 | |||
| 142 | @item | ||
| 143 | Anonymous functions are declared with the @code{lambda} term: | ||
| 144 | |||
| 145 | @example scheme | ||
| 146 | > (lambda (x) (* x x)) | ||
| 147 | #<procedure 120e348 at <unknown port>:24:0 (x)> | ||
| 148 | @end example | ||
| 149 | |||
| 150 | The above procedure returns the square of its argument. Since everything is | ||
| 151 | an expression, the @code{lambda} expression returns an anonymous procedure, | ||
| 152 | which can in turn be applied to an argument: | ||
| 153 | |||
| 154 | @example scheme | ||
| 155 | > ((lambda (x) (* x x)) 3) | ||
| 156 | 9 | ||
| 157 | @end example | ||
| 158 | |||
| 159 | @item | ||
| 160 | Anything can be assigned a global name with @code{define}: | ||
| 161 | |||
| 162 | @example scheme | ||
| 163 | > (define a 3) | ||
| 164 | > (define square (lambda (x) (* x x))) | ||
| 165 | > (square a) | ||
| 166 | 9 | ||
| 167 | @end example | ||
| 168 | |||
| 169 | @item | ||
| 170 | Procedures can be defined more concisely with the following syntax: | ||
| 171 | |||
| 172 | @example scheme | ||
| 173 | (define (square x) (* x x)) | ||
| 174 | @end example | ||
| 175 | |||
| 176 | @item | ||
| 177 | A list structure can be created with the @code{list} procedure: | ||
| 178 | |||
| 179 | @example scheme | ||
| 180 | > (list 2 a 5 7) | ||
| 181 | (2 3 5 7) | ||
| 182 | @end example | ||
| 183 | |||
| 184 | @item | ||
| 185 | The @emph{quote} disables evaluation of a parenthesized expression: the first | ||
| 186 | term is not called over the other terms. Thus it effectively returns a list | ||
| 187 | of terms. | ||
| 188 | |||
| 189 | @example scheme | ||
| 190 | > '(display (string-append "Hello " "Guix" "\n")) | ||
| 191 | (display (string-append "Hello " "Guix" "\n")) | ||
| 192 | > '(2 a 5 7) | ||
| 193 | (2 a 5 7) | ||
| 194 | @end example | ||
| 195 | |||
| 196 | @item | ||
| 197 | The @emph{quasiquote} disables evaluation of a parenthesized expression until | ||
| 198 | a comma re-enables it. Thus it provides us with fine-grained control over | ||
| 199 | what is evaluated and what is not. | ||
| 200 | |||
| 201 | @example scheme | ||
| 202 | > `(2 a 5 7 (2 ,a 5 ,(+ a 4))) | ||
| 203 | (2 a 5 7 (2 3 5 7)) | ||
| 204 | @end example | ||
| 205 | |||
| 206 | Note that the above result is a list of mixed elements: numbers, symbols (here | ||
| 207 | @code{a}) and the last element is a list itself. | ||
| 208 | |||
| 209 | @item | ||
| 210 | Multiple variables can be named locally with @code{let}: | ||
| 211 | |||
| 212 | @example scheme | ||
| 213 | > (define x 10) | ||
| 214 | > (let ((x 2) | ||
| 215 | (y 3)) | ||
| 216 | (list x y)) | ||
| 217 | (2 3) | ||
| 218 | > x | ||
| 219 | 10 | ||
| 220 | > y | ||
| 221 | ERROR: In procedure module-lookup: Unbound variable: y | ||
| 222 | @end example | ||
| 223 | |||
| 224 | Use @code{let*} to allow later variable declarations to refer to earlier | ||
| 225 | definitions. | ||
| 226 | |||
| 227 | @example scheme | ||
| 228 | > (let* ((x 2) | ||
| 229 | (y (* x 3))) | ||
| 230 | (list x y)) | ||
| 231 | (2 6) | ||
| 232 | @end example | ||
| 233 | |||
| 234 | @item | ||
| 235 | The keyword syntax is @code{#:}; it is used to create unique identifiers. | ||
| 236 | @pxref{Keywords,,, guile, GNU Guile Reference Manual}. | ||
| 237 | |||
| 238 | @item | ||
| 239 | The percentage @code{%} is typically used for read-only global variables in | ||
| 240 | the build stage. Note that it is merely a convention, like @code{_} in C. | ||
| 241 | Scheme treats @code{%} exactly the same as any other letter. | ||
| 242 | |||
| 243 | @item | ||
| 244 | Modules are created with @code{define-module}. For instance | ||
| 245 | |||
| 246 | @example scheme | ||
| 247 | (define-module (guix build-system ruby) | ||
| 248 | #:use-module (guix store) | ||
| 249 | #:export (ruby-build | ||
| 250 | ruby-build-system)) | ||
| 251 | @end example | ||
| 252 | |||
| 253 | defines the module @code{guix build-system ruby} which must be located in | ||
| 254 | @file{guix/build-system/ruby.scm} somewhere in the Guile load path. It | ||
| 255 | depends on the @code{(guix store)} module and it exports two variables, | ||
| 256 | @code{ruby-build} and @code{ruby-build-system}. | ||
| 257 | @end itemize | ||
| 258 | |||
| 259 | For a more detailed introduction, check out | ||
| 260 | @uref{http://www.troubleshooters.com/codecorn/scheme_guile/hello.htm, Scheme | ||
| 261 | at a Glance}, by Steve Litt. | ||
| 262 | |||
| 263 | One of the reference Scheme books is the seminal ``Structure and | ||
| 264 | Interpretation of Computer Programs'', by Harold Abelson and Gerald Jay | ||
| 265 | Sussman, with Julie Sussman. You'll find a | ||
| 266 | @uref{https://mitpress.mit.edu/sites/default/files/sicp/index.html, free copy | ||
| 267 | online}, together with | ||
| 268 | @uref{https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/, | ||
| 269 | videos of the lectures by the authors}. The book is available in Texinfo | ||
| 270 | format as the @code{sicp} Guix package. Go ahead, run @code{guix install | ||
| 271 | sicp} and start reading with @code{info sicp} (or with the Emacs Info reader). | ||
| 272 | An @uref{https://sarabander.github.io/sicp/, unofficial ebook is also | ||
| 273 | available}. | ||
| 274 | |||
| 275 | You'll find more books, tutorials and other resources at | ||
| 276 | @url{https://schemers.org/}. | ||
| 277 | |||
| 278 | |||
| 279 | @c ********************************************************************* | ||
| 280 | @node Packaging | ||
| 281 | @chapter Packaging | ||
| 282 | |||
| 283 | @cindex packaging | ||
| 284 | |||
| 285 | This chapter is dedicated to teaching you how to add packages to the | ||
| 286 | collection of packages that come with GNU Guix. This involves writing package | ||
| 287 | definitions in Guile Scheme, organizing them in package modules, and building | ||
| 288 | them. | ||
| 289 | |||
| 290 | @menu | ||
| 291 | * Packaging Tutorial:: A tutorial on how to add packages to Guix. | ||
| 292 | @end menu | ||
| 293 | |||
| 294 | @node Packaging Tutorial | ||
| 295 | @section Packaging Tutorial | ||
| 296 | |||
| 297 | GNU Guix stands out as the @emph{hackable} package manager, mostly because it | ||
| 298 | uses @uref{https://www.gnu.org/software/guile/, GNU Guile}, a powerful | ||
| 299 | high-level programming language, one of the | ||
| 300 | @uref{https://en.wikipedia.org/wiki/Scheme_%28programming_language%29, Scheme} | ||
| 301 | dialects from the | ||
| 302 | @uref{https://en.wikipedia.org/wiki/Lisp_%28programming_language%29, Lisp family}. | ||
| 303 | |||
| 304 | Package definitions are also written in Scheme, which empowers Guix in some | ||
| 305 | very unique ways, unlike most other package managers that use shell scripts or | ||
| 306 | simple languages. | ||
| 307 | |||
| 308 | @itemize | ||
| 309 | @item | ||
| 310 | Use functions, structures, macros and all of Scheme expressiveness for your | ||
| 311 | package definitions. | ||
| 312 | |||
| 313 | @item | ||
| 314 | Inheritance makes it easy to customize a package by inheriting from it and | ||
| 315 | modifying only what is needed. | ||
| 316 | |||
| 317 | @item | ||
| 318 | Batch processing: the whole package collection can be parsed, filtered and | ||
| 319 | processed. Building a headless server with all graphical interfaces stripped | ||
| 320 | out? It's possible. Want to rebuild everything from source using specific | ||
| 321 | compiler optimization flags? Pass the @code{#:make-flags "..."} argument to | ||
| 322 | the list of packages. It wouldn't be a stretch to think | ||
| 323 | @uref{https://wiki.gentoo.org/wiki/USE_flag, Gentoo USE flags} here, but this | ||
| 324 | goes even further: the changes don't have to be thought out beforehand by the | ||
| 325 | packager, they can be @emph{programmed} by the user! | ||
| 326 | @end itemize | ||
| 327 | |||
| 328 | The following tutorial covers all the basics around package creation with Guix. | ||
| 329 | It does not assume much knowledge of the Guix system nor of the Lisp language. | ||
| 330 | The reader is only expected to be familiar with the command line and to have some | ||
| 331 | basic programming knowledge. | ||
| 332 | |||
| 333 | @subsection A "Hello World" package | ||
| 334 | |||
| 335 | The “Defining Packages” section of the manual introduces the basics of Guix | ||
| 336 | packaging (@pxref{Defining Packages,,, guix, GNU Guix Reference Manual}). In | ||
| 337 | the following section, we will partly go over those basics again. | ||
| 338 | |||
| 339 | ``GNU hello'' is a dummy project that serves as an idiomatic example for | ||
| 340 | packaging. It uses the GNU build system (@code{./configure && make && make | ||
| 341 | install}). Guix already provides a package definition which is a perfect | ||
| 342 | example to start with. You can look up its declaration with @code{guix edit | ||
| 343 | hello} from the command line. Let's see how it looks: | ||
| 344 | |||
| 345 | @example scheme | ||
| 346 | (define-public hello | ||
| 347 | (package | ||
| 348 | (name "hello") | ||
| 349 | (version "2.10") | ||
| 350 | (source (origin | ||
| 351 | (method url-fetch) | ||
| 352 | (uri (string-append "mirror://gnu/hello/hello-" version | ||
| 353 | ".tar.gz")) | ||
| 354 | (sha256 | ||
| 355 | (base32 | ||
| 356 | "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i")))) | ||
| 357 | (build-system gnu-build-system) | ||
| 358 | (synopsis "Hello, GNU world: An example GNU package") | ||
| 359 | (description | ||
| 360 | "GNU Hello prints the message \"Hello, world!\" and then exits. It | ||
| 361 | serves as an example of standard GNU coding practices. As such, it supports | ||
| 362 | command-line arguments, multiple languages, and so on.") | ||
| 363 | (home-page "https://www.gnu.org/software/hello/") | ||
| 364 | (license gpl3+))) | ||
| 365 | @end example | ||
| 366 | |||
| 367 | As you can see, most of it is rather straightforward. But let's review the | ||
| 368 | fields together: | ||
| 369 | |||
| 370 | @table @samp | ||
| 371 | @item name | ||
| 372 | The project name. Using Scheme conventions, we prefer to keep it | ||
| 373 | lower case, without underscore and using dash-separated words. | ||
| 374 | |||
| 375 | @item source | ||
| 376 | This field contains a description of the source code origin. The | ||
| 377 | @code{origin} record contains these fields: | ||
| 378 | |||
| 379 | @enumerate | ||
| 380 | @item The method, here @code{url-fetch} to download via HTTP/FTP, but other methods | ||
| 381 | exist, such as @code{git-fetch} for Git repositories. | ||
| 382 | @item The URI, which is typically some @code{https://} location for @code{url-fetch}. Here | ||
| 383 | the special `mirror://gnu` refers to a set of well known locations, all of | ||
| 384 | which can be used by Guix to fetch the source, should some of them fail. | ||
| 385 | @item The @code{sha256} checksum of the requested file. This is essential to ensure | ||
| 386 | the source is not corrupted. Note that Guix works with base32 strings, | ||
| 387 | hence the call to the @code{base32} function. | ||
| 388 | @end enumerate | ||
| 389 | |||
| 390 | @item build-system | ||
| 391 | |||
| 392 | This is where the power of abstraction provided by the Scheme language really | ||
| 393 | shines: in this case, the @code{gnu-build-system} abstracts away the famous | ||
| 394 | @code{./configure && make && make install} shell invocations. Other build | ||
| 395 | systems include the @code{trivial-build-system} which does not do anything and | ||
| 396 | requires from the packager to program all the build steps, the | ||
| 397 | @code{python-build-system}, the @code{emacs-build-system}, and many more | ||
| 398 | (@pxref{Build Systems,,, guix, GNU Guix Reference Manual}). | ||
| 399 | |||
| 400 | @item synopsis | ||
| 401 | It should be a concise summary of what the package does. For many packages a | ||
| 402 | tagline from the project's home page can be used as the synopsis. | ||
| 403 | |||
| 404 | @item description | ||
| 405 | Same as for the synopsis, it's fine to re-use the project description from the | ||
| 406 | homepage. Note that Guix uses Texinfo syntax. | ||
| 407 | |||
| 408 | @item home-page | ||
| 409 | Use HTTPS if available. | ||
| 410 | |||
| 411 | @item license | ||
| 412 | See @code{guix/licenses.scm} in the project source for a full list of | ||
| 413 | available licenses. | ||
| 414 | @end table | ||
| 415 | |||
| 416 | Time to build our first package! Nothing fancy here for now: we will stick to a | ||
| 417 | dummy "my-hello", a copy of the above declaration. | ||
| 418 | |||
| 419 | As with the ritualistic "Hello World" taught with most programming languages, | ||
| 420 | this will possibly be the most "manual" approach. We will work out an ideal | ||
| 421 | setup later; for now we will go the simplest route. | ||
| 422 | |||
| 423 | Save the following to a file @file{my-hello.scm}. | ||
| 424 | |||
| 425 | @example scheme | ||
| 426 | (use-modules (guix packages) | ||
| 427 | (guix download) | ||
| 428 | (guix build-system gnu) | ||
| 429 | (guix licenses)) | ||
| 430 | |||
| 431 | (package | ||
| 432 | (name "my-hello") | ||
| 433 | (version "2.10") | ||
| 434 | (source (origin | ||
| 435 | (method url-fetch) | ||
| 436 | (uri (string-append "mirror://gnu/hello/hello-" version | ||
| 437 | ".tar.gz")) | ||
| 438 | (sha256 | ||
| 439 | (base32 | ||
| 440 | "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i")))) | ||
| 441 | (build-system gnu-build-system) | ||
| 442 | (synopsis "Hello, Guix world: An example custom Guix package") | ||
| 443 | (description | ||
| 444 | "GNU Hello prints the message \"Hello, world!\" and then exits. It | ||
| 445 | serves as an example of standard GNU coding practices. As such, it supports | ||
| 446 | command-line arguments, multiple languages, and so on.") | ||
| 447 | (home-page "https://www.gnu.org/software/hello/") | ||
| 448 | (license gpl3+)) | ||
| 449 | @end example | ||
| 450 | |||
| 451 | We will explain the extra code in a moment. | ||
| 452 | |||
| 453 | Feel free to play with the different values of the various fields. If you | ||
| 454 | change the source, you'll need to update the checksum. Indeed, Guix refuses to | ||
| 455 | build anything if the given checksum does not match the computed checksum of the | ||
| 456 | source code. To obtain the correct checksum of the package declaration, we | ||
| 457 | need to download the source, compute the sha256 checksum and convert it to | ||
| 458 | base32. | ||
| 459 | |||
| 460 | Thankfully, Guix can automate this task for us; all we need is to provide the | ||
| 461 | URI: | ||
| 462 | |||
| 463 | @c TRANSLATORS: This is example shell output. | ||
| 464 | @example sh | ||
| 465 | $ guix download mirror://gnu/hello/hello-2.10.tar.gz | ||
| 466 | |||
| 467 | Starting download of /tmp/guix-file.JLYgL7 | ||
| 468 | From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz... | ||
| 469 | following redirection to `https://mirror.ibcp.fr/pub/gnu/hello/hello-2.10.tar.gz'... | ||
| 470 | …10.tar.gz 709KiB 2.5MiB/s 00:00 [##################] 100.0% | ||
| 471 | /gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz | ||
| 472 | 0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i | ||
| 473 | @end example | ||
| 474 | |||
| 475 | In this specific case the output tells us which mirror was chosen. | ||
| 476 | If the result of the above command is not the same as in the above snippet, | ||
| 477 | update your @code{my-hello} declaration accordingly. | ||
| 478 | |||
| 479 | Note that GNU package tarballs come with an OpenPGP signature, so you | ||
| 480 | should definitely check the signature of this tarball with `gpg` to | ||
| 481 | authenticate it before going further: | ||
| 482 | |||
| 483 | @c TRANSLATORS: This is example shell output. | ||
| 484 | @example sh | ||
| 485 | $ guix download mirror://gnu/hello/hello-2.10.tar.gz.sig | ||
| 486 | |||
| 487 | Starting download of /tmp/guix-file.03tFfb | ||
| 488 | From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz.sig... | ||
| 489 | following redirection to `https://ftp.igh.cnrs.fr/pub/gnu/hello/hello-2.10.tar.gz.sig'... | ||
| 490 | ….tar.gz.sig 819B 1.2MiB/s 00:00 [##################] 100.0% | ||
| 491 | /gnu/store/rzs8wba9ka7grrmgcpfyxvs58mly0sx6-hello-2.10.tar.gz.sig | ||
| 492 | 0q0v86n3y38z17rl146gdakw9xc4mcscpk8dscs412j22glrv9jf | ||
| 493 | $ gpg --verify /gnu/store/rzs8wba9ka7grrmgcpfyxvs58mly0sx6-hello-2.10.tar.gz.sig /gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz | ||
| 494 | gpg: Signature made Sun 16 Nov 2014 01:08:37 PM CET | ||
| 495 | gpg: using RSA key A9553245FDE9B739 | ||
| 496 | gpg: Good signature from "Sami Kerola <kerolasa@@iki.fi>" [unknown] | ||
| 497 | gpg: aka "Sami Kerola (http://www.iki.fi/kerolasa/) <kerolasa@@iki.fi>" [unknown] | ||
| 498 | gpg: WARNING: This key is not certified with a trusted signature! | ||
| 499 | gpg: There is no indication that the signature belongs to the owner. | ||
| 500 | Primary key fingerprint: 8ED3 96E3 7E38 D471 A005 30D3 A955 3245 FDE9 B739 | ||
| 501 | @end example | ||
| 502 | |||
| 503 | You can then happily run | ||
| 504 | |||
| 505 | @c TRANSLATORS: Do not translate this command | ||
| 506 | @example sh | ||
| 507 | $ guix package --install-from-file=my-hello.scm | ||
| 508 | @end example | ||
| 509 | |||
| 510 | You should now have @code{my-hello} in your profile! | ||
| 511 | |||
| 512 | @c TRANSLATORS: Do not translate this command | ||
| 513 | @example sh | ||
| 514 | $ guix package --list-installed=my-hello | ||
| 515 | my-hello 2.10 out | ||
| 516 | /gnu/store/f1db2mfm8syb8qvc357c53slbvf1g9m9-my-hello-2.10 | ||
| 517 | @end example | ||
| 518 | |||
| 519 | We've gone as far as we could without any knowledge of Scheme. Before moving | ||
| 520 | on to more complex packages, now is the right time to brush up on your Scheme | ||
| 521 | knowledge. @pxref{A Scheme Crash Course} to get up to speed. | ||
| 522 | |||
| 523 | @c TODO: Continue the tutorial | ||
| 524 | |||
| 525 | |||
| 526 | @c ********************************************************************* | ||
| 527 | @node System Configuration | ||
| 528 | @chapter System Configuration | ||
| 529 | |||
| 530 | Guix offers a flexible language for declaratively configuring your Guix | ||
| 531 | System. This flexibility can at times be overwhelming. The purpose of this | ||
| 532 | chapter is to demonstrate some advanced configuration concepts. | ||
| 533 | |||
| 534 | @pxref{System Configuration,,, guix, GNU Guix Reference Manual} for a complete | ||
| 535 | reference. | ||
| 536 | |||
| 537 | @menu | ||
| 538 | * Customizing the Kernel:: Creating and using a custom Linux kernel on Guix System. | ||
| 539 | @end menu | ||
| 540 | |||
| 541 | @node Customizing the Kernel | ||
| 542 | @section Customizing the Kernel | ||
| 543 | |||
| 544 | Guix is, at its core, a source based distribution with substitutes | ||
| 545 | (@pxref{Substitutes,,, guix, GNU Guix Reference Manual}), and as such building | ||
| 546 | packages from their source code is an expected part of regular package | ||
| 547 | installations and upgrades. Given this starting point, it makes sense that | ||
| 548 | efforts are made to reduce the amount of time spent compiling packages, and | ||
| 549 | recent changes and upgrades to the building and distribution of substitutes | ||
| 550 | continues to be a topic of discussion within Guix. | ||
| 551 | |||
| 552 | The kernel, while not requiring an overabundance of RAM to build, does take a | ||
| 553 | rather long time on an average machine. The official kernel configuration, as | ||
| 554 | is the case with many GNU/Linux distributions, errs on the side of | ||
| 555 | inclusiveness, and this is really what causes the build to take such a long | ||
| 556 | time when the kernel is built from source. | ||
| 557 | |||
| 558 | The Linux kernel, however, can also just be described as a regular old | ||
| 559 | package, and as such can be customized just like any other package. The | ||
| 560 | procedure is a little bit different, although this is primarily due to the | ||
| 561 | nature of how the package definition is written. | ||
| 562 | |||
| 563 | The @code{linux-libre} kernel package definition is actually a procedure which | ||
| 564 | creates a package. | ||
| 565 | |||
| 566 | @example scheme | ||
| 567 | (define* (make-linux-libre version hash supported-systems | ||
| 568 | #:key | ||
| 569 | ;; A function that takes an arch and a variant. | ||
| 570 | ;; See kernel-config for an example. | ||
| 571 | (extra-version #f) | ||
| 572 | (configuration-file #f) | ||
| 573 | (defconfig "defconfig") | ||
| 574 | (extra-options %default-extra-linux-options) | ||
| 575 | (patches (list %boot-logo-patch))) | ||
| 576 | ...) | ||
| 577 | @end example | ||
| 578 | |||
| 579 | The current @code{linux-libre} package is for the 5.1.x series, and is | ||
| 580 | declared like this: | ||
| 581 | |||
| 582 | @example scheme | ||
| 583 | (define-public linux-libre | ||
| 584 | (make-linux-libre %linux-libre-version | ||
| 585 | %linux-libre-hash | ||
| 586 | '("x86_64-linux" "i686-linux" "armhf-linux" "aarch64-linux") | ||
| 587 | #:patches %linux-libre-5.1-patches | ||
| 588 | #:configuration-file kernel-config)) | ||
| 589 | @end example | ||
| 590 | |||
| 591 | Any keys which are not assigned values inherit their default value from the | ||
| 592 | @code{make-linux-libre} definition. When comparing the two snippets above, | ||
| 593 | you may notice that the code comment in the first doesn't actually refer to | ||
| 594 | the @code{#:extra-version} keyword; it is actually for | ||
| 595 | @code{#:configuration-file}. Because of this, it is not actually easy to | ||
| 596 | include a custom kernel configuration from the definition, but don't worry, | ||
| 597 | there are other ways to work with what we do have. | ||
| 598 | |||
| 599 | There are two ways to create a kernel with a custom kernel configuration. The | ||
| 600 | first is to provide a standard @file{.config} file during the build process by | ||
| 601 | including an actual @file{.config} file as a native input to our custom | ||
| 602 | kernel. The following is a snippet from the custom @code{'configure} phase of | ||
| 603 | the @code{make-linux-libre} package definition: | ||
| 604 | |||
| 605 | @example scheme | ||
| 606 | (let ((build (assoc-ref %standard-phases 'build)) | ||
| 607 | (config (assoc-ref (or native-inputs inputs) "kconfig"))) | ||
| 608 | |||
| 609 | ;; Use a custom kernel configuration file or a default | ||
| 610 | ;; configuration file. | ||
| 611 | (if config | ||
| 612 | (begin | ||
| 613 | (copy-file config ".config") | ||
| 614 | (chmod ".config" #o666)) | ||
| 615 | (invoke "make" ,defconfig)) | ||
| 616 | @end example | ||
| 617 | |||
| 618 | Below is a sample kernel package. The @code{linux-libre} package is nothing | ||
| 619 | special and can be inherited from and have its fields overridden like any | ||
| 620 | other package: | ||
| 621 | |||
| 622 | @example scheme | ||
| 623 | (define-public linux-libre/E2140 | ||
| 624 | (package | ||
| 625 | (inherit linux-libre) | ||
| 626 | (native-inputs | ||
| 627 | `(("kconfig" ,(local-file "E2140.config")) | ||
| 628 | ,@@(alist-delete "kconfig" | ||
| 629 | (package-native-inputs linux-libre)))))) | ||
| 630 | @end example | ||
| 631 | |||
| 632 | In the same directory as the file defining @code{linux-libre-E2140} is a file | ||
| 633 | named @file{E2140.config}, which is an actual kernel configuration file. The | ||
| 634 | @code{defconfig} keyword of @code{make-linux-libre} is left blank here, so the | ||
| 635 | only kernel configuration in the package is the one which was included in the | ||
| 636 | @code{native-inputs} field. | ||
| 637 | |||
| 638 | The second way to create a custom kernel is to pass a new value to the | ||
| 639 | @code{extra-options} keyword of the @code{make-linux-libre} procedure. The | ||
| 640 | @code{extra-options} keyword works with another function defined right below | ||
| 641 | it: | ||
| 642 | |||
| 643 | @example scheme | ||
| 644 | (define %default-extra-linux-options | ||
| 645 | `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html | ||
| 646 | ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #t) | ||
| 647 | ;; Modules required for initrd: | ||
| 648 | ("CONFIG_NET_9P" . m) | ||
| 649 | ("CONFIG_NET_9P_VIRTIO" . m) | ||
| 650 | ("CONFIG_VIRTIO_BLK" . m) | ||
| 651 | ("CONFIG_VIRTIO_NET" . m) | ||
| 652 | ("CONFIG_VIRTIO_PCI" . m) | ||
| 653 | ("CONFIG_VIRTIO_BALLOON" . m) | ||
| 654 | ("CONFIG_VIRTIO_MMIO" . m) | ||
| 655 | ("CONFIG_FUSE_FS" . m) | ||
| 656 | ("CONFIG_CIFS" . m) | ||
| 657 | ("CONFIG_9P_FS" . m))) | ||
| 658 | |||
| 659 | (define (config->string options) | ||
| 660 | (string-join (map (match-lambda | ||
| 661 | ((option . 'm) | ||
| 662 | (string-append option "=m")) | ||
| 663 | ((option . #t) | ||
| 664 | (string-append option "=y")) | ||
| 665 | ((option . #f) | ||
| 666 | (string-append option "=n"))) | ||
| 667 | options) | ||
| 668 | "\n")) | ||
| 669 | @end example | ||
| 670 | |||
| 671 | And in the custom configure script from the `make-linux-libre` package: | ||
| 672 | |||
| 673 | @example scheme | ||
| 674 | ;; Appending works even when the option wasn't in the | ||
| 675 | ;; file. The last one prevails if duplicated. | ||
| 676 | (let ((port (open-file ".config" "a")) | ||
| 677 | (extra-configuration ,(config->string extra-options))) | ||
| 678 | (display extra-configuration port) | ||
| 679 | (close-port port)) | ||
| 680 | |||
| 681 | (invoke "make" "oldconfig")))) | ||
| 682 | @end example | ||
| 683 | |||
| 684 | So by not providing a configuration-file the @file{.config} starts blank, and | ||
| 685 | then we write into it the collection of flags that we want. Here's another | ||
| 686 | custom kernel: | ||
| 687 | |||
| 688 | @example scheme | ||
| 689 | (define %macbook41-full-config | ||
| 690 | (append %macbook41-config-options | ||
| 691 | %filesystems | ||
| 692 | %efi-support | ||
| 693 | %emulation | ||
| 694 | (@@@@ (gnu packages linux) %default-extra-linux-options))) | ||
| 695 | |||
| 696 | (define-public linux-libre-macbook41 | ||
| 697 | ;; XXX: Access the internal 'make-linux-libre' procedure, which is | ||
| 698 | ;; private and unexported, and is liable to change in the future. | ||
| 699 | ((@@@@ (gnu packages linux) make-linux-libre) (@@@@ (gnu packages linux) %linux-libre-version) | ||
| 700 | (@@@@ (gnu packages linux) %linux-libre-hash) | ||
| 701 | '("x86_64-linux") | ||
| 702 | #:extra-version "macbook41" | ||
| 703 | #:patches (@@@@ (gnu packages linux) %linux-libre-5.1-patches) | ||
| 704 | #:extra-options %macbook41-config-options)) | ||
| 705 | @end example | ||
| 706 | |||
| 707 | In the above example @code{%filesystems} is a collection of flags enabling | ||
| 708 | different filesystem support, @code{%efi-support} enables EFI support and | ||
| 709 | @code{%emulation} enables a x86_64-linux machine to act in 32-bit mode also. | ||
| 710 | @code{%default-extra-linux-options} are the ones quoted above, which had to be | ||
| 711 | added in since they were replaced in the @code{extra-options} keyword. | ||
| 712 | |||
| 713 | This all sounds like it should be doable, but how does one even know which | ||
| 714 | modules are required for a particular system? Two places that can be helpful | ||
| 715 | in trying to answer this question is the | ||
| 716 | @uref{https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Kernel, Gentoo | ||
| 717 | Handbook} and the | ||
| 718 | @uref{https://www.kernel.org/doc/html/latest/admin-guide/README.html?highlight=localmodconfig, | ||
| 719 | documentation from the kernel itself}. From the kernel documentation, it | ||
| 720 | seems that @code{make localmodconfig} is the command we want. | ||
| 721 | |||
| 722 | In order to actually run @code{make localmodconfig} we first need to get and | ||
| 723 | unpack the kernel source code: | ||
| 724 | |||
| 725 | @example shell | ||
| 726 | tar xf $(guix build linux-libre --source) | ||
| 727 | @end example | ||
| 728 | |||
| 729 | Once inside the directory containing the source code run @code{touch .config} | ||
| 730 | to create an initial, empty @file{.config} to start with. @code{make | ||
| 731 | localmodconfig} works by seeing what you already have in @file{.config} and | ||
| 732 | letting you know what you're missing. If the file is blank then you're | ||
| 733 | missing everything. The next step is to run: | ||
| 734 | |||
| 735 | @example shell | ||
| 736 | guix environment linux-libre -- make localmodconfig | ||
| 737 | @end example | ||
| 738 | |||
| 739 | and note the output. Do note that the @file{.config} file is still empty. | ||
| 740 | The output generally contains two types of warnings. The first start with | ||
| 741 | "WARNING" and can actually be ignored in our case. The second read: | ||
| 742 | |||
| 743 | @example shell | ||
| 744 | module pcspkr did not have configs CONFIG_INPUT_PCSPKR | ||
| 745 | @end example | ||
| 746 | |||
| 747 | For each of these lines, copy the @code{CONFIG_XXXX_XXXX} portion into the | ||
| 748 | @file{.config} in the directory, and append @code{=m}, so in the end it looks | ||
| 749 | like this: | ||
| 750 | |||
| 751 | @example shell | ||
| 752 | CONFIG_INPUT_PCSPKR=m | ||
| 753 | CONFIG_VIRTIO=m | ||
| 754 | @end example | ||
| 755 | |||
| 756 | After copying all the configuration options, run @code{make localmodconfig} | ||
| 757 | again to make sure that you don't have any output starting with "module". | ||
| 758 | After all of these machine specific modules there are a couple more left that | ||
| 759 | are also needed. @code{CONFIG_MODULES} is necessary so that you can build and | ||
| 760 | load modules separately and not have everything built into the kernel. | ||
| 761 | @code{CONFIG_BLK_DEV_SD} is required for reading from hard drives. It is | ||
| 762 | possible that there are other modules which you will need. | ||
| 763 | |||
| 764 | This post does not aim to be a guide to configuring your own kernel however, | ||
| 765 | so if you do decide to build a custom kernel you'll have to seek out other | ||
| 766 | guides to create a kernel which is just right for your needs. | ||
| 767 | |||
| 768 | The second way to setup the kernel configuration makes more use of Guix's | ||
| 769 | features and allows you to share configuration segments between different | ||
| 770 | kernels. For example, all machines using EFI to boot have a number of EFI | ||
| 771 | configuration flags that they need. It is likely that all the kernels will | ||
| 772 | share a list of filesystems to support. By using variables it is easier to | ||
| 773 | see at a glance what features are enabled and to make sure you don't have | ||
| 774 | features in one kernel but missing in another. | ||
| 775 | |||
| 776 | Left undiscussed however, is Guix's initrd and its customization. It is | ||
| 777 | likely that you'll need to modify the initrd on a machine using a custom | ||
| 778 | kernel, since certain modules which are expected to be built may not be | ||
| 779 | available for inclusion into the initrd. | ||
| 780 | |||
| 781 | @c ********************************************************************* | ||
| 782 | @node Acknowledgments | ||
| 783 | @chapter Acknowledgments | ||
| 784 | |||
| 785 | Guix is based on the @uref{https://nixos.org/nix/, Nix package manager}, | ||
| 786 | which was designed and | ||
| 787 | implemented by Eelco Dolstra, with contributions from other people (see | ||
| 788 | the @file{nix/AUTHORS} file in Guix.) Nix pioneered functional package | ||
| 789 | management, and promoted unprecedented features, such as transactional | ||
| 790 | package upgrades and rollbacks, per-user profiles, and referentially | ||
| 791 | transparent build processes. Without this work, Guix would not exist. | ||
| 792 | |||
| 793 | The Nix-based software distributions, Nixpkgs and NixOS, have also been | ||
| 794 | an inspiration for Guix. | ||
| 795 | |||
| 796 | GNU@tie{}Guix itself is a collective work with contributions from a | ||
| 797 | number of people. See the @file{AUTHORS} file in Guix for more | ||
| 798 | information on these fine people. The @file{THANKS} file lists people | ||
| 799 | who have helped by reporting bugs, taking care of the infrastructure, | ||
| 800 | providing artwork and themes, making suggestions, and more---thank you! | ||
| 801 | |||
| 802 | This document includes adapted sections from articles that have previously | ||
| 803 | been published on the Guix blog at @uref{https://guix.gnu.org/blog}. | ||
| 804 | |||
| 805 | |||
| 806 | @c ********************************************************************* | ||
| 807 | @node GNU Free Documentation License | ||
| 808 | @appendix GNU Free Documentation License | ||
| 809 | @cindex license, GNU Free Documentation License | ||
| 810 | @include fdl-1.3.texi | ||
| 811 | |||
| 812 | @c ********************************************************************* | ||
| 813 | @node Concept Index | ||
| 814 | @unnumbered Concept Index | ||
| 815 | @printindex cp | ||
| 816 | |||
| 817 | @bye | ||
| 818 | |||
| 819 | @c Local Variables: | ||
| 820 | @c ispell-local-dictionary: "american"; | ||
| 821 | @c End: | ||
diff --git a/doc/local.mk b/doc/local.mk index 336e961c4f0..850612605b8 100644 --- a/doc/local.mk +++ b/doc/local.mk | |||
| @@ -26,7 +26,8 @@ info_TEXINFOS = %D%/guix.texi \ | |||
| 26 | %D%/guix.es.texi \ | 26 | %D%/guix.es.texi \ |
| 27 | %D%/guix.fr.texi \ | 27 | %D%/guix.fr.texi \ |
| 28 | %D%/guix.ru.texi \ | 28 | %D%/guix.ru.texi \ |
| 29 | %D%/guix.zh_CN.texi | 29 | %D%/guix.zh_CN.texi \ |
| 30 | %D%/guix-cookbook.texi | ||
| 30 | 31 | ||
| 31 | %C%_guix_TEXINFOS = \ | 32 | %C%_guix_TEXINFOS = \ |
| 32 | %D%/contributing.texi \ | 33 | %D%/contributing.texi \ |
| @@ -108,6 +109,12 @@ $(srcdir)/%D%/guix.%.texi: po/doc/guix-manual.%.po $(srcdir)/%D%/contributing.%. | |||
| 108 | -$(AM_V_POXREF)$(xref_command) | 109 | -$(AM_V_POXREF)$(xref_command) |
| 109 | -mv "$@.tmp" "$@" | 110 | -mv "$@.tmp" "$@" |
| 110 | 111 | ||
| 112 | $(srcdir)/%D%/guix-cookbook.%.texi: po/doc/guix-cookbook.%.po | ||
| 113 | -$(AM_V_PO4A)$(PO4A_TRANSLATE) $(PO4A_PARAMS) -m "%D%/guix-cookbook.texi" -p "$<" -l "$@.tmp" | ||
| 114 | -sed -i "s|guix-cookbook\.info|$$(basename "$@" | sed 's|texi$$|info|')|" "$@.tmp" | ||
| 115 | -$(AM_V_POXREF)$(xref_command) | ||
| 116 | -mv "$@.tmp" "$@" | ||
| 117 | |||
| 111 | $(srcdir)/%D%/contributing.%.texi: po/doc/guix-manual.%.po | 118 | $(srcdir)/%D%/contributing.%.texi: po/doc/guix-manual.%.po |
| 112 | -$(AM_V_PO4A)$(PO4A_TRANSLATE) $(PO4A_PARAMS) -m "%D%/contributing.texi" -p "$<" -l "$@.tmp" | 119 | -$(AM_V_PO4A)$(PO4A_TRANSLATE) $(PO4A_PARAMS) -m "%D%/contributing.texi" -p "$<" -l "$@.tmp" |
| 113 | -$(AM_V_POXREF)$(xref_command) | 120 | -$(AM_V_POXREF)$(xref_command) |
diff --git a/po/doc/local.mk b/po/doc/local.mk index fb3c5aee03c..f1a52615c18 100644 --- a/po/doc/local.mk +++ b/po/doc/local.mk | |||
| @@ -23,9 +23,13 @@ DOC_PO_FILES= \ | |||
| 23 | %D%/guix-manual.ru.po \ | 23 | %D%/guix-manual.ru.po \ |
| 24 | %D%/guix-manual.zh_CN.po | 24 | %D%/guix-manual.zh_CN.po |
| 25 | 25 | ||
| 26 | DOC_COOKBOOK_PO_FILES= | ||
| 27 | |||
| 26 | EXTRA_DIST = \ | 28 | EXTRA_DIST = \ |
| 27 | %D%/guix-manual.pot \ | 29 | %D%/guix-manual.pot \ |
| 28 | $(DOC_PO_FILES) | 30 | %D%/guix-cookbook.pot \ |
| 31 | $(DOC_PO_FILES) \ | ||
| 32 | $(DOC_COOKBOOK_PO_FILES) | ||
| 29 | 33 | ||
| 30 | POT_OPTIONS = --package-name "guix" --package-version "$(VERSION)" \ | 34 | POT_OPTIONS = --package-name "guix" --package-version "$(VERSION)" \ |
| 31 | --copyright-holder "Ludovic Courtès" \ | 35 | --copyright-holder "Ludovic Courtès" \ |
| @@ -52,6 +56,27 @@ doc-po-update-%: | |||
| 52 | exit 1; \ | 56 | exit 1; \ |
| 53 | fi | 57 | fi |
| 54 | 58 | ||
| 59 | doc-po-update-cookbook-%: | ||
| 60 | @lang=`echo "$@" | sed -e's/^doc-po-update-//'` ; \ | ||
| 61 | output="$(srcdir)/po/doc/guix-cookbook.$$lang.po" ; \ | ||
| 62 | input="$(srcdir)/po/doc/guix-cookbook.pot" ; \ | ||
| 63 | if test -f "$$output"; then \ | ||
| 64 | test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ | ||
| 65 | echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $$output $$input"; \ | ||
| 66 | cd $(srcdir) \ | ||
| 67 | && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ | ||
| 68 | '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ | ||
| 69 | $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) "$$output" "$$input";; \ | ||
| 70 | *) \ | ||
| 71 | $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} "$$output" "$$input";; \ | ||
| 72 | esac; \ | ||
| 73 | }; \ | ||
| 74 | touch "$$output"; \ | ||
| 75 | else \ | ||
| 76 | echo "File $$output does not exist. If you are a translator, you can create it with 'msginit'." 1>&2; \ | ||
| 77 | exit 1; \ | ||
| 78 | fi | ||
| 79 | |||
| 55 | $(srcdir)/po/doc/%.pot-update: doc/%.texi | 80 | $(srcdir)/po/doc/%.pot-update: doc/%.texi |
| 56 | $(AM_V_PO4A)$(PO4A_UPDATEPO) -M UTF-8 -f texinfo -m "$<" \ | 81 | $(AM_V_PO4A)$(PO4A_UPDATEPO) -M UTF-8 -f texinfo -m "$<" \ |
| 57 | -p "$$(echo $@ | sed 's|-update||')" $(POT_OPTIONS) | 82 | -p "$$(echo $@ | sed 's|-update||')" $(POT_OPTIONS) |
| @@ -64,6 +89,7 @@ doc-pot-update: | |||
| 64 | $(MAKE) $(srcdir)/po/doc/guix.pot-update; \ | 89 | $(MAKE) $(srcdir)/po/doc/guix.pot-update; \ |
| 65 | $(MAKE) $(srcdir)/po/doc/contributing.pot-update; \ | 90 | $(MAKE) $(srcdir)/po/doc/contributing.pot-update; \ |
| 66 | done | 91 | done |
| 92 | $(MAKE) $(srcdir)/po/doc/guix-cookbook.pot-update; | ||
| 67 | msgcat $(addprefix $(srcdir)/po/doc/, $(TMP_POT_FILES)) > $(srcdir)/po/doc/guix-manual.pot | 93 | msgcat $(addprefix $(srcdir)/po/doc/, $(TMP_POT_FILES)) > $(srcdir)/po/doc/guix-manual.pot |
| 68 | rm -f $(addprefix $(srcdir)/po/doc/, $(TMP_POT_FILES)) | 94 | rm -f $(addprefix $(srcdir)/po/doc/, $(TMP_POT_FILES)) |
| 69 | 95 | ||
| @@ -72,5 +98,10 @@ doc-po-update: doc-pot-update | |||
| 72 | lang="`echo "$$f" | $(SED) -es'|.*/guix-manual\.\(.*\)\.po$$|\1|g'`"; \ | 98 | lang="`echo "$$f" | $(SED) -es'|.*/guix-manual\.\(.*\)\.po$$|\1|g'`"; \ |
| 73 | $(MAKE) "doc-po-update-$$lang"; \ | 99 | $(MAKE) "doc-po-update-$$lang"; \ |
| 74 | done | 100 | done |
| 101 | for f in $(DOC_COOKBOOK_PO_FILES); do \ | ||
| 102 | lang="`echo "$$f" | $(SED) -es'|.*/guix-cookbook\.\(.*\)\.po$$|\1|g'`"; \ | ||
| 103 | $(MAKE) "doc-po-update-cookbook-$$lang"; \ | ||
| 104 | done | ||
| 105 | |||
| 75 | 106 | ||
| 76 | .PHONY: doc-po-update doc-pot-update | 107 | .PHONY: doc-po-update doc-pot-update |
