@@ -243,5 +243,218 @@ set of packages.
243
243
244
244
</section >
245
245
246
+ <section xml : id =" sec-declarative-package-management" >
247
+ <title >Declarative Package Management</title >
248
+
249
+ <section xml : id =" sec-building-environment" >
250
+ <title >Build an environment</title >
251
+
252
+ <para >
253
+ Using <literal >packageOverrides</literal >, it is possible to manage
254
+ packages declaratively. This means that we can list all of our desired
255
+ packages within a declarative Nix expression. For example, to have
256
+ <literal >aspell</literal >, <literal >bc</literal >,
257
+ <literal >ffmpeg</literal >, <literal >coreutils</literal >,
258
+ <literal >gdb</literal >, <literal >nixUnstable</literal >,
259
+ <literal >emscripten</literal >, <literal >jq</literal >,
260
+ <literal >nox</literal >, and <literal >silver-searcher</literal >, we could
261
+ use the following in <filename >~/.config/nixpkgs/config.nix</filename >:
262
+ </para >
263
+
264
+ <screen >
265
+ {
266
+ packageOverrides = pkgs: with pkgs; {
267
+ myPackages = pkgs.buildEnv {
268
+ name = "my-packages";
269
+ paths = [ aspell bc coreutils gdb ffmpeg nixUnstable emscripten jq nox silver-searcher ];
270
+ };
271
+ };
272
+ }
273
+ </screen >
274
+
275
+ <para >
276
+ To install it into our environment, you can just run <literal >nix-env -iA
277
+ nixpkgs.myPackages</literal >. If you want to load the packages to be built
278
+ from a working copy of <literal >nixpkgs</literal > you just run
279
+ <literal >nix-env -f. -iA myPackages</literal >. To explore what's been
280
+ installed, just look through <filename >~/.nix-profile/</filename >. You can
281
+ see that a lot of stuff has been installed. Some of this stuff is useful
282
+ some of it isn't. Let's tell Nixpkgs to only link the stuff that we want:
283
+ </para >
284
+
285
+ <screen >
286
+ {
287
+ packageOverrides = pkgs: with pkgs; {
288
+ myPackages = pkgs.buildEnv {
289
+ name = "my-packages";
290
+ paths = [ aspell bc coreutils gdb ffmpeg nixUnstable emscripten jq nox silver-searcher ];
291
+ pathsToLink = [ "/share" "/bin" ];
292
+ };
293
+ };
294
+ }
295
+ </screen >
296
+
297
+ <para >
298
+ <literal >pathsToLink</literal > tells Nixpkgs to only link the paths listed
299
+ which gets rid of the extra stuff in the profile.
300
+ <filename >/bin</filename > and <filename >/share</filename > are good
301
+ defaults for a user environment, getting rid of the clutter. If you are
302
+ running on Nix on MacOS, you may want to add another path as well,
303
+ <filename >/Applications</filename >, that makes GUI apps available.
304
+ </para >
305
+
306
+ </section >
307
+
308
+ <section xml : id =" sec-getting-documentation" >
309
+ <title >Getting documentation</title >
310
+
311
+ <para >
312
+ After building that new environment, look through
313
+ <filename >~/.nix-profile</filename > to make sure everything is there that
314
+ we wanted. Discerning readers will note that some files are missing. Look
315
+ inside <filename >~/.nix-profile/share/man/man1/</filename > to verify this.
316
+ There are no man pages for any of the Nix tools! This is because some
317
+ packages like Nix have multiple outputs for things like documentation (see
318
+ section 4). Let's make Nix install those as well.
319
+ </para >
320
+
321
+ <screen >
322
+ {
323
+ packageOverrides = pkgs: with pkgs; {
324
+ myPackages = pkgs.buildEnv {
325
+ name = "my-packages";
326
+ paths = [ aspell bc coreutils ffmpeg nixUnstable emscripten jq nox silver-searcher ];
327
+ pathsToLink = [ "/share/man" "/share/doc" /bin" ];
328
+ extraOutputsToInstall = [ "man" "doc" ];
329
+ };
330
+ };
331
+ }
332
+ </screen >
333
+
334
+ <para >
335
+ This provides us with some useful documentation for using our packages.
336
+ However, if we actually want those manpages to be detected by man, we need
337
+ to set up our environment. This can also be managed within Nix
338
+ expressions.
339
+ </para >
340
+
341
+ <screen >
342
+ {
343
+ packageOverrides = pkgs: with pkgs; rec {
344
+ myProfile = writeText "my-profile" ''
345
+ export PATH=$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin:/sbin:/bin:/usr/sbin:/usr/bin
346
+ export MANPATH=$HOME/.nix-profile/share/man:/nix/var/nix/profiles/default/share/man:/usr/share/man
347
+ '';
348
+ myPackages = pkgs.buildEnv {
349
+ name = "my-packages";
350
+ paths = [
351
+ (runCommand "profile" {} ''
352
+ mkdir -p $out/etc/profile.d
353
+ cp ${myProfile} $out/etc/profile.d/my-profile.sh
354
+ '')
355
+ aspell
356
+ bc
357
+ coreutils
358
+ ffmpeg
359
+ man
360
+ nixUnstable
361
+ emscripten
362
+ jq
363
+ nox
364
+ silver-searcher
365
+ ];
366
+ pathsToLink = [ "/share/man" "/share/doc" /bin" "/etc" ];
367
+ extraOutputsToInstall = [ "man" "doc" ];
368
+ };
369
+ };
370
+ }
371
+ </screen >
372
+
373
+ <para >
374
+ For this to work fully, you must also have this script sourced when you
375
+ are logged in. Try adding something like this to your
376
+ <filename >~/.profile</filename > file:
377
+ </para >
378
+
379
+ <screen >
380
+ #!/bin/sh
381
+ if [ -d $HOME/.nix-profile/etc/profile.d ]; then
382
+ for i in $HOME/.nix-profile/etc/profile.d/*.sh; do
383
+ if [ -r $i ]; then
384
+ . $i
385
+ fi
386
+ done
387
+ fi
388
+ </screen >
389
+
390
+ <para >
391
+ Now just run <literal >source $HOME/.profile</literal > and you can starting
392
+ loading man pages from your environent.
393
+ </para >
394
+
395
+ </section >
396
+
397
+ <section xml : id =" sec-gnu-info-setup" >
398
+ <title >GNU info setup</title >
399
+
400
+ <para >
401
+ Configuring GNU info is a little bit trickier than man pages. To work
402
+ correctly, info needs a database to be generated. This can be done with
403
+ some small modifications to our environment scripts.
404
+ </para >
405
+
406
+ <screen >
407
+ {
408
+ packageOverrides = pkgs: with pkgs; rec {
409
+ myProfile = writeText "my-profile" ''
410
+ export PATH=$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin:/sbin:/bin:/usr/sbin:/usr/bin
411
+ export MANPATH=$HOME/.nix-profile/share/man:/nix/var/nix/profiles/default/share/man:/usr/share/man
412
+ export INFOPATH=$HOME/.nix-profile/share/info:/nix/var/nix/profiles/default/share/info:/usr/share/info
413
+ '';
414
+ myPackages = pkgs.buildEnv {
415
+ name = "my-packages";
416
+ paths = [
417
+ (runCommand "profile" {} ''
418
+ mkdir -p $out/etc/profile.d
419
+ cp ${myProfile} $out/etc/profile.d/my-profile.sh
420
+ '')
421
+ aspell
422
+ bc
423
+ coreutils
424
+ ffmpeg
425
+ man
426
+ nixUnstable
427
+ emscripten
428
+ jq
429
+ nox
430
+ silver-searcher
431
+ texinfoInteractive
432
+ ];
433
+ pathsToLink = [ "/share/man" "/share/doc" "/share/info" "/bin" "/etc" ];
434
+ extraOutputsToInstall = [ "man" "doc" "info" ];
435
+ postBuild = ''
436
+ if [ -x $out/bin/install-info -a -w $out/share/info ]; then
437
+ shopt -s nullglob
438
+ for i in $out/share/info/*.info $out/share/info/*.info.gz; do
439
+ $out/bin/install-info $i $out/share/info/dir
440
+ done
441
+ fi
442
+ '';
443
+ };
444
+ };
445
+ }
446
+ </screen >
447
+
448
+ <para >
449
+ <literal >postBuild</literal > tells Nixpkgs to run a command after building
450
+ the environment. In this case, <literal >install-info</literal > adds the
451
+ installed info pages to <literal >dir</literal > which is GNU info's default
452
+ root node. Note that <literal >texinfoInteractive</literal > is added to the
453
+ environment to give the <literal >install-info</literal > command.
454
+ </para >
455
+
456
+ </section >
457
+
458
+ </section >
246
459
247
460
</chapter >
0 commit comments