documentation/adding-libraries.md
This guide covers adding new projects and NuGet packages to SkiaSharp.
The repo has a non-standard structure due to multi-platform packaging requirements.
Related: Adding APIs | Architecture
Key points for creating a new library:
<PackagingGroup> in .csproj, add entry to scripts/VERSIONS.txt<SignAssembly>false</SignAssembly> if framework isn't signeddotnet pack from .csproj (no nuspec needed)Files to create/modify:
source/SkiaSharp.MyLibrary/ - New project folderscripts/VERSIONS.txt - Add version entrySkiaSharp uses a one-project-per-TFM structure to handle complex multi-platform packaging requirements. This avoids issues with:
Each TFM gets its own project for consistency. Shared code uses file linking with wildcards from a shared folder.
All versioning information lives in scripts/VERSIONS.txt. The build system reads this file and extracts the correct version based on the <PackagingGroup> property.
Set the <PackagingGroup> property in your .csproj - this is the NuGet package ID:
<PackagingGroup>SkiaSharp.MyLibrary</PackagingGroup>
Then add a corresponding entry in scripts/VERSIONS.txt:
# In scripts/VERSIONS.txt (under # nuget versions section)
SkiaSharp.MyLibrary nuget 3.119.2
The format is: PackageId nuget version (whitespace separated).
By default, all projects are strong named to assist users who require this feature. However, not all assemblies can be strong named because the actual framework may not be. For example, Xamarin.Forms is not strong named, so we cannot strong name the SkiaSharp views.
As a result, this must be turned off via the <SignAssembly> property:
<SignAssembly>false</SignAssembly>
Here's a minimal project:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Target frameworks - use variables from SkiaSharp.Build.props -->
<TargetFrameworks>$(TFMCurrent)</TargetFrameworks>
<!-- Namespace for the library -->
<RootNamespace>SkiaSharp</RootNamespace>
<!-- NuGet package ID - must match entry in VERSIONS.txt -->
<PackagingGroup>SkiaSharp.MyLibrary</PackagingGroup>
<!-- Package metadata -->
<Title>SkiaSharp MyLibrary Support</Title>
<PackageDescription>This package adds MyLibrary support to SkiaSharp.</PackageDescription>
<!-- Disable strong naming if framework isn't signed -->
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<ItemGroup>
<!-- External framework dependency -->
<PackageReference Include="MyLibrary" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<!-- Reference core SkiaSharp -->
<ProjectReference Include="..\..\..\binding\SkiaSharp\SkiaSharp.csproj" />
</ItemGroup>
</Project>
If multiple projects share common code, use file linking:
<ItemGroup>
<!-- Include shared source files from a sibling folder -->
<Compile Include="..\SkiaSharp.MyLibrary.Shared\**\*.cs" Link="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
To include .targets or .props files that run in consuming projects:
<ItemGroup>
<!-- Include build targets in the NuGet package -->
<None Include="build\SkiaSharp.MyLibrary.targets" PackagePath="build\$(TargetFramework)\" Pack="true" />
</ItemGroup>
NuGet packages are built using SDK-style dotnet pack directly from the .csproj files. The build system automatically:
VERSIONS.txt based on <PackagingGroup>To pack all NuGets:
dotnet cake --target=nuget
The output is placed in output/nugets/.
Note: The
scripts/nuget/folder contains nuspec files only for special meta-packages (like_NuGets,_NativeAssets) that bundle multiple packages together. Regular libraries don't need nuspec files.
Once all the properties are set in the .csproj file, a build will place all the files and docs in the correct sub-folders in the output directory. And, then the NuGet packaging task will just use that folder as the base.
To create a new library:
source/TargetFrameworks, RootNamespace, PackagingGroupscripts/VERSIONS.txtbuild.cake SUPPORTED_NUGETS dictionary (required for sample packaging)output/ directory⚠️ Dual Registration: New NuGet package IDs must be registered in both
scripts/VERSIONS.txt(nuget type) ANDbuild.cakeSUPPORTED_NUGETS. Missing either causes theCreateSamplesDirectorytask to fail when convertingProjectReferencetoPackageReferencein output samples.