幫忙改進 C++ LSP 體驗

索引当中都已经是绝对路径了:

└⋊> jq . < ~/.cquery_cached_index/@Volumes@HDD@Users@gqj/Dropbox@scratch@c@[email protected]
{
  "last_modification_time": 1520075011,
  "language": 1,
  "import_file": "/Volumes/HDD/Users/gqj/Dropbox/scratch/c/os-detecting-makefile/main.c",
  "args": [
    "%clang",
    "/Volumes/HDD/Users/gqj/Dropbox/scratch/c/os-detecting-makefile/main.c"
  ],
  "includes": [
    {
      "line": 0,
      "resolved_path": "/usr/include/stdio.h"
    }
  ],
  "dependencies": [...],
  "skipped_by_preprocessor": [...],
  "types": [...],
  "funcs": [...],
  "vars": [...]
}

src/project.cc

这里断点看 config->project_dir 是什么

用环境变量CQUERY_TRACEME=1提早停下 Debugging · jacobdufault/cquery Wiki · GitHub

之后 gdb/lldb attach + continue

从执行的顺序看,早在 initialize.cc:482 cacheDirectory 就已经是 $HOME/.cquery_cached_index/ 了:

L482 request->paramsinitializationOptions是输入,没有修改过。。所以服务端是无辜的

我认为问题在于lsp-methods.el

(defun lsp--start (client &optional extra-init-params)
  (when lsp--cur-workspace
    (user-error "LSP mode is already enabled for this buffer"))
  (cl-assert client)
  (let* ((root (file-truename (funcall (lsp--client-get-root client))))

file-truename展开了symlink

经过调试发现是 projectile 的锅:

ls--start
    |
    + lsp--client-get-root
        |
        +-> cqeury--get-root
            |
            +--> projectile-project-root

projectile-project-root 返回的是 $HOME


解决方法是:

(with-eval-after-load 'projectile
  (setq projectile-project-root-files-top-down-recurring
        (append '("compile_commands.json"
                  ".cquery")
                projectile-project-root-files-top-down-recurring)))

昨天有人改cquery--get-root逻辑 Prevent projectile-project-root from masking subprojects by jaelsasser · Pull Request #21 · cquery-project/emacs-cquery · GitHub

现在的行为:

我希望 ~/Dev/llvm/{projects/lld,tools/clang} 不要被当作 :rootUri ,因此用

    (setq cquery-project-roots '("~/Dev/llvm-project" "~/Dev/llvm"))

更新了cquery, 目前使用功能不正常, 现象为:

  1. 使用.cquery文件时, 无法识别其中的include路径, 响应的头文件和函数定义均被lsp-ui-flycheck报搞找不到.
  2. 使用.cquery文件时, 可以进行函数的定义跳转, 但是无法找到函数的引用列表.
  3. 使用compile_commands.json时, cquery会在初始化的时候崩溃(这里面有个疑问是, cquery崩溃后, 是否有不重启emacs就使cquery重新运行的方法?).
1 个赞

cquery在centos7上编译报错:

 ./waf configure
Setting top to                           : /home/jun/source/cquery 
Setting out to                           : /home/jun/source/cquery/build 
Checking for 'clang++' (C++ compiler)    : /bin/clang++ 
Checking for header stdio.h              : not found 
The configuration failed
(complete log in /home/jun/source/cquery/build/config.log)

开发机, g++和clang都安装了, stdio.h是肯定有的, waf配置却找不到

看log好像是clang++的版本太低, 如何让它下载新版本?

找不到就是环境变量设置的问题了,LDFLAGS/CPPFLAGS,如果存在多个版本的 llvm,还要设置 PATH=/path/to/llvm/<ver>/bin:$PATH。打开 config.log 看看详细信息。

会不会是少了一个 build 参数? ./waf configure build

你是按 wiki 上编译的吗?

$ git submodule update --init && ./waf configure build # --variant=debug if you want to report issues.

config.log里最后的错误信息:

----------------------------------------
Checking for header stdio.h
==>
#include <stdio.h>

int main(int argc, char **argv) {
    (void)argc; (void)argv;
    return 0;
}

<==
[1/2] Compiling ^[[32mbuild/.conf_check_c16aab83fa0ff098a7a93f7cbfd670c6/test.cpp^[[0m

['/bin/clang++', '-g', '-Wall', '-Wno-sign-compare', '-Werror', '-std=c++14', '-O3', '
err: error: invalid value 'c++14' in '-std=c++14'

应该是centos7里的clang版本太低了(3.4.2), 不支持c++14, 导致编译失败. 感觉这个检测逻辑有点不太合理, 关键点是不支持c++14, 而不是stdio.h不存在

在mac上编译成功了, 现在在centos7下有问题

确实太老了, 我 debian 9 的 clang 都 3.9, backports 都 5.0了。 我刚刚看了一下, centos 的 gcc 也好老啊,估计也编译不了

是啊, centos就是这幅德行, 不过市场挺大, 比如teamviewer最新版都不支持debian 8了,但是还支持centos7. debian 8的软件比centos 7要新很多

昨天再centos上编译了最新版cquery, 相关emacs包都用的最新的, 再emacs中启动cquery之后, emacs会卡一段时间, 系统cpu占用很高(可能再索引, 这个可以理解), 但这个过程中, emacs进程偶尔也占用100%cpu(cpu总共4核)有点不太理解,还会报如下错误(20条左右):

error in process filter: save-excursion: End of buffer
error in process filter: End of buffer

error in process filter: save-excursion: End of buffer

error in process filter: End of buffer

我也经常看到,不明。

emacs进程偶尔也占用100%

  • 可能是 flycheck。看看设置diagnostics.frequencyMs有没有用。这样键入多个字符时,flycheck不会连续报错
    (setq cquery-extra-init-params
          '(:cacheFormat "msgpack" :completion (:detailedLabel t) :xref (:container t)
                         :diagnostics (:frequencyMs 5000)))

不大会用 waf (wscript)…

clang 3.5大概能编译通过。clang 3.4把wscript-std=c++14改成-std=c++1y试试,或者CXXFLAGS=-std=c++1y ./waf configure

使用.cquery文件时, 无法识别其中的include路径, 响应的头文件和函数定义均被lsp-ui-flycheck报搞找不到.

cquery崩溃后, 是否有不重启emacs就使cquery重新运行的方法?).

M-x projectile-kill-buffers,重新打开一个文件

没有编辑文件, 仅方向键上下移动(很卡), 照理说此时flycheck不会运行.

这个值看了一下是nil

此时没有做这些操作, 仅方向键上下移动