Repository navigation
Cannot properly set Include and Defines with third-party compilers #4269
Description
Type: LanguageService
Describe the bug
- OS and Version: Windows 10 (Windows_NT x64 10.0.17763)
- VS Code Version: 1.38.1
- C/C++ Extension Version: 0.25.1
- It does not seem possible to use
compileCommandsplus other global includes/defines taken fromincludePathanddefinesproperties respectively.
I'm using a third-party compiler (ARM) which has its own includes and defines, but I also need to use project-related include/defines taken from compile_commands.json (generated via CMake).
I'm trying to set compiler-specific includes/defines manually, and then use compileCommands property for project-specific includes/defines.
This is a minimal version of my c_cpp_properties.json:
{
"configurations": [
{
"name": "ARM",
"compilerPath": "",
"cStandard": "c99",
"cppStandard": "c++03",
"intelliSenseMode": "gcc-x86",
"compileCommands": "${workspaceFolder:Project}/.vscode/compile_commands.json",
"defines": [
"__ARM__"
],
"includePath": [
"\"C:\\Program Files (x86)\\ARM_Compiler_5.06u4\\include\""
]
}
],
"version": 4
}
Also I would like to set something like "intelliSenseMode": null, because neither MSVC, GCC nor CLang are correct choices for my case. Why does IntelliSense need this info?
This is the full Log Diagnostics output (except sensitive paths):
-------- Diagnostics - 18/9/2019, 17:30:29
Version: 0.25.1
Current Configuration:
{
"name": "ARM",
"compilerPath": "",
"cStandard": "c99",
"cppStandard": "c++03",
"intelliSenseMode": "gcc-x86",
"compileCommands": "d:\\path/.vscode/compile_commands.json",
"defines": [
"__ARM__"
],
"includePath": [
"\"C:\\Program Files (x86)\\ARM_Compiler_5.06u4\\include\""
],
"compilerArgs": [],
"browse": {
"path": [
"\"C:\\Program Files (x86)\\ARM_Compiler_5.06u4\\include\"",
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
}
}
Translation Unit Mappings:
[ D:\path\myfile.cpp ]:
D:\PATH\MYFILE.CPP
Translation Unit Configurations:
[ D:\path\myfile.cpp ]:
Process ID: 3332
Memory Usage: 21 MB
Includes:
D:\PATH\INCLUDE1
D:\PATH\INCLUDE2
D:\...
...
Defines:
__ARM__
Standard Version: c++03
IntelliSense Mode: gcc-x64
Other Flags:
--g++
--gnu_version=80100
Total Memory Usage: 21 MB
This is a screenshot to show the problems encountered:

I see 3 main problems:
- Include paths: the include path list (inside Log Diagnostics) does not contain the
includePathspecified inc_cpp_properties.json, but only the paths found incompile_commands.json; Since myincludePathis not present, the compiler headers are not recognized (e.g.string.his not found as you can see from the screen); - Defines: viceversa, the defines list contains only the ones specified manually into
c_cpp_properties.jsonbut does not contain the ones fromcompile_commands.json; moreover, even if the macro is present in the list (e.g.__ARM__), the editor does not recognizes it and the wrong preprocessor branch is greyed out! - IntelliSense Mode: it seems that there is no suitable intelliSenseMode for my use case; I put gcc-x86, but CPPTools seems to ignore it anyway (you can see gcc-x64 in the Log Diagnostics); I would also like to avoid the section "Other Flags" which seems to contain gcc-related stuff.
Expected behavior
In the Log Diagnostics I expect to see the union of includes/defines from both c_cpp_properties.json and compile_commands.json, and I expect them to work in the editor.
Activity
CfirTsabari commentedon Sep 18, 2019
hi,
try to change this:
"includePath": [
""C:\Program Files (x86)\ARM_Compiler_5.06u4\include""
]
to this:
"includePath": [
""C:\Program Files (x86)\ARM_Compiler_5.06u4\include\**""
]
sean-mcmanus commentedon Sep 18, 2019
CfirTsabari Using "**" with system includes is not recommended because the ordering may not be correct. If subfolders are required, it's better to just list them in the correct order.
gentooise Our compiler only supports emulation of cl.exe, gcc, and clang, so it needs to be set to one of these modes.
It looks like our C/C++: Log Diagnostics command has a bug in the compile_commands.json scenario where it is showing the c_cpp_properties.json instead of the defines obtained from the compile_commands.json -- I could file a new bug for that: #4270 .
Our compile_commands.json and configurationProvider were designed to ignore the includePath and defines in c_cpp_properties.json, unless a source file is encountered that doesn't have configuration info. One workaround is to set your compilerPath to a .bat (Windows) or .sh (Linux/Mac) script that outputs the system includes and defines you want, such as
Let us know if that workaround doesn't work for you. We have a fix pending for the lack of support for "${workspaceFolder}" in the compilerPath and compilerArgs: #3440 .
sean-mcmanus commentedon Sep 18, 2019
Actually, it looks like the arm compiler should be "the same" as gcc. Can you check what error occurs when you specific that compiler as the compilerPath? Is our mechanism for querying the compiler for system includes and defines failing? enabling debug logging might give better failure info.
sean-mcmanus commentedon Sep 18, 2019
Is the ARM compiler you're using publicly available for us to try out?
sean-mcmanus commentedon Sep 18, 2019
Also, we don't have the proper flags/settings enabled to give 100% correct results for ARM -- specifically we need to add intelliSenseMode's for gcc-arm, gcc-arm64, clang-arm, clang-arm64, windows-arm, windows-arm64 support. I should file a new issue to track that: #4271
gentooise commentedon Sep 19, 2019
Ok, is it only an aesthetic problem then?
I understand. I will try ASAP and let you know, but I do not understand some details of the expected output format (
search starts here:,^<...^>?). Could you directly give me an output example for the script?Unfortunately not, ARM Compiler is not the same as GCC, it is a commercial compiler that has its own includes, macros, and command line arguments. I can put it in
compilerPathanyway and let you know ASAP, but I already know how this compiler works:--list_macros), but the output format does not seem equivalent to the gcc one.My point is that it could be useful to have a generic way to handle compilers that are not specifically supported: your hint about a script file could be one way to do it. Another way could be to have the possibility to (manually) put other includes/defines in addition to the ones found in
compile_commands.json.Unfortunately not, it can be only used by purchasing a license.
Please note that the compiler is not gcc-arm or clang-arm. The correct names are
armccandarmclang, and they have nothing to do with gcc. I already know it because I recently encountered similar issues for an eclipse plugin (here).Finally, I have another question: which is the purpose of the
configurationProvider? What does it add with respect tocompileCommandsoption? Because in my case I'm using CMake with CMake Tools VSCode extension, and this extension is made to be a configuration provider. But to me this seems redundant, because the information provided by the CMake Tools is always taken fromcompile_commands.json, which is the unique source of information that comes out from CMake. So, which is the difference between usingcompileCommandsonly,configurationProvideronly or both of them?gentooise commentedon Sep 19, 2019
Yes it is failing because it seems to switch to MinGW GCC. This is the output of Log Diagnostics:
As you can see, it assumes that the compiler is MinGW GCC, and takes in all its include paths.
Anyway, I enabled debug logging but I don't see any output difference, please tell me where to find debug logs (if any).
gentooise commentedon Sep 19, 2019
I tried also this, and I got the same result as above (same Log Diagnostics), except for the line:
"compilerPath": "${workspaceRoot}/.vscode/compile.bat",where compile.bat contains the following:
sean-mcmanus commentedon Sep 20, 2019
Yeah, the defines being incorrect is a bug in the logging output.
The
^<is just to escape the<so the output should not contain the^but otherwise should appear the same -- you may need to escape other characters though too.If you're using CMake and the CMake Tools extension, you would probably get better results if you set the configurationProvider setting and not the compileCommands setting. Is the CMake Tools extension able to get the correct system includes/defines?
The .bat file probably doesn't work because haven't shipped the fix for
${workspaceFolder}not working in compilerPath: #3440 . However, even after using the full path, I'm getting "Compiler include path not found"...so we need to investigate why that isn't working -- it might only work with Linux-style paths currently.gentooise commentedon Sep 20, 2019
Got it, thanks.
I'm probably not using the CMake Tools extension correctly, because I get this when opening cpp files:

