The road to Nix, a functional package manager to rule them all

Daily progress update:

  • Yesterday’s changes to create a shell.nix, while very beneficial to create a cache reliably, brought some issues, notably:
    • with fastlane (some issue building the unf_ext gem). Today was spent mostly bringing Nix’s fastlane package to status-react, so we don’t use it from outside and don’t have to build the Gems;
    • the iOS build started failing, which turned out to be due to the fact that mkShell brings stdenv by default, instead of the stdenvNoCC that we need in iOS.
1 Like

Daily progress update:

  • The fastlane migration will take more work than expected, so I’m splitting that into a separate PR, so that the status-go PR can be submitted for review later today.
  • Created PR to upstream gomobile nix package.

Daily progress update:

  • With the help of @jakubgs, the Makefile now has a clean syntax for implicitly entering a temp Nix shell when needed.

I’ve also done away with the make setup command, so now when you clone the repo you can run something like make release-android and it will:

  1. install Nix;
  2. pull all required dependencies;
  3. build/deploy the Android app.

Result when running make release-android after git clone without further user intervention:

real    13m5.198s
user    3m38.569s
sys     0m27.528s

Daily progress update:

  • the Nix status-go branch has been merged! :sparkler::tada::fireworks: No more downloading artifacts from Digital Ocean.
  • investigated Nix fastlane some more, but it looks like it is too dependent on the host macOS system for it to be reliable, so no real advantage on macOS systems. Will likely drop this branch.
  • pushing two other branches for completion which should make Nix much easier to use (basically not any worse than pre-Nix usability, due to implicit calls to nix-shell and even implicit call to make setup if needed).
3 Likes

Daily progress update:

  • Babysitting the outstanding Nix PRs and merging them;
  • Looking into yarn2nix, a promising tool to integrate our node dependencies into Nix and avoid having to symlink things depending on whether we’re building for desktop or mobile (would like it to be done automatically depending on which Makefile target is being executed).

Daily progress update:

  • Looked into yarn2nix, and although it worked perfectly for normal node packages (it would create a symlinked node_modules into the Nix store cached node_modules), React Native Android gradle tasks didn’t like it, because they want to be able to write to node_modules. So I’m abandoning that investigation;
  • Currently looking into leveraging androidenv.androidsdk instead of our own download of the Android SDK. Some preliminary findings:
    • Even though we can easily point the env vars to the SDK in the nix store, it will not be usable by the gradle tasks, since the SDK licenses are not accepted in nixpkgs (which makes sense, each individual developer needs to accept the license and create his own ID). We also can’t use sdkmanager to accept the licenses since it would try to write to the immutable nix store directory.
    • The next best approach is to copy the nixpkgs Android SDK to our managed location (~/.status/Android/Sdk) any time we detect it is not present. This has the advantage that it creates a single source of truth in terms of SDK sub-package versions in the nix expression, and is much faster to recreate after we clean the home directory folder.

As we can see, Nix can be a painful medicine, but it does force us to recognize which parts of our setup are impure (such as the gradle tasks or the Android SDK) and manage it accordingly.

Daily progress update:

  • Merged the remaining PRs (optimizing the Makefile so it causes Nix to only install/build the bare minimum required, copy Android SDK from nix store and license it instead of downloading from internet, migrate Node.js to 10.15, and shell.nix refactor);
  • Started working on getting our builds to pass with nix-shell --pure flag, which forbids access to network, directories outside the nix store/repo and environment variables, so that we can be guaranteed as much as possible that my build is identical to the CI build and your build.
    Known impediments:

I’ll be on vacations the next couple of weeks, so don’t expect a lot of progress in this area during that time, but there’s plenty of cool stuff coming down the pipe once I get back!

Daily progress update:

  • Created first Android build based on a Nix pure environment:
    • Created utility Android SDK Nix package that links to nixpkgs’ androidenv but accepts licenses. This allows us to avoid copying the Android SDK to the user’s home folder and having to manage that, but most importantly, it removes a barrier to pure Android builds;
    • Managed to successfully build with nixpkgs’ fastlane instead of using ruby/bundler packages. This is another step towards pure Android builds. On iOS we still install fastlane the usual way, until we can fix the error we get on that platform.
1 Like

Daily progress update:

  • Breaking up status-go Nix package into per-platform packages, so that testing user branches has a much faster feedback loop.

Daily progress update:

  • Finished breaking up status-go Nix package into per-platform packages and created PR.
  • Start looking into approach to build Windows Qt and status-go/status-react in Nix, so we can have a pure environment.

Hi @pedro , nix packages is very big…it’s not convenient for devs in China to build cause of the GFW block. It would be great if there is an speed up image source within China to download the nix packages… i’m struggling with building atm… :expressionless:

