Build error when packaging multiple nuget targets - c#

I'm attempting to make a Nuget package for multiple framework targets (.netstandard20 and net46). I am able to build the solution and the outputs appear on disk as expected, but whenever I try to package them (Visual Studio 2019 or msbuild directly), I'm getting the following error:
error MSB4057: The target "_GetBuildOutputFilesWithTfm" does not exist in the project.
I'm not using a .nuspec file and the developer packages of my target frameworks are installed correctly.
Here's my .csproj (with nuget metadata excluded for brevity) - it's pretty basic:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
<ReleaseVersion>1.0</ReleaseVersion>
<PackageVersion>1.0</PackageVersion>
...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType></DebugType>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net46'">
<PackageReference Include="NuGet.Build.Tasks.Pack" Version="5.2.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<PackageReference Include="NuGet.Build.Packaging" Version="0.2.2" />
</ItemGroup>
</Project>
Does anyone have any ideas??
Thanks

Removing references to NuGet.Build.Tasks.Pack and NuGet.Build.Packaging allows targeting only .NET Standard 2.0 and getting the desired behavior.

Related

What is the difference between <UseMauiEssentials> and <UseMaui> in the Android/iOS csproj file? Should I use both in my csproj files?

I want to use .NET MAUI in my existing Android and iOS projects but I'm not sure if I need to add UseMauiEssentials and UseMaui or only one of them to my existing csproj files. Currently I use Xamarin.Essentials and some other Xamarin NuGet packages in my Android and iOS projects.
My Android csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-android</TargetFramework>
<SupportedOSPlatformVersion>23</SupportedOSPlatformVersion>
<OutputType>Exe</OutputType>
<ApplicationId>com.companyname.AndroidprojectwithXamarin</ApplicationId>
<ApplicationVersion>1</ApplicationVersion>
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
<PackageReference Include="MonoGame.Framework.Android" Version="3.8.1.303" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.4" />
</ItemGroup>
<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
<Message Text="Restoring dotnet tools" Importance="High" />
<Exec Command="dotnet tool restore" />
</Target>
</Project>
My iOS csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-ios</TargetFramework>
<OutputType>Exe</OutputType>
<SupportedOSPlatformVersion>15.0</SupportedOSPlatformVersion>
<CodesignKey>iPhone Developer</CodesignKey>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<CreatePackage>false</CreatePackage>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<CreatePackage>false</CreatePackage>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
<PackageReference Include="MonoGame.Framework.iOS" Version="3.8.1.303" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.4" />
</ItemGroup>
<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
<Message Text="Restoring dotnet tools" Importance="High" />
<Exec Command="dotnet tool restore" />
</Target>
</Project>
What is the difference between UseMauiEssentials and UseMaui in the Android/iOS csproj files? Should I use both in my csproj files?
Is it necessary to remove the Xamarin.Essentials NuGet package from my projects? Is it necessary to add another .NET MAUI NuGet package if I want to use .NET MAUI? Or should I leave the Xamarin.Essentials NuGet package installed?
As you've already found, Xamarin.Essentials was a separate project. Essentials was basically an abstraction layer for all kinds of APIs that are available across the different platforms (iOS, Android, Windows) but don't necessarily have any UI.
Since Xamarin.Forms was a UI framework, all of Essentials was not included in Forms. In fact, you can use Xamarin.Essentials with a traditional Xamarin application if you want, there is no dependency on Forms.
With the introduction of .NET MAUI, Essentials as a separate concept kind of went away. Essentials is now an integrated part of .NET MAUI and it's just APIs that are available for you to use.
However, those APIs still have no dependency on .NET MAUI and you should be able to use Essentials without using .NET MAUI. And that is where we get to the answer of this question: use UseMauiEssentials if you just want to use the APIs formerly known as Essentials, or, if you're going to use all of .NET MAUI anyway, just include UseMaui that will also bring in Essentials automatically.

Project reference in Nuget

I need to create a Nuget of project A which is dependent on project B (not a nuget project, local one).
I have added Project B as project dependency to project A and enabled property to generate package on build. It is creating nuget package file but not including all the files from project A.
I tried few things and google also but not finding much help.
I found one similar question Build NuGet Package automatically including referenced dependencies
but not working. I am able to create pkg but with few files copied over. while I can see all the files in debug folder. No idea on what basis Nuget is picking few files from project A.
Can anyone tell me what's wrong here.
<Project Sdk="Microsoft.NET.Sdk" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetFramework>net462</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageVersion>1.0.0.0-alpha</PackageVersion>
<Platforms>x64</Platforms>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<PlatformTarget>x64</PlatformTarget>
<NoWarn></NoWarn>
<WarningsAsErrors />
<OutputPath>bin\Debug</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<NoWarn></NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<OutputPath>bin\Release</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Configuration" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="someProject.csproj">
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<IncludeAssets>all</IncludeAssets>
</ProjectReference>
</ItemGroup>
<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
<BuildOutputInPackage Include="#(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))"/>
</ItemGroup>
</Target>
</Project>

