microsoft / vscode-cmake-tools

CMake integration in Visual Studio Code
https://marketplace.visualstudio.com/items?itemName=vector-of-bool.cmake-tools
MIT License
1.48k stars 454 forks source link

Header files missing in certain cases when add_custom_command() is used. #4099

Open chessing-c4 opened 1 month ago

chessing-c4 commented 1 month ago

Brief Issue Summary

Under some circumstances that I have not been able to nail down, using the "add_custom_command()" causes header files to not show up in the CMake Project Outline in VSCode.

If you clone the "cpp-with-rust" repo from https://github.com/paandahl/cpp-with-rust and then modify the "add_executable()" line in the CMakeList.txt to contain "include/multibuf.h" you will see that multibuf.h doesn't show up in the project outline.

However, if you comment out the "add_custom_command()" block, and set the "${BLOBSTORE_BRIDGE_CPP}" variable to an empty value before the "add_executable()" call, you will see that the header file will show up again.

I have tried a few different permutations of "add_custom_command()" to attempt to narrow down what is happening, but I have been unable to. I DO know that the merge presence of an "add_custom_command()" doesn't cause the breakage. It seems to happen as a result of something that the "cargo" command that is being run does.

CMake Tools Diagnostics

{
  "os": "linux",
  "vscodeVersion": "1.93.1",
  "cmtVersion": "1.19.52",
  "configurations": [
    {
      "folder": "/home/chris/src/libtraceability/t/cpp-with-rust",
      "cmakeVersion": "3.30.2",
      "configured": true,
      "generator": "Ninja",
      "usesPresets": false,
      "compilers": {
        "C": "/usr/bin/gcc",
        "CXX": "/usr/bin/g++"
      }
    }
  ],
  "cpptoolsIntegration": {
    "isReady": true,
    "hasCodeModel": true,
    "activeBuildType": "Debug",
    "buildTypesSeen": [
      "Debug"
    ],
    "requests": [],
    "responses": [],
    "partialMatches": [],
    "targetCount": 1,
    "executablesCount": 1,
    "librariesCount": 0,
    "targets": [
      {
        "name": "cpp_with_rust",
        "type": "EXECUTABLE"
      }
    ]
  },
  "settings": [
    {
      "communicationMode": "automatic",
      "useCMakePresets": "auto",
      "configureOnOpen": true
    }
  ]
}

Debug Log

