Reputation: 30235
Is it possible to use a newer dotnet SDK building C++/CLI vcxproj than their target framework?
We have a large solution containing C#, C++ and a handful of C++/CLI projects. The target framework is set to .NET 6 (latest LTS and all that). At the same time I'd like to use C# 11 and which requires the use of a .NET 7 sdk when building.
For normal C# projects I can simply use a global.json to specify .NET 7 (when using a new enough VS) while keeping TargetFramework=6.0.
When doing the same with C++/CLI projects I get a NETSDK1145 error:
Error NETSDK1145 The Apphost pack is not installed and NuGet package restore is not supported. Upgrade Visual Studio, remove global.json if it specifies a certain SDK version, and uninstall the newer SDK. For more options visit https://aka.ms/targeting-apphost-pack-missing Pack Type:Apphost, Pack directory: C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Host.win-x64, targetframework: net6.0, Pack PackageId: Microsoft.NETCore.App.Host.win-x64, Pack Package Version: 6.0.16 C:\Program Files\dotnet\sdk\7.0.203\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets 135
The link says something about setting
<ItemGroup>
<KnownAppHostPack Update="@(KnownAppHostPack)">
<AppHostPackVersion Condition="'%(TargetFramework)' == 'TARGETFRAMEWORK'">EXISTINGVERSION</AppHostPackVersion>
</KnownAppHostPack>
</ItemGroup>
but does not say anything about possible problems or the consequences of doing so. I'm also not sure how I'd do that if people might have different .NET 7 SDKs installed (I don't want to force a single SDK).
Upvotes: 0
Views: 1387
Reputation: 25543
For me installing this .NET 6 sdk solved the issue.
Specifically this one.
For the exact project that is giving me this problem, right click and go to properties. Go to Advanced and you can see .NET 6 as follows.
Upvotes: 0
Reputation: 30235
So far just setting the app host package to a .NET 6 variant while building using .NET 7 seems to be working just fine.
To make this streamlined to use, I wrote a simple inline roslyn code factory that finds the newest app host package for the required target framework (nb the hardcoded runtime identifier - you'll have to see what msbuild identifier exists for a general solution).
On the build system the used .NET SDK and its runtime version are hardcoded for reproducability
<UsingTask TaskName="GetAppHostVersionTask"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildBinPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<NetCoreTargetingPackRoot ParameterType="System.String" Required="true" />
<KnownAppHostPack ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<RuntimeIdentifiers ParameterType="System.String" Required="true" />
<TargetFramework ParameterType="System.String" Required="true" />
<HighestSupportedVersion ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
#pragma warning disable CS0162 // False positive warning
var runtimeName = this.KnownAppHostPack[0].ItemSpec;
var packDirectory = Path.Combine(this.NetCoreTargetingPackRoot, $"{runtimeName}.Host.{this.RuntimeIdentifiers}");
var supportedVersion = this.TargetFramework.Substring("net".Length);
var versionToUse = Directory.EnumerateDirectories(packDirectory)
.Select(Path.GetFileName)
.Where(dirName => dirName.StartsWith(supportedVersion, StringComparison.OrdinalIgnoreCase))
.OrderByDescending(Version.Parse)
.FirstOrDefault();
if (versionToUse is null)
{
this.Log.LogError($"'{packDirectory}' does not contain any pack runtime for target framework {this.TargetFramework}.");
return false;
}
this.Log.LogMessage(MessageImportance.High, $"AppHostPackVersion set to {versionToUse}");
this.HighestSupportedVersion = versionToUse;
return true;
]]>
</Code>
</Task>
</UsingTask>
<Target Name="SetAppHostPackVersion" BeforeTargets="ProcessFrameworkReferences">
<GetAppHostVersionTask
NetCoreTargetingPackRoot="$(NetCoreTargetingPackRoot)"
KnownAppHostPack="@(KnownAppHostPack)"
RuntimeIdentifiers="win-$(Platform)"
TargetFramework="$(TargetFramework)"
Condition=" '$(MyAppHostPackVersion)' == '' ">
<Output TaskParameter="HighestSupportedVersion" PropertyName="MyAppHostPackVersion" />
</GetAppHostVersionTask>
<ItemGroup>
<KnownAppHostPack Update="@(KnownAppHostPack)">
<AppHostPackVersion>$(MyAppHostPackVersion)</AppHostPackVersion>
</KnownAppHostPack>
<KnownFrameworkReference Update="@(KnownFrameworkReference)">
<TargetingPackVersion>$(MyAppHostPackVersion)</TargetingPackVersion>
</KnownFrameworkReference>
</ItemGroup>
</Target>
I'll report back if there's any bug reports that can be traced back to this, but so far it looks good. Seems like the ABI is stable across versions.
Upvotes: 0
Reputation: 2826
Im probably going to be the bearer of bad news here.
My understanding of it is that probably wont work for you. If you field it out correctly I think it would look like this
<ItemGroup>
<KnownAppHostPack Update="@(KnownAppHostPack)">
<AppHostPackVersion Condition="'%(TargetFramework)' == 'net6.0'">EXISTINGVERSION</AppHostPackVersion>
</KnownAppHostPack>
</ItemGroup>
As your telling Apphost what specific version to use. If done correctly this would potentially solve the NETSDK1145 error; however, it would only solve that error, it wouldnt update it for the whole project which would likely be full of issues.
Your likely just going to be hopping from one bug to another even if that works
It will probably just be quicker to update your project. Visual studios supports Net7 targets now
https://developercommunity.visualstudio.com/t/Add-NET70-target-for-CCLI-Projects/10232939
Upvotes: 1