Extract git branch name while building C# project

While building the C# project locally/CI server, I wanted to control the NuGet package reference in the .csproj file. If the developer is building a C# project on github master branch (locally/CI server) I would like to add RC build NuGet package reference otherwise PRE releases NuGet package reference. How to do this? Can someone please assist me?
Some thoughts like -
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<GitBranch>$(GitBranch.Trim())</GitBranch>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GitInfo" Version="2.2.0" />
</ItemGroup>
<Choose>
<When Condition="$(GitBranch) == 'master'">
<ItemGroup>
<PackageReference Include="Data.Account.Domain.Messaging" Version="1.0.0-rc*" IncludePrerelease="true" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<PackageReference Include="Data.Account.Domain.Messaging" Version="1.0.0-pre*" IncludePrerelease="true" />
</ItemGroup>
</Otherwise>
</Choose>
</Project>
You could read the git branch from the .git/HEAD file. Naive implementation like
<PropertyGroup>
<GitBranch>$([System.IO.File]::ReadAlltext('$(MsBuildThisFileDirectory)\.git\HEAD').Replace('ref: refs/heads/', '').Trim())</GitBranch>
</PropertyGroup>
You might want to adjust how you get the path to that file, and perhaps use something more robust (e.g. if you just checkout a random commit in git, the file won't contain a branch name but a commit SHA)
You could also use variable $(GitRoot) from GitInfo itself to build the path, just a small adaption to the existing code but helped for my case where I had to deal with nested folders.
<PropertyGroup>
<GitBranch>$([System.IO.File]::ReadAlltext('$(GitRoot)\.git\HEAD').Replace('ref: refs/heads/', '').Trim())</GitBranch>
</PropertyGroup>

use .net core sdk in MSBuild project

I have a PCL-project with different functions and classes for each platform. I want to implement .net core support now. But I cant use controls like UserControl because the Microsoft.NET.Sdk.WindowsDesktop SDK isn't referenced. The .net framework is easy to implement because I only have to reference each assembly... But in .net core, I can't reference the assembly...
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;xamarin.ios10;xamarin.mac20;xamarin.tvos10;monoandroid10.0;tizen40</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">uap10.0.17763;net472;netcoreapp3.1;$(TargetFrameworks)</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('net4')) And '$(OS)' == 'Windows_NT' ">
...
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System.Xaml" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netcoreapp3')) And '$(OS)' == 'Windows_NT' ">
...
<SDKReference Include="Microsoft.NET.Sdk.WindowsDesktop" />
</ItemGroup>
That's my executable app, referencing the PCL-project above;
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<ProjectReference ...... />
</ItemGroup>
</Project>
I already tried this to reference the SDK but its not working.
<SDKReference Include="Microsoft.NET.Sdk.WindowsDesktop" />
I want to implement .net core support now. But I cant use controls
like UserControl because the Microsoft.NET.Sdk.WindowsDesktop SDK
isn't referenced. The .net framework is easy to implement because I
only have to reference each assembly... But in .net core, I can't
reference the assembly..
After doing a deep research, I found that Microsoft.NET.Sdk.WindowsDesktop cannot be used by SDKReference.
As a suggestion, you could create a custom targets file and then import it into your PCL-project to use the Net Core SDK.
1) create a file called custom.targets in your PCL project folder.
2) Then add these in custom.targets:
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>
3) import this in xxx.csproj file of PCL-Project.
<Import Project="$(ProjectDir)custom.targets" Condition=" $(TargetFramework.StartsWith('netcoreapp3')) And '$(OS)' == 'Windows_NT' "/>
4) Then restart your project. Although there are some warnings that reminds you that some sdks are repeatedly quoted, you can ignore them and it will not have any impact on your project.
You can check this, which works well in my side.

Error when building System.ValueTuple in .NetStandard 2.0 project

I have a .NetStandard project that uses System.ValueTuple.
It builds fine in visual studio whether or not I include the System.ValueTuple nuget package.
However it fails either way when I build it on team-city with the error:
error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference?
Teamcity is hosted on an environment with both the latest .Net Core SDK and the latest .NetFramework SDK.
When I change the target framework to .NetCoreApp2.0 it builds fine.
Any ideas as to what could be going on?
For Reference, here is my csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Version>$(VersionSuffix)</Version>
<Authors>**********</Authors>
<Product>**********</Product>
<Description>**********</Description>
<PackageTags>**********</PackageTags>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Copyright>**********</Copyright>
<PackageProjectUrl>http://**********</PackageProjectUrl>
<PackageLicenseUrl>http://**********</PackageLicenseUrl>
<PackageIconUrl>http://**********</PackageIconUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.4.1" />
<PackageReference Include="RabbitMQ.Client" Version="5.0.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="**********" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\**********" />
</ItemGroup>
The error went away when I started using DotNet Restore instead of Nuget Restore.
I have no idea why.
You most probably need to add a reference to System.ValueTuple.dll. You can do this by installing the System.ValueTuple package from nuget.

Categories