Open sean-mcmanus opened 3 years ago
C++ modules: exist 4 years IntelliSense:
C++ modules: exist 4 years IntelliSense:
Also C++ modules: supported by all major compilers, CMake, and build systems IntelliSense:
C++ modules: exist 4 years IntelliSense:
Also C++ modules: supported by all major compilers, CMake, and build systems IntelliSense:
We continue to work with EDG (our front end compiler that powers IntelliSense) to ensure that this is a priority and we'll get it to the C++ extension as soon as we can. The initial implementation was based on msvc's IFC format as the other compilers were not as quick to add modules support. Official CMake support only arrived last year.
Because this extension supports more compilers than Visual Studio does, we have asked EDG for a more general-purpose implementation. IntelliSense can be made to work with modules for projects built with the msvc compiler - set the switches and keep your build up to date - but we have not officially supported modules yet because we need support for all compilers.
C++ modules: exist 4 years IntelliSense:
Also C++ modules: supported by all major compilers, CMake, and build systems IntelliSense:
We continue to work with EDG (our front end compiler that powers IntelliSense) to ensure that this is a priority and we'll get it to the C++ extension as soon as we can. The initial implementation was based on msvc's IFC format as the other compilers were not as quick to add modules support. Official CMake support only arrived last year.
Because this extension supports more compilers than Visual Studio does, we have asked EDG for a more general-purpose implementation. IntelliSense can be made to work with modules for projects built with the msvc compiler - set the switches and keep your build up to date - but we have not officially supported modules yet because we need support for all compilers.
Is there an example project anywhere, where it works in vs code, cmake and msvc?
Is there an example project anywhere, where it works in vs code, cmake and msvc?
I'm sorry, I just tried it and it doesn't appear to be working reliably. I found a bug in the processing of "/ifcSearchDir" and "/reference" which must have regressed at some point. After fixing that, I'm still seeing issues in the language server which I haven't tracked down.
After stepping through the language server, I see how it's finding and loading the compiled modules. I'm blocked by one last thing which is that the version of cl.exe I'm using outputs an IFC with a version greater than our language server knows about. The update for this version was recently merged into VS and won't make it to the C++ extension until 1.20, so IntelliSense won't work with the latest version of the MSVC compiler.
That aside, here is what I did (which will depend on a small fix which will be added to 1.19).
CMakeLists.txt
cmake_minimum_required(VERSION 3.28)
project(modules)
set(CMAKE_CXX_STANDARD 20)
add_executable(test)
target_sources(test PUBLIC main.cpp)
target_sources(test PUBLIC
FILE_SET CXX_MODULES FILES
foo.ixx)
# Copy ifc files for IntelliSense
install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/test.dir/
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ifc
FILES_MATCHING PATTERN "*.ifc"
)
main.cpp
import foo;
int main()
{
Foo();
}
foo.ixx
module;
#include <iostream>
export module foo;
export void Foo()
{
std::cout << "hello modules!" << std::endl;
}
c_cpp_properties.json
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**"
],
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "windows-msvc-x64",
"compilerPath": "cl.exe",
"compilerArgs": [
"/ifcSearchDir", "${workspaceFolder}/build/ifc"
]
}
],
"version": 4
}
settings.json
{
"cmake.generator": "Ninja"
}
It is important to note that you should use Ninja to build your CMake project because it compiles the modules into foo.ifc
instead of foo.ixx.ifc
which the Visual Studio 2022 generator does. The language server does not know how to combine /ifcSearchDir
with /reference
so you would have to map all of your modules as full paths to make it work if you use the latter. If you use Ninja you only have to set the search dir and it will find the compiled modules.
When my fix goes in (1.19.3), IntelliSense should start working for .ixx and .cppm files, but you will get an error in main.cpp until we get the IFC version update in 1.20.
Nobody will name their cross platform code in .ixx Although i believe cmake will tag the files as modules even when not ixx
Nice work, Bob. Looking forward to the fix.
nobody will name their cross platform code in .ixx seems like C++ modules will never take off at this rate.
MSVC allows you to use any extension you want with module files, provided it's properly designated as a module in CMakeLists. This adds the "/interface" argument to each of these files, bypassing the .ixx forced naming convention. But I agree that it should not be forced by default and left up to the developer, similar to GCC and Clang. But as for whether or not a module file not ending in .ixx will work with IntelliSense is another matter that the folks here will have to solve.
I failed to mention that .cppm will also be recognized. You don't have to name your files .ixx according to the msvc preference.
then the only complaint i would have is that
"compilerArgs": [
"/ifcSearchDir", "${workspaceFolder}/build/CMakeFiles/test.dir"
]
would not work for multiple cmake projects, in my case. I have a dozen dependencies and 3-5 projects in my workspace. I can try it tomorow since now it is bed time here. One solution is to specify this in cmake for each project, but that still means non cross platform jargon in cmake.
You should be able to specify multiple search dirs (just like includePath has multiple search paths). So this would be supported:
"compilerArgs": [
"/ifcSearchDir", "${workspaceFolder}/build/CMakeFiles/target1.dir",
"/ifcSearchDir", "${workspaceFolder}/build/CMakeFiles/target2.dir"
]
https://github.com/microsoft/vscode-cpptools/issues/6302#issuecomment-1930791901
When my fix goes in (1.19.3), IntelliSense should start working for .ixx and .cppm files, but you will get an error in main.cpp until we get the IFC version update in 1.20.
IFC file ".../<module>.ifc" has unsupported version 0.43 C/C++(3373)
C/C++ v1.19.8
, looking forward 1.20
, cheer you all up 🥇
C++ modules: exist 4 years IntelliSense:
I moved to CLion Nova. It just works over there 🤷 Maybe when Microsoft invests more resources into this issue, I will see again
1.20.0 was just published. The IFC unsupported version 0.43 error should be gone now. Though now I'm seeing that the server is holding a reference to the built .ifc files. 😞 Closing those files in the editor will release the file lock so that you can build again, but since it's a bit disruptive, I added an INSTALL step to my CMakeLists.txt to copy the .ifc's somewhere else so that rebuilding doesn't get blocked on IntelliSense. Something like this:
install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/test.dir/
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ifc
FILES_MATCHING PATTERN "*.ifc"
)
I'll update my example above. When you need to update your ifc's for IntelliSense, you can either close your source files and run the "CMake: Install" command once all of the servers have been shut down (there's about a 5 second delay), or run "Reload Window" and then "CMake: Install".
Switched to pre-release v1.20 version and everything works!
Little lifehack with CMake - running install
after build can be automated with:
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND
${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR} --config $<CONFIG>)
Sad that it is still only a workaround for msvc
compiler since clang
does not generates any .ifc
s for Intellisense :(
Shouldn't the IntelliSense be based on the source files as opposed to the compiled .ifc's? It's a bit impractical to have to first compile the project in order for it to work. Is this a feature planned in the future?
Shouldn't the IntelliSense be based on the source files as opposed to the compiled .ifc's? It's a bit impractical to have to first compile the project in order for it to work. Is this a feature planned in the future?
Yes, and that's why we don't have any sort of modules support for gcc/clang yet. We are waiting anxiously for EDG (company that provides our compiler front-end) to support modules more generally.
It is important to note that you should use Ninja to build your CMake project because it compiles the modules into
foo.ifc
instead offoo.ixx.ifc
which the Visual Studio 2022 generator does. The language server does not know how to combine/ifcSearchDir
with/reference
so you would have to map all of your modules as full paths to make it work if you use the latter. If you use Ninja you only have to set the search dir and it will find the compiled modules.
The other way is updated vcxproj file with script.
$vcxproj = Get-ChildItem "./build/*.vcxproj"
foreach ($i in vcxproj) {
(Get-Conntent $i) -replace ".ixx.ifc", ".ifc" | Set-Content $i
}
Switched to pre-release v1.20 version and everything works! Little lifehack with CMake - running
install
after build can be automated with:add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR} --config $<CONFIG>)
Sad that it is still only a workaround for
msvc
compiler sinceclang
does not generates any.ifc
s for Intellisense :(
I found a way that CMake & VSCode can use with Visual Studio 2022 generator.
# CMakeLists.txt
install(SCRIPT install.cmake)
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD COMMAND
${CMAKE_COMMAND} --install ${CMAKE_BINARY_DIR} --config $<CONFIG>
)
# install.cmake
include(CMakePrintHelpers) # cmake_print_variables
# cmake_print_variables(CMAKE_CURRENT_BINARY_DIR)
file(GLOB_RECURSE ifc_src ${CMAKE_CURRENT_BINARY_DIR}/*.ixx.ifc)
set(ifc_dest ${CMAKE_CURRENT_BINARY_DIR}/ifc)
if(NOT EXISTS ${ifc_dest})
file(MAKE_DIRECTORY ${ifc_dest})
endif()
foreach(item ${ifc_src})
cmake_path(GET item EXTENSION LAST_ONLY last_ext) # src/m.ixx.ifc -> .ifc
cmake_path(GET item STEM name_we) # src/m.ixx.ifc -> m
set(newname ${ifc_dest}/${name_we}${last_ext}) # -> dest/m.ifc
# cmake_print_variables(newname)
file(COPY_FILE ${item} ${newname}) # src/m.ixx.ifc -> dest/m.ifc
endforeach()
I am learning C++ using VSCode and MSVC Build Tools. I read about MSVC's module support and how to consume the standard library using modules and also using individual header units. I read this thread entirely, installed the C/C++ extension v1.20.1 (pre-release), and successfully configured IntelliSense support for modules.
It's great that IntelliSense is now able to import declarations from the compiled std.ifc interface file too, when it's included in the /ifcSearchDir
path.
However, I am facing issues making it work with compiled standard library header units like <print>
, <string>
, <vector>
, etc. Having read the MSVC compiler reference in detail, I am able to get the build done successfully. However, the red squiggles from IntelliSense are what I'd really want to get rid of. I am aware that importing std
is a more recommended practice than using header units, but I was just experimenting and successfully compiled a source that imports the latter. But the IntelliSense support is now lost.
My (minimal) source code:
import <print>;
int main() {
std::println("Hello World!");
return 0;
}
Contents of c_cpp_properties.json file:
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}\\**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"compilerPath": "cl.exe",
"cStandard": "c17",
"cppStandard": "c++23",
"compilerArgs": [
"/ifcSearchDir",
"${workspaceFolder}\\ifc"
],
"intelliSenseMode": "windows-msvc-x64",
"windowsSdkVersion": "10.0.22621.0"
}
],
"version": 4
}
tasks.json
{
"tasks": [
{
"type": "shell",
"label": "C++23: Build project from active workspace",
"options": {
"shell": {
"executable": "cmd.exe",
"args": [
"/C",
"if not exist \"${workspaceFolder}\"\\output\\ ( mkdir \"${workspaceFolder}\"\\output )",
"else ( del /q \"${workspaceFolder}\"\\output )",
"&&",
"if not exist \"${workspaceFolder}\"\\ifc\\ ( mkdir \"${workspaceFolder}\"\\ifc )",
"else (del /q \"${workspaceFolder}\"\\ifc )",
"&&"
]
},
"cwd": "${workspaceFolder}"
},
"command": "cmd.exe",
"args": [
"/C",
"cl.exe",
"/EHsc",
"/std:c++latest",
"/exportHeader",
"/headerName:angle",
"/Fooutput\\",
"/ifcOutput",
"ifc\\",
"print",
"&&",
"cl.exe",
"/Zi",
"/EHsc",
"/c",
"/std:c++latest",
"/nologo",
"/headerUnit:angle",
"print=ifc\\print.ifc",
"/Fooutput\\",
"${workspaceFolder}\\*.cpp",
"&&",
"link.exe",
"/out:output\\${workspaceFolderBasename}.exe",
"output\\*.obj",
"&&",
"cd",
"output",
"&&",
"del",
"*.obj"
],
"problemMatcher": [
"$msCompile"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Builds header unit dependency, compiles source file and links them together"
}
],
"version": "2.0.0"
}
Even after the build succeeds and print.ifc gets generated in the ifc\ subdirectory, IntelliSense is unable associate it with the import
statement and reports "print" is not an importable header C/C++(3270)
error.
The following screenshot shows this situation:
How to resolve this issue? I can conveniently use import std;
in all my learning projects and get good IntelliSense support, but i really want to know what's going wrong here despite the build success. Am I missing any compilerArgs
besides /ifcSearchDir
?
Also there's a second issue. While IntelliSense is able to import declarations from std.ifc (derived by compiling std.ixx standard library module), it isn't able to do the same for std.compat
, even when std.compat.ifc lies in the /ifcSearchDir
path. Strangely enough, this occurs only when the code uses members from the std
namespace wherein IntelliSense encounters an internal error C/C++(1504)
. When only C runtime functions from the global namespace (like printf()
) are used, there's no issue at all. If required I can share the relevant configuration and source files from that project too.
For now, I would really like to know how I can work around the first issue of IntelliSense not recognizing compiled header units.
@AR-devJ, C++20 modules
feature is still not full-scale implemented and somewhat raw. And even being not perfectly designed due to macros handling (omitting) and other flaws.
You have 2 options:
Visual Studio 22
(Community) - is a best free C++ compiler for Windows with fully implemented c++ modules featureI picked variant â„–2 while starting pet-project in 2024 coz I want to have ability to develop with all 3 major compilers (msvc
, gcc
, clang
) in VS Code IDE, which is not possible right now. Modules is not a core c++ feature, so feel free to skip for now since you can adopt/learn them later.
@AR-devJ, The experience with header units is still sub-optimal. You might find that the red squiggles you're seeing around types defined in the standard headers will exist in Visual Studio as well (since we use largely the same tech for IntelliSense). We are tracking a number of these issues and are reporting them to EDG as we become aware of them. If there are any that are particularly annoying for you, you may report them in a new issue and we'll check them against the ones we are tracking to make sure they all get reported.
@AR-devJ same issue here.
whenimport std
or some <header>
, I always use
#ifndef my_module
#include <print>
#else
import <print>
#endif
to cheat the vscode intellisense, and add /D my_module
into compiler args.
if you insist on using import/export
in vscode, this might be a cost-effective trick.
p.s.: It's so disgusting that C++ module is designed to improve compile speed, code safety and maintainability but it turns out we spent lots of time to achieve it. Really sad.
@LiAuTraver Utterly sad indeed. It looks like all the resources are thrown somewhere else and someone on top doesn't deem C++ anything but a legacy maintenance-mode language anymore.
With this AI bullshit creeping out of every corner of recent VSCode builds and elsewhere, they might be as well deeming the olden programming with human brain and hands not worth the fuss itself.
@mitsukuri Microsoft is still investing in C++, lots of Microsoft products are still built on C++, all the resources aren't being thrown somewhere else, and it's not in legacy maintenance-mode. You can read about the work that is being done at https://devblogs.microsoft.com/cppblog/ .
Our IntelliSense compiler is based on the EDG compiler and they haven't finished implementing modules support yet. See https://www.edg.com/c/features and click on the C++ 20 link:
Other compilers haven't even finished implemented modules 100% to spec: see https://en.cppreference.com/w/cpp/compiler_support
I've personally been very impressed by the AI tools like GitHub Copilot -- I highly recommend trying them out yourself. They can do code reviews (and actually find bugs, unideal code, etc.), rewrite/improve comments, generate code, complete lines of code, answer programming questions, etc.
@AR-devJ same issue here. when
import std
or some<header>
, I always use#ifndef my_module #include <print> #else import <print> #endif
to cheat the vscode intellisense, and add
/D my_module
into compiler args. if you insist on usingimport/export
in vscode, this might be a cost-effective trick.p.s.: It's so disgusting that C++ module is designed to improve compile speed, code safety and maintainability but it turns out we spent lots of time to achieve it. Really sad.
I do the same, and by the way, you can use #ifdef __INTELLISENSE__
, which is defined for when the IntelliSense engine parses files.
CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
in your [preset file | command-line | script] to "0e5b6991-d74f-4b3d-a41c-cf096e0b2508"
import std
handlingcmake_minimum_required(VERSION 3.30)
project(Test-C++Modules LANGUAGES CXX)
add_executable(Test-C++Modules Main.cpp)
target_compile_features(Test-C++Modules PRIVATE cxx_std_23)
set_target_properties(Test-C++Modules PROPERTIES CXX_MODULE_STD ON)
target_compile_options(Test-C++Modules PRIVATE $<$<CXX_COMPILER_ID:MSVC>:/ifcSearchDir$<TARGET_PROPERTY:__cmake_cxx23,BINARY_DIR>\\CMakeFiles\\__cmake_cxx23.dir\\$<CONFIG>>)
Do note that you need to compile your code for IntelliSense to light up, as the target CMake target
__cmake_cxx23
is only created when you trigger your first build.
However, it would be lovely if CppTools would learn to react to modmap
files generated by CMake. I don't really care about which extension bears the bulk of the load, CppTools or CMakeTools, but it does generate a module map for every object file. In this simplest of cases, it generates <build_root>\CMakeFiles\Test-C++Modules.dir\Debug\Main.cpp.obj.modmap
:
-reference std=CMakeFiles\__cmake_cxx23.dir\Debug\std.ifc
It would be lovely if ifcSearchDir
need not be set in scripts on targets with this fairly horrendous syntax only to light up external tooling features when the project otherwise compiles just fine.
@bobbrow @sean-mcmanus
@MathiasMagnus we understand that there are several pain points with modules right now. From the C++ extension's perspective, the changes you mention should go into CMake Tools because the C++ extension does not attempt to understand the build system. I would recommend opening an issue on the CMake Tools repo if you haven't already.
It looks like Microsoft is forcing everyone to Rust.
It looks like Microsoft is forcing everyone to Rust.
although it's off-topic I think, to be fair, not the fault of Microsoft, the C++ ecosystem itself has so many historical problems and the language just has no owners but a committee. Every slight change needs several companies to work together for it. not an implementer myself, I was also wondering why module feature was so hard to implement in C++ than other languages.
See the previous Windows/cl.exe-only issue at https://github.com/microsoft/vscode-cpptools/issues/6290 (UPDATE: the issue was deleted, see https://github.com/microsoft/vscode-cpptools/issues/8256#issuecomment-941809096 ).
NOTE: C++20 modules importing works for cl.exe if you set /ifcSearchDir (and possibly other modules args if necessary); however the IntelliSense support is still in active development so there are lots of known issues/bugs still.
This is dependent on IntelliSense parser changes from VS (i.e. open file Linux solutions in VS don't have module importing support for IntelliSense either).
EDIT: example here: https://github.com/microsoft/vscode-cpptools/issues/6302#issuecomment-1930791901