Closed andyleejordan closed 6 years ago
Please ignore the random spaces in the pastes, copying from PowerShell is awful.
$ /TP -working-directory C:/Users/andschwa/src/mesos/build -xc++ -std=c++14
This is weird. The compiler driver is missing in the list of args
.
https://github.com/cquery-project/cquery/blob/master/src/clang_translation_unit.cc#L88
https://github.com/cquery-project/cquery/blob/master/src/project.cc#L147
Is the compiler driver clang-cl.exe
recognized by this function? You may LOG_S(INFO) << "+++" << result.args[0]
and view it in the --log-file=/tmp/cq.log
log file or std::cerr <<< ...
and view it in the lsp-cquery stderr
buffer.
See https://github.com/Valloric/ycmd/pull/789, you may need to have --driver-model=cl
in all compiler arguments or in cquery.index.extraClangArguments
(this is a VSCode thing, I'm not sure what the equivalent Emacs one is).
Okay, so I got a bit further. Using extraClangArgs
I got --driver-mode=cl
passed in, which is necessary, but I discovered a few more problems. Thanks for the pointer @Riatre.
Passing extra clang
arguments using the Emacs extension:
(customize-set-variable 'cquery-extra-init-params '(:extraClangArguments ("--driver-mode=cl"))
However, @MaskRay is also correct, it is bizarre that the arguments don't have the compile driver itself (e.g. clang
, or in my case cl.exe
which would be wrong even if it found it). There are a couple problems around this. Since my project is configured with MSVC, not Clang, the compiler is cl.exe
, and the options start with /
instead of -
. This screws with the logic found here. My temporary, Windows-only patch looks like this:
// ie, compiler schedular such as goma. This allows correct parsing for
// command lines like "goma clang -c foo".
std::string::size_type dot;
- while (i < entry.args.size() && entry.args[i][0] != '-' &&
+ while (i < entry.args.size() &&
+ entry.args[i][0] != '-' &&
+ entry.args[i][0] != '/' && // Windows options: WILL BREAK LINUX.
// Do not skip over main source filename
NormalizePathWithTestOptOut(entry.args[i]) != result.filename &&
// There may be other filenames (e.g. more than one source filenames)
...
!entry.args[i].compare(dot + 1, 3, "exe")))
++i;
// Include the compiler in the args.
+ bool is_msvc = false;
if (i > 0)
- result.args.push_back(entry.args[i - 1]);
+ // Replace `cl.exe` with `clang++.exe --driver-mode=cl`.
+ if (entry.args[i - 1].compare(entry.args[i].size() - 6, 6, "cl.exe")) {
+ is_msvc = true;
+ result.args.push_back("clang++.exe");
+ result.args.push_back("--driver-mode=cl");
+ }
+ else
+ result.args.push_back(entry.args[i - 1]);
else {
// TODO Drop this back compatibility
// Args probably came from a /.cquery file, which likely has just flags.
So far with this I can properly keep all the arguments, and replace cl.exe
with clang++.exe --driver-mode=cl
(also negates needing to set that in Emacs Lisp). This lets the rest of the cl.exe
arguments (well, almost) be understood by clang++.exe
.
Another problem is that I have an argument, /permisssive-
, that clang-cl
does not recognize (but should). For now, I'm adding this to cquery's internal blacklist, but should also upstream this to the Clang project. It's a valid cl.exe
argument.
Similarly, cquery assumes the compile driver is clang, not clang in cl-mode. So it adds the arguments -working-directory <build/path>
, -xc++
, -std=c++14
, etc., which now break clang in cl mode. The former actually breaks it entirely because of the way the argument is structured, the latter ones just get ignored. I am currently working on mapping these (-Xclang
looks promising).
Finally, the Windows absolute-path logic assumes the paths always use /
, never \
, which isn't true in my case with cl.exe.
Command line parsing is really hard... https://github.com/cquery-project/cquery/issues/236 https://github.com/cquery-project/cquery/issues/377
Indeed. Ah man but I want to get this working so bad since pretty much nothing else works with Mesos well. Especially on Windows.
I actually want to remove these -xc
-std=c11
-xc++
-std=c++14
flags as they complicate the logic, but I guess someone will complain about that (I incline to disregard the complaint)
The compiler driver detection logic may be replaced by detecting if the first few arguments are executable. I wonder if goma
appears in the compile_commands.json
"arguments"
used for building Chrome.
We may add an option to invoke an external script to give us the processed compile_commands.json
contents, not the file on the disk, as something similar to .ycm_extra_conf.py
How does -working-directory
break clang-cl?
You may also use .cquery
which overrides compile_commands.json
. Since d5ce5845b2391138f2b4b9f2e25d6b87ac32dbe6 the file can exist in sub directories.
emacs-cquery locates the project root with (locate-dominating-file default-directory ".cquery")
, which needs changing for hierarchical .cquery
files.
https://github.com/cquery-project/emacs-cquery/blob/master/cquery-common.el#L50
I actually want to remove these -xc -std=c11 -xc++ -std=c++14 flags
I am not sure if that's a good idea. Last year I had a project for which I intentionally supplied -xc -std=c89
expecting the compiler to respect it and warn me about anything that got introduced in later standards.
The compiler driver detection logic may be replaced by detecting if the first few arguments are executable.
What about the following:
clang-cl --driver-mode=gcc
clang++ --driver-mode=cl
I actually want to remove these -xc -std=c11 -xc++ -std=c++14 flags
I am not sure if that's a good idea. Last year I had a project for which I intentionally supplied -xc -std=c89 expecting the compiler to respect it and warn me about anything that got introduced in later standards.
I think we are on the same page :) Before yesterday, cquery adds -std=c11
or -std=c++14
if the project does not specify -std=
. I changed that and now it only adds options when .cquery
is used, not when compile_commands.json
is used. https://github.com/cquery-project/cquery/wiki/Getting-started#cquery
What about the following: clang-cl --driver-mode=gcc clang++ --driver-mode=cl
The "Strip all arguments consisting the compiler command," logic is used to support goma or other compiler scheduler.
https://github.com/cquery-project/cquery/blob/master/src/project.cc#L146 I dislike the logic and do not use it in "compilationDatabaseCommand"
mode.
@MaskRay
Re: working-directory
How does -working-directory break clang-cl?
clang-cl
doesn't recognize the -working-directory
flag, as it expects only cl
-like flags. So these arguments:
clang++.exe --driver-mode=cl -working-directory C:/Users/andschwa/src/mesos/build
Produce this error:
error: error reading 'C:/Users/andschwa/src/mesos/build'
Re: compiledb
We may add an option to invoke an external script to give us the processed compile_commands.json contents, not the file on the disk
This could be interesting, given this extension.
That said, I'm happy to use Ninja and therefore CMake's CMAKE_EXPORT_COMPILE_COMMANDS
to produce a compile_commands.json
. It's tricky to integrate clang-cl
support, but I think doable. The logic of "if compile driver == cl.exe, use clang++ --driver-mode-cl` seems sound.
But I'll also try a compiledb. It might work better.
At the cost of extra 3 lines, e15f57f9c732b1c544e6e7bf2ae8a2729c9eb41a, .cquery
for clang-cl
is supported.
These should work.
# .cquery
% cat /tmp/d/.cquery
clang-cl
/I
inc
[
{ "arguments": [ "clang-cl", "/Iinc", "a.cc" ], "directory": "/tmp/c", "file": "a.cc" }
]
Please add support for Windows for this commit https://github.com/cquery-project/cquery/commit/eadc53abe9af1e28d0a1abba40da7a16864de919 and use "compilationDatabaseCommand"
if you want to support more complicated setting.
Welcome to discuss Windows support in https://gitter.im/cquery-project/Lobby
clang-cl doesn't recognize the -working-directory flag, as it expects only cl-like flags.
That's not correct. clang-cl /I include_dir_foo -I include_dir_bar -c foo.c -o foo
happily produces foo.obj
respecting both -I
and /I
- at least on unix-like systems.
clang -working-directory=/tmp/c -c a.cc
clang --driver-mode=cl -working-directory=/tmp/c -c a.cc
I guess cl mode takes -working-directory
as an unknown warning option and ignores it.
I guess cl mode takes -working-directory as an unknown warning option and ignores it.
Exactly this.
Please add support for Windows for this commit eadc53a and use "compilationDatabaseCommand" if you want to support more complicated setting.
Sorry, I had to put this on hold for a bit. I'll try this out next. I really want to get this working.
Ironically I need to implement the same semantics here as in Mesos. Should be doing it this week.
Note that CL driver support is relatively new and has not seen much use, so bugs are to be expected. Someone should report the -working-directory
bug to the llvm devs.
Back to the original topic of parsing command line, yes it's quite hard and annoying.
Since there's always a question which directory are the paths relative to, ycmd has include_paths_relative_to_dir
as part of its .ycm_extra_conf.py
. So instead of supplying -working-directory
to libclang, ycmd uses include_paths_relative_to_dir
to make all paths absolute.
@andschwa Ycmd isn't as feature rich, but maybe you'd have less troubles getting it to work with your project.
@MaskRay I hope you won't mind me "promoting" ycmd.
https://github.com/cquery-project/cquery/pull/501 Changes cquery to do the same. Has ycmd had any issues with this approach?
Not at all. At least not with the absolute paths part of the code.
Ycmd is more aggressive when it comes to sanitising flags. It will remove all positional parameters that are not include paths. This caused some issues with recognising when /I
is a flag and not an absolute path, but I believe we have taken care of CL driver by now.
I hope you won't mind me "promoting" ycmd.
That's fine :)
Thanks @jacobdufault for implementing GetExternalCommandOutput
. Work and a vacation got in the way.
Sure :)
@MaskRay With the latest version of cquery (built with bundled Clang 6.0.0 after reading #219), this is now working for me with Mesos on Windows. I am so happy. I can jump to definitions, find references, have syntax errors highlighted, preprocessor guards are greyed, completions are available, the works! I'm sorry I wasn't more helpful. I think where I left off was trying to get cquery built with my own system clang, and then llvm-config wasn't working (and 6.0.0 wasn't bundle yet... or even released), and I had to get back to work. I saw several things go in that I'd (sort of) fixed in a WIP branch I never posted :(
But anyway, thank you all. This is f***ing fantastic.
Oh, and my setup is just using Ninja to generate a compile_commands.json
, which with the clang-cl
driver mode, is working just fine. I had to make Ninja work on Mesos' Windows build, which was a whole different story... but it's faster, so improvements were found there too.
:), cquery has had some quality-of-life improvements for windows recently (such as automatically discovering system include headers). You may still run into some issues with vscode opening duplicate files with different path casing.
Hello,
I am trying to get
cquery
up and running for Mesos on Windows. I've succesfully builtcquery
and got Emacs setup to use it; and I have Mesos successfully building with Ninja on Windows (which lets me use the CMake generatedcompile_commands.json
. However, whencquery
tries to index one of my files, I get this error:I've tried doing what it said, and under
clang++.exe
directly, it fails because the syntax iscl.exe
syntax. (Note: I cannot compile the whole project withclang
on Windows, some our dependencies e.g. GoogleTest don't support it, but the Mesos sources themselves compile withclang
on other platforms).Running the same arguments under
clang-cl.exe
gets me a bit further (after putting double quotes around the paths because the embedded dashes otherwise cause more syntax errors), and finally I got to this error and am stumped:There is only one source file specified, so the error doesn't make sense to me.
Has anyone gotten
cquery
to work on Windows with a CMake-generated Ninja-driven MSVC project?