I had a couple people attempt this for the dev environment of https://www.oilshell.org/ with Nix, and it wasn't entirely successful. (Not Guix, but my understanding is that Guix would have the same issues)
As background, we've long had a set of evolving shell scripts that fetch and build dependencies at specific versions -- like bash/dash/zsh/mksh/busybox to test against, re2c to generate code, CommonMark, Python 3.10, MyPy with pip dependencies, and (bonus) R with CRAN dependencies.
1. OS X and libc, which is not really a problem since our existing scripts don't solve it either. It was just one motivation for Nix that didn't quite work out.
2. The file system layout becomes different, and Oil's shell tests rely on that. So containers ended up being easier. The whole build and test system runs in OCI containers under Docker and podman now, so it's pretty reproducible and automated.
But I still think it would be nice if someone who actually knows Nix and Guix (unlike me) tries again. The dependencies are more stable now than 2 years ago.
I think you have to write like 10 Nix or Guix expressions from scratch with the exact tarballs that we use. (Otherwise the tests will break even more, because Oil's tests are extremely detailed and find bugs in specific versions of specific shells.)
Right now we have a 134 line shell.nix that tries to reuse Oil's scripts, but I think it doesn't gibe with the way that Nix and Guix are meant to be used. Probably the real solution would be more like 1000 lines from scratch?
I remember that Nix Flakes was what I thought Nix was going to be, but at the time it wasn't ready. I thought Nix was supposed to solve the "it works on my machine" problem but it actually doesn't -- you still need a CI because it's possible to write .nix expressions in ways that break the sandboxing (unlike Bazel where you always get it).
I had ran this by someone who knows Guix and my takeaway was that Guix is basically the same in that regard.
A key problem is that, at least for awhile, I want it to work in parallel with our existing system ... not have a "big break".
As long as you don't hardcode "expected paths" (like in the FHS) in the filesystem, and expose the expectations you have via some configuration (environment variables and flags are fine), then packaging your software for Nix is pretty straightforward.
Also, reading back on that, I think the hardest part would be "PyPI dependencies" of MyPy, and "CRAN dependencies of R scripts like dplyr". These have what I call the "rewriting upstream" problem.
Though maybe a hybrid approach can work? Or does that defeat the purpose? I think a problem with these kinds of systems is that they can be "all or nothing". If you're halfway in, and halfway out, you don't get any benefits.
For lang-specific package managers that have a lockfile format, it's possible to write tooling that lets you run `cargo lock` or whatever and then generate the required Nix expressions for those dependencies. For stuff that doesn't support such a format, if you had your scripts export to your own little json lockfile format, you could have Nix read that (Nix expressions can ingest json).
There's some ongoing work to better support 'generating' those Nix expressions and using them in builds without explicitly storing them anywhere, as well (John Ericson's RFCs on 'import-from-derivation' and related functionality), and for unifying such tooling (dream2nix). (This kind of thing is what the `guix import` CLI does, but it has some limitations.)
There's some talk of possibly using Oil Shell for a port of Nixpkgs to Windows, although another language might be chosen by whoever really takes up that work. People interested in adding native Windows support to Nix might be interested in helping you sort out Nix packaging for Oil (I see there is a package currently, but it's not a source build).
> Linux is unique among operating systems due to the fact that the Kernel and Libc are developed independently. Linux is maintained by creator Linus Torvalds and a community of contributors. Glibc, the most popular Libc for Linux, is maintained by the GNU project. As a result, Linux has a strong separation between Syscalls and Libc.
> [ ... ]
> To accomplish this, Linux provides a stable list of syscalls that it has maintained across many versions. This is specified for i386 at arch/x86/entry/syscalls/syscall_32.tbl in the kernel tree. The syscalls specified here are the interface through which the Libc communicates with the kernel. As a result, applications built in 1992 can run on a modern kernel, provided it comes with copies of all its libraries.
> The macOS Libc is called libSystem. It is available on all macOS systems at /usr/lib/libSystem.B.dylib. This library is the main interface that binary compatibility is maintained in macOS. Unlike Linux, macOS maintains a stable interface in libSystem that all executables are expected to link to. This interface is guaranteed by Apple to be stable between versions.
> In Nixpkgs, we maintain this compatibility through a list of symbols that are exported by libSystem. This is a simple text list and is available for viewing at NixOS/nixpkgs/pkgs/os-specific/darwin/apple-source-releases/Libsystem/system_c_symbols. The symbol list is created by listing symbols (nm) on the minimum macOS version that we support (for my PR, 10.12). We do some linking tricks to ensure that everything that we build in Nixpkgs only contains those symbols. This means that we can reproducibly build on newer versions of macOS, while maintaining compatibility with older macOS versions. Unfortunately, newer symbols introduced in later versions cannot be used even on systems that have those symbols.
> A side effect of macOS design, is that fully static executables are not supported in macOS as they are on Linux. Without a stable syscall interface, there is nothing to provide compatibility between versions. As a result, Apple does not support this type of linking.
So Nixpkgs does do some things to try to let you peg builds only to what's available in older versions of the macOS libc, but it doesn't try to let you bring your own libc.
There's at least one libc that does claim this kind of portability of course, and is the subject of lots of good posts here on HN. Maybe the author of Cosmopolitan libc ( https://justine.lol/cosmopolitan/index.html ) might have something insightful to say here.
I think performance expectations for shells on Windows are pretty different. The first time I open PowerShell in a given session on my work computer, it takes ~9 seconds on average, without a particularly complex config.
That said, I think it can also makes sense to aim higher in terms of performance at the cost of a more bespoke Windows implementation. lol
As background, we've long had a set of evolving shell scripts that fetch and build dependencies at specific versions -- like bash/dash/zsh/mksh/busybox to test against, re2c to generate code, CommonMark, Python 3.10, MyPy with pip dependencies, and (bonus) R with CRAN dependencies.
I wrote about 2 problems here: https://lobste.rs/s/s5co2f/where_contributors_have_problems_...
1. OS X and libc, which is not really a problem since our existing scripts don't solve it either. It was just one motivation for Nix that didn't quite work out.
2. The file system layout becomes different, and Oil's shell tests rely on that. So containers ended up being easier. The whole build and test system runs in OCI containers under Docker and podman now, so it's pretty reproducible and automated.
But I still think it would be nice if someone who actually knows Nix and Guix (unlike me) tries again. The dependencies are more stable now than 2 years ago.
I think you have to write like 10 Nix or Guix expressions from scratch with the exact tarballs that we use. (Otherwise the tests will break even more, because Oil's tests are extremely detailed and find bugs in specific versions of specific shells.)
Right now we have a 134 line shell.nix that tries to reuse Oil's scripts, but I think it doesn't gibe with the way that Nix and Guix are meant to be used. Probably the real solution would be more like 1000 lines from scratch?
I remember that Nix Flakes was what I thought Nix was going to be, but at the time it wasn't ready. I thought Nix was supposed to solve the "it works on my machine" problem but it actually doesn't -- you still need a CI because it's possible to write .nix expressions in ways that break the sandboxing (unlike Bazel where you always get it).
I had ran this by someone who knows Guix and my takeaway was that Guix is basically the same in that regard.
A key problem is that, at least for awhile, I want it to work in parallel with our existing system ... not have a "big break".