<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <title>Daniel Duan's Articles About NixOS</title>
        <link>https://duan.ca/tag/nixos/</link>
        <atom:link href="https://duan.ca/tag/nixos/feed.xml" rel="self" type="application/rss+xml" />
            <item>
                <title>Naive NixOS Rust Development</title>
                <description>&#60;p&#62;tl;dr: To work on Rust project with nix-shell, rls and extensions such as
&#60;code&#62;rust-analysis&#60;/code&#62;, &#60;code&#62;rust-src&#60;/code&#62;, without caring too much about specific Rust
toolchain version (except for it being &#60;code&#62;stable&#60;/code&#62;), use the following &#60;code&#62;shell.nix&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;let
  moz_overlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz);
  nixpkgs = import &#38;lt;nixpkgs&#38;gt; {
    overlays = [ moz_overlay ];
  };
  ruststable = (nixpkgs.latest.rustChannels.stable.rust.override {
    extensions = [ &#38;quot;rust-src&#38;quot; &#38;quot;rust-analysis&#38;quot; ];}
  );
in
  with nixpkgs;
  stdenv.mkDerivation {
    name = &#38;quot;rust&#38;quot;;
    buildInputs = [ rustup ruststable ];
  }
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;When you have a Nix hammer, everything looks like a Nix expression.&#60;/p&#62;
&#60;p&#62;Having used NixOS on a real PC for a number of days, this is the impression
I get from the world of Nix. Unfortunately, so far, it&#39;s been a negative for me.&#60;/p&#62;
&#60;p&#62;One of the most exciting thing I want to use Nix for is to bootstrap development
environment with &#60;code&#62;nix-shell&#60;/code&#62;. I imagined it to be similar to using &#60;a href=&#34;https://pipenv-fork.readthedocs.io/en/latest/&#34;&#62;pipenv&#60;/a&#62;
with Python, except for everything. Well, I&#39;ve since learned that it&#39;s not true
(yet?) for many reasons.&#60;/p&#62;
&#60;p&#62;Modern programming languages come with their own attempt at &#60;em&#62;reproducibility&#60;/em&#62;.
Some does it better than others. To make it concrete, I&#39;m talking about things
like &#60;a href=&#34;https://haskellstack.org&#34;&#62;Stack&#60;/a&#62; for Haskell or &#60;a href=&#34;https://rustup.rs/&#34;&#62;rustup&#60;/a&#62; for Rust: given the source code, how do
I make it build in the way the project intended? What&#39;s the correct version of
the compiler, runtime, and tools that works best with this revision of the
source code? The common solution usually follows this pattern: as author of
a project, specify as much as you can, the environment best suited for the
current state of the project. As a &#38;quot;builder&#38;quot;, use a &#60;em&#62;single program&#60;/em&#62; that&#39;s
capable of updating itself, as well as ensuring that the project builds exactly
as specified, including managing the compiler/runtime/tooling versions, etc.&#60;/p&#62;
&#60;p&#62;This &#60;em&#62;single program&#60;/em&#62;&#39;s role is very much the same as the Nix system, except the
latter is independent of programming languages: &#60;code&#62;rustup&#60;/code&#62; installs Rust, so does
Nix. That&#39;s a bad thing. As a package manager, Nix either have to tightly
integrate with each of these other package managers, leveraging their evolving
behaviors to give its user the build environment; or, it must replace them.
The former is impractical; the latter, well, sucks.&#60;/p&#62;
&#60;p&#62;Back to reality. This is the experience I want to have with NixOS: Some programs
I use daily such as Alacritty, NeoVim, Firfox, etc, are installed globally and
readily available. They are part of my &#60;code&#62;/etc/nixos/configuration.nix&#60;/code&#62;. So far so
good. Now, I regularly program in a few languages. For each of the project, I&#39;d
like to have a &#60;code&#62;shell.nix&#60;/code&#62; that brings in its compilers, libraries, LSP servers,
etc. This is what &#60;code&#62;nix-shell&#60;/code&#62; is supposed to give me! This is known as the &#38;quot;per
project&#38;quot; setup.&#60;/p&#62;
&#60;p&#62;Let&#39;s see: with Rust, that means &#60;code&#62;rustc&#60;/code&#62; (compiler), &#60;code&#62;cargo&#60;/code&#62; (package manager),
&#60;code&#62;rls&#60;/code&#62;, &#60;code&#62;rust-src&#60;/code&#62; and &#60;code&#62;rust-analysis&#60;/code&#62; (LSP). In macOS, I&#39;d install all of these
globally with &#60;code&#62;rustup&#60;/code&#62;. In NixOS...well, I can ask for &#60;code&#62;rustup&#60;/code&#62; for my project:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;with import &#38;lt;nixpkgs&#38;gt; {};

stdenv.mkDerivation {
  name = &#38;quot;rust&#38;quot;;
  nativeBuildInputs = [ rustup ];
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;...which gives me &#60;code&#62;rustup&#60;/code&#62; and nothing else. That&#39;s right, you don&#39;t even get
a &#60;code&#62;rustc&#60;/code&#62; after running &#60;code&#62;nix-shell&#60;/code&#62;. But &#60;code&#62;rustup&#60;/code&#62; can get you everything else,
all I need to do is ask. Hmm, do I need to run a series of set-up commands with
&#60;code&#62;rustup&#60;/code&#62; every time I enter the environment? No? I just need to run it the first
time? Until the cached tools get deleted by some garbage collection mechanism?
That seems unsatisfying, doesn&#39;t it?&#60;/p&#62;
&#60;p&#62;Instead of &#60;code&#62;rustup&#60;/code&#62;, I could also ask Nix to use the &#60;code&#62;rustc&#60;/code&#62;/&#60;code&#62;cargo&#60;/code&#62;/&#60;code&#62;rls&#60;/code&#62; it
knows about directly. This is marginally better. Except I still need &#60;code&#62;rust-src&#60;/code&#62;
and &#60;code&#62;rust-analysis&#60;/code&#62; for my needs. As far as I can tell, these &#60;a href=&#34;https://github.com/rust-lang/rls&#34;&#62;RLS&#60;/a&#62; components
are out of Nix&#39;s control (as of today).&#60;/p&#62;
&#60;p&#62;Everywhere on the internet I looked, for every problem that
Nix-the-package-manager doesn&#39;t work out-of-the-box, there&#39;s someone responding
along the line of &#38;quot;you can write some Nix expression yourself&#38;quot;. In other words,
Nix-the-language is powerful enough to solve it, probably. In the case of Rust,
luckily, Mozilla wrote enough Nix expressions for us and provides them via an
&#60;a href=&#34;https://github.com/mozilla/nixpkgs-mozilla&#34;&#62;overlay&#60;/a&#62;. These expressions are rich enough to meet my needs.
As you can see in the tl;dr at the top, when entering the development
environment, nix-shell would: download the overlay&#39;s source code (from the
internet, or local cache), load the expression it includes, mix in my
customization, and execute it.&#60;/p&#62;
&#60;p&#62;That marks the end of my search. I like the final solution because it&#39;s mostly
&#38;quot;vanilla&#38;quot; Nix and doesn&#39;t require me to mess with a bunch of other tools. For
solutions that do, read &#60;a href=&#34;https://xeiaso.net/blog/how-i-start-nix-2020-03-08/&#34;&#62;this&#60;/a&#62;.&#60;/p&#62;
&#60;hr /&#62;
&#60;p&#62;At end of the day, my needs are pretty basic: consistency from rustup and
convenience from nix-shell. I didn&#39;t need to pin the compiler to a specific Rust
release, or checksum the final build output.&#60;/p&#62;
&#60;p&#62;I&#39;m very new to both technologies so there may be a follow-up post sometime in
the future.&#60;/p&#62;
</description>
                <pubDate>Thu, 07 May 2020 11:04:58 -0700</pubDate>
                <link>https://duan.ca/2020/05/07/nix-rust-development/</link>
                <guid isPermaLink="true">https://duan.ca/2020/05/07/nix-rust-development/</guid>
            </item>
    </channel>
</rss>