[main] Configuring project: cpp-with-rust 
[main] Saving open files before configure/build
[driver] Removing /home/chris/src/libtraceability/t/cpp-with-rust/build/CMakeCache.txt
[driver] Removing /home/chris/src/libtraceability/t/cpp-with-rust/build/CMakeFiles
[expand] expanded ${workspaceFolder}/build
[driver] Start configure 
[driver] Running pre-configure checks and steps
[driver] Using compilers in GCC 13.2.0 x86_64-linux-gnu for configure
[expand] expanded ${workspaceFolder}/build
[cmakefileapi-driver] Configuring using kit
[cmakefileapi-driver] Invoking CMake /usr/bin/cmake with arguments ["-DCMAKE_BUILD_TYPE:STRING=Debug","-DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE","-DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc","-DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++","-DSKB_TARGET_LIB_DIR=/home/chris/src/skb/lib/x86_64-unknown-linux-gnu","-DSKB_TARGET_INCLUDE_DIR=/home/chris/src/skb/Include","-DUNDEFINED_SANITIZER=On","-DADDRESS_SANITIZER=On","-DPAHO_WITH_SSL=TRUE","-DPAHO_BUILD_SAMPLES=TRUE","--no-warn-unused-cli","-S/home/chris/src/libtraceability/t/cpp-with-rust","-B/home/chris/src/libtraceability/t/cpp-with-rust/build","-G","Ninja"]
[proc] Executing command: /usr/bin/cmake -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++ -DSKB_TARGET_LIB_DIR=/home/chris/src/skb/lib/x86_64-unknown-linux-gnu -DSKB_TARGET_INCLUDE_DIR=/home/chris/src/skb/Include -DUNDEFINED_SANITIZER=On -DADDRESS_SANITIZER=On -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_SAMPLES=TRUE --no-warn-unused-cli -S/home/chris/src/libtraceability/t/cpp-with-rust -B/home/chris/src/libtraceability/t/cpp-with-rust/build -G Ninja
[proc]   with environment: {"CARGO_NET_GIT_FETCH_WITH_CLI":"true","CHROME_DESKTOP":"code-url-handler.desktop","CINNAMON_VERSION":"6.2.9","CLUTTER_IM_MODULE":"ibus","DBUS_SESSION_BUS_ADDRESS":"unix:path=/run/user/1000/bus","DESKTOP_SESSION":"cinnamon","DISPLAY":":1","GDK_BACKEND":"x11","GDMSESSION":"cinnamon","GIO_LAUNCHED_DESKTOP_FILE":"/usr/share/applications/code.desktop","GIO_LAUNCHED_DESKTOP_FILE_PID":"21149","GJS_DEBUG_OUTPUT":"stderr","GJS_DEBUG_TOPICS":"JS ERROR;JS LOG","GNOME_DESKTOP_SESSION_ID":"this-is-deprecated","GPG_AGENT_INFO":"/run/user/1000/gnupg/S.gpg-agent:0:1","GSM_SKIP_SSH_AGENT_WORKAROUND":"true","GTK3_MODULES":"xapp-gtk3-module","GTK_IM_MODULE":"ibus","GTK_MODULES":"gail:atk-bridge","HOME":"/home/chris","LANG":"en_US.UTF-8","LESSCLOSE":"/usr/bin/lesspipe %s %s","LESSOPEN":"| /usr/bin/lesspipe %s","LOGNAME":"chris","ORIGINAL_XDG_CURRENT_DESKTOP":"X-Cinnamon","PATH":"/home/chris/.local/bin:/home/chris/bin:/home/chris/.cargo/bin:/home/chris/.local/bin:/home/chris/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/go/bin:/usr/local/go/bin","PWD":"/home/chris","QT_ACCESSIBILITY":"1","QT_IM_MODULE":"ibus","SESSION_MANAGER":"local/chris-Precision-5820-Tower-X-Series:@/tmp/.ICE-unix/3125,unix/chris-Precision-5820-Tower-X-Series:/tmp/.ICE-unix/3125","SHELL":"/bin/bash","SHLVL":"0","SSH_AUTH_SOCK":"/run/user/1000/keyring/ssh","USER":"chris","USERNAME":"chris","VSCODE_AMD_ENTRYPOINT":"vs/workbench/api/node/extensionHostProcess","VSCODE_CODE_CACHE_PATH":"/home/chris/.config/Code/CachedData/38c31bc77e0dd6ae88a4e9cc93428cc27a56ba40","VSCODE_CRASH_REPORTER_PROCESS_TYPE":"extensionHost","VSCODE_CWD":"/home/chris","VSCODE_HANDLES_UNCAUGHT_ERRORS":"true","VSCODE_IPC_HOOK":"/run/user/1000/vscode-3ee20757-1.93-main.sock","VSCODE_NLS_CONFIG":"{\"userLocale\":\"en-us\",\"osLocale\":\"en-us\",\"resolvedLanguage\":\"en\",\"defaultMessagesFile\":\"/usr/share/code/resources/app/out/nls.messages.json\",\"locale\":\"en-us\",\"availableLanguages\":{}}","VSCODE_PID":"21149","WINDOWPATH":"2","XAUTHORITY":"/run/user/1000/gdm/Xauthority","XDG_CONFIG_DIRS":"/etc/xdg/xdg-cinnamon:/etc/xdg","XDG_CURRENT_DESKTOP":"X-Cinnamon","XDG_DATA_DIRS":"/usr/share/gnome:/usr/share/cinnamon:/usr/share/gnome:/home/chris/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/","XDG_RUNTIME_DIR":"/run/user/1000","XDG_SEAT":"seat0","XDG_SESSION_CLASS":"user","XDG_SESSION_DESKTOP":"cinnamon","XDG_SESSION_ID":"3","XDG_SESSION_TYPE":"x11","XDG_VTNR":"2","XMODIFIERS":"@im=ibus","_":"/usr/share/code/code","ELECTRON_RUN_AS_NODE":"1","VSCODE_DOTNET_INSTALL_TOOL_ORIGINAL_HOME":"/home/chris","VSCODE_L10N_BUNDLE_LOCATION":""}
[cmake] Not searching for unused variables given on the command line.
[cmake] -- The C compiler identification is GNU 13.2.0
[cmake] -- The CXX compiler identification is GNU 13.2.0
[cmake] -- Detecting C compiler ABI info
[cmake] -- Detecting C compiler ABI info - done
[cmake] -- Check for working C compiler: /usr/bin/gcc - skipped
[cmake] -- Detecting C compile features
[cmake] -- Detecting C compile features - done
[cmake] -- Detecting CXX compiler ABI info
[cmake] -- Detecting CXX compiler ABI info - done
[cmake] -- Check for working CXX compiler: /usr/bin/g++ - skipped
[cmake] -- Detecting CXX compile features
[cmake] -- Detecting CXX compile features - done
[cmake] -- Configuring done (0.5s)
[cmake] -- Generating done (0.0s)
[cmake] -- Build files have been written to: /home/chris/src/libtraceability/t/cpp-with-rust/build
[cmakefileapi-parser] Read reply folder: /home/chris/src/libtraceability/t/cpp-with-rust/build/.cmake/api/v1/reply
[cmakefileapi-parser] Found index files: ["cache-v2-0b8f47cbd1446980a287.json","cmakeFiles-v1-106258fa387a6685486b.json","codemodel-v2-f94df4806e9ab7ec8682.json","directory-.-Debug-f5ebdc15457944623624.json","index-2024-09-27T20-48-29-0661.json","target-cpp_with_rust-Debug-34910e5e8831d632de61.json","toolchains-v1-0dec0620bd9b8879ca34.json"]
[cache] Reading CMake cache file /home/chris/src/libtraceability/t/cpp-with-rust/build/CMakeCache.txt
[cache] Parsing CMake cache string
[extension] [7110] cmake.cleanConfigureAll finished (returned {"result":0,"resultType":0})

