From e63a4c7504a4452a74c543933a685bead0623724 Mon Sep 17 00:00:00 2001 From: Zoey Pessanha Date: Sat, 30 Aug 2025 01:05:01 -0300 Subject: [PATCH 1/3] refactor: allow burrito/multiple app nix build --- .gitignore | 3 ++ flake.lock | 50 +++++++------------ flake.nix | 127 ++++++++++++++++++++++++++-------------------- nix/expert.nix | 133 ++++++++++++++++++++++++++++++++++++++++++++----- nix/hash | 2 +- 5 files changed, 215 insertions(+), 100 deletions(-) diff --git a/.gitignore b/.gitignore index c4b805b8..bc1f6a02 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,6 @@ apps/forge/src/future_elixir_parser.erl **/burrito_out .notes/ + +# Nix files +result diff --git a/flake.lock b/flake.lock index 08730fa5..1d1622bd 100644 --- a/flake.lock +++ b/flake.lock @@ -2,17 +2,15 @@ "nodes": { "beam-flakes": { "inputs": { - "flake-parts": [ - "flake-parts" - ], + "flake-parts": "flake-parts", "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1754773944, - "narHash": "sha256-N7OHT0uUblt9XXqRXS18u74/AIo+dpXIRe7Y4Wr/7J8=", + "lastModified": 1756346526, + "narHash": "sha256-ejG8c5hp6OsiPyFeM0GBbx3ytkoA8XWZR6SEXwx2xX8=", "owner": "elixir-tools", "repo": "nix-beam-flakes", - "rev": "ac950a8ca59a5f4c32fc0669637672f1e63573ec", + "rev": "00ec29d1b20cad1c3b8736b373eedcab7f049a13", "type": "github" }, "original": { @@ -26,11 +24,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1719994518, - "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", + "lastModified": 1754487366, + "narHash": "sha256-pHYj8gUBapuUzKV/kN/tR3Zvqc7o6gdFB9XKXIp1SQ8=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", + "rev": "af66ad14b28a127c5c0f3bbb298218fc63528a18", "type": "github" }, "original": { @@ -57,14 +55,17 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1719876945, - "narHash": "sha256-Fm2rDDs86sHy0/1jxTOKB1118Q0O3Uc7EC0iXvXKpbI=", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" + "lastModified": 1753579242, + "narHash": "sha256-zvaMGVn14/Zz8hnp4VWT9xVnhc8vuL3TStRqwk22biA=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "0f36c44e01a6129be94e3ade315a5883f0228a6e", + "type": "github" }, "original": { - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz" + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" } }, "nixpkgs_2": { @@ -84,24 +85,7 @@ "root": { "inputs": { "beam-flakes": "beam-flakes", - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2", - "systems": "systems" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" + "nixpkgs": "nixpkgs_2" } } }, diff --git a/flake.nix b/flake.nix index 076c1124..1f8f7bf3 100644 --- a/flake.nix +++ b/flake.nix @@ -3,72 +3,91 @@ inputs.nixpkgs.url = "flake:nixpkgs"; inputs.beam-flakes.url = "github:elixir-tools/nix-beam-flakes"; - inputs.beam-flakes.inputs.flake-parts.follows = "flake-parts"; - - inputs.flake-parts.url = "github:hercules-ci/flake-parts"; - inputs.systems.url = "github:nix-systems/default"; outputs = { self, - systems, + nixpkgs, beam-flakes, ... - } @ inputs: - inputs.flake-parts.lib.mkFlake {inherit inputs;} { - imports = [beam-flakes.flakeModule]; - flake = { - lib = { - mkExpert = {erlang}: erlang.callPackage ./nix/expert.nix {}; - }; - }; + }: let + inherit (nixpkgs.lib) genAttrs; + inherit (nixpkgs.lib.systems) flakeExposed; - systems = import systems; + forAllSystems = f: + genAttrs flakeExposed ( + system: let + pkgs = import nixpkgs {inherit system;}; + in + f pkgs + ); + in { + imports = [beam-flakes.flakeModule]; - perSystem = {pkgs, ...}: let - erlang = pkgs.beam.packages.erlang_25; - expert = self.lib.mkExpert {inherit erlang;}; - in { - formatter = pkgs.alejandra; + lib = { + mkExpert = { + erlang, + system, + elixir ? erlang.elixir, + hash ? builtins.readFile ./nix/hash, + }: + erlang.callPackage ./nix/expert.nix {inherit elixir hash;}; + }; - apps.update-hash = let - script = pkgs.writeShellApplication { - name = "update-hash"; + formatter = forAllSystems ({alejandra}: alejandra); - runtimeInputs = [pkgs.nixFlakes pkgs.gawk]; + apps.update-hash = forAllSystems (pkgs: let + script = pkgs.writeShellApplication { + name = "update-hash"; - text = '' - nix --extra-experimental-features 'nix-command flakes' \ - build --no-link "${self}#__fodHashGen" 2>&1 | gawk '/got:/ { print $2 }' || true - ''; - }; - in { - type = "app"; - program = "${script}/bin/update-hash"; - }; + runtimeInputs = [pkgs.nixFlakes pkgs.gawk]; - packages = { - inherit expert; - default = expert; + text = '' + nix --extra-experimental-features 'nix-command flakes' \ + build --no-link "${self}#__fodHashGen" 2>&1 | gawk '/got:/ { print $2 }' || true + ''; + }; + in { + type = "app"; + program = "${script}/bin/update-hash"; + }); - __fodHashGen = expert.mixFodDeps.overrideAttrs (final: curr: { - outputHash = pkgs.lib.fakeSha256; - }); - }; - beamWorkspace = { - enable = true; - devShell.languageServers.elixir = false; - devShell.languageServers.erlang = false; - versions = { - elixir = "1.17.3"; - erlang = "27.3.4.1"; - }; - devShell.extraPackages = with pkgs; [ - zig - xz - just - _7zz - ]; + packages = forAllSystems (pkgs: let + # burrito doesnt have newest OTP26 releases version + erlang_26 = pkgs.beam.interpreters.erlang.override rec { + version = "26.2.5.9"; + src = pkgs.fetchFromGitHub { + owner = "erlang"; + repo = "otp"; + rev = "OTP-${version}"; + sha256 = "sha256-FRNVmaeBUCFLmfhE9JVb1DgC/MIoryDV7lvh+YayRNA="; }; }; - }; + expert = self.lib.mkExpert { + erlang = pkgs.beam.packagesWith erlang_26; + system = pkgs.system; + }; + in { + inherit expert; + default = expert; + + __fodHashGen = expert.mixFodDeps.overrideAttrs (final: curr: { + outputHash = pkgs.lib.fakeSha256; + }); + }); + beamWorkspace = forAllSystems (pkgs: { + enable = true; + devShell.languageServers.elixir = false; + devShell.languageServers.erlang = false; + versions = { + elixir = "1.17.3"; + erlang = "27.3.4.1"; + }; + devShell.extraPackages = with pkgs; [ + zig + xz + just + _7zz + ]; + }); + }; } diff --git a/nix/expert.nix b/nix/expert.nix index 7fcf4f18..c04ea213 100644 --- a/nix/expert.nix +++ b/nix/expert.nix @@ -1,43 +1,152 @@ { + lib, mixRelease, fetchMixDeps, elixir, + hash ? builtins.readFile ./hash, writeScript, + makeWrapper, + git, + cacert, + zig, + xz, + _7zz, + system, }: mixRelease rec { pname = "expert"; version = "development"; - src = ./..; + src = lib.cleanSource ./..; mixFodDeps = fetchMixDeps { - inherit pname; - inherit version; + pname = "mix-deps-${pname}"; + inherit src version hash; + mixEnv = "prod"; - src = ./..; + # Fix SSL issues for git dependencies + nativeBuildInputs = [git cacert]; + GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt"; + SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt"; - sha256 = builtins.readFile ./hash; + installPhase = '' + runHook preInstall + cd apps/expert; mix deps.get ''${MIX_ENV:+--only $MIX_ENV}; cd -; + find "$TEMPDIR/deps" -path '*/.git/*' -a ! -name HEAD -exec rm -rf {} + + cp -r --no-preserve=mode,ownership,timestamps $TEMPDIR/deps $out + runHook postInstall + ''; }; + nativeBuildInputs = [ + makeWrapper + git + cacert + zig + xz + _7zz + ]; + + MIX_ENV = "prod"; + EXPERT_RELEASE_MODE = "burrito"; + + # SSL certificates for git operations + # GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt"; + # SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt"; + + # Simple configurePhase - work from expert app and let Mix handle everything + configurePhase = '' + runHook preConfigure + export MIX_HOME=$TEMPDIR/.mix + export HEX_HOME=$TEMPDIR/.hex + cd apps/expert + mix deps.compile --no-deps-check + runHook postConfigure + ''; + + buildPhase = let + burritoTarget = + { + "aarch64-darwin" = "darwin_arm64"; + "x86_64-darwin" = "darwin_amd64"; + "aarch64-linux" = "linux_arm64"; + "x86_64-linux" = "linux_amd64"; + }."${system}" or (throw "Unsupported system: ${system}"); + in '' + runHook preBuild + export BURRITO_TARGET=${burritoTarget} + export HOME=$TMPDIR/home + export XDG_CACHE_HOME=$TMPDIR/cache + mkdir -p $HOME $XDG_CACHE_HOME + ln -sf ../../deps ../engine/deps + ln -sf ../../deps ../forge/deps + mix compile --no-deps-check + mix release expert --overwrite --path ./release_build + runHook postBuild + ''; + installPhase = '' runHook preInstall + mkdir -p $out + cp -r release_build/* $out/ - mix do compile --no-deps-check, package --path "$out" + # Handle burrito output if it exists + if [ -d "burrito_out" ]; then + mkdir -p $out/burrito_out + cp -r burrito_out/* $out/burrito_out/ + fi + + find $out -type l -exec test ! -e {} \; -delete runHook postInstall ''; preFixup = let activate_version_manager = writeScript "activate_version_manager.sh" '' - true + #!/usr/bin/env bash + true ''; + + burritoBinary = + { + "aarch64-darwin" = "expert_darwin_arm64"; + "x86_64-darwin" = "expert_darwin_amd64"; + "aarch64-linux" = "expert_linux_arm64"; + "x86_64-linux" = "expert_linux_amd64"; + }."${system}" or null; in '' - substituteInPlace "$out/bin/start_expert.sh" --replace 'elixir_command=' 'elixir_command="${elixir}/bin/"' - rm "$out/bin/activate_version_manager.sh" - ln -s ${activate_version_manager} "$out/bin/activate_version_manager.sh" + # Fix paths in start script + if [ -f "$out/bin/start_expert.sh" ]; then + substituteInPlace "$out/bin/start_expert.sh" \ + --replace 'elixir_command=' 'elixir_command="${elixir}/bin/"' - mv "$out/bin" "$out/binsh" + rm -f "$out/bin/activate_version_manager.sh" + ln -s ${activate_version_manager} "$out/bin/activate_version_manager.sh" - makeWrapper "$out/binsh/start_expert.sh" "$out/bin/expert" --set RELEASE_COOKIE expert + mv "$out/bin" "$out/binsh" + makeWrapper "$out/binsh/start_expert.sh" "$out/bin/expert" \ + --set RELEASE_COOKIE expert + fi + + # Use Burrito binary if it exists for this system + if [ -n "${burritoBinary}" ] && [ -f "$out/burrito_out/${burritoBinary}" ]; then + mkdir -p $out/bin + cp "$out/burrito_out/${burritoBinary}" "$out/bin/expert" + chmod +x "$out/bin/expert" + fi + + # Copy Erlang cookie so distributed mode works + if [ -f "$out/releases/COOKIE" ]; then + mkdir -p $out/var + cp "$out/releases/COOKIE" "$out/var/COOKIE" + chmod 600 "$out/var/COOKIE" + fi ''; + + # meta = with lib; { + # description = "Expert - Elixir Language Server"; + # homepage = "https://github.com/elixir-lang/expert"; + # license = licenses.mit; + # platforms = platforms.unix; + # }; } diff --git a/nix/hash b/nix/hash index aea3a2db..91c083ba 100644 --- a/nix/hash +++ b/nix/hash @@ -1 +1 @@ -sha256-ojl0uUaODC4pJDGY/Mv8prdkorhQ2PAnWNTx9vXUkfc= +sha256-8fdC0LO0W0pChaINkGm1STEemRGVy9B0fHcJffsbziI= From c47bdeda89661a3c7684439d658e6576801b5082 Mon Sep 17 00:00:00 2001 From: Zoey Pessanha Date: Sat, 30 Aug 2025 01:35:11 -0300 Subject: [PATCH 2/3] feat: add nix overlays for default version --- flake.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flake.nix b/flake.nix index 1f8f7bf3..65aabf33 100644 --- a/flake.nix +++ b/flake.nix @@ -51,6 +51,12 @@ program = "${script}/bin/update-hash"; }); + overlays = { + default = final: _prev: { + expert-lsp = self.packages.${final.system}.expert; + }; + }; + packages = forAllSystems (pkgs: let # burrito doesnt have newest OTP26 releases version erlang_26 = pkgs.beam.interpreters.erlang.override rec { From 23ab14d5547b7903218dea8cd598582e57e6310d Mon Sep 17 00:00:00 2001 From: Zoey Pessanha Date: Sat, 30 Aug 2025 02:13:29 -0300 Subject: [PATCH 3/3] chore: remove unecessary nix deps inputs and comments --- nix/expert.nix | 42 +++++++++++------------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/nix/expert.nix b/nix/expert.nix index c04ea213..c73d1d58 100644 --- a/nix/expert.nix +++ b/nix/expert.nix @@ -6,17 +6,17 @@ hash ? builtins.readFile ./hash, writeScript, makeWrapper, - git, - cacert, zig, xz, _7zz, system, }: mixRelease rec { + MIX_ENV = "prod"; + EXPERT_RELEASE_MODE = "burrito"; + pname = "expert"; version = "development"; - src = lib.cleanSource ./..; mixFodDeps = fetchMixDeps { @@ -24,11 +24,6 @@ mixRelease rec { inherit src version hash; mixEnv = "prod"; - # Fix SSL issues for git dependencies - nativeBuildInputs = [git cacert]; - GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt"; - SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt"; - installPhase = '' runHook preInstall cd apps/expert; mix deps.get ''${MIX_ENV:+--only $MIX_ENV}; cd -; @@ -38,23 +33,8 @@ mixRelease rec { ''; }; - nativeBuildInputs = [ - makeWrapper - git - cacert - zig - xz - _7zz - ]; + nativeBuildInputs = [makeWrapper zig xz _7zz]; - MIX_ENV = "prod"; - EXPERT_RELEASE_MODE = "burrito"; - - # SSL certificates for git operations - # GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt"; - # SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt"; - - # Simple configurePhase - work from expert app and let Mix handle everything configurePhase = '' runHook preConfigure export MIX_HOME=$TEMPDIR/.mix @@ -90,7 +70,6 @@ mixRelease rec { mkdir -p $out cp -r release_build/* $out/ - # Handle burrito output if it exists if [ -d "burrito_out" ]; then mkdir -p $out/burrito_out cp -r burrito_out/* $out/burrito_out/ @@ -143,10 +122,11 @@ mixRelease rec { fi ''; - # meta = with lib; { - # description = "Expert - Elixir Language Server"; - # homepage = "https://github.com/elixir-lang/expert"; - # license = licenses.mit; - # platforms = platforms.unix; - # }; + meta = with lib; { + description = "Official Elixir Language Server Protocol implementation"; + repository = "https://github.com/elixir-lang/expert"; + homepage = "https://expert-lsp.org"; + license = licenses.mit; + platforms = platforms.unix; + }; }