Subject: Re: Specify the build dir for Nix

From: phodina <[email-masked]>
Date: Mon, 31 Oct 2022 19:18:29 +0000

Hi Tobias,

thanks for feedback!

> 
> > (build-dir nix-configuration-build-dir ;string
> > (default "/tmp"))
> 
> 
> ‘directory’. Plz, no unnec. abbrev.
> 
> The concept LGTM. Calling it a ‘build directory’ might be editorialising too much. Does Nix use it for anything else?

I've updated the patch so there is no abbreviation. I asked on Nix matrix channel and was told just for derivations. But I'm not expert so take it with grain of salt.

Ludo',
you have a lot insight into the build infrastructure and you also took the concepts from Nix.

What do you think about this approach? It should not be premanently set to block device as you loose throughput and increase latency, but it's neccessary for some derivations as not everybody can have powerful machine at their disposal.

Is there some way to share the approach with guix daemon? If I remeber correctly the derivation is offloaded to nix backend - the contents of `nix` directory (haven't yet had the chance to go through the C code).

I guess the machines behind 'https://ci.guix.gnu.org' have enough resources. Or is there some script that handles large derivations? 

Also this might be interesting problem for embedded devices though offloading is definitely the best approach.

----
Petr

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

* gnu/services/nix.scm (<nix-configuration>)[build-directory]: 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..825cf0831d 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-directory} (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..dcf994b603 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-directory     nix-configuration-build-directory ;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-directory 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-directory _ _ 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-directory)
+                         "PATH=/run/current-system/profile/bin")))
        (respawn? #f)
        (stop #~(make-kill-destructor)))))))
 
-- 
2.37.2