Additional Information

No response

kuch3n commented 1 month ago

The add_custom_command statement is missingBYPRODUCTS if you're using ninja.

Also i don't see a header file getting passed to add_executable. Is it generated by the call to add_custom_command? Or is it just the .cc file itself?

And it might be worth a look at dependency chains if you're generating code.

Maybe this solves your problem

v-frankwang commented 1 month ago

@gcampbell-msft I was able to reproduce this issue using a user supplied project, here are the detailed steps to reproduce it:

Repro steps:

  1. Clone the "cpp-with-rust" from https://github.com/paandahl/cpp-with-rust
  2. At the “add_executable()” line add include/multibuf.h
  3. Save the CMakeLists.txt file and observe the project outline

image

Set BLOBSTORE_BRIDGE_CPP to null before the add_executable line image

CMake Tools Diagnostics.txt

v-frankwang commented 1 month ago

@kuch3n The reproduction step of chessing-c4 has at the “add_executable()” line add include/multibuf.h, when I add the BYPRODUCTS attribute to add_custom_command the problem still reproduces, can you give us some suggestions? Can you give us some suggestions?

kuch3n commented 1 month ago
CMakeLists.txt ``` cmake_minimum_required(VERSION 3.22) project(cpp_with_rust) include(FetchContent) set(CMAKE_CXX_STANDARD 17) set(CARGO_MANIFEST ${CMAKE_SOURCE_DIR}/Cargo.toml) set(CARGO_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR}) set(BLOBSTORE_SOURCE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/lib.rs") set(BLOBSTORE_BRIDGE_CPP ${CARGO_TARGET_DIR}/cxxbridge/blobstore/src/lib.rs.cc) set(BLOBSTORE_BRIDGE_HEADER "${CARGO_TARGET_DIR}/cxxbridge/blobstore/src/lib.rs.h") set(BLOBSTORE_LIB ${CARGO_TARGET_DIR}/debug/${CMAKE_STATIC_LIBRARY_PREFIX}blobstore${CMAKE_STATIC_LIBRARY_SUFFIX}) file(MAKE_DIRECTORY "${CARGO_TARGET_DIR}/cxxbridge/blobstore/src/") add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/main.rs.h COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/src COMMAND touch -f ${CMAKE_CURRENT_BINARY_DIR}/src/main.rs.h USES_TERMINAL COMMENT "Running cargo..." ) execute_process(COMMAND cargo build --manifest-path ${CARGO_MANIFEST} --target-dir ${CMAKE_CURRENT_BINARY_DIR}) add_custom_target(blobstore-gen DEPENDS ${BLOBSTORE_BRIDGE_CPP} ${BLOBSTORE_BRIDGE_HEADER} ${BLOBSTORE_LIB}) add_library(test_with_generated STATIC ${CMAKE_CURRENT_BINARY_DIR}/src/main.rs.h ${CMAKE_CURRENT_SOURCE_DIR}/src/main.h ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp) add_library(test STATIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.h ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp) target_include_directories(test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/src ${CARGO_TARGET_DIR}/cxxbridge/blobstore/src/) set_source_files_properties(${BLOBSTORE_BRIDGE_CPP} PROPERTIES SYMBOLIC TRUE GENERATED TRUE) set_source_files_properties(${BLOBSTORE_BRIDGE_CPP} PROPERTIES SYMBOLIC TRUE GENERATED TRUE) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/src/main.rs.h PROPERTIES GENERATED TRUE) add_executable(cpp_with_rust ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/main.h ${CMAKE_CURRENT_SOURCE_DIR}/src/multibuf.cpp ${BLOBSTORE_BRIDGE_CPP} ${BLOBSTORE_BRIDGE_HEADER}) add_dependencies(cpp_with_rust blobstore-gen) add_dependencies(test blobstore-gen) target_include_directories( cpp_with_rust PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${CARGO_TARGET_DIR}/cxxbridge/blobstore/src/ ${CARGO_TARGET_DIR}/cxxbridge/blobstore/include/ ) target_link_libraries(cpp_with_rust ${BLOBSTORE_LIB}) set_target_properties( cpp_with_rust PROPERTIES ADDITIONAL_CLEAN_FILES ${CARGO_TARGET_DIR} ) # Windows-only configuration if(WIN32) target_link_libraries(cpp_with_rust userenv ws2_32 bcrypt) set_target_properties( cpp_with_rust PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreadedDLL" RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR} RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR} ) endif() ```

