0

I'm working on a C++ project using ccls (the LSP language server) and lsp-mode in Emacs. I also have a CMake project definition for my project. My project builds correctly with make using the Makefile generated by CMake, but ccls says that my #include is not found.

Here's the project structure:

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

The CMakeLists.txt file looks like this:

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
  )

This generates the following compile_commands.json (which is what ccls uses):

[
{
  "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 looks like this:

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

src/SomeClass.hpp looks like this:

#include "SomeClass.hpp"

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

And main.cpp looks like this:

#include "SomeClass.hpp"

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

It's in main.cpp where I get the error from LSP. It says 'SomeClass.hpp' file not found.

So why is ccls not able to find this include?

ironchicken
  • 754
  • 6
  • 19

2 Answers2

2

ccls tries to find SomeClass.hpp in the root of your project. It should be fine when you change the first line of your main.cpp to this (At least for me it resolved the error):

#include "src/SomeClass.hpp" 
  • I perhaps should have made this clear in my question: I want to _not_ have to use the `src/` path in the `#include` because it's handled by the `CMakeLists.txt` file. I'm seeing it as redundant in the `#include`. `ccls` is able to find vendor libraries that live outside my project and I'm hoping that it should be able to do the same with my internal "library". – ironchicken Feb 21 '22 at 17:38
  • I've just tried configuring `lsp-mode` to use `clangd` instead of `ccls` and now this `#include` is not flagged as an error. – ironchicken Feb 23 '22 at 07:41
  • Happy to hear that you could resolve your problem! I thought that I have tried your example code both with `ccls` and `clangd` and saw no difference but maybe I am wrong. :) – user18269798 Feb 24 '22 at 20:22
0

The solution I used was to use clangd instead of ccls.

In Emacs with lsp-mode I didn't find it super obvious how to set this up. lsp-mode doesn't seem to have a way of specifying which language server (or "client") you want to use for a language when there's more than one available. Instead, it has a kind of denylist of language servers you don't want to use. So my C++ Emacs set up now looks like this:

(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)
ironchicken
  • 754
  • 6
  • 19