Skip to content

Add IntelliSense for C++20 modules importing #6302

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
sean-mcmanus opened this issue Oct 13, 2020 · 100 comments
Open

Add IntelliSense for C++20 modules importing #6302

sean-mcmanus opened this issue Oct 13, 2020 · 100 comments

Comments

@sean-mcmanus
Copy link
Contributor

sean-mcmanus commented Oct 13, 2020

See the previous Windows/cl.exe-only issue at #6290 (UPDATE: the issue was deleted, see #8256 (comment) ).

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: #6302 (comment)

@sean-mcmanus sean-mcmanus added this to the Tracking milestone Oct 13, 2020
@sean-mcmanus sean-mcmanus added the Visual Studio Inherited from Visual Studio label Nov 3, 2020
@Colengms Colengms changed the title Add cross-platform IntelliSense for C++20 modules importing Add IntelliSense for C++20 modules importing Oct 13, 2021
@cjwijtmans
Copy link

Is there any way to get it somewhat working or does it not parse .ifc files at all?

@sean-mcmanus
Copy link
Contributor Author

sean-mcmanus commented Oct 19, 2021

@cjwijtmans It may work with msvc mode with .ifc files for cl.exe, but it's not officialy supported yet. We process /headerUnit, /ifcSearchDir, /reference, and /stdIfcDir in compilerArgs.

@Bigous
Copy link

Bigous commented Mar 8, 2022

I don't know if it's only for me, but #6290 just goes to 404 error...
The intellisense is not working for imports at all.

The definition:
image

And whe we use it:
image

But the compiler has no complains....

image

@sean-mcmanus
Copy link
Contributor Author

@Bigous It's not officially supported, but we do have code that processes various modules command lines. Can you provide the command line args you're using in compilerArgs, particularly those that are modules-related?

@Bigous
Copy link

Bigous commented Mar 9, 2022

Hi @sean-mcmanus , actually I'm using the CMake to build... but essentially it's /std:c++latest /experimental:module /EHsc /MD.

It's a project to learn what C++20 brings and I really liked the module feature. I think it will save tons of time in compile.

I just uploaded the project to github so you can see all easily

@sean-mcmanus
Copy link
Contributor Author

sean-mcmanus commented Mar 9, 2022

  1. You currently need to change it to something like target_compile_options(cpp20 PRIVATE "/experimental:module" "/ifcSearchDir\"C:\\pathTo\\build\""), i.e. see https://devblogs.microsoft.com/cppblog/standard-c20-modules-support-with-msvc-in-visual-studio-2019-version-16-8/ .
  2. But I'm seeing error "IFC file "C:\pathTo\build\Utils.Numbers.ifc" has unsupported version 0.41", so I'm looking into that...

@sean-mcmanus
Copy link
Contributor Author

sean-mcmanus commented Mar 9, 2022

@Bigous Good news -- it works correctly with 1.9.2 (Pre-Release), i.e. the 0.41 version error goes away.

@sean-mcmanus
Copy link
Contributor Author

@Bigous However, I'm seeing what appears to be an incorrect IntelliSense error: "expression preceding parentheses of apparent call must have (pointer-to-) function type" -- I'm looking into filing a bug on that against our shared VS parser...

@sean-mcmanus
Copy link
Contributor Author

@Bigous Our VS parser team is still actively developing the IntelliSense feature for modules, so incorrect IntelliSense errors like that are "expected" at this point (and possibly other IntelliSense issues).

@Bigous
Copy link

Bigous commented Mar 10, 2022

Hi @sean-mcmanus , thanks for the effort!
If I can help with anything, you can count on me.

@str0yd
Copy link

str0yd commented Mar 16, 2022

Do you guys have some time frame when we can expect it working? I tried it a few days ago but it was incredibly slow, or not working at all. It felt like it was kinda random.

Same in Visual Studio 2022.

I think the modules are one of the most exiting changes in C++20 because having to maintain both source and header file is at least for me effort that could be avoided.

@sean-mcmanus
Copy link
Contributor Author

@str0yd It's being actively developed. I don't know of any set timeframes, i.e. it could be a year or so. We get updates periodically. I'm guessing the VS C++ team might release a blog or something when they get IntelliSense modules support "finished".

@fatboyzz
Copy link

