Skip to content
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

Bug: Version mismatch #1440

Closed
laultman opened this issue Oct 18, 2024 · 9 comments
Closed

Bug: Version mismatch #1440

laultman opened this issue Oct 18, 2024 · 9 comments

Comments

@laultman
Copy link

laultman commented Oct 18, 2024

Version

2.0.240405.15

Summary

This issue produces error that seem to point to CppWinRT and in fact the VS team said it is a CppWinRT issue. I am making a note here for those who might have a reported mismatch with some version of CppWinRT that you don't recall installing.
Visual Studio Installer installs a default version of CppWinRT that is a version that is in their build chain for a particular release. That is the default fallback version used no matter what you may specify as the Windows SDK version for your project. The VS behavior of falling back happens when some project that uses CppWinRT without explicitly declaring a version.
In my case this did not become apparent until I switched a project from a static to a dynamic version for my project. The VS documentation states that it automatically uses CppWinRT but fails to state that it is the install version in spite of the fact that you may subsequently install the correct version on your dev computer. This install is not an update it is a side-by-side additional version, VS continues to use the one defined it its original install.

The solution is to explicitly define the version and propagate that across all your projects that call that code. This may require a new feature branch in your source control, that is a normal problem we must deal with.

You can add the version to your package.config or edit the vcproj file with the matching version.

Reproducible example

#include <winrt/base.h>

#using <winrt/WindowsFoundation>

// if you have other projects that reference this project and in the other projects you specify cppWinRT and a version, // you must ensure that all use the same version.

Expected behavior

Since VS has a default property for WinRT, it should have at least a value for the resolved WinRT version in the General section of the properties to allow developers to see the version. If the developer selects a Vcpkg or a Nuget that has a version. VS should use the resolved value property to indicate a mismatch and list the values of all referenced projects. This would have save me a few days of work searching and CoPiloting.

Actual behavior

Output Window shows error in a WinRT mismatch and the version of the installed VS WinRT. Developer has no way to verify where this version comes from.

Additional comments

This clearly falls into the category VS blogs talk about as quality of life improvements.

@sylveon
Copy link
Contributor

sylveon commented Oct 18, 2024

I believe it's probably falling back to the version included in the Windows SDK, VS doesn't include its own cppwinrt headers.

The error generated by the #pragma detect_mismatch should identify which files are mismatching, at the very least.

@laultman
Copy link
Author

@sylveon I'll start using the pragma you mentioned. You are correct that VS itself does not have its own cppwinrt header, rather it installs a version in the Program Files X86 under the Windows Kits, selected by the user or uses the defaults of VS installer. What it does seem to do is maintain somewhere a default reference to at least what was installed by the VS installer. This is likely because it is the only one VS could "know" about. This naturally would not prevent the developer from removing it - that is another can of worms. Nor does it prevent the developer from installing other versions of cppwinrt or using vcpkg or nuget. That is the problem effectively that I had, is a mismatch between the different sources one of which was the VS default fall back version which I did not know about. I was not aware that cppWinRT was included in the Windows SDK nor was I aware that VS "automatically" created references to cppWinRT. Automatic, is really the built-in links to the Windows SDK. While id does not matter to me now, I still don't know why VS fell back to a much earlier version unless it uses the minimum target platform specified rather than the target platform version select. I typically use the setting for "latest installed version" rather than a specific SDK. If this is the behavior to fall back to minimum, then using latest really isn't much value.

@sylveon
Copy link
Contributor

sylveon commented Oct 20, 2024

The pragma is what C++/WinRT uses to generate the error, using it yourself won't do much benefit.

The Windows Kits folder is where the Windows SDK gets installed.

What is happening here is that VS by default adds the folders from the Windows SDK to the include order, and the SDK contains an outdated copy of C++/WinRT headers (even the latest Windows SDK does). When you install the C++/WinRT NuGet, it adds its own set of headers higher in the include order.

@dmachaj
Copy link
Contributor

dmachaj commented Oct 21, 2024

I think @sylveon is right. The Windows SDK includes a bunch of cppwinrt generated headers and the version of cppwinrt used to generate those headers is always going to be older than the latest cppwinrt. Often a lot older.

I believe the appropriate fix here is to ensure that the include directories are ordered such that the cppwinrt generated outputs local to your project are always used before the versions in the Windows SDK. That will ensure that the pragma mismatch is satisfied because all generated headers have the exact same version of cppwinrt. My understanding is that the project templates have the correct include ordering by default.

@sylveon
Copy link
Contributor

sylveon commented Oct 21, 2024

The NuGet itself ensures it is in the right place in the include order.

"Uses cppwinrt without declaring a version" suggests to me they were mixing projects where the NuGet was installed and others where it wasn't.

@laultman
Copy link
Author

In this case the "they" who is using mixed versions is me. I clearly did not understand how VS "decides" how to order things. I also didn't know that in the absence of a specific declaration that it used the Windows SDK, which happens to be listed first in the includes list.
What still is somewhat of a mystery, if I build a dll that depends on CppWinRT and I use a particular version and later we create another dll or a partner creates a dll that uses a different version, that needs to consume our dll, what happens.
What did happen in my case, Microsoft built the project and did not define any version. Later (4 years) I used their source code in my project. Since it was source code VS simply used the local copy version from the SDK but the vcproj had an import statement. One of my projects specifically used the CppWinRT nuget from a much later version. The individual projects would build but because of the references to the projects the linker kept failing on the mismatch.
Tracking these dependencies is painful, curing them is harder, vcpkg and nuget both have their place, but versioning is fragile at best. I don't know of a "best solution" for this?

@dmachaj
Copy link
Contributor

dmachaj commented Oct 21, 2024

It is not a requirement that all DLLs within a single process must use the same version of cppwinrt. Rather, all of the translation units combining into a binary (DLL) must agree on the cppwinrt version.

The primary purpose of cppwinrt is to take WinRT API definitions, in the form of a .winmd file, and project them into C++ headers so that C++ code can call WinRT APIs. As long as each DLL is self-consitent about the cppwinrt version and produces its own projects from winmd files then it will match and be fine. The trouble is when versions are crossed.

@sylveon
Copy link
Contributor

sylveon commented Oct 21, 2024

Yes, mixing TUs with different versions risks running into ODR issues.

@laultman
Copy link
Author

Sometimes just finding the edges is the hardest part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants