Define C# preprocessor symbol in NuGet package - .net-core

Can a NuGet package define a preprocessor symbol for the consuming project? And if so, how?

If your package (My.ExamplePackage) contains an MSBuild file named like the package name + .targets in the build directory (so build\MyExamplePackage.targets), you can use it to amend the DefineConstants property that may have been set to defaults or reset in the project:
<Project>
<PropertyGroup>
<DefineConstants>$(DefineConstants);MY_PREPOCESSOR_SYMBOL</DefineConstants>
</PropertyGroup>
</Project>
While the package can contain both a .props and .targets file, the .targets file will be imported after the main body of the csproj file being built so if it the project re-sets DefineConstants (meaning not adding to it by prepending $(DefineConstant);), the .targtes file has a chance of adding to this property.

Related

Define a C# preprocessor symbol based on NuGet PackageReference

I'd like to make define a symbol NEWTONSOFT if (and only if) the Newtonsoft.Json NuGet package is added as a PackageReference to my .NET Core app. How can I do that?
EDIT: To clarify, I'd like add the symbol, if the reference is present. And if I delete the reference, the symbol should no longer be defined - but I should not manually add/remove the symbol definition. Something like this:
<Choose>
<When Condition=" '$(PackageReference).Identity'=='Newtonsoft.Json' ">
<PropertyGroup>
<DefineConstants>HDN</DefineConstants>
</PropertyGroup>
</When>
</Choose>
Except this does not work.
A way to do this sort of automatically is including a target that contributes build logic into your csproj file like this:
<Target Name="AddPackageSpecificConstants" BeforeTargets="BeforeCompile">
<PropertyGroup>
<DefineConstants Condition="#(Reference->AnyHaveMetadataValue('NuGetPackageId','Newtonsoft.Json'))">$(DefineConstants);NEWTONSOFT_JSON</DefineConstants>
<DefineConstants Condition="#(Reference->AnyHaveMetadataValue('NuGetPackageId','YamlDotNet '))">$(DefineConstants);YAML_DOT_NET</DefineConstants>
</PropertyGroup>
</Target>
By hooking into the build process this can detect if your code has any compile-time references (meaning the API surface of the pacakges is available in your C# code) to specific NuGet packages, even if they are only transitively referenced (e.g. you reference a library that references Newtonsoft.Json so your could can use it).
By doing definitions like <X>$(X);</X> the additional constants are added to the property so this leavs intact anything the SDK gives you by default based on the target framework or your other project contents.
You can add your Conditional compilation symbols in Debug tab of Project Properties and use Roslyn Preprocessor directives like this :
#if NEWTONSOFT && !JSON.NET
// Your Codes
#endif
Based on Microsoft Docs, You have not any preprocessor directive for Nuget packages.

.NET Core/Standard .csproj file, embedding license file without it being added to a project using the package?

The past couple of days I've been getting warnings when compiling my .NET Standard/Core projects:
NuGet.Build.Tasks.Pack.targets(202, 5): [NU5125] The 'licenseUrl' element will be deprecated. Consider using the 'license' element instead.
To fix this, I switched to using <PackageLicenseFile>...</PackageLicenseFile> instead of <PackageLicenseUrl>...</PackageLicenseUrl>.
However, in order for this to work, I have to add the license file to my package (naturally), but it gets added to the content and contentFiles directory, which means that a project using this package gets the license file added to it.
Is there a way to embed the license file so that PackageLicenseFile works correctly, without adding the license file to projects using the package?
This is the section I added to the .csproj file in order to embed the license file:
<ItemGroup>
<Content Include="..\LICENSE" />
</ItemGroup>
The output package structure:
_rels
package
lib
contentFiles
+- any
+- netstandard2.0
+- LICENSE
content
+- LICENSE
Could I, for instance, add it to a separate folder inside the package, other than content?
The recommended way of packing a licence file with the package is
<PropertyGroup>
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<None Include="LICENSE.txt" Pack="true" PackagePath="$(PackageLicenseFile)"/>
</ItemGroup>
But also there now is PackageLicenseExpression which can be used as an alternative to license files / URLs as you have mentioned in your comment.
See NuGet's wiki entry Packaging License within the nupkg for more details.

Including Unmanaged DLL in NuGet Package Using csproj

I'm developing a .NET Core 2.1 library that depends on an unmanaged DLL. I'd like to include the unmanaged DLL in the NuGet package as well. The problem that I am running into is that if I try to specify all of the information in the .csproj file, the dotnet build process throws the following warning:
warning NU5100: The assembly 'content\lib\subdir\somedll.dll' is not
inside the 'lib' folder and hence it won't be added as a reference
when the package is installed into a project. Move it into the
'lib' folder if it needs to be referenced.
I know that I can embed the unmanaged DLLs by writing a .nuspec (in fact, I have). However, it seems like I shouldn't need to write one with the latest .csproj file format.
Question: How can I use the .csproj file to embed unmanaged DLLs in a NuGet package?
Specifying <ItemGroup><None> in the .csproj file seems to include the files in the output directory but they do not make it into the NuGet package.
Specifying <ItemGroup><Content> in t he .csproj file will get them added to the NuGet package but in the Content directory instead of in the Lib directory.
If I really have to have both a .csproj file and a .nuspec file, what is the best practice for where to put the metadata? In t he .csproj file? In the .nuspec file? Maintain and sync both? Is there a something in the tool chain that can do this for me?
I'm working in Visual Studio Code V1.24, and .NET Core/dotnet V2.1.
You need to specify explicit package path metadata on the element so that the dll/so/dylib file ends up at the right place in the package so that it is recognised as runtime-specific native DLL:
<ItemGroup>
<None Include="unmanaged.dll" Pack="true" PackagePath="runtimes\win-x64\native" />
</ItemGroup>

.nupkg does not contains dll of project instead it copies whole project in package after vsts build

****i'm building the nuget package using vsts build, once the build is created it does not contains dll of project instead it's just copying whole project in nuget packages.which is not expected****
Based on the code of nuspec file, you include all files, so all files will be in the package, you need to specify the files/folders that you want to include into the package.
The simple way is that you can specify the project file instead of nuspec file to package.

How to avoid my own nuget package overwrite the target project web.config and global.aspx file when they install my package

I was created one nuget package using following step.
First I created one Asp.net Mvc application
The I created spec file using nuget spec command
Then I edited $id$,$version$,$author$,$description$ ect..
Then I created package using following command.
nuget pack myproject.csproj -Build -Properties Configuration=Release
It was created one myproject.1.0.0.0.nupkg
Then I copy the file And past into C:\LocalNuGetFeed\myproject.1.0.0.0.nupkg
I already configure the local repository in my VS
My problem is
When I install this package from any other project it ask following question.
But as per my requirement I don't want to move this file to target project. Suppose user give y the it overwrite the target project file because of it i face lot reference problem.
**File Conflict
File 'Web.config' already exists in project 'CRM'. Do you want to overwrite it?
[Y] Yes [A] Yes to All [N] No [L] No to All [?] Help (default is "N"):
File Conflict
File 'Global.asax' already exists in project 'CRM'. Do you want to overwrite it?
[Y] Yes [A] Yes to All [N] No [L] No to All [?] Help (default is "N"):**
But in my package I don't want to move this above two file from package to target project.
Is any way to avoid transform Global.asax and Web.config move from package to target project.
In my .nuspec file I added following line
<files>
<file src="Web.config" target = "" exclude="Web.config"/>
<file src="*.asax" target = "" exclude="*.asax"/>
<file src="Content\*.css" target="Content\" />
<file src="Scripts\*.js" target="Content\Scripts\" />
</files>
But it include the web.config file AND Global.aspx file in Content folder My resultant package look like bellow
myproject.1.0.0.0
>> Content
....css
>>Script
..Js file
web.config
Global.asax
I was solved this using following command to crate package
nuget pack CrmHtmlController.csproj -IncludeReferencedProjects -Exclude **\*.config;**\*.asax
so it exclude all .congig and .asax file from package.
Take a look at your .nuspec file. It's just an XML file, so you can open it up with any text editor. See how it define which files to include at <package><files>? Remove those files that you don't want. A handy tool if you want to do this with a GUI is NuGet Package Manager.
Nuget includes the web.config in your package, because the build action of the web.config is "Content". This is by default and necessary for a classic publish of an asp.net web site.
If you don't want this, propably because your assembly is only a component of another web site, you can change the build action to "None" and nuget will not take it any longer.

Resources