It looks like no headers are shown at all if a header is missing at configure time. Even if headers are touched at configure time, they're still missing in the outline.

If the generated header is not given as as source, other headers show up again. Compare targets test_with_generated and test.

I've added ./src/main.h manually to show above behaviour.

kuch3n commented 1 month ago

The api reply even lists the generated header filer:

        {
            "backtrace" : 1,
            "isGenerated" : true,
            "path" : "build/src/main.rs.h",
            "sourceGroupIndex" : 0
        },
        {
            "backtrace" : 1,
            "path" : "src/main.h",
            "sourceGroupIndex" : 0
        },

The difference is the isGenerated key

kuch3n commented 1 month ago

I've deleted all isGenerated keys, restarted VSCode and the "missing" headers show up in the project outline.

So if you specify sources which are genearted by, e.g., OUTPUT or BYPRODUCTS, above key gets set and the project outline gets borked.

gcampbell-msft commented 1 month ago

@chessing-c4 @kuch3n Reading through the above investigation, would it be correct to say that this issue is a request to show generated headers in the project outline?

chessing-c4 commented 1 month ago

@gcampbell-msft I don't believe that is correct from my perspective. In my case, none of the header files from the project show up. It doesn't matter if they were generated or not. Honestly, I am less concerned about the generated ones, and more interested in the ones that exist as part of the static source tree.

I will try to find a few minutes today to do what @kuch3n mentioned and see if that resolves the issue. But, from what he describes, it sounds like it might. (If I follow what @kuch3n is saying, they are saying that when "isGenerated" shows up in that file, none of the headers show up. Which is what I am seeing. Or, more specifically, "the project outline gets borked."

gcampbell-msft commented 1 month ago

Interesting, okay, sounds like it definitely warrants investigation, I'll mark it down for investigation and put it in the backlog.

kuch3n commented 1 month ago

yes, as soon as the isGenerated key shows up in the API response, no header shows up at all for a target containing generated files.

If you manually delete those keys and restart visual studio code, all headers, including those generated, show up again.

v-frankwang commented 1 month ago

@kuch3n Thank you very much for your reply, our developers are investigating this issue and we'll update the review with any results as soon as we have them.