diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 1cdf937d09..e71e6a60be 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -103,15 +103,19 @@ jobs: authToken: ${{ secrets.HLS_CACHIX_AUTH_TOKEN }} - name: Build development shell run: nix develop --print-build-logs --profile dev - - name: Build development shell (GHC 9.0.1) - run: nix develop --print-build-logs .#haskell-language-server-901-dev --profile dev + - name: Build all development shell (without nix dependencies) + run: nix develop --print-build-logs .#all-simple-dev-shells --profile dev + # We only build nix dev shell for current GHC version because some are + # failing with different GHC version on darwin. + - name: Build development shell with nix dependencies for current GHC version + run: nix develop --print-build-logs .#all-nix-dev-shells --profile dev - name: Push development shell if: ${{ env.HAS_TOKEN == 'true' }} run: cachix push haskell-language-server dev - name: Build binaries run: nix build --print-build-logs - - name: Build binaries (GHC 9.0.1) - run: nix build --print-build-logs .#haskell-language-server-901 + - name: Build all binaries + run: nix build --print-build-logs .#all-haskell-language-server - name: Push binaries if: ${{ env.HAS_TOKEN == 'true' }} run: nix path-info --json | jq -r '.[].path' | cachix push haskell-language-server diff --git a/configuration-ghc-901.nix b/configuration-ghc-901.nix index 62d83c9cc0..789a5d2e19 100644 --- a/configuration-ghc-901.nix +++ b/configuration-ghc-901.nix @@ -10,6 +10,8 @@ let hpkgsOverride = hself: hsuper: with pkgs.haskell.lib; { + hlsDisabledPlugins = disabledPlugins; + fourmolu = hself.fourmolu_0_4_0_0; primitive-extras = hself.primitive-extras_0_10_1_2; diff --git a/configuration-ghc-921.nix b/configuration-ghc-921.nix index 81a189ba70..fbb3bee780 100644 --- a/configuration-ghc-921.nix +++ b/configuration-ghc-921.nix @@ -5,28 +5,39 @@ let disabledPlugins = [ "hls-brittany-plugin" "hls-stylish-haskell-plugin" + "hls-hlint-plugin" + "hls-haddock-comments-plugin" + "hls-tactics-plugin" + # That one is not technically a plugin, but by putting it in this list, we + # get it removed from the top level list of requirement and it is not pull + # in the nix shell. + "shake-bench" ]; hpkgsOverride = hself: hsuper: with pkgs.haskell.lib; { + hlsDisabledPlugins = disabledPlugins; + fourmolu = hself.callCabal2nix "fourmolu" inputs.fourmolu {}; primitive-extras = hself.primitive-extras_0_10_1_2; ghc-exactprint = hself.callCabal2nix "ghc-exactprint" inputs.ghc-exactprint {}; constraints-extras = hself.callCabal2nix "constraints-extras" inputs.constraints-extras {}; retrie = hself.callCabal2nix "retrie" inputs.retrie {}; + + # Hlint is still broken hlint = doJailbreak (hself.callCabal2nix "hlint" inputs.hlint {}); + hiedb = hself.hiedb_0_4_1_0; # Re-generate HLS drv excluding some plugins haskell-language-server = hself.callCabal2nixWithOptions "haskell-language-server" ./. (pkgs.lib.concatStringsSep " " [ "-f-brittany" - "-f-stylishhaskell" + "-f-stylishHaskell" "-f-hlint" "-f-haddockComments" - "-f-alternateNumberFormat" - "-f-eval" + "-f-tactics" ]) { }; # YOLO diff --git a/flake.lock b/flake.lock index 63fe7a6be4..8a2edb2643 100644 --- a/flake.lock +++ b/flake.lock @@ -110,6 +110,18 @@ "url": "https://hackage.haskell.org/package/hlint-3.3.6/hlint-3.3.6.tar.gz" } }, + "implicit-hie-cradle": { + "flake": false, + "locked": { + "narHash": "sha256-2NmucBBI7Qi1UGXWG27XFZRCeqeRiwVFWmJKZnp6R5U=", + "type": "tarball", + "url": "https://hackage.haskell.org/package/implicit-hie-cradle-0.3.0.5/implicit-hie-cradle-0.3.0.5.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://hackage.haskell.org/package/implicit-hie-cradle-0.3.0.5/implicit-hie-cradle-0.3.0.5.tar.gz" + } + }, "lsp": { "flake": false, "locked": { @@ -216,6 +228,7 @@ "ghc-exactprint": "ghc-exactprint", "gitignore": "gitignore", "hlint": "hlint", + "implicit-hie-cradle": "implicit-hie-cradle", "lsp": "lsp", "lsp-test": "lsp-test", "lsp-types": "lsp-types", diff --git a/flake.nix b/flake.nix index 92a4324aa4..2743d1b95e 100644 --- a/flake.nix +++ b/flake.nix @@ -55,6 +55,10 @@ url = "https://hackage.haskell.org/package/hlint-3.3.6/hlint-3.3.6.tar.gz"; flake = false; }; + implicit-hie-cradle = { + url = "https://hackage.haskell.org/package/implicit-hie-cradle-0.3.0.5/implicit-hie-cradle-0.3.0.5.tar.gz"; + flake = false; + }; }; outputs = inputs@{ self, nixpkgs, flake-compat, flake-utils, pre-commit-hooks, gitignore, ... }: @@ -113,11 +117,7 @@ lsp-types = hsuper.callCabal2nix "lsp-types" inputs.lsp-types {}; lsp-test = hsuper.callCabal2nix "lsp-test" inputs.lsp-test {}; - implicit-hie-cradle = hself.callCabal2nix "implicit-hie-cradle" - (builtins.fetchTarball { - url = "https://hackage.haskell.org/package/implicit-hie-cradle-0.3.0.5/implicit-hie-cradle-0.3.0.5.tar.gz"; - sha256 = "15a7g9x6cjk2b92hb2wilxx4550msxp1pmk5a2shiva821qaxnfq"; - }) { }; + implicit-hie-cradle = hself.callCabal2nix "implicit-hie-cradle" inputs.implicit-hie-cradle {}; # https://github.com/NixOS/nixpkgs/issues/140774 ormolu = @@ -236,76 +236,145 @@ dontInstall = true; }; + mkDevShell = hpkgs: cabalProject: with pkgs; mkShell { + name = "haskell-language-server-dev-ghc${hpkgs.ghc.version}"; + # For theses tools packages, we use ghcDefault + # This removes a rebuild with a different GHC version + # Theses programs are tools, used as binary, independently of the + # version of GHC. + # The drawback of this approach is that our shell may pull two GHC + # version in scope (the default one, and the one defined in + # `hpkgs`.) + # The advantage is that we won't have to rebuild theses tools (and + # dependencies) with a recent GHC which may not be supported by + # them. + buildInputs = [ + # our compiling toolchain + hpkgs.ghc + pkgs.cabal-install + # @guibou: I'm not sure hie-bios is needed + ghcDefault.hie-bios + # Dependencies needed to build some parts of hackage + gmp zlib ncurses + # Changelog tooling + (gen-hls-changelogs ghcDefault) + # For the documentation + pythonWithPackages + # @guibou: I'm not sure this is needed. + hlint + ghcDefault.opentelemetry-extra + capstone tracy + # ormolu + # stylish-haskell + ]; + + + shellHook = '' + # @guibou: I'm not sure theses lines are needed + export LD_LIBRARY_PATH=${gmp}/lib:${zlib}/lib:${ncurses}/lib:${capstone}/lib + export DYLD_LIBRARY_PATH=${gmp}/lib:${zlib}/lib:${ncurses}/lib:${capstone}/lib + export PATH=$PATH:$HOME/.local/bin + + # Enable the shell hooks + ${(pre-commit-check ghcDefault).shellHook} + + # If the cabal project file is not the default one. + # Print a warning and generate an alias. + if [ ${cabalProject} != "cabal.project" ] + then + echo "Cabal won't be able to build your project without using the project file "${cabalProject}", such as:" + echo " cabal --project-file=${cabalProject}" + echo "An alias "cabal_project" is available. Use it like:" + echo " cabal_project build" + + alias cabal_project='cabal --project-file=${cabalProject}' + fi + ''; + }; + # Create a development shell of hls project # See https://github.com/NixOS/nixpkgs/blob/5d4a430472cafada97888cc80672fab255231f57/pkgs/development/haskell-modules/make-package-set.nix#L319 - mkDevShell = hpkgs: + mkDevShellWithNixDeps = hpkgs: cabalProject: with pkgs; + let simpleShell = mkDevShell hpkgs cabalProject; + in hpkgs.shellFor { + name = "haskell-language-server-dev-nix-ghc${hpkgs.ghc.version}"; + inherit (simpleShell) shellHook buildInputs; + doBenchmark = true; packages = p: with builtins; map (name: p.${name}) (attrNames - (if hpkgs.ghc.version == "9.0.1" then - removeAttrs hlsSources ghc901Config.disabledPlugins - else if hpkgs.ghc.version == "9.2.1" then - removeAttrs hlsSources ghc921Config.disabledPlugins - else - hlsSources)); - buildInputs = [ gmp zlib ncurses capstone tracy (gen-hls-changelogs hpkgs) pythonWithPackages ] - ++ (with hpkgs; [ - cabal-install - hie-bios - hlint - # ormolu - # stylish-haskell - opentelemetry-extra - ]); + # Disable dependencies should not be part of the shell. + (removeAttrs hlsSources (hpkgs.hlsDisabledPlugins or []))); src = null; - shellHook = '' - export LD_LIBRARY_PATH=${gmp}/lib:${zlib}/lib:${ncurses}/lib:${capstone}/lib - export DYLD_LIBRARY_PATH=${gmp}/lib:${zlib}/lib:${ncurses}/lib:${capstone}/lib - export PATH=$PATH:$HOME/.local/bin - ${if hpkgs.ghc.version != "9.0.1" then (pre-commit-check hpkgs).shellHook else ""} - ''; }; # Create a hls executable # Copied from https://github.com/NixOS/nixpkgs/blob/210784b7c8f3d926b7db73bdad085f4dc5d79418/pkgs/development/tools/haskell/haskell-language-server/withWrapper.nix#L16 mkExe = hpkgs: with pkgs.haskell.lib; - justStaticExecutables (overrideCabal hpkgs.haskell-language-server + (enableSharedExecutables (overrideCabal hpkgs.haskell-language-server (_: { postInstall = '' - remove-references-to -t ${hpkgs.ghc} $out/bin/haskell-language-server remove-references-to -t ${hpkgs.shake.data} $out/bin/haskell-language-server remove-references-to -t ${hpkgs.js-jquery.data} $out/bin/haskell-language-server remove-references-to -t ${hpkgs.js-dgtable.data} $out/bin/haskell-language-server remove-references-to -t ${hpkgs.js-flot.data} $out/bin/haskell-language-server ''; - })); + }))).overrideAttrs(old: { + pname = old.pname + "-ghc${hpkgs.ghc.version}"; + }); in with pkgs; rec { + # Developement shell with only compiler + simpleDevShells = { + haskell-language-server-dev = mkDevShell ghcDefault "cabal.project"; + haskell-language-server-884-dev = mkDevShell ghc884 "cabal.project"; + haskell-language-server-8107-dev = mkDevShell ghc8107 "cabal.project"; + haskell-language-server-901-dev = mkDevShell ghc901 "cabal-ghc90.project"; + haskell-language-server-921-dev = mkDevShell ghc921 "cabal-ghc921.project"; + }; - packages = { - # dev shell - haskell-language-server-dev = mkDevShell ghcDefault; - haskell-language-server-884-dev = mkDevShell ghc884; - haskell-language-server-8107-dev = mkDevShell ghc8107; - haskell-language-server-901-dev = mkDevShell ghc901; - haskell-language-server-921-dev = mkDevShell ghc921; + # Developement shell, haskell packages are also provided by nix + nixDevShells = { + haskell-language-server-dev-nix = mkDevShellWithNixDeps ghcDefault "cabal.project"; + haskell-language-server-884-dev-nix = mkDevShellWithNixDeps ghc884 "cabal.project"; + haskell-language-server-8107-dev-nix = mkDevShellWithNixDeps ghc8107 "cabal.project"; + haskell-language-server-901-dev-nix = mkDevShellWithNixDeps ghc901 "cabal-ghc90.project"; + haskell-language-server-921-dev-nix = mkDevShellWithNixDeps ghc921 "cabal-ghc921.project"; + }; - # hls package + allPackages = { haskell-language-server = mkExe ghcDefault; haskell-language-server-884 = mkExe ghc884; haskell-language-server-8107 = mkExe ghc8107; haskell-language-server-901 = mkExe ghc901; haskell-language-server-921 = mkExe ghc921; + }; + + devShells = simpleDevShells // nixDevShells; + + packages = allPackages // { + # See https://github.com/NixOS/nix/issues/5591 + # nix flake cannot build a list/set of derivation in one command. + # Using a linkFarmFromDrvs, I'm creating a unique entry point to + # build all HLS versions. + # This is used in CI to test and populate cache for packages + # distributed using nix. + all-haskell-language-server = linkFarmFromDrvs "all-haskell-language-server" (lib.unique (builtins.attrValues allPackages)); + + # Same for all shells + # We try to build as much as possible, but not much shells are + # working (especially on darwing), so this list is limited. + all-nix-dev-shells = linkFarmFromDrvs "all-dev-shells" (builtins.map (shell: shell.inputDerivation) (lib.unique [nixDevShells.haskell-language-server-dev-nix])); - # docs + all-simple-dev-shells = linkFarmFromDrvs "all-dev-shells" (builtins.map (shell: shell.inputDerivation) (lib.unique (builtins.attrValues simpleDevShells))); docs = docs; }; defaultPackage = packages.haskell-language-server; - devShell = packages.haskell-language-server-dev; + devShell = devShells.haskell-language-server-dev; }); }