I set the /ifcSearchDir for .ifc files.
For my module "Math" the line:
import Math;
Got error "Can't find module file ***/Math.edgm"
No idea what is .edgm file. And it is not generated in my project directory.
But "Go To Definition" works for names exported from module.

@waruqi
Copy link

waruqi commented Aug 13, 2022

Is there now support for c++20 modules for gcc/clang in addition to ifc?

@sean-mcmanus
Copy link
Contributor Author

@waruqi Not yet.

@luca-script
Copy link

luca-script commented Sep 30, 2024

Seeing as there hasn't been many updates for a while, I would suggest a solution similar to below:

For support with GCC and Clang, I would personally take the approach adding support for the C++ module mapper API used by GCC, as documented partially here in the GCC documentation (And its references) and implemented in libcody.
And extending the protocol with many more commands for various purposes (i.e. source file translation)

With that support, an implementation of a smart build system (Which does not include CMake, as it currently generates module dependency files, which are incredibly inefficient) can create a service which talks to the C++ language server and tells it where modules are.
This also allows the build system to apply any transformations or create virtual files if generated files are needed.

This would be preferrable to requiring a build system to generate lots of files or a module dependency tree or resolution file, which is not desirable and should not be done.

We could also with the ability to talk to a module mapper/build service, do things like file-specific compilers or configuration queries via more protocol extensions, as the protocol implemented by libcody can be easily extended with new commands if need be.
i.e. our language service can ask the build tool important questions for proper language service availability and functionality:

sequenceDiagram
    Language Service->>Build Tool: MODULE-SOURCE foo.bar
    Build Tool->>Language Service: PATHNAME /workspace/dependencies/foo/src/bar.cpp
    Language Service->>Build Tool: FILE-CONFIGURATION /workspace/dependencies/foo/src/bar.cpp
    Build Tool->>Language Service: PATHNAME /tmp/configuration-7aee052f0c19772a6e436d184816ad7d
    Language Service->>Build Tool: FILE-UPDATE /workspace/src/kaz.cpp <start offset>:<end offset> <start offset>:<end offset> <start offset>:<end offset>
    Note right of Build Tool: The build tool rebuilds the module
    Build Tool->>Language Service: ERRORS 182:"Variable 'foo' not found" 173:"Undefined reference to function 'bar'"
    Language Service->>Build Tool: RUN-TESTS
    Build Tool->>Language Service: BOOL TRUE
Loading

The advantage of such a system is that a build system like CMake can easily add new features without waiting for LSP support, and allowing the build tool to be aware of the language service and rebuild files in the background, which would greatly accelerate the developer experience.
The disadvantage would be requiring an implementation of this system, and proper maintenance.
In addition, I'm not sure if Visual Studio will implement such features, or if a seperate system will be required (Seeing as Visual Studio likes to do its own thing regarding C++ feature support)
In addition, we'd probably need to gate it behind an option in .vscode/settings.json:

