Update FAQ

Paul Smith 2019-01-02 00:40:37 -05:00 committed by Fangrui Song
parent cec23afef0
commit 62321899f2

242
FAQ.md

@ -1,17 +1,88 @@
### `.ccls-cache/`
## Compiling with Visual Studio
The cache directory is `.ccls-cache/` by default. It can be shared among different clients. You may add `.ccls-cache` to the global gitignore file `~/.config/git/ignore`
If your project is compiled with MSVC, you may set the compiler driver in
`.ccls` to [`clang-cl`](Customization#clang--clang--clang-cl), and use the
initialization option
[`clang.extraArgs`](Customization#clangextraargs--clangexcludeargs) to pass
three options: `-fms-extensions -fms-compatibility -fdelayed-template-parsing`.
### Does it support `compile_flags.txt`?
See https://clang.llvm.org/docs/MSVCCompatibility.html
## Compiling with GCC
GCC is very similar to Clang and most options are portable. If you are using
options with GCC which are not available in Clang you can use
[`clang.excludeArgs`](Customization#clangextraargs--clangexcludeargs) to
remove them.
If you want to convince Clang to use the GCC header files you can add the
`--gcc-toolchain` option either via the [`.ccls` file](Customization#ccls-file)
or the [`clang.extraArgs](Customization#clangextraargs--clangexcludeargs)
initialization option. For example to choose the GCC system header files you
might add:
```
--gcc-toolchain=/usr
```
to your `.ccls` file.
## Full indexing takes a long time / crushes my system
For large projects, full indexing can be a significant burden. Once the
initial index is complete, future indexing will be proportional to the number
of files changed.
While full indexing is required for complete cross-reference support, if you
are making targeted edits on large codebases it may not be worthwhile to index
the entire thing. There are various ways to reduce the impact and scope of
indexing.
* You can reduce the number of CPU cores used for indexing by setting the
[`index.threads`](Customization#indexthreads) initialization option.
* You can avoid indexing parts of the codebase you are not interested in by
setting the [`index.initialBlacklist`](Customization#indexinitialBlacklist)
initialization option.
* You can avoid indexing any of the codebase by default, and only indexing
files as you open them, by setting `index.initialBlacklist` to `["."]` (a
regular expression that will match every file).
Note that when you edit a header file, `ccls` will automatically open the
associated (by name) source file if one exists, and index it as well to locate
definitions of symbols declared in the header file. For example, if you edit
a file `a.h` and `ccls` can locate a file `a.cpp` then it will index that as
well.
## Can `ccls` be started directly?
Yes `ccls` can be run in stand-alone mode using the
[`--index`](Customization#--indexroot) option. If your client uses
[`clang.extraArgs`](Customization#clangextraargs) be sure to use the same ones
when invoking `ccls` in stand-alone mode, otherwise the flags mismatch will
cause re-indexing when invoked from the client.
Here's an example:
```sh
ccls --index=$HOME/llvm --init='{"clang":{"extraArgs": ["--gcc-toolchain=/usr"]}}'
```
## Does `ccls` support `compile_flags.txt`?
No. https://github.com/MaskRay/ccls/issues/110
### Some C/C++ headers are not recognized
## Some C/C++ headers are not recognized
#### if you are emacs user, make sure company-lsp is used
<kbd>M-x</kbd> `company-diag`, make sure`Used backend:` includes `company-lsp`.
First, if you are Emacs `company` mode user make sure company-lsp is used: run
<kbd>M-x</kbd> `company-diag` and make sure`Used backend:` includes
`company-lsp`.
There are at least three sets of implicit include paths. They take effect without your `-I` option in `.ccls` or `compile_commands.json`
#### Checking header locations
There are at least three sets of implicit include paths. They take effect
without your `-I` option in `.ccls` or `compile_commands.json`
```c++
// a.cc
@ -23,41 +94,56 @@ There are at least three sets of implicit include paths. They take effect withou
#include <stddef.h>
```
Put `a.cc` in some directory with `echo clang++ > .ccls`. Open the file, you should be able to jump to `stdio.h` `new` `stddef.h` when you trigger `textDocument/definition` on the include lines.
Put `a.cc` in some directory with `echo clang++ > .ccls`. Open the file, you
should be able to jump to `stdio.h` `new` `stddef.h` when you trigger
`textDocument/definition` on the include lines.
Note that this might not work on Windows. To solve this, add the system include directories to compile_commands.json via your build system of choice using the INCLUDE environment variable (available after executing VsDevCmd.bat).
Note that this might not work on Windows. To solve this, add the system
include directories to compile_commands.json via your build system of choice
using the INCLUDE environment variable (available after executing
VsDevCmd.bat).
For CMake this can be achieved in a single line: `target_include_directories(<target> SYSTEM PRIVATE $ENV{INCLUDE})`
#### Check if `-resource-dir` is correct
#### Verify the Clang Resource Directory is correct
Check `Clang_EXECUTABLE` in your `CMakeCache.txt`. The output of command `$Clang_EXECUTABLE -print-resource-dir` will be passed to `-DDEFAULT_RESOURCE_DIRECTORY`. Make sure you can locate `include/stddef.h` in the resource directory.
Use the `--log-file` command line option to generate a log file and look for
the line `initialize.cc:nnn I use -resource-dir=<path>`. Make sure the path
`<path>` still exists and you can locate the file `<path>/include/stddef.h`.
If not, then you need to use the
[`clang.resourceDir`](Customization#clangresourcedir) initialization option to
tell `ccls` where to find the Clang resource directory. See also
[Clang Resource Directory](Install#clang-resource-directory).
#### `-isystem`
ccls infers system search paths (e.g. `/usr/include`). The underneath mechanism is similar to that of `clang -v -E -x c++ /dev/null`.
ccls infers system search paths (e.g. `/usr/include`). The underneath
mechanism is similar to that of `clang -v -E -x c++ /dev/null`.
`-isystem` system include paths is usually unnecessary. But for cross compiling or on some bizarre system you may have to specify them. A simple approach other than trial and error (changing `.ccls` and restarting your editor) is to use `c-index-test`.
Adding system include paths is usually unnecessary, but when cross-compiling
or in some odd situations you may have to specify them. A simple approach
other than trial and error (changing `.ccls` and restarting your editor) is to
use `c-index-test`.
`Debug/clang+llvm-6.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/c-index-test -index-file local /tmp/c/a.cc -isystem/usr/include/c++/7.3.0 -isystemyour_include_path2`
Play with your `-isystem` options until you get a group of options that you can add to [`.ccls`](https://github.com/MaskRay/ccls/wiki/Getting-started#ccls)
Play with your `-isystem` options until you get a group of options that you
can add to the [`.ccls` file](Customization#ccls-file) or add through
`clang.extraArgs`.
If you want the ccls binary at a specific location use a symlink - do not move the binary itself.
## Inspect index files
If you want to specify additional search paths:
If you need to inspect the contents of the index files, use
[`cacheFormat`](Customization#cacheformat) to specify JSON output format.
* `print '%clang\n%cpp -std=gnu++17\n-isystem/tmp/include' > .ccls`
* emacs-ccls: `(setq ccls-extra-init-params '(:clang (:extraArgs ["-isystem" "/tmp/include"])))`
You can use `jq` to format the JSON file to be more readable:
### Inspect index files
```sh
jq . < /tmp/ccls/@tmp@c/a.cc.json
```
Read [[Initialization options]] how to set `"cacheFormat": "json"`.
If `"cacheDirectory": "/tmp/ccls"`, and the source file is `/tmp/c/a.cc`,
run `jq . < /tmp/ccls/@tmp@c/a.cc.json`
### Project root detection
## Project root detection
[emacs-ccls](https://github.com/MaskRay/emacs-cquery/) locates the project root in the following order:
@ -77,7 +163,7 @@ proj
.git
```
### Maximum number of file descriptors
## Maximum number of file descriptors
Some projects may require more than 1000 file descriptors. Remember to increase `RLIMIT_NOFILE`.
@ -91,11 +177,14 @@ ulimit -n 32768
* soft nofile 32768
```
### Diagnostics in headers
## Diagnostics in headers
For efficiency, headers are compiled on their own (as if `clang [options] a.h`) to utilize Clang's preamble optimization.
For efficiency, headers are compiled on their own (as if `clang [options]
a.h`) to utilize Clang's preamble optimization.
For headers that are not self-contained (e.g. some `/usr/include/bits/*.h` which require a predefined macro) ccls emits diagnostics that you don't see when building the project.
For headers that are not self-contained (e.g. some `/usr/include/bits/*.h`
which require a predefined macro) ccls emits diagnostics that you don't see
when building the project.
```c
// a.c
@ -108,30 +197,47 @@ For headers that are not self-contained (e.g. some `/usr/include/bits/*.h` which
#endif
```
One approach ccls explored before was to compile its import file `a.c`, but it caused severe performance issues for some projects.
For smaller files this does not matter and checking for a header guard may help the situation.
One approach ccls explored before was to compile its import file `a.c`, but it
caused severe performance issues for some projects. For smaller files this
does not matter and checking for a header guard may help the situation.
### Multi-version headers
## Multi-version headers
A header can be included in different translation units with different compiler flags. It may behave differently via `#ifdef`.
Ideally, there should be some mechanism to switch among different views (compiler flags) when you are editing the file.
A header can be included in different translation units with different
compiler flags. It may behave differently via `#ifdef`. Ideally, there should
be some mechanism to switch among different views (compiler flags) when you
are editing the file.
For efficiency, a header is only indexed with one set of compiler flags, so either the `#if` block or `#else` is indexed, the other is left blank.
For efficiency, a header is only indexed with one set of compiler flags, so
either the `#if` block or `#else` is indexed, the other is left blank.
For macros, there is code to track different usage, thus you may find them able to jump to multiple targets.
`index.multiVersion` is an experimental option to index every version to certify that the author is aware of this issue :)
It may not be very useful though. It is of type `number` but not `boolean` as the author is also aware of other dimensions of the multi-version problem.
For macros, there is code to track different usage, thus you may find them
able to jump to multiple targets. `index.multiVersion` is an experimental
option to index every version to certify that the author is aware of this
issue :) It may not be very useful though. It is of type `number` but not
`boolean` as the author is also aware of other dimensions of the multi-version
problem.
### Completion and diagnostics
## Completion and diagnostics
While most cross reference requests (`textDocument/definition` `textDocument/references` `$ccls/member` ...) are served by the index (`query.h:DB`) and have a global view, completion and diagnostics are single-TU features.
They use unsaved buffers and require re-parsing for each new request.
While most cross reference requests (`textDocument/definition`
`textDocument/references` `$ccls/member` ...) are served by the index
(`query.h:DB`) and have a global view, completion and diagnostics are
single-TU features. They use unsaved buffers and require re-parsing for each
new request.
### Definitions
## Definitions
`textDocument/definition` jumps to the definitions (there can be many across many TUs, thinking of odr violation) if available. If the cursor is on a definition, jump to declarations instead.
`textDocument/definition` jumps to the definitions (there can be many across
many TUs, thinking of odr violation) if available. If the cursor is on a
definition, jump to declarations instead.
When jumping from a dependent name in a template, ccls tries its best to get every target when the information is available. If the template is written in a main file and you instantiate it multiple times, it can assuredly find all target. However if the template is in a header, because by default a header is indexed for one TU, you won't get all targets. See the discussion about `index.multiVersion`.
When jumping from a dependent name in a template, ccls tries its best to get
every target when the information is available. If the template is written in
a main file and you instantiate it multiple times, it can assuredly find all
target. However if the template is in a header, because by default a header is
indexed for one TU, you won't get all targets. See the discussion about
`index.multiVersion`.
* <code>void <kbd>foo</kbd>();</code> A declaration jumps to the definition
* <code>void <kbd>foo</kbd>() {}</code> The definition lists all declarations
@ -144,43 +250,46 @@ When jumping from a dependent name in a template, ccls tries its best to get eve
* <code>namespace <kbd>ns</kbd> {</code> find original or extension namespaces
* <code>// ns::<kbd>foo</kbd></code> in comments, it recognizes the identifier around the cursor, approximately finds the best matching symbol and jumps to it; on `ns`, it jumps to the namespace
### Hover
## Hover
`textDocument/hover` is served by the index, which is built when you save the file. This model is simple to implement and has lower CPU cycles, but the drawback is that you don't get immediate hover information for newly-created declarations that are not in the index.
`textDocument/hover` is served by the index, which is built when you save the
file. This model is simple to implement and has lower CPU cycles, but the
drawback is that you don't get immediate hover information for newly-created
declarations that are not in the index.
See the initialization option `index.onChange`.
### References
## References
* <code><kbd>#include &lt;iostream&gt;</kbd></code> lists all `#include` lines in the project pointing to the included file
* <code><kbd>&#91;&#93;(){}</kbd></code> lists all(?) lambda expressions thanks to implicit `std::function` move constructor
* <code>extern int <kbd>a</kbd>;</code> If `ReferenceContext.includeDeclaration` is true, the definition and declarations are also listed.
* If no references is found but the point is on the first line, list `#include` lines referencing current file.
### `textDocument/implementation`
## `textDocument/implementation`
* <code>struct <kbd>B</kbd>{virtual void <kbd>f</kbd>();};</code> derived classes or virtual function overrides
### `$ccls/vars`
## `$ccls/vars`
* <code><kbd>A</kbd> <kbd>a</kbd>;</code> lists all instances of user-defined `A`.
* <code>int <kbd>i</kbd>;</code> lists all instances of `int`.
### [`$ccls/call`](https://github.com/MaskRay/ccls/blob/master/src/messages/ccls_call.cc)
## [`$ccls/call`](https://github.com/MaskRay/ccls/blob/master/src/messages/ccls_call.cc)
Find callers. If parameter `callee:true` is specified, find callees instead.
Specify `hierarchy:true` to enable hierarchical view.
### [`$ccls/inheritance`](https://github.com/MaskRay/ccls/blob/master/src/messages/ccls_inheritance.cc)
Find base classes/overriden functions. If parameter `derived:true` is specified, find derived classes/functions instead.
It also works fine for jumping between primary template and partial specialization.
## [`$ccls/inheritance`](https://github.com/MaskRay/ccls/blob/master/src/messages/ccls_inheritance.cc)
Find base classes/overriden functions. If parameter `derived:true` is
specified, find derived classes/functions instead. It also works fine for
jumping between primary template and partial specialization.
Specify `hierarchy:true` to enable hierarchical view.
### [`$ccls/member`](https://github.com/MaskRay/ccls/blob/master/src/messages/ccls_member.cc)
## [`$ccls/member`](https://github.com/MaskRay/ccls/blob/master/src/messages/ccls_member.cc)
Recursively list member variables of a record type. 😂 nobody has implemented vscode-ccls UI for the feature. Help wanted!
@ -189,3 +298,26 @@ Recursively list member variables of a record type. 😂 nobody has implemented
If parameter `kind:3` is specified, list member functions/functions in a namespace
* <code>struct <kbd>A</kbd>{void f();};</code> lists `A::f()`
## Cases
On a laptop with one (i7-6600U CPU @ 2.60GHz, hyper-threading, `nproc`=4), 4
indexers. llvm+clang+extra+lld+compiler-rt (2018-06-10)
* initial indexing: 1 hour; load: 20s
* resident set size is about 1GiB (the peak RSS during indexing is below 2GiB)
* `du -sh .ccls-cache` => 580M
radare2 (2017-06-10)
```
CC=clang CXX=clang++ LDFLAGS=-fuse-ld=lld meson . debug --buildtype=debug --prefix ~/.config/radare2/debug
ln -s debug/compile_commands.json
```
* initial indexing: 78s; load: 3s
* 300MiB
* `du -sh .ccls-cache` => 107M
Note: ccls can serve LSP requests while it is doing the initial indexing of
the project.