facebookarchive / nuclide

An open IDE for web and native mobile development, built on top of Atom
https://nuclide.io
Other
7.79k stars 683 forks source link

Clang system headers are not included by default #916

Open phord opened 7 years ago

phord commented 7 years ago

Issue and Steps to Reproduce

I get errors reported in diagnostics that I do not see when I compile the file in the shell using the command from my compile_commands.json. Is there some what to verify the compiler command line being used? I checked in the /tmp/nuclide--logs/nuclide.log, but the details are not there. I see some results in /tmp/nuclide/clang/, but still no hint as to what the used switches are.

Expected Behavior

Clang compile should use the commands found in compile_commands.json at the top of the project. Errors reported to Diagnostics should match what I see on the commandline console.

Actual Behavior

Different errors are reported which suggest the wrong --std switch is used, wrong include files are found, etc.

Versions

Additional Details

└── (empty)

Outline seems to work now, but autocomplete and "goto" do not seem right at all. In Nuclide-clang I have all the checkmarks unchecked: [ ] Enable diagnostics with default flags [ ] Enable default compilation flags

Edit: add libclang.so version

hansonw commented 7 years ago

The flags are visible as flags to a clang_server.py process, so you can do ps ax | grep clang_server to see the flags. Do those match up?

phord commented 7 years ago

Yes, thanks. Those do match what I expected from my compile_commands.json.

When I copy those switches from ps and run clang with them, I see 6 warnings-as-errors generated and 6 definition-reference notes. In Nuclide, however, I see 8 completely different errors for the same file, including "too many errors emitted, stopping now".

It's not a subtle difference. The two sets of reported errors have nothing in common.

From the cmdline:

error: 'execute' overrides a member function but is not marked 'override' [-Werror,-Winconsistent-missing-override]
error: comparison of unsigned expression >= 0 is always true [-Werror,-Wtautological-compare]
error: comparison of constant 2 with expression of type 'my_type' is always true [-Werror,-Wtautological-constant-out-of-range-compare]
error: comparison of constant 2 with expression of type 'my_type' is always true [-Werror,-Wtautological-constant-out-of-range-compare]
error: comparison of constant 2 with expression of type 'my_type' is always true [-Werror,-Wtautological-constant-out-of-range-compare]
error: moving a local object in a return statement prevents copy elision [-Werror,-Wpessimizing-move]

--

From Nuclide:

Error   Clang  1   too few template arguments for class template 'my_template_type' template is declared here      
Error   Clang  1   too few template arguments for class template 'my_template_type' template is declared here      
Error   Clang  1   too many errors emitted, stopping now      
Error   Clang  80   field has incomplete type 'my_template_type' forward declaration of 'my_template_type'      
Error   Clang  81   field has incomplete type 'my_template_type' forward declaration of 'my_template_type'      
Error   Clang  84   field has incomplete type 'my_template_type' forward declaration of 'my_template_type'      
Error   Clang  122   field has incomplete type 'my_template_type' forward declaration of 'my_template_type'      
Error   Clang  123   field has incomplete type 'my_template_type' forward declaration of 'my_template_type'

I'll poke around in clang_server.py and see if I can get it to cough up some answers. Appreciate any further suggestions, though.

hansonw commented 7 years ago

The two Clang versions may not be in sync; we use libclang not clang directly. What versions of clang and libclang do you have installed? (probably check your apt packages). I'd recommend at least having libclang 3.7+ installed.

On Tue, Dec 6, 2016 at 10:14 AM, Phil Hord notifications@github.com wrote:

Yes, thanks. Those do match what I expected from my compile_commands.json.

When I copy those switches from ps and run clang with them, I see 6 warnings-as-errors generated and 6 definition-reference notes. In Nuclide, however, I see 8 completely different errors for the same file, including "too many errors emitted, stopping now".

It's not a subtle difference. The two sets of reported errors have nothing in common.

From the cmdline:

error: 'execute' overrides a member function but is not marked 'override' [-Werror,-Winconsistent-missing-override] error: comparison of unsigned expression >= 0 is always true [-Werror,-Wtautological-compare] error: comparison of constant 2 with expression of type 'my_type' is always true [-Werror,-Wtautological-constant-out-of-range-compare] error: comparison of constant 2 with expression of type 'my_type' is always true [-Werror,-Wtautological-constant-out-of-range-compare] error: comparison of constant 2 with expression of type 'my_type' is always true [-Werror,-Wtautological-constant-out-of-range-compare] error: moving a local object in a return statement prevents copy elision [-Werror,-Wpessimizing-move]

--

From Nuclide:

Error Clang 1 too few template arguments for class template 'my_template_type' template is declared here Error Clang 1 too few template arguments for class template 'my_template_type' template is declared here Error Clang 1 too many errors emitted, stopping now Error Clang 80 field has incomplete type 'my_template_type' forward declaration of 'my_template_type' Error Clang 81 field has incomplete type 'my_template_type' forward declaration of 'my_template_type' Error Clang 84 field has incomplete type 'my_template_type' forward declaration of 'my_template_type' Error Clang 122 field has incomplete type 'my_template_type' forward declaration of 'my_template_type' Error Clang 123 field has incomplete type 'my_template_type' forward declaration of 'my_template_type'

