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

add C++ PackageReference support #3145

Closed
wants to merge 5 commits into from

Conversation

mingkuang-Chuyu
Copy link

@mingkuang-Chuyu mingkuang-Chuyu commented Dec 3, 2019

Home issue

NuGet/Home#8874

New Feature

As we all know, C ++ has not supported PackageReference, which has led to a lot of repeated redundancy in C ++ projects.

So I add request a PR, to add VC++ Project PackageReference support.

However, before merging PR, Microsoft.NuGet.targets file in another git
https://github.com/dotnet/NuGet.BuildTasks also needs to be updated.

For details, see the RP of NuGet.BuildTasks:
dotnet/NuGet.BuildTasks#67

Thanks~

mingkuang

Testing/Validation

Tests Added: No
Reason for not adding tests: Do't know.
Validation:

@rrelyea
Copy link
Contributor

rrelyea commented Dec 3, 2019

We need to get the C++ team involved in this.
Solving this to work with vcxproj projects from command line, but not working in VS -- is likely not a good strategy.

Here is the uservoice logging customer feedback about this:
https://developercommunity.visualstudio.com/idea/351636/use-packagereference-in-vcxproj.html

@mingkuang-Chuyu
Copy link
Author

mingkuang-Chuyu commented Dec 4, 2019

We need to get the C++ team involved in this.
Solving this to work with vcxproj projects from command line, but not working in VS -- is likely not a good strategy.

Here is the uservoice logging customer feedback about this:
https://developercommunity.visualstudio.com/idea/351636/use-packagereference-in-vcxproj.html

?????
My solution can work well with very few changes. If you need vs native support, who knows when to support it? Now it's 2019, can we make C++ work better? Please understand us C++ developers.

@mingkuang-Chuyu
Copy link
Author

Just read the calendar, it turns out that it will be 2020 soon, but nuget has not yet supported it.

@rrelyea
Copy link
Contributor

rrelyea commented Dec 4, 2019

@mingkuang-Chuyu - like @nkolev92 gave you feedback on another recent PR...

It is best for you to open an issue in nuget/home/issues - that describes what you want to do and why...
rather than discuss those kind of topics in the middle of a PR.

Tell us what you are trying to do...and why it is or isn't ok to do without changes in VS' C++ project system too.

Then, if we get agreement on your plans, a specification of the changes may be appropriate. Then a PR...

@mingkuang-Chuyu
Copy link
Author

mingkuang-Chuyu commented Dec 4, 2019

@mingkuang-Chuyu - like @nkolev92 gave you feedback on another recent PR...

It is best for you to open an issue in nuget/home/issues - that describes what you want to do and why...
rather than discuss those kind of topics in the middle of a PR.

Tell us what you are trying to do...and why it is or isn't ok to do without changes in VS' C++ project system too.

Then, if we get agreement on your plans, a specification of the changes may be appropriate. Then a PR...

Thanks, got it

@mingkuang-Chuyu
Copy link
Author

mingkuang-Chuyu commented Dec 4, 2019

@rrelyea Hi, I opened an issue at home, hoping to get everyone's approval, nuget makes C++ better!

best

