Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ apps/forge/src/future_elixir_parser.erl
**/burrito_out

.notes/

# Nix files
result
50 changes: 17 additions & 33 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

133 changes: 79 additions & 54 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,97 @@

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
];
};
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 {
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
];
});
};
}
117 changes: 103 additions & 14 deletions nix/expert.nix
Original file line number Diff line number Diff line change
@@ -1,43 +1,132 @@
{
lib,
mixRelease,
fetchMixDeps,
elixir,
hash ? builtins.readFile ./hash,
writeScript,
makeWrapper,
zig,
xz,
_7zz,
system,
}:
mixRelease rec {
MIX_ENV = "prod";
EXPERT_RELEASE_MODE = "burrito";

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 = ./..;

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 zig xz _7zz];

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"
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 = "Official Elixir Language Server Protocol implementation";
repository = "https://github.com/elixir-lang/expert";
homepage = "https://expert-lsp.org";
license = licenses.mit;
platforms = platforms.unix;
};
}
2 changes: 1 addition & 1 deletion nix/hash
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sha256-ojl0uUaODC4pJDGY/Mv8prdkorhQ2PAnWNTx9vXUkfc=
sha256-8fdC0LO0W0pChaINkGm1STEemRGVy9B0fHcJffsbziI=
Loading