vscode-cmake-tools icon indicating copy to clipboard operation
vscode-cmake-tools copied to clipboard

CMake default invocation command arguments differs (ctrl+s on CMakeLists.txt vs. Build)

Open GuillaumeDua opened this issue 3 years ago • 4 comments

Brief Issue Summary


-B/build folder taking into account for configuration, but not for build


When pressing ctrl+s on a CMakeLists.txt file opened, vscode-cmake-tools extension may runs the following command :

[proc] Executing command: /usr/bin/cmake --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/clang -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/clang++ -S/mnt/path_to_my_project -B/mnt/c/path_to_my_project/build -G "Unix Makefiles"

So projects ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR} differs, which is totally OK.

However, when I press the "Build" button on the bottom side of vscode, then I get :

[proc] Executing command: /usr/bin/cmake --build /mnt/c/path_to_my_project/build --config Debug --target all -j 14 --

And now projects ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR} are the same.

This generates files in the sources, suchs as :

  • CMakeFiles/
  • cmake_install.cmake
  • CTestTestfile.cmake
  • Makefile
  • _deps/

which are most likely duplicates of what already exist in my top-level cmake project's /build

Also, invoking the command CMake: Clean does not clean those cmake-generated files.

CMake Tools Diagnostics

No response

Debug Log

No response

Additional Information

  • The build task is the default one, and most likely everything (fresh vscode & extensions installation)
  • running on WSL Ubuntu-22.04 LTS
  • the projects sources are on Windows 10 (/mnt/c/path_to_project)
  • using vscode version 1.68.0

Top-level project's CMakeLists.txt :

cmake_minimum_required(VERSION 3.8 FATAL_ERROR)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS OFF)

# --- Top-project
## Project name = folder
get_filename_component(this_dir_name ${CMAKE_CURRENT_LIST_DIR} NAME)
## cleanup project name
string(REPLACE " " "-" ProjectId ${this_dir_name})
string(REPLACE "/" "_" ProjectId ${ProjectId})

project(${ProjectId})
message(STATUS "[${CMAKE_PROJECT_NAME}] loading content ...")

# --- tests
include(CTest)
enable_testing()

# Loading subdirectories/subprojects
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/subprojects/)

# dependency graph
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/RunGraphviz.cmake)

For the project's FS structure, subprojects is a hierarchy where folders without source code contains the following CMakeLists.txt

# (1) dept-agnostic subdirectory includer

# Loading subdirectories
include(${CMAKE_SOURCE_DIR}/cmake/add_all_subdirectories.cmake)
add_all_subdirectories()

which invokes

# add_all_subdirectories.cmake

# Add all subdirectories in a way that create a hierarchy,
# using INTEFACE library as virtual namespace

function(target_name_from_path output path_value)
    # Project name = folder
    file(RELATIVE_PATH this_dir_name "${PROJECT_SOURCE_DIR}" "${path_value}")
    # cleanup project name
    string(REPLACE " " "-" output_alias_value ${this_dir_name})
    string(REPLACE "/" "__" output_value ${output_alias_value})
    string(REPLACE "/" "::" output_alias_value ${output_alias_value})

    # "return" value to parent scope
    set(${output}       ${output_value} PARENT_SCOPE)
    set(${output}_alias ${output_alias_value} PARENT_SCOPE)
endfunction()

function(add_all_subdirectories) # optional : path

    if (NOT DEFINED ARGV0)
        set(path_to_subdirs ${CMAKE_CURRENT_SOURCE_DIR})
    else()
        set(path_to_subdirs ${ARGV0})
    endif()

    target_name_from_path(target_name "${path_to_subdirs}")
    message(STATUS "[${PROJECT_NAME}] loading bundle  (${target_name_alias}) ...")

    add_library(${target_name} OBJECT ${PROJECT_SOURCE_DIR}/cmake/empty) # tricks to create a "group"
    if (NOT "${target_name_alias}" STREQUAL "${target_name}")
        add_library(${target_name_alias} ALIAS ${target_name})
    endif()

    file(GLOB subprojects_list LIST_DIRECTORIES true ${path_to_subdirs}/*)
    foreach(dir ${subprojects_list})
        if (IS_DIRECTORY ${dir} AND EXISTS ${dir}/CMakeLists.txt)

            add_subdirectory(${dir})

            # top-down hierarchy (for organization/structure purpose)
            target_name_from_path(child_target_name "${dir}")
            add_dependencies(${target_name} ${child_target_name})
        endif()
    endforeach()

endfunction()

and directories containing source-code contains the following CMakeLists.txt :

# (2) project and depth agnostic subproject
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

include(${CMAKE_SOURCE_DIR}/cmake/add_all_subdirectories.cmake)
target_name_from_path(target_name "${CMAKE_CURRENT_SOURCE_DIR}")
file(RELATIVE_PATH this_dir_name "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "[${CMAKE_PROJECT_NAME}] loading project [${target_name_alias}] ...")

project(${target_name})

add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/source.cpp)
add_executable(${target_name_alias} ALIAS ${target_name})
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)

add_test(
    NAME test_${PROJECT_NAME}
    COMMAND ${PROJECT_NAME}
)

So if in one of (2) CMakeLists.txt file, I add :

message(STATUS ">>>> ${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS ">>>> ${CMAKE_CURRENT_BINARY_DIR}")

It results the following output :

on ctrl+s (with the pop-up Configuring project: Configuring Project appearing on the bottom-right of the screen)

[cmake] -- >>>> /mnt/c/path_to_project/path_to_subproject/subproject_name
[cmake] -- >>>> /mnt/c/path_to_project/build/path_to_subproject/subproject_name

but when clicking the "build" button

[cmake] -- >>>> /mnt/c/path_to_project/path_to_subproject/subproject_name
[cmake] -- >>>> /mnt/c/path_to_project/path_to_subproject/subproject_name

GuillaumeDua avatar Jun 10 '22 09:06 GuillaumeDua

Are you saying that running a build is reconfiguring CMake? I wouldn't expect the message command to evaluate during a cmake --build command.

If you run those same two cmake commands that you shared in your terminal outside of VS Code (the one for the ctl+s behavior, and the one for clicking the build button), do you get the same result?

bobbrow avatar Jun 10 '22 16:06 bobbrow

Looks like it is reconfiguring indeed : the message is

If I run both command in a terminal, the behavior is the same as if I'd invoke them respectively using ctrl+s shortcut and ⚙Build button.

Which are :

/usr/bin/cmake --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/clang -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/clang++ -S/mnt/c/.../Projects/project_name -B/mnt/c/.../Projects/project_name/build -G "Unix Makefiles"
/usr/bin/cmake --build /mnt/c/.../Projects/project_name/build --config Debug --target all -j 14 --

GuillaumeDua avatar Jun 13 '22 08:06 GuillaumeDua

If I run both command in a terminal, the behavior is the same as if I'd invoke them respectively using ctrl+s shortcut and ⚙Build button.

Just to confirm, when you run the commands in the terminal, does it still generate the build files in the wrong place? I ask because if you can reproduce the problem in the terminal (without our extension), then I don't think there's anything we can do to fix it. A bug would need to be opened against CMake to ask Kitware to fix it.

bobbrow avatar Jun 13 '22 22:06 bobbrow

Yes indeed, as mentioned https://github.com/microsoft/vscode-cmake-tools/issues/2590#issuecomment-1153600142. I'll open an issue on Kitware side then, thanks for your time.

GuillaumeDua avatar Jun 15 '22 16:06 GuillaumeDua

This was determined to be an upstream issue. Closing.

bobbrow avatar Aug 29 '22 20:08 bobbrow