CMake 项目构建但在 LSP 中显示包含错误

CMake project builds but shows include error in LSP

我正在使用 Emacs 中的 ccls(LSP 语言服务器)和 lsp-mode 开发一个 C++ 项目。我的项目也有一个 CMake 项目定义。我的项目使用 make 使用 CMake 生成的 Makefile 正确构建,但是 ccls 说找不到我的 #include

项目结构如下:

+ CMakeLists.txt
+ main.cpp
+ src/
|\
| + SomeClass.cpp
| + SomeClass.hpp

CMakeLists.txt 文件如下所示:

cmake_minimum_required(VERSION 3.22)

project(includefail)

set(simple_VERSION_MAJOR 0)
set(simple_VERSION_MINOR 1)

add_executable(
  includefail
  ${CMAKE_SOURCE_DIR}/main.cpp
  ${CMAKE_SOURCE_DIR}/src/SomeClass.cpp
  )

target_include_directories(
  includefail PRIVATE
  ${CMAKE_SOURCE_DIR}/src
  )

这会生成以下 compile_commands.jsonccls 使用的内容):

[
{
  "directory": "/home/user/code/c/include-fail/build",
  "command": "/usr/bin/c++  -I/home/user/code/c/include-fail/src  -o CMakeFiles/includefail.dir/main.cpp.o -c /home/user/code/c/include-fail/main.cpp",
  "file": "/home/user/code/c/include-fail/main.cpp"
},
{
  "directory": "/home/user/code/c/include-fail/build",
  "command": "/usr/bin/c++  -I/home/user/code/c/include-fail/src  -o CMakeFiles/includefail.dir/src/SomeClass.cpp.o -c /home/user/code/c/include-fail/src/SomeClass.cpp",
  "file": "/home/user/code/c/include-fail/src/SomeClass.cpp"
}
]

src/SomeClass.hpp 看起来像这样:

class SomeClass {
public:
    SomeClass();
private:
    int x;
};

src/SomeClass.hpp 看起来像这样:

#include "SomeClass.hpp"

SomeClass::SomeClass() {
    x = 1;
}

main.cpp 看起来像这样:

#include "SomeClass.hpp"

int main(int argc, char* arv[]) {
    SomeClass sc = SomeClass();
    return 0;
}

main.cpp 我从 LSP 得到错误。它说 'SomeClass.hpp' file not found.

那么为什么 ccls 找不到这个包含?

ccls 尝试在项目的根目录中找到 SomeClass.hpp。 当您将 main.cpp 的第一行更改为此时应该没问题(至少对我来说它解决了错误):

#include "src/SomeClass.hpp" 

我使用的解决方案是使用clangd而不是ccls

在带有 lsp-mode 的 Emacs 中,我发现如何设置它不是很明显。 lsp-mode 似乎没有办法在有多种可用语言时指定要为一种语言使用哪种语言服务器(或“客户端”)。相反,它有一种您不想使用的语言服务器的拒绝列表。所以我的 C++ Emacs 设置现在看起来像这样:

(defun my/c++-mode ()
  (setq lsp-disabled-clients '(ccls))
  (setq-default flycheck-disabled-checkers '(c/c++-cppcheck c/c++-gcc))
  (lsp))

(add-hook 'c++-mode-hook 'my/c++-mode)