Where to put my custom lsp binary written in go

Hi community!

I’m coding an language server in go as a personal project and I want to run it on Helix my code editor but I can’t find out where and how to place my binary file. I guess that Helix looks for that file in a /bin folder but we all now that Nixos works differently. How can I build my binary using nix and get its path so Helix can load it? Maybe buildGoModule is useful in this case but as a nixos fresh user I want to get some input from the community please.

Currently, Helix doesn’t get the path any path I put in /home. That makes me think that for some reason nixos store is the answer but I’m not about it.

Did you configure it in your languages.toml?

Depends on how you setup the start command in your LSP client.

But in my opinion, any setup that requires or only considers hard coded paths, instead of resolving binary names in PATH is plain broken.

So configure helix to look in PATH, and then provide the LSP through PATH, be it by environment.systemPackages, home.packages, nix-env -i, nix profile install, nix shell, or a declarative devshell, with or without flakes.

1 Like

Yeah! I did it in a couple of ways but I’m sure this has to do with Helix not being able to see the binary. Thanks for taking time :slight_smile:

Yeah! I need to find out how to make the binary visible by including it in PATH. Thanks for the hint!

Alright I wrote this nix expression based on this example:

let
  pkgs = import <nixpkgs>{};
in
pkgs.buildGoModule(finalAttrs: {
  pname = "cslsp";
  version = "0.1";

  src = ./.;
  vendorHash = null;

})

I got a store binary by running nix build -f myfile without any issue but I don’t know exactly how to add it to PATH. I did a bit of research an found that buildInputs should be the answer however I don’t know how to do it. At this point I fell I’m just shooting in the dark so I’d better dig a bit deeper into dev shells to understand them better. If anybody has reading material to read, please by all means. More than I solution I’m always grateful, learning how nix works in this case is super valuable

Assuming nix build gave you an output derivation which provides binaries.

What you describe as PATH can have different realisations, I lack a better term here, depending on what you choose.

A few possibilities as you already know:

  • buildInputs, nativeBuildInputs of another derivation, i.e., just buildInputs = [ (callPackage ./yourdrvsrc {}) ]
  • environment.systemPackages of configuration.nix
  • home.packages of home.nix

All these basically would add certain subfolders, i.e., bin of your original derivation’s nix store path to, i.e., the PATH of the context the according program is launched in.

You can as well select yourself the binary aka lib.getExe pkgs.yourdrv or in your case something akin to lib.getExe (callPackage ./yourdrvsrc {}) or if the binary has a name different from the derivation itself or there are multiple binaries lib.getExe’ pkgs.yourdrv “binaryname”.

Thanks! I added buildInputs = [(callPackage ./yourdrvsrc{}) to my shell.nix file in the following way:

{pkgs ? import <nixpkgs>{}}:  
pkgs.mkShell {
  packages = with pkgs; [
    go gopls golangci-lint delve gotools 
  ]; 
  buildInputs = [(pkgs.callPackage ./lspbuilder.nix)];
  hardeningDisable = ["fortify"];
  shellHook = ''nu'';
}

I did this because I think it’s the right answer to my question. However, it outputs this:

error:
       … while calling the 'derivationStrict' builtin
         at «nix-internal»/derivation-internal.nix:37:12:
           36|
           37|   strict = derivationStrict drvAttrs;
             |            ^
           38|

       … while evaluating derivation 'nix-shell'
         whose name attribute is located at /nix/store/gw7fxaw8z5szcqlzyzcnrshzi60zj664-source/pkgs/stdenv/generic/make-derivation.nix:651:11

       … while evaluating attribute 'buildInputs' of derivation 'nix-shell'
         at /nix/store/gw7fxaw8z5szcqlzyzcnrshzi60zj664-source/pkgs/stdenv/generic/make-derivation.nix:722:11:
          721|           depsHostHost = hostHostOutputs;
          722|           buildInputs = hostTargetOutputs;
             |           ^
          723|           depsTargetTarget = targetTargetOutputs;

       (stack trace truncated; use '--show-trace' to show the full, detailed trace)

       error: Dependency is not of a valid type: element 1 of buildInputs for nix-shell

Where ./lspbuilder.nix is:

let
  pkgs = import <nixpkgs>{};
in
pkgs.buildGoModule(finalAttrs: {
  pname = "cslsp";
  version = "0.1";

  src = ./.;
  vendorHash = null;
})

What is a dependency type in this case? What sort of dependency types do we have in NixOS?

I missed curly braces in buildInputs = [(pkgs.callPackage ./lspbuilder.nix)]; line. However, when I put them where they should I get:

error:
       … while calling the 'derivationStrict' builtin
         at «nix-internal»/derivation-internal.nix:37:12:
           36|
           37|   strict = derivationStrict drvAttrs;
             |            ^
           38|

       … while evaluating derivation 'nix-shell'
         whose name attribute is located at /nix/store/gw7fxaw8z5szcqlzyzcnrshzi60zj664-source/pkgs/stdenv/generic/make-derivation.nix:651:11

       … while evaluating attribute 'buildInputs' of derivation 'nix-shell'
         at /nix/store/gw7fxaw8z5szcqlzyzcnrshzi60zj664-source/pkgs/stdenv/generic/make-derivation.nix:722:11:
          721|           depsHostHost = hostHostOutputs;
          722|           buildInputs = hostTargetOutputs;
             |           ^
          723|           depsTargetTarget = targetTargetOutputs;

       (stack trace truncated; use '--show-trace' to show the full, detailed trace)

       error: 'functionArgs' requires a function

I’m right now a frustrated beginner, so please be patient. What’s 'functionArgs' in this case?

Adjust your lspbuilder.nix to be a function:

{buildGoModule}:
buildGoModule (finalAttrs: {
  pname = "cslsp";
  version = "0.1";

  src = ./.;
  vendorHash = null;
})
{pkgs ? import <nixpkgs> {}}:
pkgs.mkShell {
  packages = with pkgs; [
    go
    gopls
    golangci-lint
    delve
    gotools

    (callPackage ./lspbuilder.nix {})
  ];
}
3 Likes

Hi! Thanks a lot for taking time :slight_smile: This was the last bit I was missing

Cheers!

1 Like