Subject: [bug#58903] Specify the build dir for Nix

From: phodina <[email-masked]>
Date: Mon, 31 Oct 2022 15:37:09 +0000

Hello,

I'd like to upstream this patch to Nix service and hear your thoughts on the matter.

The issue is that there are some packages that fail to build even on realtively powerful machine due to resource exhaustion - not enough RAM.

The solution for that is to extract and build the derivation on block device instead of tmpfs.

The solution for this is to specify the environment variable TMPDIR​ and point it e.g. to `/var/tmp​`.

Unfortunately I'm not aware of any other way how to specify I'd like to build just this package in other directory (other than `/tmp`).

Also is there some other way how Guix handles this issue? I might be also used in Nix.

FIY the reason I have to use Nix is to build the Android image [1]

1 https://github.com/danielfullmer/robotnix

----
Petr

From 2d20cede80daf21ad355438a0d041b6dcba4a20b Mon Sep 17 00:00:00 2001
From: Petr Hodina <[email-masked]>
Date: Mon, 31 Oct 2022 16:12:38 +0100
Subject: [PATCH] services: nix: Add more configuration fields.

* gnu/services/nix.scm (<nix-configuration>)[build-dir]: New field.
(nix-service-etc, nix-shepherd-service): Take them into account.
* doc/guix.texi (Nix): Update it.

diff --git a/doc/guix.texi b/doc/guix.texi
index 80fb3bc47f..5eed0112d2 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -37111,6 +37111,26 @@ The Nix package to use.
 @item @code{sandbox} (default: @code{#t})
 Specifies whether builds are sandboxed by default.
 
+@item @code{build-dir} (default: @code{"/tmp"})
+Specifies build directory. This is useful to change if there is not enough RAM
+on the machine (e.g. embedded targets) or if building big packages (e.g.
+chromium).
+
+Normally the default location is @code{"/tmp"} which is mostly represented by
+@code{tmpfs}. Therefore this solution is fast and does not perform any IO to the
+nonvolatile block storage (unless swap is enabled). However, the user might
+encounter build failure when building large packages (e.g. @code{chromium})
+which take a lot of space when unpacking, the build artifacts consume more space
+and the linking stage might fail due to insufficient amount of RAM for LTO as
+all the object files are loaded into memory.
+
+This can be overcome by storing the intermediate files of the derivation in
+other locations such as @code{"/var/tmp/"} that are usually storaged on block
+device.
+
+Be aware that on embedded targets this option will result in more flash wear out
+due to large amount of writes.
+
 @item @code{build-sandbox-items} (default: @code{'()})
 This is a list of strings or objects appended to the
 @code{build-sandbox-items} field of the configuration file.
diff --git a/gnu/services/nix.scm b/gnu/services/nix.scm
index df04a85c22..ee49c0d594 100644
--- a/gnu/services/nix.scm
+++ b/gnu/services/nix.scm
@@ -54,6 +54,8 @@ (define-record-type* <nix-configuration>
                        (default nix))
   (sandbox             nix-configuration-sandbox ;boolean
                        (default #t))
+  (build-dir           nix-configuration-build-dir ;string
+                       (default "/tmp"))
   (build-sandbox-items nix-configuration-build-sandbox-items ;list of strings
                        (default '()))
   (extra-config        nix-configuration-extra-config ;list of strings
@@ -106,7 +108,7 @@ (define (nix-activation _)
 
 (define nix-service-etc
   (match-lambda
-    (($ <nix-configuration> package sandbox build-sandbox-items extra-config)
+    (($ <nix-configuration> package sandbox build-dir build-sandbox-items extra-config)
      (let ((ref-file (references-file package)))
        `(("nix/nix.conf"
           ,(computed-file
@@ -130,7 +132,7 @@ (define internal-sandbox-paths
 (define nix-shepherd-service
   ;; Return a <shepherd-service> for Nix.
   (match-lambda
-    (($ <nix-configuration> package _ _ _ extra-options)
+    (($ <nix-configuration> package _ build-dir _ _ extra-options)
      (list
       (shepherd-service
        (provision '(nix-daemon))
@@ -138,7 +140,10 @@ (define nix-shepherd-service
        (requirement '())
        (start #~(make-forkexec-constructor
                  (list (string-append #$package "/bin/nix-daemon")
-                       #$@extra-options)))
+                       #$@extra-options)
+                 #:environment-variables
+                   (list (string-append "TMPDIR=" build-dir)
+                         "PATH=/run/current-system/profile/bin")))
        (respawn? #f)
        (stop #~(make-kill-destructor)))))))
 
-- 
2.37.2