Devenv: nixpkgs.mkShell.override alternative

Hi all, @domenkozar,

thank you for the awesome devenv!
I have question which I’ve been struggling to answer on my own: given devenv, is it possible to override stdenv?

The Context

I’ve got a flakified env for building swift projects (e.g. this one):

{
  outputs = { self, nixpkgs, flake-utils, }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in
      {
        # https://github.com/NixOS/nixpkgs/issues/242779#issuecomment-1732558769
        devShells.default = pkgs.mkShell.override { stdenv = pkgs.swift.stdenv; } {
          buildInputs = with pkgs;[
            swift
            swiftpm
            swiftPackages.Foundation
            darwin.apple_sdk.frameworks.AppKit
          ];

          # https://github.com/NixOS/nix/issues/6677
          shellHook = ''
            export PS1='\n\[\033[1;32m\][nix-shell:\w]\$\[\033[0m\] '
          '';
        };
      });
}

as per swift on nixos can't compile hello world: error: undefined reference to '__dso_handle' · Issue #242779 · NixOS/nixpkgs · GitHub, stdenv overriding is required, otherwise things fall apart (e.g. Foundation not being found).

The issue

I can’t properly translate stdenv overriding to devenv concepts (replaceStdenv is a last resort and doesn’t count):

{
  inputs = {
    nixpkgs.url = "nixpkgs/nixpkgs-unstable";
    devenv.url = "github:cachix/devenv";
  };
  nixConfig = {
    extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=";
    extra-substituters = "https://devenv.cachix.org";
  };
  outputs = { self, nixpkgs, devenv, flake-utils, }@inputs:
    flake-utils.lib.eachDefaultSystem (system:
      let
        # fully rebuilds the toolchain - not a replacement for nixpkgs.mkShell.override
        pkgs = import nixpkgs {
          inherit system;
          config.replaceStdenv = {pkgs}: pkgs.swift.stdenv;
        };
      in
      {
        devShells.default = devenv.lib.mkShell {
          inherit inputs pkgs;
          modules = [
            ({ pkgs, config, ... }: {
              languages.nix.enable = true;

              pre-commit.hooks = {
                nixpkgs-fmt.enable = true;
                yamllint.enable = true;
              };


              # https://github.com/NixOS/nix/issues/6677
              enterShell = ''
                export PS1='\n\[\033[1;32m\][nix-shell:\w]\$\[\033[0m\] '
              '';

              packages = with pkgs;[
                swift
                swiftpm
                swiftPackages.Foundation
                darwin.apple_sdk.frameworks.AppKit
              ];
            })
          ];
        };
      });
}

Hacking around

Digging thru sources has lead me to the referred devshell’s mkNakedShell. devenv’s (re)-implementation declares stdenv as input parameter, which confused me, as the let expression which follows, redeclares it?

It made me doubt if it actually would’ve worked, if I had figured out a less intrusive way to solve my problem (which I have not).

Disclaimer: that’s just noob’s attempt to get a grasp on things, so everything stated here has a potential to be the opposite of the truth :slight_smile:

Thanks a lot!
Peter

1 Like

Hey Peter,

You’re right that we need to implement this properly on the devenv side, could you open an issue for it?

We’d need a way to specify what stdenv is used before any of the modules get called, likely in devenv.yaml