-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Linux also needs heuristic workaround for libclang default include paths #2330
Comments
I'm using clang and every my .ycm_extra_cong.py contains such script def LoadSystemIncludes():
regex = re.compile(ur'(?:\#include \<...\> search starts here\:)(?P<list>.*?)(?:End of search list)', re.DOTALL);
process = subprocess.Popen(['clang', '-v', '-E', '-x', 'c++', '-'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE);
process_out, process_err = process.communicate('');
output = process_out + process_err;
includes = [];
for p in re.search(regex, output).group('list').split('\n'):
p = p.strip();
if len(p) > 0 and p.find('(framework directory)') < 0:
includes.append('-isystem');
includes.append(p);
return includes; With its output being appended to returned flags. I do not experience any problems with stdlib. |
@PawelSevcio Can you share your full .ycm_extra_conf.py ? I am very interested. |
@meritozh sure, it's in attachment, but there is nothing special in it really. |
I too have noticed that libclang does not include To me it seems like a sane decision for |
The use of cross toolchains (or any non-default toolchains) is a real and legit concern. However, it is also true that because of the upstream libclang change, there are: 1) changes in the default behaviour for common Linux users (system headers no longer included by default); 2) some behaviour differences between Mac and Linux versions (it used to be the case that both would include the system headers by default -- Linux version was due to libclang behaviours while Mac version is due to the heuristics in the YCM Python script). These were the main reasons I suggested adding some similar heuristic workaround for Linux as well. But now, considering all these concerns, it might also be good if we can come up with a more elegant solution instead of workarounds. After all, it is really annoying that even a single-file "hello world" would also require a |
I don't see anything wrong with requiring That said I am open to suggestions and willing to debate to find a solution fitting all of us. |
But that's the thing: projects don't (and shouldn't) specify the include path to standard libraries because it's the compiler's job to do that. Right now, the That's also ignoring the fact that it would be nice to be able edit a 3-line "Hello world" type program without having to first write a 20+ line As for:
Yes, that is a valid case, but it is also a rare case. It seems far better for including the default system headers to be an opt-out feature than the current hack of having to copy code to parse clang's debugging output into every |
(until ycm-core/YouCompleteMe#2330 is fixed).
(until ycm-core/YouCompleteMe#2330 is fixed).
Ideally it would be, but the projects that are cross compiled are definitely not using native clang as the compiler, it's just not a possibility. I also do not think that people that use C and are primarily cross compiling are rare. Everyone I've ever met that is using C as one's primary language is working with embedded systems and quite often bare-metal, myself included. My every single project for the last four years was cross compiled and I don't see anything changing that in the forseeable future.
I would agree that is a good option. I don't mind including one more line of vimscript, but I also know Valloric and the others don't like to expose any configuration to end users. They even think requiring |
That's a reasonable thing to assume. And your compiler probably does. Though, try using home-built OSS clang on a Mac. Anyway, realise that the precompiled libclang binaries that we use simply don't know where your standard library is installed. The clang devs try their very best to guess, but they can't know where the designers of your arbitrary system decided to arbitrarily secrete the c++ standard library. It seems the clang driver itself knows better and I know that some of the team are working towards libclang having better heuristics. Until then, there is little we can do other than YCM developers writing workarounds for each and every arbitrary system layout. We concede to do it on Mac because, while different for other OSes, Apple always put the libraries in the same place. Unfortunately, and hugely regrettably, that is not true of any of the other supported OSes, and we're not willing to develop and maintain hacks and workarounds for each and every flavour of each and every OS. In particular, it seems wasteful given that the workaround is trivial (just tell libclang where your standard library is). While I realise this next point is a straw man, I somehow feel compelled to address it...
For most users, def FlagsForFile( file_name, **kwargs ):
return { 'flags': [ '-x', 'c++', '-std=c++11' ] } I'm not sure how often serious developers write a 3-line "Hello, world!" programs, and how useful a code comprehension engine would be for such toy projects, but many thousands of users use YCM on large applications in professional environments, so we really don't see the toy project use case as a major driver for a complex and brittle feature such as this one. As has been mentioned multiple times, if all you do is toy projects, we recommend writing a global extra conf file with the requisite 2-20 lines in it (depending on your requirements). You could always indeed incorporate my default-extra-conf branch which somewhat removes the need for project-specific
Quite right! We discussed it at length, but Tern provides no way to avoid
As above, if we had a solution, it would not be optional.
I literally never do that, and use YCM on linux every day. But that's not really the point, I suppose. The point is if libclang can't parse your code, we can't provide completions. You need to tell libclang how to parse your code. |
I suppose the other thing to point out is that we don't even have a solution, so debating the merits of doing or not doing that nonexistent solution is really not super productive. I realise I have made a nonzero contribution in that regard. |
I'd like to know why it works for you, then, because it doesn't for me (on up-to-date Debian testing). If I put exactly this in def FlagsForFile( file_name, **kwargs ):
return { 'flags': [ '-x', 'c++', '-std=c++11' ], 'do_cache': True } and then open this #include <iostream>
int main() {
std::cout << "hello world\n";
} I get everything on the std::cout line error-highlighted, with status message It seems I have to add I'd happily like a nicer (i.e. two lines) way to do this, but the "for most users" version that you posted above isn't working. Edit: just to be more precise, without the added
|
@bstaletic sorry I guess I misled the discussion: having a configuration file for every project is fine, but the real problem is about hand-coding the default include paths in the conf, something you wouldn't specify in Makefile or CMake if you are doing some common local Linux development and is non-trivial to find out. Furthermore, every time after gcc/clang is upgraded, you have to go back to all these configuration files and change the paths. @puremourning , first thanks for the insight! It is true (and sad) that there seems to be no "elegant" (as on Mac) workaround on Linux. The only way I could think of is to automate the manual process of grepping clang's verbose output (see @pawelsevcio 's script), which is quite hacky. (BTW, @jagerman , actually this is not likely to break; the usage comes from gcc and is used in many build hacks.) Yet I'm wondering how you can (1) use that 2-line |
Quite
Quite. This is already a pain for macOS due to seemingly arbitrary reorganisations between versions. The YCM development team are just not capable of doing this nontrivial exercise when any of the 10k users deigns to install their compiler and/or standard library in a nonstandard location? I don't think the 5 of us quite have that time to commit, I'm afraid.
As we've said before, we can't do this because we can't even guarantee that clang is installed in YCM runtime environments; there is no requirement for that to be the case. I think we would only consider any practical heuristic that is:
Take a look at our test suite. |
It's actually pretty easy to break: just uninstall the clang binary (ycmd only depends on libclang, not clang itself). (As @puremourning just mentioned). |
Oh yeah I forgot the requirement of having An interesting update here: I just noticed that I could not reproduce this issue any more on my machine. It is not caused by changes in YCM -- I've verified by checking out to 30871bc (recursively) I originally mentioned. The most likely explanation is my system updates (it's Arch Linux, you know), and I'm still trying to find out the exact reason. |
There's a very good chance that the needed clang system includes in linux are to be found in @Hexcles - I've also noticed that the stdlib headers get picked up now, but the clang includes don't, which causes a failure for, among other things, |
@jagerman No mine is working fine. And you sure it's missing clang-includes? That's not supposed to happen! YCM explicitly deals with this problem by including a copy of I'm on Arch Linux, clang 3.9.0 by the way. And the libclang is downloaded by YCM, 3.9.0. |
Actually, this In that case, sorry for all the noise: it seems like whatever was missing picking up the stdlib headers is fixed (and apparently on the clang side of things), and missing things like stdint.h is a problem specific to the Debian package (which has a debian bug filed). Moreover editing "foo.cpp" (and variants thereof) in my home directory works again without errors (or needed custom configuration). |
Joy \0/ |
Issue Prelude
Please complete these steps and check these boxes (by putting an
x
insidethe brackets) before filing your issue:
Frequently Asked Questions section.
about to report and couldn't find an answer to my problem. (See Using default .ycm_extra_conf.py, the standard c++11 headers are not found. #303 )
vim --version
.:YcmDebugInfo
.:YcmToggleLogs stderr
.version) I am using.
my issue.
that any help I receive is a selfless, heartfelt gift of their free time. I
know I am not entitled to anything and will be polite and courteous.
actually perform all of these steps.
Thank you for adhering to this process! It ensures your issue is resolved quickly and that neither your nor our time is needlessly wasted.
Issue Details
This issue was discussed in #303. Here's a quick recap: libclang does not always use the default header search paths as the clang binary does, namely the C++ stdlib tends to be missing. It was discovered that macOS was more prone to this issue, while libclang seemed to include the default search paths correctly in Linux (at least for the official libclang binary). Therefore, a workaround was added for macOS only.
New problem: however, since the clang 3.8.0 release (as well as the most recent 3.9.0 release currently used in YCM), the official libclang binary for Linux also seems to stop including the default search paths. (I haven't verified the code change on libclang side, but simply speculated from the behaviour.) I do realize that FAQ already covers this issue, but I think it would be good to add a workaround for Linux similar to what we did for macOS in 11edf12 under the same rationale. (Yet the Linux workaround might be harder/uglier because of the version number in the path...)
A trivial example:
And
:YcmDiags
would complain about missing headers. After I explicitly added-isystem /usr/include/c++/6.2.1
(since I have GCC 6.2.1) to the flags, everything worked.FWIW, here's my system info:
The text was updated successfully, but these errors were encountered: