Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Omnisharp does not find Unity3D assemblies #1948

Closed
HiPhish opened this issue Sep 17, 2020 · 31 comments
Closed

Omnisharp does not find Unity3D assemblies #1948

HiPhish opened this issue Sep 17, 2020 · 31 comments

Comments

@HiPhish
Copy link

HiPhish commented Sep 17, 2020

Hello,

I am trying to get Omnisharp to work with a Unity3D project on GNU/Linux (Kubuntu 20.04). My editor is Neovim 0.5 (pre-release) which includes its own LSP client. Neovim downloaded the latest Omnisharp release (1.37.1). The server is working, I am getting diagnostic messages, documentation and code completion, but it acts as if it does not know anything about Unity.

  • mono --version shows 6.8.0.105 for the globally installed Mono
  • The launch command used by Neovim is ~/.cache/nvim/nvim_lsp/omnisharp/run --languageserver --hostPID <PID of Neovim process>

I would assume that Omnisharp uses its bundled Mono. How can I get Omnisharp to produce log files, and where can I find them?

Screenshot_20200917_183504

@snowgoon88
Copy link

My ultimate goal is nearly the same : use emacs+lsp on Unity files. (see #1947)
I got some debug by manually running omnisharp with ./run -s <project_root_path> -v > logfile (and then killing the server process once messages where logged in the file). Not sure it is the best way.

@R0flcopt3r
Copy link

Go to /usr/lib/mono and check what the latest version you have, then set FrameworkPathOverride to point to that folder.

For me it's worked setting it to both /usr/lib/mono/4.5 and /usr/lib/mono/4.8-api.

export FrameworkPathOverride=/lib/mono/4.5

@snowgoon88
Copy link

I have not yet tried this solution (and I will) but..
I did manage to get it working on Emacs by modifying the run script in omnisharp-roselyn to take into account the globally installed mono if present and if the version is high enough.

Everything is here : emacs-lsp/lsp-mode#2188 (comment)

@ericdallo
Copy link

I have the issue with emacs lsp-mode, @razzmatazz do you know what could it be?

@razzmatazz
Copy link
Contributor

razzmatazz commented Sep 21, 2020

I have the issue with emacs lsp-mode, @razzmatazz do you know what could it be?

I am afraid I have no experience with Unity. My question is, does vscode manage to do it better, and if they do (and they are by far the most popular client for omnisharp-roslyn IMHO) -- then we can replicate the solutions in lsp-mode by looking at the workarounds/framework/mono discovery code VS Code does.

@filipw
Copy link
Member

filipw commented Sep 21, 2020

When OmniSharp starts on its own embedded Mono it will have no reference assemblies for desktop ..NET and Unity and other non-.NET Core development won't work or be limited.

In VS Code there is a setting to start OmniSharp on global Mono instead and that allows full compatibility with all desktop .NET development. I would imagine in this case a setting like this is needed too.

However, I don't think this is an issue for OmniSharp itself as it already provides the necessary tools for achieving this - it's just the client must make the decisions, therefore I would recommend to move this issue to the client implementation(s).

@nickspoons
Copy link
Member

How does VSCode do this, @filipw? Is it a command line flag passed to the server? Or are you referring to omnisharp.json settings?

@snowgoon88
Copy link

On VS code (Linux), I tried playing with setting ALWAYS use global mono and setting the path to the global mono (it is done via a .json file) and then restart the server several times (with the command palette of VS code). But it does not work : Unity referenced functions/classes are not recognized.

With Emacs (Linux, and my run file), it works in two steps : open the .cs file -> server started once with global mono. Then, I restart the server from Emacs (using lsp-mode) and it work.

So, I guess the issus is client depend, sadly...

@filipw
Copy link
Member

filipw commented Sep 21, 2020

@nickspoons there is a setting omnisharp.useGlobalMono which can be set to always. It then uses global Mono form the PATH to start OmniSharp.exe process. Additionally a custom path can be provided too. https://github.com/OmniSharp/omnisharp-vscode/blob/97768562a4f950db687d5d9314da4a854c9e6f4c/src/omnisharp/launcher.ts#L264-L277

@snowgoon88 if you have trouble with VS Code, please open an issue in https://github.com/OmniSharp/omnisharp-vscode and provide your OmniSharp log with omnisharp.logginglevel: "debug" enabled.

@ericdallo
Copy link

Thanks for the help everybody, I tested with emacs and vscode using the useGlobalMono and pointing to mono6 path, but it didn't work too, but I think it's my OS's fault. I use NixOS, and my mono global installation does not have msbuild updated.

@filipw
Copy link
Member

filipw commented Sep 21, 2020

ah that could be - not every mono distro has MSBuild bundled

@ericdallo
Copy link

FTR this issue is related: NixOS/nixpkgs#95911

@HiPhish
Copy link
Author

HiPhish commented Sep 21, 2020

Thank you everyone for your input. To summarize, the issue is that the bundled Mono cannot find any 3rd party assemblies at all. It is the responsibility of the client to start the server with a global Mono installation. I have for now modified the run script to change one variable:

bin_dir=/usr/bin  # Previous value: ${base_dir}/bin

That way when the run script starts the server ("${mono_cmd}" "${omnisharp_cmd}" "$@") it will use usr/bin/mono as the Mono binary.

Now the next question is how to tell the server which Mono to use. From looking at the run script there does not appear to be any way of passing a command-line option or environment variable to the script. So I figure the best course of action would be to forego the run script altogether and just invoke mono and omnisharp directly. From the looks of it the script does not really do much anyway.

Is this the correct way? From what I can understand the VS Code plugin does the same. Please correct me if I'm wrong, I don't actually know TypeScript, so I'm just taking an educated step.

Screenshot_20200921_190746

@ericdallo
Copy link

ericdallo commented Sep 22, 2020

For NixOS users I fixed with this: NixOS/nixpkgs#98435, basically, the msbuild inside the omnisharp does not work for unity, that's why using a global mono works for everybody.
Thanks for the help @filipw

@filipw
Copy link
Member

filipw commented Jan 22, 2021

I will close this because at the end, this is by design - OmniSharp doesn't ship with reference assemblies for .NET Framework. we will add a better error message in #2029 so that it's clear that full Mono is needed when reference assemblies are not found

@filipw filipw closed this as completed Jan 22, 2021
@axelson
Copy link

axelson commented Jan 27, 2021

@nickspoons there is a setting omnisharp.useGlobalMono which can be set to always. It then uses global Mono form the PATH to start OmniSharp.exe process. Additionally a custom path can be provided too. https://github.com/OmniSharp/omnisharp-vscode/blob/97768562a4f950db687d5d9314da4a854c9e6f4c/src/omnisharp/launcher.ts#L264-L277

Is that setting part of the configuration for omnisharp-roslyn? I don't see it documented on the configuration page: https://github.com/OmniSharp/omnisharp-roslyn/wiki/Configuration-Options

Or is it VSCode specific or something else?

@nickspoons
Copy link
Member

@axelson That's a VSCode setting, regarding how the OmniSharp-roslyn process is started.

@HiPhish
Copy link
Author

HiPhish commented Jan 28, 2021

Is there a way of setting this option outside of VSCode as well? Like a command-line parameter, environment variable or configuration file?

@ndavd
Copy link

ndavd commented Feb 1, 2021

Hi I'm on Windows using nvim lspconfig omnisharp language server. It doesn't recognize the assemblies as well. When loading a basic script it says that it couldn't find monobehavior class

@Mathijs-Bakker
Copy link
Contributor

Mathijs-Bakker commented Feb 3, 2021

@HiPhish Thanks!

Mono binaries on latest MacOS's are installed elsewhere..
Thought I post it here as it could be of any help for others.

bin_dir=/Library/Frameworks/Mono.framework/Versions/Current/bin

Schermafbeelding 2021-02-03 om 23 47 35

Note: Unity doesn't generate .sln and .csproj files. So for Neovim you have to create them yourself, in case of new projects. Or open a .cs file in VS or Rider and let them auto generate it for you.

@harrisonmg
Copy link

harrisonmg commented Oct 20, 2021

I'm having the same issue as @HiPhish, omnisharp with neovim LSP. Omnisharp works but acts like all Unity related things don't exist. This thread was helpful but didn't get me all the way home. My details:

mono: 6.12.0.147
msbuild: 16.10.1
omnisharp run script:

#!/usr/bin/env bash

base_dir="/opt/omnisharp"
bin_dir=${base_dir}/bin
etc_dir=${base_dir}/etc
omnisharp_dir=${base_dir}/omnisharp

mono_cmd=/usr/bin/mono

config_file=/etc/mono/config

omnisharp_cmd=${omnisharp_dir}/OmniSharp.exe
no_omnisharp=false

export MONO_CFG_DIR=${etc_dir}
export MONO_ENV_OPTIONS="--assembly-loader=strict --config ${config_file}"
export FrameworkPathOverride=/lib/mono/4.8-api # this line doesn't seem to change anything, neither does ../4.5

"${mono_cmd}" "${omnisharp_cmd}" "$@"

The only thing in my lsp.log is a bunch of

[WARN][2021-10-20 16:19:00] ...lsp/handlers.lua:401     "OmniSharp.Extensions.LanguageServer.Server.LspServerOutputFilter: Tried to send request or notification before initialization was completed and will be sent later OmniSharp.Extensions.JsonRpc.Client.OutgoingNotification | @Request='OmniSharp.Extensions.JsonRpc.Client.OutgoingNotification'"

until the server initializes after a number of minutes.

Anything else I can try? Thanks!

EDIT: Also, I've manually generated .csproj files through the Unity editor for the following categories: embedded packages, local packages, registry packages, and built-in packages. I've experimented with other combinations to no avail.

@morabitom
Copy link

@harrisonmg I had better luck by avoiding the run script entirely, I tried to mess with it quite a bit like you did. Here is the way I setup the server with nvim, instead of calling the run script I call omnisharp using global mono directly.

locallspconfig = require "lspconfig"
local pid = vim.fn.getpid()
local omnisharp_bin = "/home/mark/.local/share/nvim/lsp_servers/omnisharp/omnisharp/omnisharp/OmniSharp.exe" 

return {
    cmd = { "mono", omnisharp_bin, "--languageserver","--hostPID", tostring(pid) },
    filetypes = { "cs", "vb" },
    init_options = {},
    on_new_config = function(new_config, new_root_dir)
          if new_root_dir then
            table.insert(new_config.cmd, '-s')
            table.insert(new_config.cmd, new_root_dir)
          end
        end,
    root_dir = lspconfig.util.root_pattern("*.sln");
}

@willparsons
Copy link

I still get the same issue that MonoBehaviour and other Unity types cannot be found. Even with the fix that @HiPhish gave.

@nyngwang
Copy link

@HiPhish @Mathijs-Bakker With dotnet-6.0 since there is no script file run, all the solutions on this thread didn't work for me :(

@filipw
Copy link
Member

filipw commented Feb 14, 2022

.NET 6.0 build of OmniSharp does not support Unity.

@nyngwang
Copy link

nyngwang commented Feb 14, 2022

.NET 6.0 build of OmniSharp does not support Unity.

Edit: ^ This info turns out to be very helpful for my debugging. And for people who don't know, the [Mono build of OmniSharp] mentioned in the following comment is this one: omnisharp-mono.tar.gz

@filipw
Copy link
Member

filipw commented Feb 14, 2022

The Mono build of OmniSharp, but started with global Mono installation from your machine (not the lightweight Mono OmniSharp ships with).

@nyngwang
Copy link

@harrisonmg I had better luck by avoiding the run script entirely, I tried to mess with it quite a bit like you did. Here is the way I setup the server with nvim, instead of calling the run script I call omnisharp using global mono directly.

locallspconfig = require "lspconfig"
local pid = vim.fn.getpid()
local omnisharp_bin = "/home/mark/.local/share/nvim/lsp_servers/omnisharp/omnisharp/omnisharp/OmniSharp.exe" 

return {
    cmd = { "mono", omnisharp_bin, "--languageserver","--hostPID", tostring(pid) },
    filetypes = { "cs", "vb" },
    init_options = {},
    on_new_config = function(new_config, new_root_dir)
          if new_root_dir then
            table.insert(new_config.cmd, '-s')
            table.insert(new_config.cmd, new_root_dir)
          end
        end,
    root_dir = lspconfig.util.root_pattern("*.sln");
}

@morabitom Thank you so much! This works! I'm on the newest version v1.38.0.

@harrisonmg
Copy link

@harrisonmg I had better luck by avoiding the run script entirely, I tried to mess with it quite a bit like you did. Here is the way I setup the server with nvim, instead of calling the run script I call omnisharp using global mono directly.

locallspconfig = require "lspconfig"
local pid = vim.fn.getpid()
local omnisharp_bin = "/home/mark/.local/share/nvim/lsp_servers/omnisharp/omnisharp/omnisharp/OmniSharp.exe" 

return {
    cmd = { "mono", omnisharp_bin, "--languageserver","--hostPID", tostring(pid) },
    filetypes = { "cs", "vb" },
    init_options = {},
    on_new_config = function(new_config, new_root_dir)
          if new_root_dir then
            table.insert(new_config.cmd, '-s')
            table.insert(new_config.cmd, new_root_dir)
          end
        end,
    root_dir = lspconfig.util.root_pattern("*.sln");
}

Thanks, but no dice. I don't know what else I could be doing wrong. I'm using the Mono build of OmniSharp mentioned by @nyngwang and mono 6.8.0.105 (though 6.12.0.147 also didn't work).

I still get a load of

"OmniSharp.Extensions.LanguageServer.Server.LspServerOutputFilter: Tried to send request or notification before initialization was completed and will be sent later OmniSharp.Extensions.JsonRpc.Client.OutgoingNotification | @Request='OmniSharp.Extensions.JsonRpc.Client.OutgoingNotification'"

messages until the server eventually initializes after an unacceptably long few minutes (perhaps because of all the type or namespace not found errors?)

This is driving me nuts.

@nyngwang
Copy link

nyngwang commented May 15, 2022

@harrisonmg Which Omnisharp release exactly did you install on your computer? Have had a long time not writing C# but I might also check it later.

@harrisonmg
Copy link

harrisonmg commented May 15, 2022

Currently I have installed mono version 6.12.0.122 using these instructions and doing sudo apt install mono-complete.

Edit: on Ubuntu 20.04.4 LTS, running in WSL

Thanks for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests