<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>diary &amp;mdash; Jerry of the Week</title>
    <link>https://write.in0rdr.ch/tag:diary</link>
    <description>ˈdʒɛri - Individual who sends life against the grain no matter the consequences</description>
    <pubDate>Thu, 23 Apr 2026 23:15:11 +0000</pubDate>
    <item>
      <title>Building and installing a C project with Nix</title>
      <link>https://write.in0rdr.ch/building-and-installing-a-c-project-with-nix</link>
      <description>&lt;![CDATA[Today I learned how to build and install a simple C project on Nix(OS).&#xA;&#xA;After some reading on the Internet 📚, I finally understood the basics of building and installing a package from C sources using a Nix expression file (the .nix file in the following examples).&#xA;&#xA;#packaging #coding #nix #diary #c&#xA;&#xA;!--more--&#xA;&#xA;The expression file uses the standard build environment 🧰. Essentially, this environment abstracts the traditional Makefile based build proces (i.e., make &amp;&amp; make install).&#xA;&#xA;For learning purposes, I decided to package my hobby project, the text-based journaling program diary 📓.&#xA;&#xA;Writing the Nix expression file&#xA;&#xA;I built the expression file based on a an example from the Nix book.&#xA;&#xA;The Nix expression file diary.nix to install the stable version of the diary program fetches the source by tag from the Git repository:&#xA;&#xA;let&#xA;  pkgs = import nixpkgs { };&#xA;in&#xA;  pkgs.stdenv.mkDerivation {&#xA;    name = &#34;diary&#34;;&#xA;    version = &#34;v0.10&#34;;&#xA;    buildInputs = with pkgs; [&#xA;      ncurses&#xA;      curlFull&#xA;      lttng-ust&#xA;    ];&#xA;&#xA;    src = pkgs.fetchgit {&#xA;      url = &#34;https://git.in0rdr.ch/diary.git&#34;;&#xA;      rev = &#34;refs/tags/v0.10&#34;;&#xA;      hash = &#34;sha256-jDPfqUjf0ZETYqPxvEJ2/YFFjNsF7yvVQiThc5yMvjc=&#34;;&#xA;    };&#xA;&#xA;    installPhase = &#39;&#39;&#xA;      install -d $out/bin&#xA;      install -d $out/share/man/man1&#xA;      install -m755 diary $out/bin/&#xA;      install -m644 man1/diary.1 $out/share/man/man1/&#xA;    &#39;&#39;;&#xA;  }&#xA;&#xA;The mkDerivation call does most of the work. There we define the package name and version, as well all of the dependencies required to build the project. In this case, the diary program depends on the curl and ncurses libraries as well as the lttng tracing library.&#xA;&#xA;The source code src can be fetched conveniently from Git (using the fetchgit &#34;builder&#34;) or from other remote sources (see related &#34;fetch&#34; builtin functions).&#xA;&#xA;To build a nightly release from the master branch, I only had to slightly tune the src of the unstable Nix expression:&#xA;&#xA;    src = pkgs.fetchgit {&#xA;      url = &#34;https://git.in0rdr.ch/diary.git&#34;;&#xA;      hash = &#34;sha256-laKIVxfqJqBkB2d0F8tOOnpAXXRzHFfpjhAzZT8MX8k=&#34;;&#xA;    };&#xA;&#xA;The sha256 hash can be obtained using nix-prefetch-git:&#xA;&#xA;get hash for the specific tag/release&#xA;nix-prefetch-git https://git.in0rdr.ch/diary.git --rev refs/tags/v0.10&#xA;&#xA;get hash for latest nightly build from master branch&#xA;nix-prefetch-git https://git.in0rdr.ch/diary.git&#xA;&#xA;Finally, the installPhase needed a bit of tuning and has a small difference to what is commonly used in a Makefile on a traditional Linux distribution. But that was not too hard either, I simply had to translate my install target from the already existing Makefile.&#xA;&#xA;The  install target:&#xA;install: $(TARGET)&#xA;        install -m755 $(TARGET) $(BINDIR)/$(TARGET)&#xA;        install -d $(MANDIR)/man1&#xA;        install -m644 $(MAN1) $(MANDIR)/$(MAN1)&#xA;&#xA;The corresponding Nix installPhase:&#xA;      install -d $out/bin&#xA;      install -d $out/share/man/man1&#xA;      install -m755 diary $out/bin/&#xA;      install -m644 man1/diary.1 $out/share/man/man1/&#xA;&#xA;Very similar indeed. One point to note here is that the fixup phase will automatically install the man pages to the correct location.&#xA;&#xA;Building and installing the C project&#xA;&#xA;Once the expression file is written, building and installing the program is a peace of cake 🍰:&#xA;&#xA;Build stable package&#xA;nix-build nix/diary.nix&#xA;&#xA;Build latest nightly version&#xA;nix-build nix/diary-unstable.nix&#xA;&#xA;To install the package from the expression file to the user environment:&#xA;Install stable package&#xA;nix-env -i -f nix/diary.nix&#xA;&#xA;Install latest nightly version&#xA;nix-env -i -f nix/diary-unstable.nix&#xA;&#xA;You can even verify the location of the man page by using manpath -q or query the installed package with nix-env -q.&#xA;&#xA;Next steps&#xA;&#xA;Now that we have drafted the basic expression file, we might also add it to the nixpkgs repository on GitHub. I haven&#39;t checked the contributor requirements in detail yet.&#xA;&#xA;div style=&#34;text-align:center; font-size: 0.8em&#34;&#xD;&#xA;a href=&#34;https://write.in0rdr.ch/feed&#34;&amp;#128732; RSS/a | a href=&#34;https://m.in0rdr.ch/in0rdr&#34;&amp;#128024; Fediverse/a | a href=&#34;https://chat.in0rdr.ch/#/guest?join=p0c@conference.in0rdr.ch&#34;&amp;#128172; XMPP/a&#xD;&#xA;/div]]&gt;</description>
      <content:encoded><![CDATA[<p>Today I learned how to build and install a simple C project on Nix(OS).</p>

<p>After some reading on the Internet 📚, I finally understood the basics of building and installing a package from C sources using a Nix expression file (the <code>.nix</code> file in the following examples).</p>

<p><a href="https://write.in0rdr.ch/tag:packaging" class="hashtag"><span>#</span><span class="p-category">packaging</span></a> <a href="https://write.in0rdr.ch/tag:coding" class="hashtag"><span>#</span><span class="p-category">coding</span></a> <a href="https://write.in0rdr.ch/tag:nix" class="hashtag"><span>#</span><span class="p-category">nix</span></a> <a href="https://write.in0rdr.ch/tag:diary" class="hashtag"><span>#</span><span class="p-category">diary</span></a> <a href="https://write.in0rdr.ch/tag:c" class="hashtag"><span>#</span><span class="p-category">c</span></a></p>



<p>The expression file uses the <strong><a href="https://nixos.org/manual/nixpkgs/stable/#part-stdenv">standard build environment</a></strong> 🧰. Essentially, this environment abstracts the traditional <code>Makefile</code> based build proces (i.e., <code>make &amp;&amp; make install</code>).</p>

<p>For learning purposes, I decided to package my hobby project, the <a href="https://diary.p0c.ch">text-based journaling program <code>diary</code></a> 📓.</p>

<h2 id="writing-the-nix-expression-file">Writing the Nix expression file</h2>

<p>I built the expression file based on a an <strong><a href="https://book.divnix.com/ch06-01-simple-c-program.html">example from the Nix book</a></strong>.</p>

<p>The Nix expression file <a href="https://code.in0rdr.ch/diary/file/nix/diary.nix.html"><code>diary.nix</code></a> to install the stable version of the <code>diary</code> program fetches the source by tag from the Git repository:</p>

<pre><code class="language-nix">let
  pkgs = import &lt;nixpkgs&gt; { };
in
  pkgs.stdenv.mkDerivation {
    name = &#34;diary&#34;;
    version = &#34;v0.10&#34;;
    buildInputs = with pkgs; [
      ncurses
      curlFull
      lttng-ust
    ];

    src = pkgs.fetchgit {
      url = &#34;https://git.in0rdr.ch/diary.git&#34;;
      rev = &#34;refs/tags/v0.10&#34;;
      hash = &#34;sha256-jDPfqUjf0ZETYqPxvEJ2/YFFjNsF7yvVQiThc5yMvjc=&#34;;
    };

    installPhase = &#39;&#39;
      install -d $out/bin
      install -d $out/share/man/man1
      install -m755 diary $out/bin/
      install -m644 man1/diary.1 $out/share/man/man1/
    &#39;&#39;;
  }
</code></pre>

<p>The <code>mkDerivation</code> call does most of the work. There we define the package <code>name</code> and <code>version</code>, as well all of the dependencies required to build the project. In this case, the <code>diary</code> program depends on the <code>curl</code> and <code>ncurses</code> libraries as well as the <code>lttng</code> tracing library.</p>

<p>The source code <code>src</code> can be fetched conveniently from Git (using the <a href="https://nixos.org/manual/nix/stable/language/builtins.html#builtins-fetchGit"><code>fetchgit</code> “builder”</a>) or from other remote sources (see related <a href="https://nixos.org/manual/nix/stable/language/builtins.html">“fetch” builtin functions</a>).</p>

<p>To build a nightly release from the master branch, I only had to slightly tune the <code>src</code> of the <a href="https://code.in0rdr.ch/diary/file/nix/diary-unstable.nix.html">unstable Nix expression</a>:</p>

<pre><code class="language-nix">    src = pkgs.fetchgit {
      url = &#34;https://git.in0rdr.ch/diary.git&#34;;
      hash = &#34;sha256-laKIVxfqJqBkB2d0F8tOOnpAXXRzHFfpjhAzZT8MX8k=&#34;;
    };
</code></pre>

<p>The sha256 hash can be obtained using <a href="https://search.nixos.org/packages?channel=23.11&amp;show=nix-prefetch-git"><code>nix-prefetch-git</code></a>:</p>

<pre><code class="language-bash"># get hash for the specific tag/release
nix-prefetch-git https://git.in0rdr.ch/diary.git --rev refs/tags/v0.10

# get hash for latest nightly build from master branch
nix-prefetch-git https://git.in0rdr.ch/diary.git
</code></pre>

<p>Finally, the <a href="https://nixos.org/manual/nixpkgs/stable/#ssec-install-phase"><code>installPhase</code></a> needed a bit of tuning and has a small difference to what is commonly used in a <code>Makefile</code> on a traditional Linux distribution. But that was not too hard either, I simply had to translate my <code>install</code> target from the <a href="https://code.in0rdr.ch/diary/file/Makefile.html">already existing <code>Makefile</code></a>.</p>

<p>The  <code>install</code> target:</p>

<pre><code class="language-Makefile">install: $(TARGET)
        install -m755 $(TARGET) $(BINDIR)/$(TARGET)
        install -d $(MANDIR)/man1
        install -m644 $(MAN1) $(MANDIR)/$(MAN1)
</code></pre>

<p>The corresponding Nix <code>installPhase</code>:</p>

<pre><code class="language-nix">      install -d $out/bin
      install -d $out/share/man/man1
      install -m755 diary $out/bin/
      install -m644 man1/diary.1 $out/share/man/man1/
</code></pre>

<p>Very similar indeed. One point to note here is that the <a href="https://nixos.org/manual/nixpkgs/stable/#ssec-fixup-phase"><code>fixup</code> phase</a> will automatically install the man pages to the correct location.</p>

<h2 id="building-and-installing-the-c-project">Building and installing the C project</h2>

<p>Once the expression file is written, <a href="https://code.in0rdr.ch/diary/file/docs/NIX.md.html">building and installing</a> the program is a peace of cake 🍰:</p>

<pre><code class="language-bash"># Build stable package
nix-build nix/diary.nix

# Build latest nightly version
nix-build nix/diary-unstable.nix
</code></pre>

<p>To install the package from the expression file to the user environment:</p>

<pre><code class="language-bash"># Install stable package
nix-env -i -f nix/diary.nix

# Install latest nightly version
nix-env -i -f nix/diary-unstable.nix
</code></pre>

<p>You can even verify the location of the man page by using <code>manpath -q</code> or query the installed package with <code>nix-env -q</code>.</p>

<h2 id="next-steps">Next steps</h2>

<p>Now that we have drafted the basic expression file, we might also add it to the <code>nixpkgs</code> repository on GitHub. I haven&#39;t checked the <a href="https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md">contributor requirements</a> in detail yet.</p>

<div style="text-align:center; font-size: 0.8em">
<a href="https://write.in0rdr.ch/feed">🛜 RSS</a> | <a href="https://m.in0rdr.ch/in0rdr">🐘 Fediverse</a> | <a href="https://chat.in0rdr.ch/#/guest?join=p0c@conference.in0rdr.ch">💬 XMPP</a>
</div>
]]></content:encoded>
      <guid>https://write.in0rdr.ch/building-and-installing-a-c-project-with-nix</guid>
      <pubDate>Mon, 15 Apr 2024 18:20:17 +0000</pubDate>
    </item>
  </channel>
</rss>