namespace NuGet.PackageManagement.VisualStudio
{
/// <summary>
/// Contains the information specific to a Visual Basic or C# project.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update comment

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@Scottj1s
Copy link

Scottj1s commented Dec 6, 2019

@mingkuang-Chuyu, thanks for your contribution. It looks like the VC support was mostly cloned from the existing VsManagedLanguagesProjectSystemServices.cs? Is there any functionality that you had to disable? For example, it looks like ProjectReference support was removed.

{
Assumes.Present(targetFramework);

//await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why couldn't _threadingService be used?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found out that they are actually the same object.

await _threadingService.JoinableTaskFactory.SwitchToMainThreadAsync();

//C++ Project not support Reference
return new ProjectRestoreReference[] { };
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this refer to VC project-project references? What functionality is this omitting?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because native C++ does not support assembly references, so I returned an empty list.

metadataValues.Add(LibraryIncludeFlagUtils.GetFlagString(privateAssetsFlag).Replace(',', ';'));
}

NuGetUIThreadHelper.JoinableTaskFactory.Run(async delegate
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain rationale for making some of these operations async, compared with VsManagedLanguagesProjectSystemServices.cs?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this is a mistake.

@mingkuang-Chuyu
Copy link
Author

@mingkuang-Chuyu, thanks for your contribution. It looks like the VC support was mostly cloned from the existing VsManagedLanguagesProjectSystemServices.cs? Is there any functionality that you had to disable? For example, it looks like ProjectReference support was removed.

Yes, cloned from the VsManagedLanguagesProjectSystemServices.cs.
: )

* AddOrUpdatePackageReferenceAsync remove NuGetUIThreadHelper.JoinableTaskFactory.Run
* HasPackageReference call Get​Items​Ignoring​Condition

Thanks to Scottj1s
@mingkuang-Chuyu
Copy link
Author

@Scottj1s ,Hi, I added contentFiles support for VC++ Project.

targetFrameworks: null,
targetFramework: null,
targetFrameworks: targetFrameworks,
targetFramework: targetFramework,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is modified to provide targetFramework support for C++. In addition, I found that NuGet.CommandLine does this, so I copied its implementation.

Code Here:
https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Clients/NuGet.CommandLine/Common/MSBuildProjectSystem.cs#L63

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function requires NuGet.BuildTasks configuration to use.

Here are the changes I submitted in NuGet.BuildTasks (src/Microsoft.NuGet.Build.Tasks/Microsoft.NuGet.targets):
https://github.com/dotnet/NuGet.BuildTasks/pull/67/files#diff-5b809cf81a6b552123b02a4b102867c9

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

targetFramework matching order

  (vs2019)
native v14.20.27508, 14.21.27702, 14.22.27905, 14.23.28105 ...
      |
  (vs2017)
native v14.10.25017, 14.11.25503, 14.12.25827, 14.13.26128 ...
      |
  (vs2015) 
native v14.0 
      |
native v0.0 

For example, if the following 2 paths exist in a package:

  • build\native14.0\Test.Static.targets
  • build\native14.20\Test.Static.targets

If we use the v142 toolset (14.23.28105 vs2019), then build\native14.20\Test.Static.targets will insert * .nuget.g.targets.

If we use the v141 toolset (vs2017), then build\native14.0\Test.Static.targets will insert * .nuget.g.targets.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, using targetFramework, we can configure different static libraries for different toolsets of C++ projects.

    <dependencies>
      <group targetFramework="native14.0">
        <dependency id="Detours.Static.v140" version="4.0.1" />
      </group>
      <group targetFramework="native14.10">
        <dependency id="Detours.Static.v141" version="4.0.1" />
      </group>
      <group targetFramework="native14.20">
        <<dependency id="Detours.Static.v142" version="4.0.1" />
      </group>
    </dependencies>

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the project file (vcxproj), we can also do like this:

  <ItemGroup>
    <PackageReference Include="Detours.Static.v141" Condition=" '$(TargetFramework)' == 'native14.13.26128' ">
      <Version>4.0.1</Version>
    </PackageReference>
  </ItemGroup>

@mingkuang-Chuyu
Copy link
Author

What's going on?

@zivkan zivkan added the Community PRs created by someone not in the NuGet team label Mar 5, 2020
@AugP
Copy link

AugP commented Mar 20, 2020

Hello and thank you for the contribution! I work on the C++ team. First I want to apologize for the delay in responding - we have been actively monitoring PackageReference feedback as well as this PR, and we should have been more communicative.

From our side, here is the situation:

  • We are working on plans to improve the C++ package management story. Specifically, we want to extend the features of our existing C++ package manager, vcpkg: https://github.com/microsoft/vcpkg, and improve build system integration, but across multiple build systems, not just MSBuild. We also want vcpkg to be able to support existing NuGet-packaged libraries in some way.
  • Our concern with going all in on PackageReference is that it an MSBuild-specific concept, which would not be extensible to CMake projects or other external build systems. Within the next year or less, we want to provide the means to attach any C++ library to any of the project systems we support. We are also considering ways to provide MSVC toolsets and other build-time tools as NuGet packages, and are determining that we would want something more powerful than PackageReference to accomplish this (and again we would want to be build system agnostic).
  • If we accept this PR and do any additional work required on the IDE side to unblock PackageReference usage for C++, the work would be rendered obsolete in the future when we move to the build system agnostic model. Our concern there is that if developers do the work to migrate to C++ PackageReference, they would later realize that we don't intend to provide ongoing support and want them to move to something else. I expect that would be a frustrating experience.

So our team is not decided on whether or not to add broad PackageReference support right now. If we do, we would be resolving the issue more quickly for the many people who are looking for this feature. But we would see the solution more like a band-aid solution than a complete one, and the NuGet C++ experience would still suffer in a few ways, as it does today for packages.config:

