I've authored a dotnet core library, which is packaged using NuGet. I want to embed the debug information (and the source code if that's possible) in the dll. rather than have a separate symbols package.
According to https://github.com/ctaggart/SourceLink it looks like this is possible when invoking the compiler directly by specifying some switches to the compiler. I don't understand how the csproj file relates to invocation of the compiler.
How can I specify the flag /debug:embedded from the csproj?
Here's my csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
<AssemblyName>KamailioApi</AssemblyName>
<PackageId>KamailioApi</PackageId>
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<!-- don't change this we hack it in the TeamCity Build-->
<Version>1.0.1</Version>
<PackageVersion>1.0.1-beta</PackageVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />
<PackageReference Include="System.Xml.XmlDocument" Version="4.0.1" />
<PackageReference Include="system.xml.xpath.xmldocument" Version="4.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.6' ">
<PackageReference Include="System.Net.Requests" Version="4.3.0" />
</ItemGroup>
</Project>
You can do this with the <DebugSymbols> and <DebugType> properties, like this:
<PropertyGroup>
<DebugSymbols>true</DebugSymbols>
<DebugType>embedded</DebugType>
</PropertyGroup>
Here's an example of where I do it with MiniProfiler, note that Directory.build.props applies to all .csproj files at or below that directory level so you can specify common things in larger projects one time.
Related
I have a Library project in .net6, I have attempted to install serilog version 2.10 or serilog.AspCore version 5.0 a couple of time but both returned error. I keep getting errorPackage Serilog.Sinks.Debug 2.0.0 is not compatible with net6.0 each time. Below is the .csproj file.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.3" />
</ItemGroup>
</Project>
Does this mean serilog is not available for .net6 library project or I am not getting the version right?
I have tried the following project setup and works fine for me:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.3" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
</ItemGroup>
</Project>
You can find the full source code at https://github.com/myblindy/GrimBuilding/tree/efcore (the efcore branch).
I understand that source generators can't automatically harvest dependencies from nuget packages and you have to use a clunky work-around to get it to work, and I have done so. This is my source generator project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.0-1.final" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" PrivateAssets="all" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.*-*" GeneratePathProperty="true" PrivateAssets="all" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="6.*-*" GeneratePathProperty="true" PrivateAssets="all" />
<PackageReference Include="SQLitePCLRaw.lib.e_sqlite3" Version="2.*-*" GeneratePathProperty="true" PrivateAssets="all" />
<PackageReference Include="SQLitePCLRaw.provider.e_sqlite3" Version="2.*-*" GeneratePathProperty="true" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup>
<GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn>
</PropertyGroup>
<Target Name="GetDependencyTargetPaths">
<ItemGroup>
<TargetPathWithTargetPlatformMoniker Include="$(PKGSQLitePCLRaw_bundle_e_sqlite3)\lib\netstandard2.0\SQLitePCLRaw.batteries_v2.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PKGSQLitePCLRaw_provider_e_sqlite3)\lib\netstandard2.0\SQLitePCLRaw.provider.e_sqlite3.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PKGSQLitePCLRaw_lib_e_sqlite3)\runtimes\win-x64\native\e_sqlite3.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PKGMicrosoft_Data_Sqlite_Core)\lib\netstandard2.0\Microsoft.Data.Sqlite.dll" IncludeRuntimeDependency="false" />
</ItemGroup>
</Target>
</Project>
Since there also isn't any transitive support, I added every nested Microsoft.Data.Sqlite package one by one, generated their path property and referenced it using TargetPathWithTargetPlatformMoniker. It all works until I get to the native e_sqlite3.dll, if I use TargetPathWithTargetPlatformMoniker with it, it tries to reference it as a managed library, and it fails as expected:
4>CSC : warning CS8034: Unable to load Analyzer assembly C:\Users\meep.nuget\packages\sqlitepclraw.lib.e_sqlite3\2.0.5-pre20210521085756\runtimes\win-x64\native\e_sqlite3.dll : PE image doesn't contain managed metadata.
So given that the path is found, is there a different tag I can use to make the main project copy the e_sqlite3.dll file so the analyzer can use it?
Taken from .NET project SDK overview:
Build events
In SDK-style projects, use an MSBuild target named PreBuild or PostBuild and set the BeforeTargets property for PreBuild or the AfterTargets property for PostBuild.
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command=""$(ProjectDir)PreBuildEvent.bat" "$(ProjectDir)..\" "$(ProjectDir)" "$(TargetDir)"" />
</Target>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="echo Output written to $(TargetDir)" />
</Target>
Maybe you can move the file manually using one of these directives?
There's also this:
<Content Include="$(OutputPath)\*.dll;$(OutputPath)\*.json">
<Pack>true</Pack>
<PackagePath>build\</PackagePath>
</Content>
Could you move the file like that?
I'm making a NuGet package and my csproj looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard1.6;net461;net47</TargetFrameworks>
...
<PackageId>Package2</PackageId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Package1\Package1.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net461' OR '$(TargetFramework)'=='net47'">
<Reference Include="System.Net.Http" />
</ItemGroup>
</Project>
The project it's referencing looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard1.6;net461;net47</TargetFrameworks>
<PackageId>Package1</PackageId>
...
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<NoWarn>1701;1702; CS1591</NoWarn>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.6' OR '$(TargetFramework)'=='net461'">
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net461' OR '$(TargetFramework)'=='net47'">
<Reference Include="System.Net.Http" />
</ItemGroup>
</Project>
And inside the Package2 project it has the following line:
webRequestHandler.ClientCertificates.Add(certificate);
But it isn't building in net461 or net47, saying:
'HttpClientHandler' does not contain a definition for
'ClientCertificates' and no accessible extension method
'ClientCertificates' accepting a first argument of type
'HttpClientHandler' could be found (are you missing a using
directive or an assembly reference?)
Package2(net461),
Package2(net47)
But the only thing I've changed is removed this from the csproj for package2:
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.6' OR '$(TargetFramework)'=='net461' OR '$(TargetFramework)'=='net47'">
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.1.2" />
</ItemGroup>
Can anyone help me understand how to fix it? I don't really want to bring in that whole NuGet package just to fix this one dependency I think I'm just missing an assembly but as far as I know it should be in System.Net.Http which I should already be referencing (and so should the other project it's already dependent on).
Looks like this property is available from version 4.7.1:
https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclienthandler.clientcertificates?view=netframework-4.7.1
Note that if you select an older .NET version, you'll see a message like this:
The requested page is not available for .NET Framework 4.7.
For me the solution was to download the newest version of "System.Net.Http".
You can find it through the NuGet package manager.
At the time of writing v4.3.4 is the newest version and it contains the ClientCertificates methode.
I've swapped out the assembly reference for the NuGet package:
<ItemGroup Condition="'$(TargetFramework)'=='net47' OR '$(TargetFramework)'=='net461'">
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>
pretty sure this is the wrong thing to do™ as the assembly reference in .NET Framework should be sufficient and I'm probably going to suffer many conflicting reference issues anywhere I install my package, but this is the best I can come up with right now.
I'm on Ubuntu and I have two .NET Core 2.0 projects (Project Oranges.csproj and Apples.csproj). Oranges only contains references to NuGet packages, while Apples contains a reference to Oranges.
Running dotnet build -f netcoreapp2.0 Oranges.csproj succeeds! Oranges.dll now exists at /Oranges/bin/Debug/netcoreapp2.0/Oranges.dll.
Running dotnet build -f netcoreapp2.0 Apples.csproj fails with: error CS0009: Metadata file '/Oranges/bin/Debug/netcoreapp2.0/Oranges.dll' could not be opened -- PE image doesn't contain managed metadata
How can I go about referencing Oranges, which builds without issue, in Apples without issue?
Oranges.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<TargetFrameworks>netcoreapp2.0;net451;</TargetFrameworks>
<RootNamespace>Oranges</RootNamespace>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\GeneratedKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcore2.0'">
<DefineConstants>NETCORE2_0</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net451'">
<DefineConstants>NET4_5_1</DefineConstants>
</PropertyGroup>
<ItemGroup>
<None Remove="packages.config" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
</ItemGroup>
</Project>
Apples.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<TargetFrameworks>netcoreapp2.0;net451;</TargetFrameworks>
<RootNamespace>Apples</RootNamespace>
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
<AssemblyOriginatorKeyFile>..\..\GeneratedKey.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<None Remove="packages.config" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
<PackageReference Include="System.Composition" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Oranges\Oranges.csproj" />
</ItemGroup>
</Project>
After deleting the bin and obj folders from the project directory and rebuilding, a different error was being displayed.
CSC : error CS7027: Error signing output with public key from file 'GeneratedKey.snk' -- Assembly signing not supported. [.../Oranges/Oranges.csproj]
After some research I stumbled across a solution.
Assembly Signing Not Supported
Adding the line below to the .csproj file for each assembly that required signing resolved the issue.
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
For now it seems like if you need to sign netcore assemblies, it should be done on Windows.
I'm running a ASP.NET Core app on the .NET 4.6.1 framework. I have 1 solution with multiple projects in it. All of the projects are class libraries that reference each other via PackageReferences in their .csproj (this way we can build, package and version them independently). However, I want to be able to test their integration with one another without needing to push them up to NuGet first - aka I want to use them as ProjectReferences in the solution, but PackageReferences when building them through my Jenkins build process in order to version the components separately.
When .NET Core was project.json based, this worked fine. I would set the version at the top of the project.json and if a project existed with that version in the solution it would reference it as a project, otherwise it would look for it on my NuGet feed.
The problem with using ProjectReferences is that all project's would get the same version when they are built and sent to NuGet.
Is there any way to do this in csproj? Look for a project reference if it exists, otherwise look at NuGet?
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<VersionPrefix>1.3.0</VersionPrefix>
<TargetFramework>net461</TargetFramework>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AssemblyName>MyProject1</AssemblyName>
<PackageId>MyProject1</PackageId>
<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MyProject2" Version="1.4.0-*" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="1.1.1" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
</Project>
Above is an example, I would like MyProject2 to be referenced by ProjectReference if 1.4.0 exists in the solution.
I recently was try to do the same thing and couldn't find the answer but figured out something that works for me. You can use the Exists condition in MSBuild for the csproj to include the project reference when its there and exclude the package reference if its there:
<Project Sdk="Microsoft.NET.Sdk">
...
<ItemGroup>
<PackageReference Condition="!Exists('[path-to-project].csproj')" Include="[package-id]" Version="[pacakage-version].*" />
</ItemGroup>
...
<ItemGroup>
<ProjectReference Condition="Exists('[path-to-project].csproj')" Include="[path-to-project].csproj" />
</ItemGroup>
...
</Project>