I'll poke around in clang_server.py and see if I can get it to cough up some answers. Appreciate any further suggestions, though.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/facebook/nuclide/issues/916#issuecomment-265227129, or mute the thread https://github.com/notifications/unsubscribe-auth/AAjPYohEHWybYXdVscFOH9L6VA5vw9gkks5rFaX5gaJpZM4LE8qf .

phord commented 7 years ago

clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final) Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin

Also, I noticed my error lists above are misleading. I had "show only diagnostics for current file" checked. There's about 15 more errors attributed to other files, including this one:

Error   Clang  my_hdr2.h  26   'stddef.h' file not found

This could be the source of all the other errors.

From this FAQ:

$ clang -### -c foo.c
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
"/usr/lib/llvm-3.8/bin/clang" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" "-mrelax-all" "-disable-free" 
    "-disable-llvm-verifier" "-main-file-name" "foo.c" "-mrelocation-model" "static" "-mthread-model"  
    "posix" "-mdisable-fp-elim" "-fmath-errno" "-masm-verbose" "-mconstructor-aliases"  
    "-munwind-tables" "-fuse-init-array" "-target-cpu" "x86-64" "-dwarf-column-info"  
    "-debugger-tuning=gdb" "-coverage-file" "/home/phord/git/bld_linux/purity/foo.c"  
    "-resource-dir" "/usr/lib/llvm-3.8/bin/../lib/clang/3.8.0" "-internal-isystem" "/usr/local/include" 
    "-internal-isystem" "/usr/lib/llvm-3.8/bin/../lib/clang/3.8.0/include" "-internal-externc-isystem"  
    "/usr/include/x86_64-linux-gnu" "-internal-externc-isystem" "/include" "-internal-externc-isystem" 
     "/usr/include" "-fdebug-compilation-dir" "/home/phord/git/bld_linux/purity" "-ferror-limit" "19"  
    "-fmessage-length" "277" "-fobjc-runtime=gcc" "-fdiagnostics-show-option" "-fcolor-diagnostics"  
    "-o" "foo.o" "-x" "c" "foo.c"

Investigating further.

phord commented 7 years ago

Maybe -cc1 is a red herring. But I'm still parsing the faq.

This is suspicious:

Some header files (stddef.h, stdarg.h, and others) are shipped with Clang — these are called builtin includes. Clang searches for them in a directory relative to the location of the clang binary. If you moved the clang binary, you need to move the builtin headers, too.

Maybe I need to symlink my .so into a specific location instead of using it where it was installed by the OS pkg.

phord commented 7 years ago

The FAQ says:

the default location to look for builtin headers is in a path $(dirname /path/to/tool)/../lib/clang/3.3/include relative to the tool binary.

Presumably that "3.3" should be 3.8.

My libclang.so is at: /usr/lib/llvm-3.8/lib/libclang.so My clang stddef.h is at: /usr/lib/llvm-3.8/lib/clang/3.8.0/include/stddef.h So I expect to find stdlib headers at: /usr/lib/llvm-3.8/lib/../lib/clang/3.8/include

I tried to symlink /usr/lib/llvm-3.8/lib/clang/3.8 -> /usr/lib/llvm-3.8/lib/clang/3.8.0 with no luck.

But this does work as a workaround for this problem. I added this to each of my compile commands: -isystem /usr/lib/llvm-3.8/lib/clang/3.8.0/include

Maybe there needs to be an extra setting for the system include paths, or maybe it can be discovered somehow with libclang. In case it matters, my libclang.so and my stddef.h come from two different packages. Perhaps they are dependent on each other or some common package. I didn't dig that far.

libclang-common-3.8-dev: /usr/lib/llvm-3.8/lib/clang/3.8.0/include/stddef.h
libclang-3.8-dev: /usr/lib/llvm-3.8/lib/libclang.so
hansonw commented 7 years ago

Oh... I think @modocache was also running into this before. I wonder why the clang binary and libclang.so behave differently here. The -### flag is a great tool, thanks for that - maybe I can figure out how to obtain those same flags somehow.

hansonw commented 7 years ago

I found this related issue from YouCompleteMe: https://github.com/valloric/YouCompleteMe/issues/303

Maybe we can implement the heuristic of grabbing the paths from Clang :/

phord commented 7 years ago

I guess that would work. But it seems goofy. :roll_eyes: It's always bugged me that this is hardcoded into the compiler, even for gcc, but I don't really have a better suggestion.

If you go this route, I expect this info is worthy of caching to avoid an extra fork every time. And maybe worthy of providing the user an option to override with his own explicit paths.

Because, for example, on my system I actually have 14 different installations of the C++ stdlibs. There's even a better one to be had from llvm, and it might be installed in some user-defined location.

phord commented 7 years ago

It occurred to me that RTags doesn't have this problem. I looked at what he does there; I think he runs the compiler at startup and gets it to cough up the path. But he also allows the path to be overridden by an environment setting.

AlexTalks commented 7 years ago

This issue has been bothering me as well somewhat. YCM has the concept of the .ycm_extra_conf.py for manually providing additional compilation flags for libclang, so I figured a similar solution could be useful here. I've added support for reading a nuclide_clang_flags.json, which allows manually specifying project-wide compiler flags to add, flags to filter out, and -isystem paths to include. This solution seems to be working pretty well for me thus far actually.

If it sounds useful I'm happy to submit it as a pull request.

hansonw commented 7 years ago

Keeping this open - although @AlexTalks's contribution will help quite significantly, I imagine we still want to do this by default :)