copying path ‘/nix/store/nymkh0w8h0h70jmfyll1ivw1436v42vl-platforms-28’ from ‘https://nix-cache.status.im’…
copying path ‘/nix/store/bqn10ibvsf6wz8hqx51pl71lg2i0p80x-ndk-bundle-19.2.5345600’ from ‘https://nix-cache.status.im’…
warning: unable to download ‘https://nix-cache.status.im/nar/bqn10ibvsf6wz8hqx51pl71lg2i0p80x.nar’: HTTP error 200 (curl error: Stream error in the HTTP/2 framing layer); retrying in 309 ms
non-zero padding
copying path ‘/nix/store/hv95kz66aibdf9ckbnv5nsjgm2i1335l-nghttp2-1.36.0-lib’ from ‘https://cache.nixos.org’…
error: build of ‘/nix/store/19srs5p4257r1sjx6rvcvih2xd9s85pz-curl-7.64.0.drv’, ‘/nix/store/2dflx8j1g3n0jcivf6if87k961l4n161-status-go-v0.23.0-beta.10.drv’, ‘/nix/store/2vd4nkkw4vk42gmv113m7q35dmma0gpn-ps-1003.1-2008.drv’, ‘/nix/store/54rhqsrqnpapfk0xmqfms9n2jbgm0zlh-git-2.19.2.drv’, ‘/nix/store/9p4cyy0685n688cbsjcj1l7w69y04bi7-stdenv-darwin.drv’, ‘/nix/store/i590s78f99y2717jpmapfglfipjl8ih3-unzip-6.0.drv’, ‘/nix/store/ixfv1ghaih8nb87jykvvk7p3z3ghi6nz-node-react-native-cli-2.0.1.drv’, ‘/nix/store/jqmrra5616znb7hx16pb249f89j2g17s-ruby-2.5.3.drv’, ‘/nix/store/k8q3yla32j4r5cjcbgz8x2ba1xmsbbnh-nodejs-10.15.0.drv’, ‘/nix/store/ln690p68g41393mvmi9dpw24ds0n9z82-bundler-1.17.2.drv’, ‘/nix/store/n89ws2zm2ax58azbqhsbi9p20wvp4ax5-wget-1.20.1.drv’, ‘/nix/store/p7j89xyf5qv4qyd8jqr4l2nbzmydrd3h-androidsdk.drv’, ‘/nix/store/qspwik4smlbdyjifmwsl9id2d82l3nm9-jq-1.6.drv’, ‘/nix/store/sn9zxjphg1x7231yv4n4x42mc5g02hav-yarn-1.13.0.drv’ failed
make: *** [shell] Error 1

1 Like

finally, i used vpn to get through this…it’s big!!..> 3 GB

i won’t success without a vpn, as i said before it would be great if there is an image source choice:roll_eyes:

1 Like

I will look into a possibility of doing a read-only mirror in China/near China.

The best way would be to have multiple servers behind a load balancer that distributes traffic based on geographical location, but I don’t know how doable that would be with Nix. I’d need some kind of syncing solution between the servers.

1 Like

Daily progress update:

  • Making progress towards a pure macOS build, seems that the last remaining roadblocks are the CMake builds of qtkeychain and SnoreNotify.

Daily progress update:

  • Finished macOS pure environment update PR.
1 Like

Hey man, I’ve created a new Nix cache located in HongKong: https://nix-cache-cn.status.im/

I’ve added it to status-react in the following branch: nix-cn-cache (PR: #8170)

If you could try it out and move the cn one to be first in order in nix.conf and report back with results of using it I’d really appreciate it.

2 Likes

download from nix-cache-cn.status.im is fast,but download from cache.nixos.org is very very slow and timeout at last causing make shell failed, so it would be great if there is also a mirror of cache.nixos.org … and if there is a datetime field output before every log row, that would looks better?

2 Likes

I’m in Asia, and I can confirm cache.nixos.org is slow for me, in that, sometimes I have to restart make shell for it to complete downloading packages(if packages are to be downloaded). If I do make clean-nix and restart, it takes “eons” to download all the packages and the build system to be ready for work.

Another thing. I started using Nix as my MacOS package manager and completely got rid of Homebrew. How can I prevent nix-collect-garbage -d to not wipe out status-react packages?

1 Like

Well, then I guess our cache should be first, not second in order, so I’ve changed the nix-cn-cache branch to set substituters instead of extra-substituters and put https://cache.nixos.org as second in order:
set substituters instead of extra to make our cache the default · status-im/status-mobile@715c9c0 · GitHub
You can try it out, but I’d move the CN cache to be first in your case.

I don’t think you can. The only option could possible help you is --delete-older-than.

Smart move :-). Preventing garbage collection might be possible with --add-root (https://nixos.wiki/wiki/Storage_optimization). I’ll have to read about that.

1 Like