How does CMT get info from compile_commands.json? It reads the file directly from the current build directory? Or I have to copy it inside .vscode folder? (Consider I have different cmake-variants with different build directories).
Please tell me if this is the right place or I should open an issue for vscode-cmake-tools instead.
I used
${workspaceRoot}in fact, do you think is not working anyway?gentooise commentedon Sep 20, 2019
UPDATE: I'm going on with the batch script strategy and I noticed that also parenthesis need to be escaped with
^. Right now I have the following situation (which is partially working).c_cpp_properties.json:
compile.bat:
I get the following Log Diagnostics:
I think this is really close to be solved, but I still see the following issues:
The include path is correctly visible in the log at the end of


Includessection, but VSCode is still unsure about where to find headers (the right one is only the third choice highlighted in red):Why am I still seeing MinGW and other includes? This is a problem because later in the same cpp file I get undefined symbols because of wrong includes:
In this case, ARM compiler include is not considered at all, but I can confirm that the file
string.hexists inC:\Program Files (x86)\ARM_Compiler_5.06u4\includeand it contains a valid definition ofsnprintf(my code builds correctly).Defines are not shown inside Log Diagnostics instead, but they are working correctly inside the editor: I think this is always due to C/C++: Log Diagnostics shows incorrect defines when compile_commands.json is used #4270
The IntelliSense Mode still seems to "randomly" switch to different modes (clang-x64 in this case), but I don't know which are the effects of this.
2 remaining items
gentooise commentedon Sep 24, 2019
files.exclude seems enough as a workaround for now, thank you.
I added these lines to the
compile.bat:but cpptools now falls back to
gcc-x64.sean-mcmanus commentedon Sep 28, 2019
gentooise Ah, yeah, thanks for reporting that -- I see in the code where it's setting it to gcc-x64. I filed bug #4353 . I think we'll be able to fix that for our next release (update: it should be fixed in our next Insiders release, today or tomorrow).
sean-mcmanus commentedon Oct 2, 2019
gentooise The x86 mode not being used should be fixed with https://github.com/microsoft/vscode-cpptools/releases/tag/0.26.0-insiders . Let us know if it's not working for you.
gentooise commentedon Oct 2, 2019
That's perfect:
IntelliSense Mode: gcc-x86Thanks.
bobbrow commentedon Oct 3, 2019
I'm coming late to the discussion. We should write up some documentation about how to work with unsupported compilers.
I think a better approach is to use a combination of the
C_Cpp.default.systemIncludePathandC_Cpp.default.definessettings, but we should validate this will provide the expected results before writing up the documentation.gentooise commentedon Oct 9, 2019
Thanks for the hint. I tried your approach, but it is partially working for me. It is ok for
C_Cpp.default.systemIncludePath, but not forC_Cpp.default.defines.In particular, I'm using
C_Cpp.default.systemIncludePathandC_Cpp.default.definesin place ofcompile.bat, and I also set"C_Cpp.default.compilerPath": ""to avoid further compiler queries.However, according to this article,
C_Cpp.default.definesis ignored whencompileCommandsis set (case 1), and I verified that is happening in my case. I think it could be useful to have a correspondingC_Cpp.default.systemDefines.Here diagnostic logs (which shows my system defines anyway, even if they are not used by IntelliSense):