{
  "C_Cpp.backend": "|foobarservice $(ProjectDir)", // Run foobarservice and talk the module mapper/build tool service protocol using stdin/stdout

A fallback implementation for file list-style module dependency resolution files would need to implemented as a seperate service for support with current versions of CMake, and this would likely require further integration between CMake and its build system (Most of the time Makefiles or Ninja) for any real kind of effect.

Some answers I want to put out there so there won't be needless useless discussion (In Q&A format):
Q: Why not make a full language service at this point?
A: It is incredibly difficult to make a robust language service, and piggying off of an existing language service and only implementing module translation and build integration would significantly reduce implementation cost and complexity.
Q: Why add build integration?
A: Build integration is an important part of the modern IDE experience, and real-time rebuilding of edited modules will GREATLY speed up build times.
Q: Why extend the existing C++ module mapper protocol?
A: The existing protocol has similar enough goals that extending it makes sense. It also avoids requiring a brand new proprietary/largely undocumented protocol to be made.
Q: Why even care with this?
A: I deeply care about IDE integration, and the current state of C++ modules in IDEs is extremely poor. By adopting the ability for your build tool to provide C++ module translation and build acceleration, we can make the experience better.
Q: This is pointless, I don't want it.
A: If you don't want it, don't use it. I do not want endless "But this isn't how I want it to work ideally!!!!" comments here, as these are not productive to the current problem.
Q: How long do you think this would take to get implemented and adopted into tools like CMake?
A: I forsee it taking around 5-8 years from seeing how long it has taken for C++ modules to get proper support and considering that this is quite a bit more complex and off-topic.
Q: Why should I care? (For anyone who doesn't directly work on the language service)
A: That's the neat part, you don't. The only people who need to care about these things are the people who make compilers, make the build tools and the language services.
Q: Will this affect me as a Visual Studio and MSVC user?
A: Probably not, as Visual Studio has their own integration for this and their own (proprietary) language service which already fully supports C++ modules and build integration with MSBuild.
Q: Why this early? When GCC and Clang barely support C++ modules.
A: C++ modules will likely take a long while to be fully supported, this is just a step to C++ module adoption.

Take this not as a "we must implement this now!", but as an idea to throw out there into the void to see what people who actually work on the LSP think of this.
Also please do not reply with hate, this is unproductive and I do not want the same situation as often happens with Wayland where 30 people scream "I DON'T THINK THIS IS GOOD" and the entire conversation devolves into hatespeech against developers and implementers.

@vspefs
Copy link

vspefs commented Oct 5, 2024

Seeing as there hasn't been many updates for a while, I would suggest a solution similar to below:

For support with GCC and Clang, I would personally take the approach adding support for the C++ module mapper API used by GCC, as documented partially here in the GCC documentation (And its references) and implemented in libcody. And extending the protocol with many more commands for various purposes (i.e. source file translation)

With that support, an implementation of a smart build system (Which does not include CMake, as it currently generates module dependency files, which are incredibly inefficient) can create a service which talks to the C++ language server and tells it where modules are. This also allows the build system to apply any transformations or create virtual files if generated files are needed.

This would be preferrable to requiring a build system to generate lots of files or a module dependency tree or resolution file, which is not desirable and should not be done.

We could also with the ability to talk to a module mapper/build service, do things like file-specific compilers or configuration queries via more protocol extensions, as the protocol implemented by libcody can be easily extended with new commands if need be. i.e. our language service can ask the build tool important questions for proper language service availability and functionality:

sequenceDiagram
    Language Service->>Build Tool: MODULE-SOURCE foo.bar
    Build Tool->>Language Service: PATHNAME /workspace/dependencies/foo/src/bar.cpp
    Language Service->>Build Tool: FILE-CONFIGURATION /workspace/dependencies/foo/src/bar.cpp
    Build Tool->>Language Service: PATHNAME /tmp/configuration-7aee052f0c19772a6e436d184816ad7d
    Language Service->>Build Tool: FILE-UPDATE /workspace/src/kaz.cpp <start offset>:<end offset> <start offset>:<end offset> <start offset>:<end offset>
    Note right of Build Tool: The build tool rebuilds the module
    Build Tool->>Language Service: ERRORS 182:"Variable 'foo' not found" 173:"Undefined reference to function 'bar'"
    Language Service->>Build Tool: RUN-TESTS
    Build Tool->>Language Service: BOOL TRUE
Loading

The advantage of such a system is that a build system like CMake can easily add new features without waiting for LSP support, and allowing the build tool to be aware of the language service and rebuild files in the background, which would greatly accelerate the developer experience. The disadvantage would be requiring an implementation of this system, and proper maintenance. In addition, I'm not sure if Visual Studio will implement such features, or if a seperate system will be required (Seeing as Visual Studio likes to do its own thing regarding C++ feature support) In addition, we'd probably need to gate it behind an option in .vscode/settings.json:

{
  "C_Cpp.backend": "|foobarservice $(ProjectDir)", // Run foobarservice and talk the module mapper/build tool service protocol using stdin/stdout

A fallback implementation for file list-style module dependency resolution files would need to implemented as a seperate service for support with current versions of CMake, and this would likely require further integration between CMake and its build system (Most of the time Makefiles or Ninja) for any real kind of effect.

Some answers I want to put out there so there won't be needless useless discussion (In Q&A format): Q: Why not make a full language service at this point? A: It is incredibly difficult to make a robust language service, and piggying off of an existing language service and only implementing module translation and build integration would significantly reduce implementation cost and complexity. Q: Why add build integration? A: Build integration is an important part of the modern IDE experience, and real-time rebuilding of edited modules will GREATLY speed up build times. Q: Why extend the existing C++ module mapper protocol? A: The existing protocol has similar enough goals that extending it makes sense. It also avoids requiring a brand new proprietary/largely undocumented protocol to be made. Q: Why even care with this? A: I deeply care about IDE integration, and the current state of C++ modules in IDEs is extremely poor. By adopting the ability for your build tool to provide C++ module translation and build acceleration, we can make the experience better. Q: This is pointless, I don't want it. A: If you don't want it, don't use it. I do not want endless "But this isn't how I want it to work ideally!!!!" comments here, as these are not productive to the current problem. Q: How long do you think this would take to get implemented and adopted into tools like CMake? A: I forsee it taking around 5-8 years from seeing how long it has taken for C++ modules to get proper support and considering that this is quite a bit more complex and off-topic. Q: Why should I care? (For anyone who doesn't directly work on the language service) A: That's the neat part, you don't. The only people who need to care about these things are the people who make compilers, make the build tools and the language services. Q: Will this affect me as a Visual Studio and MSVC user? A: Probably not, as Visual Studio has their own integration for this and their own (proprietary) language service which already fully supports C++ modules and build integration with MSBuild. Q: Why this early? When GCC and Clang barely support C++ modules. A: C++ modules will likely take a long while to be fully supported, this is just a step to C++ module adoption.

Take this not as a "we must implement this now!", but as an idea to throw out there into the void to see what people who actually work on the LSP think of this. Also please do not reply with hate, this is unproductive and I do not want the same situation as often happens with Wayland where 30 people scream "I DON'T THINK THIS IS GOOD" and the entire conversation devolves into hatespeech against developers and implementers.

There's no need to extend existing facilities. CMI/BMI files are enough for a language front end to do IntelliSense. Cpptools can't provide it, simply because the vendor of its front end hasn't finished this feature. It doesn't only concern reading a new file format, but also involves quite a few problems on C++ itself, and some parts of the front end's basic structure. Clangd has finished its support for modules a while ago, which you can definitely try.
Back to CMI/BMI files. They are not designed for IntelliSense, but as a kind of standalone utility that caches the final interface and logic of a module unit. It works as a cache that helps avoid repeated work for compilers, and offers a new way to distribute your module. But just so it happens that it contains the final interface of a module unit, so front ends use it to support IntelliSense for modules. So no, though it helps front ends do IntelliSense, it's a utility for compiling your program and should not hold information that a build system/IntelliSense extension would additionally know, nor any information that makes it less portable.
And you recommended that we store source file locations and 'offsets' in CMI/BMI files, so that we can read a module's source file directly for IntelliSense. Well, now that you know a CMI/BMI file already contains the final interface of a module unit, there's no longer need for anyone to 'trace back' to the source file. Besides, what we just discussed clarifies that a CMI/BMI file shouldn't contain such information. And reading directly from source files is time-and-performance-costing. If we don't have CMI/BMI files, yes, we would HAVE to do that, and maybe do some heavy caching to get ourselves a enjoyable writing experience. But now we have them, right?
So we mentioned 'standalone' and 'portable.' Like CMI/BMI files, those dependency files are generated for this purpose, too. You should know that C++ doesn't have a default build system (or say, a standard build structure) and everything is based on little, individual translation units. So yes, we need those silly dependency files. More on CMI/BMI files and dep files here: P1838

I don't feel this is the place for some long, arrogant, cocky, and error-prone (I hope it's not) lectures. But you don't have an email or something like that, so I'll have to reply here. If my reply disturbs/annoys anybody, or it's wrong (God, I hope not), please do inform me.
And luca, if you're interested in how the language and helper facilities interact and pass information between each other, this recent paper might give you a brief view: P3335.

@Challanger524
Copy link

Move on guys, it takes too long and waiting won't speed up anything. I am starting to suspect that this feature may even never come to vscode.

@kamrann
Copy link

kamrann commented Oct 31, 2024

It appears that the processing of /reference is not taking into account the compile_commands.json directory entry for resolving relative paths.

The following gives a "cannot find module file" error:

"arguments": ["/reference", "mod=./foo.ifc"], "directory": "C:/somewhere"

whereas this does not:

"arguments": ["/reference", "mod=C:/somewhere/foo.ifc"]

Also rather annoyingly, it seems if I point the extension to a compile_commands.json file that's outside of the workspace root it will just silently behave as if it doesn't exist.

@1vanK
Copy link

1vanK commented Oct 31, 2024

Move on guys, it takes too long and waiting won't speed up anything. I am starting to suspect that this feature may even never come to vscode.

Problems with modules are not only in IDEs, but also in compilers, everything is heading towards modules being "deprecated" in the next C++ standards

@Challanger524
Copy link

Move on guys, it takes too long and waiting won't speed up anything. I am starting to suspect that this feature may even never come to vscode.

Problems with modules are not only in IDEs, but also in compilers, everything is heading towards modules being "deprecated" in the next C++ standards

Eah, modules being poorly designed by committee and overtimed by some compiler/parser vendors. Sad that C++ rushing for new useless features leaving old structural weaknesses behind.

@trexxet
Copy link

trexxet commented Dec 12, 2024

Happy new 5th year without modules support!

@mitsukuri
Copy link

What C++ committee does, how the language and its ecosystem evolves looks like a controlled Jaguar into terrain these days.

@sargon2
Copy link

sargon2 commented Dec 19, 2024

I tried to get things working with cl.exe, CMake, & Ninja on Windows. I got importing working by specifying ifcSearchDir in my CMakeLists.txt but I ran into a problem where IntelliSense held the .ifc files open in a way that nothing could write to them, which made recompiling impossible whether or not I used a copy for the ifc files. When in that state, closing vscode caused my entire system to hang and stop producing video. Not sure how that happened.

But, if I modify my CMakeLists.txt to remove the option or update it to a nonexistent directory, then I can recompile fine, then manually switch it back to the ifc folder to get Intellisense working again. It's a really heavy workaround but it does work.

In my CMakeLists.txt:

if(MSVC)
    target_compile_options(Project PRIVATE /ifcSearchDir ${PROJECT_BINARY_DIR})

This works since by default the ifc files are produced in the root of the binary dir. Then to recompile, just change it to:

if(MSVC)
    target_compile_options(Project PRIVATE /ifcSearchDir ${PROJECT_BINARY_DIR}/asdf)

Then recompile and after the compile succeeds, change it back and recompile again, and no error squigglies on imports.

I wonder why IntelliSense held the .ifc files open indefinitely (even after completing its work) and if there's any workaround to stop that behavior.

Edit: I checked using Process Explorer and the thing that has the .ifc file open preventing it from updating is cpptools-srv.exe.

Edit 2: I hadn't added my .ixx files to the CXX_MODULES FILE_SET. Once I did that it fixed the odd behavior!

@bobbrow
Copy link
Member

bobbrow commented Dec 20, 2024

@sargon2 the current implementation by EDG holds the file handle. When we get a cross-plat implementation of modules IntelliSense from them next year, this issue will be taken care of and you won't have to do anything special.

For now, my CMake example uses an install step to copy the built IFC's somewhere else for IntelliSense to read from so that you can at least recompile without having to release all of the language servers by reloading the window or closing all of the source files.

@sargon2
Copy link

sargon2 commented Dec 20, 2024

@bobbrow Thank you a ton. I was able to get it working without having to use the install target:

# Copy ifc files for IntelliSense at post-build time
add_custom_command(TARGET test
    POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E echo "Copying IFC files..."
    # COMMAND taskkill /IM cpptools-srv.exe /F # This will release the lock and Intellisense will restart itself.  But careful! It's a big hammer.
    COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_BINARY_DIR}/CMakeFiles/test.dir/ ${CMAKE_BINARY_DIR}/ifc
)

This seems to work okay and lets me do the copy after a normal F7 build is done.

Edit: I set it up so it compares the folders, and if there's a change attempts the copy, and only if the copy fails it performs the taskkill and retries. I can post that code if anyone wants it.

@starball5
Copy link

Related on Stack Overflow: How to enable proper C++ linting for modules in VS Code.

@J0hannes101
Copy link

Hi, I have a few questions regarding this issue:

  1. What is the current state of the implementation?
  2. Is there any way to use IntelliSense with C++20 modules and Clang or GCC at the moment?
  3. Is there any prospect of seeing a official implementation in the near future?

Thanks for your help!

@rdong8
Copy link

rdong8 commented Mar 16, 2025

I have a fully working C++23 devcontainer project template here using CMake, Conan, doxygen-awesom-css, Catch2 and Boost, implemented with modules and import std. The lack of editor support for modules is the only thing stopping me from switching back to VS Code from CLion.

FYI for others: the LLVM clangd extension has better module support than IntelliSense - you might want to try that instead

@evanwporter
Copy link

Adding to what @rdong8 mentioned, clangd has good module support but you need to add this line to the args passed to clangd:

--experimental-modules-support

(source).

Also this is what I've found your .clangd file should look like:

CompileFlags:
    Add: [-std=c++20, -xc++-module, -fprebuilt-module-path=build/ ]  

Mileage may vary here though.

Hopefully we can add full module support to cpptools soon.

@mapi-ng
Copy link

mapi-ng commented May 5, 2025

I'm very interested in improving syntax highlighting for C++20 modules in VS Code.

What is the best way I could contribute?
Or maybe there is an obvious solution that I'm missing.

Here's a brief description of the current state of syntax highlighting in my sample project:

OS:
Linux Ubuntu 25.04.

IDE:
VSCode 1.99.3
Extensions:
C/C++ (ms-vscode.cpptools) 1.25.3
C/C++ Extension Pack (ms-vscode.cpptools-extension-pack) 1.3.1.

Toolchain:
CMake 4.0.1
CLang 20, GCC 14 - compilation is successful with no special compilation flags.

Behavior:

Highlighting for a module file itself seems to be working nice:

Image

Importing a module in other source files results in syntax errors in the IDE (but compilation is successful).

Image

I'm building a library containing this module in the following way:

add_library(utils)
target_sources(utils PUBLIC
    FILE_SET CXX_MODULES
    FILES src/uuid_utils.cppm
)

@gwankyun
Copy link

gwankyun commented May 9, 2025

@bobbrow Thank you a ton. I was able to get it working without having to use the install target:

# Copy ifc files for IntelliSense at post-build time
add_custom_command(TARGET test
    POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E echo "Copying IFC files..."
    # COMMAND taskkill /IM cpptools-srv.exe /F # This will release the lock and Intellisense will restart itself.  But careful! It's a big hammer.
    COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_BINARY_DIR}/CMakeFiles/test.dir/ ${CMAKE_BINARY_DIR}/ifc
)

This seems to work okay and lets me do the copy after a normal F7 build is done.

Edit: I set it up so it compares the folders, and if there's a change attempts the copy, and only if the copy fails it performs the taskkill and retries. I can post that code if anyone wants it.

I need the code, post it please😄

@sargon2
Copy link

sargon2 commented May 9, 2025

I need the code, post it please😄

In copy_ifc_files.cmake:

# Arguments:
#   source_dir - Source directory for the files
#   target_dir - Target directory for the files

set(source_dir ${ARGV0})
set(target_dir ${ARGV1})

# Function to check if the copy is necessary
function(check_copy_necessary src_dir tgt_dir result)
    file(GLOB_RECURSE src_files "${src_dir}/*")
    file(GLOB_RECURSE tgt_files "${tgt_dir}/*")

    foreach(src_file IN LISTS src_files)
        string(REPLACE "${src_dir}/" "" relative_path "${src_file}")
        set(tgt_file "${tgt_dir}/${relative_path}")

        # If a target file does not exist or is older than the source file, copying is necessary
        if (NOT EXISTS "${tgt_file}" OR "${src_file}" IS_NEWER_THAN "${tgt_file}")
            set(${result} TRUE PARENT_SCOPE)
            return()
        endif()
    endforeach()

    # If we reach here, no copying is necessary
    set(${result} FALSE PARENT_SCOPE)
endfunction()

# Check if the copy is necessary
check_copy_necessary("${source_dir}" "${target_dir}" copy_necessary)

if (NOT copy_necessary)
    message(STATUS "No need to copy files; target directory is up to date.")
    return()
endif()

# Attempt to copy
message(STATUS "Attempting to copy files...")
execute_process(
    COMMAND ${CMAKE_COMMAND} -E copy_directory "${source_dir}" "${target_dir}"
    RESULT_VARIABLE copy_result
)

if (${copy_result} EQUAL 0)
    message(STATUS "Files copied successfully.")
    return()
endif()

# If the copy failed, perform taskkill and retry
message(WARNING "Initial copy failed. Attempting taskkill and retry...")
execute_process(
    COMMAND taskkill /IM cpptools-srv.exe /F
    RESULT_VARIABLE taskkill_result
)

if (NOT ${taskkill_result} EQUAL 0)
    message(FATAL_ERROR "Failed to terminate cpptools-srv.exe. Copy cannot proceed.")
endif()

execute_process(
    COMMAND ${CMAKE_COMMAND} -E copy_directory "${source_dir}" "${target_dir}"
    RESULT_VARIABLE retry_result
)

if (NOT ${retry_result} EQUAL 0)
    message(FATAL_ERROR "Retry failed. Files could not be copied.")
endif()

message(STATUS "Files copied successfully after retry.")

Invoke like:

if(MSVC) # Does not include normal build, only Intellisense
    message(STATUS "Using MSVC")
    target_compile_options(MyTarget PRIVATE /ifcSearchDir ${CMAKE_BINARY_DIR}/ifc)

    # Copy ifc files for IntelliSense at post-build time
    add_custom_command(TARGET MyTarget
        POST_BUILD
        COMMAND ${CMAKE_COMMAND} -Dsource_dir=${CMAKE_BINARY_DIR}/CMakeFiles/MyTarget.dir/
                              -Dtarget_dir=${CMAKE_BINARY_DIR}/ifc
                              -P ${CMAKE_SOURCE_DIR}/build/copy_ifc_files.cmake
    )
endif()

@gwankyun
Copy link

I need the code, post it please😄

In copy_ifc_files.cmake:

# Arguments:
#   source_dir - Source directory for the files
#   target_dir - Target directory for the files

set(source_dir ${ARGV0})
set(target_dir ${ARGV1})

# Function to check if the copy is necessary
function(check_copy_necessary src_dir tgt_dir result)
    file(GLOB_RECURSE src_files "${src_dir}/*")
    file(GLOB_RECURSE tgt_files "${tgt_dir}/*")

    foreach(src_file IN LISTS src_files)
        string(REPLACE "${src_dir}/" "" relative_path "${src_file}")
        set(tgt_file "${tgt_dir}/${relative_path}")

        # If a target file does not exist or is older than the source file, copying is necessary
        if (NOT EXISTS "${tgt_file}" OR "${src_file}" IS_NEWER_THAN "${tgt_file}")
            set(${result} TRUE PARENT_SCOPE)
            return()
        endif()
    endforeach()

    # If we reach here, no copying is necessary
    set(${result} FALSE PARENT_SCOPE)
endfunction()

# Check if the copy is necessary
check_copy_necessary("${source_dir}" "${target_dir}" copy_necessary)

if (NOT copy_necessary)
    message(STATUS "No need to copy files; target directory is up to date.")
    return()
endif()

# Attempt to copy
message(STATUS "Attempting to copy files...")
execute_process(
    COMMAND ${CMAKE_COMMAND} -E copy_directory "${source_dir}" "${target_dir}"
    RESULT_VARIABLE copy_result
)

if (${copy_result} EQUAL 0)
    message(STATUS "Files copied successfully.")
    return()
endif()

# If the copy failed, perform taskkill and retry
message(WARNING "Initial copy failed. Attempting taskkill and retry...")
execute_process(
    COMMAND taskkill /IM cpptools-srv.exe /F
    RESULT_VARIABLE taskkill_result
)

if (NOT ${taskkill_result} EQUAL 0)
    message(FATAL_ERROR "Failed to terminate cpptools-srv.exe. Copy cannot proceed.")
endif()

execute_process(
    COMMAND ${CMAKE_COMMAND} -E copy_directory "${source_dir}" "${target_dir}"
    RESULT_VARIABLE retry_result
)

if (NOT ${retry_result} EQUAL 0)
    message(FATAL_ERROR "Retry failed. Files could not be copied.")
endif()

message(STATUS "Files copied successfully after retry.")

Invoke like:

if(MSVC) # Does not include normal build, only Intellisense
    message(STATUS "Using MSVC")
    target_compile_options(MyTarget PRIVATE /ifcSearchDir ${CMAKE_BINARY_DIR}/ifc)

    # Copy ifc files for IntelliSense at post-build time
    add_custom_command(TARGET MyTarget
        POST_BUILD
        COMMAND ${CMAKE_COMMAND} -Dsource_dir=${CMAKE_BINARY_DIR}/CMakeFiles/MyTarget.dir/
                              -Dtarget_dir=${CMAKE_BINARY_DIR}/ifc
                              -P ${CMAKE_SOURCE_DIR}/build/copy_ifc_files.cmake
    )
endif()

Thank you very much.😊

@Challanger524
Copy link

@gwankyun remove your spam, please. Votes/emojis exist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

No branches or pull requests