  1. Automatic restore on project load would not work
  2. Our project caching system would not work at the time a NuGet restore is done (impacts solution load times)

Both of those issues could be fixed in theory, but we would likely shift our resources instead to the bigger solution we have been planning as it would benefit more developers.

For now, we are definitely committing to PackageReference support for C++/CLI projects targeting .NET Core, as there are cases there where developers are required to pull in NuGet packages in a workflow where packages.config no longer works at all.

I am continuing conversations with my team to determine if broader PackageReference support makes sense as a path and will keep you posted.

@mingkuang-Chuyu
Copy link
Author

mingkuang-Chuyu commented Mar 24, 2020

@AugP Thanks~

I just want to say that vcpkg does not conflict with NuGet C ++ PackageReference support. NuGet is for VS users only, while vcpkg is for all toolchains. In addition, when vcpkg provides support for VS, cannot use the interface provided by NuGet? I also expect to be more powerful and versatile, but I‘m more worried that you have not done well in a few years ...

And now our Intranet use NuGet experience is very good, can you provide a simple solution to deploy the NuGet.Tools.vsix I compiled to the Exp environment? Currently it is too much trouble to install the Visual Studio SDK. If there is an easier way, I can quickly deploy my modified NuGet plug-in to my colleagues. Hope to get your help ~

The virus has been very serious recently, and I wish you all the best.

mingkuang

@mingkuang-Chuyu
Copy link
Author

mingkuang-Chuyu commented Mar 24, 2020

Finally, as users, we don't care if NuGet supports CMake or others.

Just like we care about VS supporting GCC projects?

@mingkuang-Chuyu
Copy link
Author

mingkuang-Chuyu commented Mar 25, 2020

I thought about it for a night and had some ideas. First of all, I don't quite agree with you.

1. NuGet not only provides libraries, but also provides custom tools to enhance the IDE experience.

For example, there is a custom UI compiler. Through NuGet, we can quickly configure a custom UI compiler for the projects.

For another example, because some of the company's customer environment is Windows 2000, I developed a Windows 2000 compatible toolkit for VS2019, so that 2019 CRT + UCRT can compile Windows 2000 compatible C ++ applications directly.

Does vcpkg provide enhanced support for the IDE in these scenarios?

2. PackageReference does not depend on MSBuild

It's supported by Microsoft.NuGet.Build.Tasks.dll. For MSBuild, it doesn't know any PackageReference.

Theoretically, we can implement an adapter for CMake and let CMake know about PackageReference.

The problem is that the NuGet C++ Package transition relies on props/targets, and other toolchains don't know props/targets. If we provide more support for NuGet C++, then everyone will reduce the use of props/targets.

For example, if NuGet supports import IncludePath and LibraryPath for C++. Now there is a NuGet package named S360. Its nupkg configuration is as follows:

<package xmlns="http://schemas.microsoft.com/packaging/2013/01/nuspec.xsd">
  <metadata minClientVersion="2.5">

   <!--...................................-->

