Missing quote when preprocessor macro contains expression.
OS: Kubuntu 21.04 VSC:1.58.0 extension: 1.5.1
Hello,
in my CMakeList i have this configuration:
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D__FILENAME__='\"$(notdir $(abspath $<))\"'")
I can build applicaiton with gcc 10. In PROBLEMS section i see "errors" with missing end quoting ". This is due to you parser is reading above option as "$(notdir.
Disabling this worked "C_Cpp.errorSquiggles". But is it the only option? Are you able to support this case better?

Hi @Hadatko . How are you configuring the C/C++ Extension? Are you using the CMake Tools extension to provide configuration information from CMake directly to the C/C++ Extension? It's possible the issue has to do with configuration processing done by CMake Tools. Could you enable debug output using "C_Cpp.loggingLevel": "Debug", and post your C/C++ output leading up to the repro? Also, could you post the output of the C/C++: Log Diagnostics command with the repro file open? Those logs should give up some information about how the value of the define is being provided and processed.
Hi, thank you for quick response. My current settings:
{
"C_Cpp.default.configurationProvider": "vector-of-bool.cmake-tools",
"C_Cpp.default.browse.path": ["${workspaceFolder}/Firmware/pilot"],
"C_Cpp.clang_format_style": "file",
"C_Cpp.autocomplete": "Default",
"C_Cpp.formatting": "clangFormat",
"cmake.buildEnvironment": {
"ARMGCC_DIR": "${workspaceFolder}/Tools/gcc-arm-none-eabi"
},
"cmake.configureSettings": {
"CMAKE_C_COMPILER_WORKS": "1",
"CMAKE_CXX_COMPILER_WORKS": "1",
"CMAKE_C_COMPILER": "${workspaceFolder}/Tools/gcc-arm-none-eabi/bin/arm-none-eabi-gcc",
"CMAKE_CXX_COMPILER": "${workspaceFolder}/Tools/gcc-arm-none-eabi/bin/arm-none-eabi-g++",
"CMAKE_ASM_COMPILER": "${workspaceFolder}/Tools/gcc-arm-none-eabi/bin/arm-none-eabi-gcc"
},
"cmake.environment": {
"ARMGCC_DIR": "${workspaceFolder}/Tools/gcc-arm-none-eabi"
},
"cmake.buildDirectory": "${workspaceFolder}/Firmware/pilot/build",
"cmake.sourceDirectory": "${workspaceFolder}/Firmware/pilot/",
"cmake.buildBeforeRun": true,
"cmake.saveBeforeBuild": true,
"cmake.configureOnOpen": true,
Cpptools Extension Log
``` cpptools/didChangeCppProperties $/setTraceNotification cpptools/getCodeActions: file://~/source/tasks/i2c1_task.c (id: 75) cpptools/activeDocumentChange: file://~/source/tasks/i2c1_task.c cpptools/textEditorSelectionChange cpptools/textEditorSelectionChange cpptools/getFoldingRanges: file://~/source/tasks/i2c1_task.c (id: 76) cpptools/getCodeActions: file://~/source/tasks/i2c1_task.c (id: 77) textDocument/documentHighlight: file://~/source/tasks/i2c1_task.c (id: 78) cpptools/textEditorSelectionChange textDocument/definition: file://~/source/tasks/i2c1_task.c (id: 79) cpptools/getCodeActions: file://~/source/tasks/i2c1_task.c (id: 80) textDocument/didSave: file://~/source/tasks/i2c1_task.c tag parsing file: ~/source/tasks/i2c1_task.c cpptools/fileChanged: file://~/source/tasks/i2c1_task.c textDocument/hover: file://~/source/tasks/i2c1_task.c (id: 82) idle loop: reparsing the active document Checking for syntax errors: file://~/source/tasks/i2c1_task.c Queueing IntelliSense update for files in translation unit of: ~/source/tasks/i2c1_task.c cpptools/finishUpdateSquiggles Error squiggle count: 7 Update IntelliSense time (sec): 0.256 cpptools/getSemanticTokens: file://~/source/tasks/i2c1_task.c (id: 83) cpptools/getFoldingRanges: file://~/source/tasks/i2c1_task.c (id: 84) cpptools/getCodeActions: file://~/source/tasks/i2c1_task.c (id: 85) textDocument/hover: file://~/source/tasks/i2c1_task.c (id: 86) textDocument/didChange: file://~/source/tasks/i2c1_task.c cpptools/textEditorSelectionChange cpptools/getFoldingRanges: file://~/source/tasks/i2c1_task.c (id: 87) cpptools/getCodeActions: file://~/source/tasks/i2c1_task.c (id: 88) cpptools/getDocumentSymbols: file://~/source/tasks/i2c1_task.c (id: 89) cpptools/getDocumentSymbols cpptools/getSemanticTokens: file://~/source/tasks/i2c1_task.c (id: 90) textDocument/didChange: file://~/source/tasks/i2c1_task.c cpptools/textEditorSelectionChange cpptools/getFoldingRanges: file://~/source/tasks/i2c1_task.c (id: 91) cpptools/getCodeActions: file://~/source/tasks/i2c1_task.c (id: 92) cpptools/getDocumentSymbols: file://~/source/tasks/i2c1_task.c (id: 93) textDocument/didSave: file://~/source/tasks/i2c1_task.c tag parsing file: ~/source/tasks/i2c1_task.c cpptools/fileChanged: file://~/source/tasks/i2c1_task.c idle loop: reparsing the active document Checking for syntax errors: file://~/source/tasks/i2c1_task.c Queueing IntelliSense update for files in translation unit of: ~/source/tasks/i2c1_task.c sending 1 changes to server sending 1 changes to server cpptools/finishUpdateSquiggles Error squiggle count: 7 cpptools/getFoldingRanges: file://~/source/tasks/i2c1_task.c (id: 95) cpptools/getCodeActions: file://~/source/tasks/i2c1_task.c (id: 96) Checking for syntax errors: file://~/source/tasks/i2c1_task.c Queueing IntelliSense update for files in translation unit of: ~/source/tasks/i2c1_task.c cpptools/getSemanticTokens: file://~/source/tasks/i2c1_task.c (id: 97) cpptools/getDocumentSymbols cpptools/finishUpdateSquiggles Error squiggle count: 7 Update IntelliSense time (sec): 2.539 cpptools/getSemanticTokens: file://~/source/tasks/i2c1_task.c (id: 98) cpptools/getFoldingRanges: file://~/source/tasks/i2c1_task.c (id: 99) cpptools/getCodeActions: file://~/source/tasks/i2c1_task.c (id: 100) Database safe to open cpptools/clearCustomConfigurations Shutting down IntelliSense server: ~/source/tasks/i2c1_task.c Checking for syntax errors: file://~/source/tasks/i2c1_task.c cpptools/queryTranslationUnitSource: file://~/source/tasks/i2c1_task.c (id: 101) Custom configurations received: uri: file://~/source/tasks/i2c1_task.c config: { "defines": [ "NDEBUG", "SDK_I2C_BASED_COMPONENT_USED=1", "SERIAL_PORT_TYPE_UART=1", "FSL_RTOS_FREE_RTOS", "BOARD_USE_CODEC=1", "CODEC_WM8960_ENABLE", "PRINTF_ADVANCED_ENABLE=1", "__FILENAME__='\"$(notdir" ], "standard": "gnu99", "includePath": [ "~/erpc/infra", "~/rpmsg_lite/env/freertos", "~/erpc/transports", "~/component/eps", "~/component/i2c", "~/freertos/freertos_kernel/portable/GCC/ARM_CM4F", "~/codec", "~/srtm/channels", "~/component/lists", "~/freertos/freertos_kernel/include", "~/doc", "~/startup", "~/srtm/services", "~/CMSIS", "~/utilities", "~/src", "~/drivers/freertos", "~/srtm/include", "~/rpmsg_lite/porting", "~/srtm/srtm", "~/component/serial_manager", "~/sensors", "~/erpc/port", "~/device", "~/source", "~/board", "~/erpc/setup", "~/source/tasks", "~/CMSIS_driver", "~/pmic_driver", "~/component/uart", "~/rpmsg_lite", "~/drivers", "~/erpc/service", "~/config", "~/component/bd70528", "~/source/erpc_message", "~/build/Release/service", ], "compilerPath": "~/Tools/gcc-arm-none-eabi/bin/arm-none-eabi-gcc", "compilerArgs": [ "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-O3", "-DNDEBUG", "-DSDK_I2C_BASED_COMPONENT_USED=1", "-DSERIAL_PORT_TYPE_UART=1", "-DFSL_RTOS_FREE_RTOS", "-DBOARD_USE_CODEC=1", "-DCODEC_WM8960_ENABLE", "-Os", "-mcpu=cortex-m4", "-Wall", "-mfloat-abi=hard", "-mfpu=fpv4-sp-d16", "-mthumb", "-MMD", "-MP", "-fno-common", "-ffunction-sections", "-fdata-sections", "-ffreestanding", "-fno-builtin", "-mapcs", "-std=gnu99", "-DPRINTF_ADVANCED_ENABLE=1", "-D__FILENAME__='\"$(notdir", "$(abspath", "$I had to remove some specific project files.
Hi @Hadatko This looks like an issue with CMake Tools, so I've transferred it to the CMake Tools repo.
The custom configuration provided by CMake Tools contains:
"__FILENAME__='\"$(notdir"
I assume the resulting value of the macro should be "$(notdir $(abspath $<))", so there may be a combination of issues here related to quote matching and handling of escaping.
@Hadatko Can you confirm what the macro is defined as when built using CMake? If CMake is processing the notdir and abspath functions, that could be an issue (in addition to quote and space parsing).
What version of CMake are you using, and what generator are you using? I noticed this issue that may be related: https://discourse.cmake.org/t/base-filename-gets-set-to-compiler-depend-ts-after-update-to-cmake-3-20/3075
Hi, sorry for bothering you. I didn't know it is Cmake issue as it looked like yours.
As mentioned above, in CMakeList i have set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D__FILENAME__='\"$(notdir $(abspath $<))\"'"). notdir and abspath are gcc functions. So Cmake cannot parse it same way as gcc (because value is different for each source code) but at least they could use full origin description __FILENAME__="$(notdir $(abspath $<))"
Cmake version: cmake version 3.18.4
Thank you for your link. Definitely it looks related. But they wrote that 3.18 should be fine :/ Maybe they have a bit different issue and this one is a bit different.
COuld you point me to the issue you created in cmake repository? Thank you.
COuld you point me to the issue you created in cmake repository?
Hi @Hadatko . I transferred your original issue (this one) to the CMake Tools repo. Your last response was in the CMake Tools repo. :)
If I understand correctly, the issue is that CMake Tools is not properly parsing quoted strings containing spaces (or perhaps escaped quotes) when reading defines from the CMake build, and the value of that macro should be: "$(notdir $(abspath $<))".
(Note that parsing of arg strings within single-quotes is not supported by the shell on Windows. Some related info is here: https://github.com/microsoft/vscode-cpptools/issues/6773).
Thank you very much :) Windows is not supported in our application so it is fine. And you are understanding me correctly.
With v6 of the cpptools-api, cpptools added a compilerFragments field, and clarified that arguments passed to compilerFragments may contain shell quoting and escaping (interpreted as a command line fragment), while arguments passed to compilerArgs must not. This decision was made to allow CMake Tools to avoid having to correctly parse fragments read from CMake, as the code to do so is difficult to do correctly and should already be done correctly in cpptools.
In this case, I assume -I and -D arguments are being parsed in order to populate the includePath and defines fields of a SourceFileConfiguration. Since it looks like these are may contain shell quoting/escaping, it may be sufficient to leave them as fragments and pass them in compilerFragments. Cpptools should process the shell quoting/escaping correctly, and know what to do with them. (This makes includePath and defines fields seem unnecessary, but they are still useful for providers that do not provide a compilerPath and args/fragments, which are optional fields.)
I assume -I and -D arguments are being parsed in order to populate the includePath and defines
Actually, it looks like this assumption was incorrect. Most includes and defines are provided by CMake without any shell escaping. But CMAKE_C_FLAGS_RELEASE (etc) is actually processed as a compiler argument, so the adoption of cpptools-api v6 and passing fragments via compilerFragment will implicitly fix this issue.
This issue will be resolved after adding support for CppTools API V6: https://github.com/microsoft/vscode-cmake-tools/pull/2563