Skip to content

Commit 49cbd5b

Browse files
committed
Document more scenarios for .NET Libraries
1 parent cbba9a7 commit 49cbd5b

File tree

1 file changed

+107
-48
lines changed

1 file changed

+107
-48
lines changed
Lines changed: 107 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,63 @@
11
# NuGet 3 Package Authoring #
22

3+
## 1 .NET library ##
4+
### 1.1 Portable library targeting `dotnet` ###
5+
This is the simplest type of package. You wish to ship a portable class library in package that you intend to be consumed only in projects supporting nuget v3 and project.json. The `dotnet` target moniker represents all platforms who's .NET surface area can be represented entirely by package dependencies. For many projects using this target moniker will eliminate the need to ever list specific platforms in a package.
36

4-
## .NET library ##
5-
### pure portable on dotnet ###
6-
This is the simplest type of package. You wish to ship a portable class library in package that you intend to be consumed only in projects supporting nuget v3 and project.json.
7-
7+
The below sample illustrates the dependencies of a project.json based PCL targeting .NET Framework 4.6, Windows Universal 10.0, and ASP.NET Core 5.0. The dependency section can be generated using the third party [NuSpec.ReferenceGenerator](https://www.nuget.org/packages/NuSpec.ReferenceGenerator/) package.
88
```
99
<depenedencies>
1010
<group targetFramework="dotnet">
11-
<dependency id="System.Collections" version="4.0.0"/>
12-
<dependency id="System.Globalization" version="4.0.0"/>
13-
<dependency id="System.Linq" version="4.0.0"/>
14-
<dependency id="System.Resources.ResourceManager" version="4.0.0"/>
15-
<dependency id="System.Runtime" version="4.0.0"/>
16-
<dependency id="System.Runtime.Extensions" version="4.0.0"/>
17-
<dependency id="System.Threading" version="4.0.0"/>
11+
<dependency id="System.IO" version="4.0.10"/>
12+
<dependency id="System.Runtime" version="4.0.20"/>
1813
</group>
1914
</depenedencies>
2015
2116
lib/dotnet/System.Banana.dll
22-
2317
```
18+
### 1.2 Support packages.config with `dotnet` ###
19+
Now lets suppose that we want to target older platforms that don't yet support project.json. The below example changes the PCL to target .NET Framework 4.5, Windows 8, Windows Phone 8.1 and Windows Phone Silverlight 8.
2420

25-
### supporting nuget v2 and project types that don't yet support project.json ###
26-
NuGet v2 and packages.config in Nuget v3 will promote any indirect references to direct references. This creates a problem for the example we have so far since the dependencies of the library cannot always be updated on platforms like .NET desktop or Windows Phone where the packages just represent the surface area in the platform.
21+
Nuget using packages.config will promote any indirect references to direct references. Nuget will also offer upgrade of any packages directly referenced. This creates a problem for the example we have so far since the dependencies of the library cannot always be updated on platforms like .NET desktop or Windows Phone where the packages just represent the surface area inbox in the platform.
2722

28-
To avoid this problem we can add empty dependency groups for all of the platforms where our dependencies are included in box. This should **not** be done for platforms that rely on packages for implementation (like DNXCore, NETCore version >= 5.0, and UAP). This should also **not** be done if the version of the dependency is higher than the one inbox.
23+
To avoid this problem we can add empty dependency groups for all of the platforms where our dependencies are included in box. This should **not** be done for platforms that rely on packages for implementation (Windows Universal 10.0 and ASP.NET Core 5.0). This should only be done for platforms which you've specifically targeted in the project.
24+
25+
In order to also support installation into packages.config based portable projects NuGet requires `portable-` folder and dependency group. The dependency group is needed for the same reason as above, the file is needed because NuGet does not treat any `portable-` targets as compatible with `dotnet`.
2926
```
3027
<depenedencies>
3128
<group targetFramework="dotnet">
32-
<dependency id="System.Collections" version="4.0.0"/>
33-
<dependency id="System.Globalization" version="4.0.0"/>
34-
<dependency id="System.Linq" version="4.0.0"/>
35-
<dependency id="System.Resources.ResourceManager" version="4.0.0"/>
29+
<dependency id="System.IO" version="4.0.0"/>
3630
<dependency id="System.Runtime" version="4.0.0"/>
37-
<dependency id="System.Runtime.Extensions" version="4.0.0"/>
38-
<dependency id="System.Threading" version="4.0.0"/>
3931
</group>
4032
<!-- all depdencies are inbox in netcore45 / win8 -->
4133
<group targetFramework="netcore45"/>
42-
<!-- starting with netcore 50 dependencies come from nuget packages -->
34+
<!-- netcore50 dependencies from nuget packages -->
4335
<group targetFramework="netcore50">
44-
<dependency id="System.Collections" version="4.0.0"/>
45-
<dependency id="System.Globalization" version="4.0.0"/>
46-
<dependency id="System.Linq" version="4.0.0"/>
47-
<dependency id="System.Resources.ResourceManager" version="4.0.0"/>
36+
<dependency id="System.IO" version="4.0.0"/>
4837
<dependency id="System.Runtime" version="4.0.0"/>
49-
<dependency id="System.Runtime.Extensions" version="4.0.0"/>
50-
<dependency id="System.Threading" version="4.0.0"/>
5138
</group>
5239
<!-- more inbox frameworks -->
5340
<group targetFramework="net45"/>
5441
<group targetFramework="wp8"/>
5542
<group targetFramework="wpa81"/>
43+
<!-- required for pcl projects that don't use project.json with dotnet -->
44+
<group targetFramework="portable-netcore45+net45+wp8+wpa8"/>
5645
</depenedencies>
5746
47+
lib/portable-netcore45+net45+wp8+wpa8/System.Banana.dll
5848
lib/dotnet/System.Banana.dll
5949
```
6050

51+
The .NET and NuGet team hope to eliminate the need to create these additional dependency groups in future releases.
6152

62-
The .NET and NuGet team hope to eliminate the need to do this in future releases.
63-
64-
### native library ###
53+
### 1.3 Native library ###
6554
Some libraries can benefit from using a native component within their package. This can help to provide a performance optimized native implementation of an algorithm or directly consume some other native SDK (eg: statically link it or compile against its headers).
6655

67-
Add native runtime entries.
56+
To represent the native component we will use 'runtime/{rid}/native' folders. The '{rid}' used during package restore is determined by the runtimes section of the project.json. The '{rid}' used at package resolve time is determined by the NuGet client and should match one of the {rid}s in the project.json. In the case of the MSBuild client in Visual Studio, this is based on the project's properties like Platform and TargetFramework.
6857
```
6958
lib/dotnet/System.Banana.dll
70-
runtimes/win7-x86/native/cherry.dll
71-
runtimes/win7-x64/native/cherry.dll
59+
runtimes/win-x86/native/cherry.dll
60+
runtimes/win-x64/native/cherry.dll
7261
runtimes/win10-arm/native/cherry.dll
7362
```
7463
Note that we still use `lib` for the managed assembly. This is behaving as both the compile time and runtime asset for the managed assembly. The presense of `runtime/{rid}/native` folders does not replace lib.
@@ -78,35 +67,105 @@ The .NET assembly is likely now runtime specific since it depends on the runtime
7867
TODO: tooling to produce reference assembly.
7968
```
8069
ref/dotnet/System.Banana.dll
81-
runtimes/win7/lib/dotnet/System.Banana.dll
82-
runtimes/win7-x86/native/cherry.dll
83-
runtimes/win7-x64/native/cherry.dll
70+
runtimes/win/lib/dotnet/System.Banana.dll
71+
runtimes/win-x86/native/cherry.dll
72+
runtimes/win-x64/native/cherry.dll
8473
runtimes/win10-arm/native/cherry.dll
8574
```
8675
Note that we now need a `ref` folder. This is because the `runtimes/{rid}/lib/dotnet` folder replaces `lib/dotnet` since it is more specific. Since the `runtimes` folder is only used at runtime we need a seperate definition of the compile time asset.
8776

8877
This will give folks the right error when they try to install the package on a new runtime (eg: Linux) instead of permitting the package to install and failing to find the DLL at runtime.
8978

90-
### architecture specific implementation ###
79+
To help produce a reference assembly you can use the Microsoft.DotNet.BuildTools.GenAPI package. TODO: sample.
80+
81+
### 1.4 Architecture specific .NET library ###
9182
It may be necessary to include architecture specific managed code in your package. If this is the case the implementation assembly will need to be placed in architecture specific folders.
9283

9384
These folders are only used for the runtime asset from your package, so we'll need to provide a compile time asset. For that we use `ref`. This has the added benefit of making your architecture specific library consumable by AnyCPU projects.
9485

95-
TODO: tooling to produce reference assembly.
86+
To help produce a reference assembly you can use the Microsoft.DotNet.BuildTools.GenAPI package. TODO: sample.
9687
```
9788
ref/dotnet/System.Banana.dll
9889
runtimes/win7-x86/lib/dotnet/System.Banana.dll
9990
runtimes/win7-x64/lib/dotnet/System.Banana.dll
100-
runtimes/win10-arm/native/System.Banana.dll
91+
runtimes/win10-arm/lib/dotnet/System.Banana.dll
92+
runtimes/win7-x86/native/cherry.dll
93+
runtimes/win7-x64/native/cherry.dll
94+
runtimes/win10-arm/native/cherry.dll
95+
```
96+
97+
### 1.5 Support packages.config with `runtimes` ###
98+
Both of the previous examples used the NuGet v3 project.json feature of `runtimes` to provide OS/architecture specific assets. To do the same for packages.config based projects we'll need to approximate this feature using msbuild targets. We'll add the targets to the 'build/dotnet' folder, matching the target moniker used by our assets and give it the same name as our package.
99+
```
100+
build/dotnet/System.Banana.targets
101+
ref/dotnet/System.Banana.dll
102+
runtimes/win7-x86/lib/dotnet/System.Banana.dll
103+
runtimes/win7-x64/lib/dotnet/System.Banana.dll
104+
runtimes/win10-arm/lib/dotnet/System.Banana.dll
105+
runtimes/win7-x86/native/cherry.dll
106+
runtimes/win7-x64/native/cherry.dll
107+
runtimes/win10-arm/native/cherry.dll
101108
```
102109

103-
### cross compiling for additional platforms ###
110+
```
111+
<?xml version="1.0" encoding="utf-8"?>
112+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
113+
<!-- If the project.json file is missing assume a packages.config
114+
based project and add the NuGet v3 assets. -->
115+
<ItemGroup Condition="!Exists('project.json') AND !Exists('$(MSBuildProjectName).project.json')">
116+
<Reference Include="$(MSBuildThisFileDirectory)..\..\ref\dotnet\*.dll">
117+
<Private>false</Private>
118+
</Reference>
119+
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)..\..\runtimes\win*-$(Platform)\lib\dotnet\*.*" />
120+
<ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)..\..\runtimes\win*-$(Platform)\native\*.*" />
121+
</ItemGroup>
122+
</Project>
123+
124+
```
125+
Note that this assumes only one `{rid}` per architecture. If a package uses multiple `{rid}`s per architcture these targets will be more involved than just `win*`.
126+
127+
### 1.6 Cross compiling for additional platforms ###
128+
Expanding on the previous example, suppose that a single build of a library cannot provide the full functionality on all platforms. For example: you'd like to use the System.IO.MemoryStream.TryGetBuffer. This API is available in System.IO version 4.0.10 which is supported on .NET Framework 4.6, Windows Universal 10.0, and ASP.NET Core 5.0. The API can return the underlying byte array used by the MemoryStream without copying it. On older platforms the API is not available but a similar API ToArray() can be used which does a copy of the byte array.
129+
130+
The package will contain two different PCLs.
131+
Build A targeting .NET Framework 4.5, Windows 8, Windows Phone 8.1 and Windows Phone Silverlight 8, using MemoryStream.ToArray();
132+
Build B targeting .NET Framework 4.6, Windows Universal 10.0, and ASP.NET Core 5.0, using MemoryStream.TryGetBuffer().
133+
134+
```
135+
<depenedencies>
136+
<group targetFramework="dotnet">
137+
<dependency id="System.IO" version="4.0.10"/>
138+
<dependency id="System.Runtime" version="4.0.0"/>
139+
</group>
140+
<!-- all depdencies are inbox in netcore45 / win8 -->
141+
<group targetFramework="netcore45"/>
142+
<!-- netcore50 / uap10 dependencies from nuget packages -->
143+
<group targetFramework="netcore50">
144+
<dependency id="System.IO" version="4.0.10"/>
145+
<dependency id="System.Runtime" version="4.0.0"/>
146+
</group>
147+
<!-- more inbox frameworks -->
148+
<group targetFramework="net45"/>
149+
<group targetFramework="wp8"/>
150+
<group targetFramework="wpa81"/>
151+
<group targetFramework="portable-netcore45+net45+wp8+wpa8"/>
152+
</depenedencies>
153+
154+
lib/portable-netcore45+net45+wp8+wpa8/System.Banana.dll (build A)
155+
lib/netcore45/System.Banana.dll (build A, required since dotnet would take precedence over portable-*)
156+
lib/netcore50/System.Banana.dll (build B, required since netcore45 would take precedence over dotnet)
157+
lib/net45/System.Banana.dll (build A, required since dotnet would take precedence over portable-*)
158+
lib/net46/System.Banana.dll (build B, required since net45 would take precedence over dotnet)
159+
lib/wp8/System.Banana.dll (build A, required since dotnet would take precedence over portable-*)
160+
lib/wpa8/System.Banana.dll (build A, required since dotnet would take precedence over portable-*)
161+
lib/dotnet/System.Banana.dll (build B)
162+
```
104163

105-
## WinMD library ##
106-
### with managed implementation ###
107-
### with native implementation ###
108-
### with resources ###
109-
### supporting c++ ###
110-
### supporting javascript ###
111-
cannot include managed dll in packages that intend to support JS because JS does not handle dll references.
164+
## 2 WinMD library ##
165+
### 2.1 .NET implementation ###
166+
### 2.2 Native implementation ###
167+
### 2.3 With resources ###
168+
### 2.4 Supporting c++ ###
169+
### 2.5 Supporting javascript ###
170+
note: cannot include managed dll in packages that intend to support JS because JS does not handle dll references.
112171

0 commit comments

Comments
 (0)