  </metadata>
<files>
    <file src="S360\include\**" target="CppInclude"/><!--C++ include-->
    <file src="S360\Library\x64\**" target="CppLibrary\native\x64"/> <!--C++ x64 lib-->
    <file src="S360\Library\x86\**" target="CppLibrary\native\x86"/>
</files>
</package>

Then when NuGet's CMake adapter processes this NuGet package, it finds that the package contains CppInclude and CppLibrary directories, so it generates this configuration(CMake):

#S360.1.0.1.cmake

cmake_minimum_required(VERSION 3.5.2)

include_directories("XXXXXXXXXXXXXXXXXXXXXXXX\CppInclude")

# if(${CMAKE_GENERATOR_PLATFORM} STREQUAL "Win32")
if(${CMAKE_VS_PLATFORM_NAME} STREQUAL "Win32")
   link_directories("("XXXXXXXXXXXXXXXXXXXXXXXX\CppLibrary\native\x86")

# if(${CMAKE_GENERATOR_PLATFORM} STREQUAL "x64")
if(${CMAKE_VS_PLATFORM_NAME} STREQUAL "x64")
   link_directories("XXXXXXXXXXXXXXXXXXXXXXXX\CppLibrary\native\x64")

Then import this S360.1.0.1.cmake, and cmake can handle this Nuget package now.

At last

I hope NuGet can accept my PR. My PR will help improve the VS C++ development experience without affecting your CMake support.

Thunaks

@mingkuang-Chuyu
Copy link
Author

@AugP waiting for your good news.

@mingkuang-Chuyu
Copy link
Author

Is there any progress now?

@Nirmal4G
Copy link
Contributor

@AugP There are hybrid nuget packages that can be used for both VC and .NET projects. So, We have to support both NuGet (PackageReference) and VCPkg support in both MSBuild and CMake. I just hope whatever the solution is, doesn't let me diverge my native and managed projects. I also like the idea of Centrally managed dependencies in NuGet, would also support VC projects. And yes, the simplified project format (SDK-style) too!

@rrelyea
Copy link
Contributor

rrelyea commented Jul 16, 2020

Given the reply from @AugP (from Microsoft's C++ team) on 3/20/2020, we're going to close this PR.

I've copied his reply to the issue tracking this feature request: NuGet/Home#8874
Please move future discussions to that issue.

Thanks for engaging with us and the C++ team on this PR/Issue.

@Zingam
Copy link

Zingam commented Jul 16, 2021

@AugP A lot of time has passed since this post: #3145 (comment) and there still doesn't seem to be any roadmap of how non MSBuild system will be supported in WindowAppSDK, GameDK, etc.

@mingkuang-Chuyu
Copy link
Author

Save the following piece of xml as “Directory.Build.props” and put it in your code directory. NuGet can be used for C++ platforms above VS 16.8!!!

<?xml version="1.0" encoding="utf-8"?>
<!--
为Cpp工程强制开启 PackageReferences 支持

Visual Studio 2017使用以后只能让MSBuild以及nuget.exe支持包还原。

Visual Studio 2019 16.8或者更高版本可以直接让Visual Studio NuGet插件支持包管理。

使用方法:将此文件复制到 sln 或者 vcxproj同级目录。


作者:mingkuang
最后修订:2021-06-21

-->
<Project ToolsVersion="4.0" xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Condition="'$(MSBuildProjectExtension)' == '.vcxproj'">
    <!--强制引入PackageReferences-->
    <ProjectCapability Include="PackageReferences" />
  </ItemGroup>
  <PropertyGroup Condition="'$(MSBuildProjectExtension)' == '.vcxproj'">
    <!--指定自己的体系为native-->
    <NuGetTargetMoniker Condition="'$(NuGetTargetMoniker)' == ''">native,Version=v0.0</NuGetTargetMoniker>
    <!--如果不指定这一行,那么arm64平台会找不到RID而失败-->
    <RuntimeIdentifiers Condition="'$(RuntimeIdentifiers)' == ''">win;win-x86;win-x64;win-arm;win-arm64</RuntimeIdentifiers>
  </PropertyGroup>
  
  <!--从兼容性考虑,继续向上搜索 Directory.Build.props-->
  <PropertyGroup>
    <DirectoryBuildPropsPath>$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))</DirectoryBuildPropsPath>
  </PropertyGroup>
  <Import Project="$(DirectoryBuildPropsPath)" Condition="'$(DirectoryBuildPropsPath)' != ''"/>
</Project>

@levicki
Copy link

levicki commented Jan 21, 2022

@AugP

For now, we are definitely committing to PackageReference support for C++/CLI projects targeting .NET Core...

Why only .Net Core? Would it be too much effort to also support .Net Framework targets?

I'd love to be able to use .Net Framework NuGet packages in my C++/CLI projects without having to introduce .Net Core dependencies (vendor's code on those systems which we are interfacing with is also a mix of pure C++, C++/CLI with .Net Framework, and C# and we have no idea if and when they might switch to .Net Core).

Finally, is there any ETA for this feature?

Thanks in advance for your time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Community PRs created by someone not in the NuGet team
Projects
None yet
8 participants