Doom Emacs에 CSharp 개발 환경 구축하기
doom emacs로 설정하는 방법을 설명한다. doom emacs 설정 프레임워크를 사용하지 않는다면 doom emacs 모듈에서 사용하는 패키지 정보를 참고해서 구축하면 된다.
(doom!
:tools
lsp ; M-x vscode
:lang
(csharp +dotnet +lsp) ; unity, .NET, and mono shenanigans
)
lsp module과 csharp module을 추가한다.
.NET SDK 설치
.NET 다운로드 페이지에서 원하는 버전의 SDK를 다운로드 받아서 설치한다.
$ dotnet --info
.NET SDK (reflecting any global.json):
Version: 6.0.400
Commit: 7771abd614
런타임 환경:
OS Name: Mac OS X
OS Version: 12.5
OS Platform: Darwin
RID: osx.12-arm64
Base Path: /usr/local/share/dotnet/sdk/6.0.400/
global.json file:
Not found
Host:
Version: 6.0.8
Architecture: arm64
Commit: 55fb7ef977
.NET SDKs installed:
6.0.400 [/usr/local/share/dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.8 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.8 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Download .NET:
https://aka.ms/dotnet-download
Learn about .NET Runtimes and SDKs:
https://aka.ms/dotnet/runtimes-sdk-info
omnisharp-roslyn 설치
visual studio가 부럽지 않을 .NET 개발 플랫폼 백엔드를 설치해야 한다. 부럽지 않다는 건 사실 거짓말. C#은 visual studio가 최고다. emacs 사랑으로 커버할 수 있을 정도로 C# 언어 서비스를 제공할 수 있는 백엔드가 필요하다.
csharp-ls, omnisharp-roslyn 이렇게 두 가지 선택지가 있다. 대세로 보이는 omnisharp-roslyn
을 설치한다.
M-x lsp-install-server
자동 설치를 지원한다. 위 명령을 입력하고 omnisharp
를 선택하면 omnisharp-roslyn
을 설치한다.
lsp-mode 패키지 업그레이드
M-x lsp-install-server
자동 설치를 하면 omnisharp-osx.zip
파일을 설치한다. 게다가 macOS에서는 mono를 추가로 설치해야 한다. releases 페이지를 보면 .NET 6 지원에 M1 맥도 지원하는 것처럼 보이는 omnisharp-osx-arm64-net6.0.zip
파일을 설치하려면 어떻게 해야 할까?
(setq lsp-csharp-omnisharp-roslyn-download-url
"https://github.com/OmniSharp/omnisharp-roslyn/releases/download/v1.39.1/omnisharp-osx-arm64-net6.0.zip")
이런 식으로 변수를 세팅하면 될 것 같은데, 우선 최신 소스를 살펴보기로 했다. 얼~ 바뀌었다. M1이면 omnisharp-osx-arm64-net6.0.zip
파일을 다운로드 받는다. 866e9a3ccb1b 커밋에서 변경됐다.
doom emacs의 lsp module에서는 더 예전 버전을 사용하고 있기에 직접 버전을 올려줘야 한다.
(package! lsp-mode :pin "a0e1210f626cb7b5db16a9454d3bf61322d299df")
이렇게 doom emacs 설정을 추가하고
$ doom sync -u
sync 명령을 실행해서 패키지 업데이트를 하게 했다. -u
옵션을 붙여줘야지 내가 업데이트한 lsp-mode 패키지의 pin 커밋 아이디를 체크아웃한다.
/etc/dotnet/install_location
수정 - macOS
이러고 잘 되면 좋으련만 omnisharp-roslyn 실행에 문제가 생겼다.
A fatal error occurred. The required library libhostfxr.dylib could not be found.
If this is a self-contained application, that library should exist in [/Users/ohyecloudy/.emacs.d/.local/etc/lsp/omnisharp-roslyn/latest/omnisharp-roslyn/].
If this is a framework-dependent application, install the runtime in the global location [/usr/local/share/dotnet/x64] or use the DOTNET_ROOT environment variable to specify the runtime location or register the runtime location in [/etc/dotnet/install_location].
The .NET runtime can be found at:
- https://aka.ms/dotnet-core-applaunch?missing_runtime=true&arch=arm64&rid=osx.11.1-arm64&apphost_version=6.0.0-preview.7.21317.1
libhostfxr.dylib
파일을 못 찾아서 에러가 난다. dotnet root를 제대로 찾지 못하는 것 같다.
$ export COREHOST_TRACE=1
디버깅 정보를 출력하게 환경 변수를 세팅하고
$ ./OmniSharp
Tracing enabled @ Fri Sep 2 14:04:26 2022 UTC
--- Invoked apphost [version: 6.0.0-preview.7.21317.1, commit hash: 96a4671bc52e70024da409f5f48b0abaa30cb901] main = {
./OmniSharp
}
The managed DLL bound to this executable is: 'OmniSharp.dll'
Using environment variable DOTNET_ROOT=[/usr/local/share/dotnet/dotnet] as runtime location.
Looking for install_location file in '/etc/dotnet/install_location'.
Using install location '/usr/local/share/dotnet/x64'.
A fatal error occurred. The required library libhostfxr.dylib could not be found.
If this is a self-contained application, that library should exist in [/Users/ohyecloudy/.emacs.d/.local/etc/lsp/omnisharp-roslyn/latest/omnisharp-roslyn/].
If this is a framework-dependent application, install the runtime in the global location [/usr/local/share/dotnet/x64] or use the DOTNET_ROOT environment variable to specify the runtime location or register the runtime location in [/etc/dotnet/install_location].
COREHOST_TRACE
환경 변수 도움이 된다. /etc/dotnet/install_location
파일 내용이 문제였다.
$ cat /etc/dotnet/install_location
/usr/local/share/dotnet/x64
x64 플랫폼으로 설치한 적이 있는데, 그때 남은 찌그래기인가? 아니다 새로 싹 지우고 arm64 플랫폼으로 설치해도 파일 내용이 이렇다.
$ emacs /etc/dotnet/install_location
$ cat /etc/dotnet/install_location
/usr/local/share/dotnet
/usr/local/share/dotnet
디렉터리로 파일 내용을 수정했다.
$ ./OmniSharp
{"Event":"log","Body":{"LogLevel":"INFORMATION","Name":"OmniSharp.Stdio.Host","Message":"Starting OmniSharp on Unknown 0.0 (Unknown)"},"Seq":1,"Type":"event"}
...
잘 된다.
dotnet 6.0으로 컴파일한 omnisharp 바이너리 사용 - windows
(when IS-WINDOWS
(after! lsp-mode
(setq lsp-csharp-omnisharp-roslyn-download-url
(concat "https://github.com/omnisharp/omnisharp-roslyn/releases/latest/download/"
"omnisharp-win-x64-net6.0.zip"
)
)
)
)
windows에서는 omnisharp-win-x64.zip
파일을 다운로드 받고 있어서 직접 지정해서 받게 했다.
잘 되는지 기본 테스트
준비가 됐으면 뭐다? hello world 한 번 찍어봐야 한다. .NET Tutorial - Hello World in 5 minutes를 따라해봤다.
$ dotnet new console -o MyApp -f net6.0
애플리케이션을 만든다.
M-x sharper-main-transient
명령을 실행 후 메뉴에서 Run application
을 실행한다.
Determining projects to restore...
All projects are up-to-date for restore.
MyApp -> /Users/ohyecloudy/src/MyApp/bin/Debug/net6.0/MyApp.dll
Hello, World!
잘 된다. 끝~
org babel 지원
#+begin_src csharp
System.Console.WriteLine("Hello World!");
#+end_src
실행해보니 에러가 난다
/usr/bin/bash: line 1: mono: command not found
/usr/bin/bash: line 1: mcs: command not found
컴파일엔 mcs
를 사용하고 mono 런타임을 사용하기 때문이다. dotnet 6.0을 쓰려고 mono 설치를 안 했는데, 이것 때문에 mono를 쓰긴 싫다.
ob-csharp 코드를 찾아보다 dotnet-script를 사용하는 PR(pull request)를 발견했다. 이걸 써보기로 결정.
dotnet tool install -g dotnet-script
dotnet-script는 쉽게 설치했다.
(require 'ob-cs)
(org-babel-do-load-languages 'org-babel-load-languages
(append org-babel-load-languages
'((cs . t))))
(after! org
(add-to-list 'org-src-lang-modes '("cs" . "csharp")))
doom emacs는 org-contrib 패키지를 사용한다. 여기에 ob-csharp
패키지가 포함되어 있는데, dotnet-script를 사용하는 버전으로 덮어쓰기가 안 된다. 그래서 파일을 복사해 수정해서 직접 로드하게 고쳤다. commit 579d112af. 충돌을 피하려고 csharp
이 아닌 cs
로 정의했다.
#+begin_src cs
var version = Environment.Version;
Console.WriteLine(version.ToString());
#+end_src
#+RESULTS:
: 6.0.8
잘 된다.
링크
- :lang csharp - Doom Emacs v21.08 documentation - docs.doomemacs.org
- :tools lsp - Doom Emacs v21.08 documentation - docs.doomemacs.org
- .NET Downloads (Linux, macOS, and Windows) - dotnet.microsoft.com
- OmniSharp/omnisharp-roslyn - github.com
- dotnet-script/dotnet-script - github.com
- emacs-lsp/lsp-mode/commit/866e9a3ccb1b615b2b624499e8fc1ef8a0a80614 - github.com
- emacsmirror/org-contrib - github.com
- ohyecloudy/dotfiles/commit/579d112af8ec652ad02b4afd3e2ec93534bf79b6 - github.com
- razzmatazz/csharp-language-server - github.com
- thomas-villagers/ob-csharp - github.com
- thomas-villagers/ob-csharp/pull/2 - github.com
- Visual Studio: IDE and Code Editor for Software Developers and Teams - visual…
- Mono - mono-project.com
C-x C-s C-x C-c