arrterian / nix-env-selector

Allows switch environment for Visual Studio Code using Nix Package Manager.
MIT License
220 stars 29 forks source link

[HELP]: Share your .nix usage propose #46

Open arrterian opened 3 years ago

arrterian commented 3 years ago

Hi guys 👋 I have a plan to create a docs site for the extension. In one of the chapters, I would write about how to use the extension and nix for creating a development environment for different languages and platforms.

Could you guys share with me your nix configs for different cases that using in your real projects? It'll be good to have examples for Haskell, Rust, Go, Java, etc.

aszenz commented 3 years ago

The way I personally use nix for development envs is rather basic but it may suffice for basic documentation.

I only install the language binaries and tooling via nix and then let the languages own build system (cargo, npm, maven) handle building the actual project.

I think for development environments this is an ok practice.

Here's a basic template for an elm development environment.

let
  # pin nixpkgs to a particular commit
  nixpkgsRev = "e924a8823325472a42c06bb519cc59d4c8bda614";
  # a nix function to fetch a tar ball from github
  githubTarball = owner: repo: rev:
    builtins.fetchTarball { url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; };

  # import set of packages from nixpkgs github repo at a particular revision with the config specified below
  pkgs = import (githubTarball "nixos" "nixpkgs" nixpkgsRev) { };
in
{
  inherit pkgs;
  shell = pkgs.mkShell {
    name = "elm-dev";
    buildInputs = [
      pkgs.elmPackages.elm
      pkgs.elmPackages.elm-format
      pkgs.elmPackages.elm-test
      pkgs.nodejs-15_x
    ];
    shellHook = ''
      echo "start using elm"
    '';
  };
}

Here's one for an old node js project

let
  nixpkgsRev = "1d55adbce8af68fee04f42b562f5376be5a6026c";
  githubTarball = owner: repo: rev:
    builtins.fetchTarball { url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; };
  pkgs = import (githubTarball "nixos" "nixpkgs" nixpkgsRev) { };
in
with pkgs;{
  shell = mkShell {
    name = "dev env";
    buildInputs = [
      nodejs-10_x
      (yarn.override { nodejs = nodejs-10_x; })
      libpng12
    ];
    LD_LIBRARY_PATH="${pkgs.libpng12}/lib";
    shellHook = ''
      echo "Start working";
      echo "Run yarn serve to run the app";
    '';
  };
}

Mostly the template remains the same except for buildInputs which contains different tools for the language

arrterian commented 3 years ago

@aszenz Awesome! Thank you for sharing.

jmatsushita commented 3 years ago

There you go, I use flakes with the following flakes.nix for a haskell project:

{
  description = "Package build for gstreamer project";
  inputs.haskellNix.url = "github:input-output-hk/haskell.nix";
  inputs.nixpkgs.follows = "haskellNix/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";
  outputs = { self, haskellNix, nixpkgs, flake-utils }: 
    flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" ] (system:
    let
      overlays = [ haskellNix.overlay
        (final: prev: {
          # This overlay adds our project to pkgs
          streamlineProject =
            final.haskell-nix.project' {
              src = ./.;
              compiler-nix-name = "ghc8104";
              # projectFileName = "stack.yaml";
              modules = [{
              # Replace `extra-libraries` dependencies
                packages.cuda.components.library.libs = pkgs.lib.mkForce 
                  [ pkgs.cudatoolkit_10_2 ];
                packages.cuda.components.library.pkgconfig = pkgs.lib.mkForce 
                 [ [ pkgs.cudatoolkit_10_2 ] ];
              }];
            };
          # Maps haskell library names to nixpkgs library names
          "gstreamer-1.0" = pkgs.gst_all_1.gstreamer;
          "gstreamer-plugins-bad-1.0" = pkgs.gst_all_1.gst-plugins-bad;
          "gstreamer-plugins-good-1.0" = pkgs.gst_all_1.gst-plugins-good;
          "gstreamer-plugins-base-1.0" = pkgs.gst_all_1.gst-plugins-base;
          cuda = prev.cudatoolkit_10_2;
        })
      ];
      pkgs = import nixpkgs { inherit system overlays; config.allowUnfree = true; };
      flake = pkgs.streamlineProject.flake {};
      in flake // {
        # Built by `nix build .`
        defaultPackage = flake.packages."streamline:exe:streamline";

        # This is used by `nix develop .` to open a shell for use with
        # `cabal`, `hlint` and `haskell-language-server`
        devShell = pkgs.streamlineProject.shellFor {
          tools = {
            cabal = "latest";
            ghcid = "latest";
            hlint = "latest";
            haskell-language-server = "latest";
          };
        };
      });
}

UPDATE: This works with a shell.nix compatibility layer as described here: https://github.com/arrterian/nix-env-selector/issues/53

zyansheep commented 3 years ago

This is my flake.nix for a rust project I am currently working on.

{
    inputs = {
        utils.url = "github:numtide/flake-utils";
        naersk.url = "github:nmattia/naersk";
        fenix.url = "github:nix-community/fenix";
    };

    outputs = { self, nixpkgs, utils, naersk, fenix }:
    utils.lib.eachDefaultSystem (system: let
        pkgs = nixpkgs.legacyPackages."${system}";
        # Specify Rust Toolchain
        # Use Stable (Default)
        # naersk-lib = naersk.lib."${system}";
        # Use Nightly (provided by fenix)
        naersk-lib = naersk.lib."${system}".override {
            # Use Fenix to get nightly rust
            inherit (fenix.packages.${system}.minimal) cargo rustc;
        };
    in rec {
        # `nix build`
        packages.nixman = naersk-lib.buildPackage {
            pname = "nixman";
            root = ./.;
            nativeBuildInputs = with pkgs; [
                pkg-config
            ];
            buildInputs = with pkgs; [
                ncurses
                openssl
            ];
        };
        defaultPackage = packages.nixman;

        # `nix run`
        apps.nixman = utils.lib.mkApp {
            drv = packages.nixman;
        };
        defaultApp = apps.nixman;

        # `nix develop`
        devShell = pkgs.mkShell {
            nativeBuildInputs = packages.nixman.nativeBuildInputs;
            buildInputs = packages.nixman.buildInputs;
        };
    });
}
yusdacra commented 3 years ago

I use https://github.com/yusdacra/nix-cargo-integration in my projects. How it looks in one of my Rust projects' flake.nix:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    nixCargoIntegration = {
      url = "github:yusdacra/nix-cargo-integration";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    flakeCompat = {
      url = "github:edolstra/flake-compat";
      flake = false;
    };
  };

  outputs = inputs: inputs.nixCargoIntegration.lib.makeOutputs {
    root = ./.;
    buildPlatform = "crate2nix";
    overrides = {
      shell = common: prev: {
        packages = prev.packages ++ [ common.pkgs.musl.dev ];
        commands = prev.commands ++ [
          {
            name = "generate-cert";
            command = ''
              mkcert localhost 127.0.0.1 ::1
              mv localhost+2.pem cert.pem
              mv localhost+2-key.pem key.pem
            '';
          }
          {
            name = "run-with-console";
            command = ''RUSTFLAGS="--cfg tokio_unstable" cargo r --features console'';
          }
        ];
      };
    };
  };
}
lsap commented 6 months ago

flake.nix for Haskell is the same to @jmatsushita 's