• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..14-Dec-2021-

CreateSigningKey/H14-Dec-2021-6444

Google.OrTools.FSharp/H14-Dec-2021-396347

Google.OrTools.FSharp.Tests/H14-Dec-2021-9673

doc/H03-May-2022-264231

Directory.Build.props.inH A D14-Dec-20211.6 KiB3730

Google.OrTools.csproj.inH A D14-Dec-20217.4 KiB163145

Google.OrTools.runtime.csproj.inH A D14-Dec-20211.4 KiB3429

Google.OrTools.slnH A D14-Dec-20212.6 KiB4038

README.mdH A D14-Dec-202112.3 KiB297235

Sample.csproj.inH A D14-Dec-20211.7 KiB4740

Sample.fsproj.inH A D14-Dec-20211.7 KiB4740

Test.csproj.inH A D14-Dec-20211.5 KiB4236

README.md

1# Introduction
2
3This is the documentation page for the .NET Standard 2.0 wrapper of OR-Tools.
4
5This project aim to explain how you build a .Net native (for win-x64, linux-x64
6and osx-x64) nuget package using `dotnet` and few `.csproj`.
7
8## Table of Content
9
10* [Requirement](#requirement)
11* [Directory Layout](#directory-layout)
12* [Build](#build)
13  * [Build Process](#build-process)
14  * [Local Google.OrTools Package](#local-googleortools-package)
15    * [Building a runtime Google.OrTools Package](#building-local-runtime-googleortools-package)
16    * [Building a Local Google.OrTools Package](#building-local-googleortools-package)
17  * [Complete Google.OrTools Package](#complete-googleortools-package)
18    * [Building all runtime Google.OrTools Package](#building-all-runtime-googleortools-package)
19    * [Building a Complete Google.OrTools Package](#building-complete-googleortools-package)
20* [Examples](#examples)
21* [Appendices](#appendices)
22  * [Resources](#resources)
23  * [Issues](#issues)
24* [Misc](#misc)
25
26## Requirement
27
28The library is compiled against `netstandard2.0`, so you'll only need:
29
30* .Net Core SDK >= 3.1 LTS
31
32## Directory Layout
33
34* [`Google.OrTools.runtime.linux-x64`](Google.OrTools.runtime.linux-x64)
35Contains the .Net Standard 2.0 native project for the rid linux-x64.
36* [`Google.OrTools.runtime.osx-x64`](Google.OrTools.runtime.osx-x64)
37Contains the .Net Standard 2.0 native project for the rid osx-x64.
38* [`Google.OrTools.runtime.win-x64`](Google.OrTools.runtime.win-x64)
39Contains the .Net Standard 2.0 native project for the rid win-x64.
40* [`Google.OrTools`](Google.OrTools) Is the .Net Standard 2.0 meta-package which
41should depends on all previous available packages and contains the Reference
42Assembly.
43
44note: While Microsoft use `runtime-<rid>.Company.Project` for native libraries
45naming, it is very difficult to get ownership on it, so you should prefer to use
46`Company.Project.runtime-<rid>` instead since you can have ownership on
47`Company.*` prefix more easily.
48
49## Build
50
51Either use the CMake base build or the Makefile based build. The workflow is
52typically `make dotnet` which will build both C# and F# libraries package. The
53output will be placed in `<OR_ROOT>/temp_dotnet/packages` folder. All tests will
54be run based on this folder.
55
56### Build Process
57
58To Create a native dependent package we will split it in two parts: - A bunch of
59`Google.OrTools.runtime.{rid}.nupkg` packages for each
60[Runtime Identifier (RId)](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog)
61targeted. - A meta-package `Google.OrTools.nupkg` depending on each runtime
62packages.
63
64note: [`Microsoft.NetCore.App` packages](https://www.nuget.org/packages?q=Microsoft.NETCore.App)
65follow this layout.
66
67We have two use case scenario:
68
691.  Locally, be able to build a Google.OrTools package which **only** target the
70    local `OS Platform`, i.e. building for only one
71    [Runtime Identifier (RID)](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog).
72    \
73    note: This is useful since the C++ build is a complex process for Windows,
74    Linux and MacOS. i.e. We don't support cross-compilation for the native
75    library generation.
76
772.  Be able to create a complete cross-platform (ed. platform as multiple rid)
78    Google.OrTools package. \
79    i.e. First you generate each native Nuget package
80    (`Google.OrTools.runtime.{rid}.nupkg`) on each native architecture, then
81    copy paste these artifacts on one native machine to generate the
82    meta-package `Google.OrTools`.
83
84### Local Google.OrTools Package
85
86Let's start with scenario 1: Create a *Local* `Google.OrTools` package targeting **one**
87[Runtime Identifier (RID)](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog).
88<br>We would like to build a `Google.OrTools.nupkg` package which only depends
89on one `Google.OrTools.runtime.{rid}.nupkg` in order to work locally.
90
91The pipeline for `linux-x64` should be as follow:
92![Local Pipeline](doc/local_pipeline.svg)
93![Legend](doc/legend.svg)
94note: The pipeline will be similar for `osx-x64` and `win-x64` architecture,
95don't hesitate to look at the CI log.
96
97#### Building local runtime Google.OrTools Package
98
99disclaimer: We won't cover the C++ ortools library build. So first let's create
100the local `Google.OrTools.runtime.{rid}.nupkg` nuget package.
101
102Here some dev-note concerning this `Google.OrTools.runtime.{rid}.csproj`.
103* `AssemblyName` must be `Google.OrTools.dll` i.e. all {rid} projects **must**
104  generate an assembly with the **same** name (i.e. no {rid} in the name).
105  On the other hand package identifier will contain the {rid}...
106  ```xml
107  <RuntimeIdentifier>{rid}</RuntimeIdentifier>
108  <AssemblyName>Google.OrTools</AssemblyName>
109  <PackageId>Google.OrTools.runtime.{rid}</PackageId>
110  ```
111* Once you specify a `RuntimeIdentifier` then `dotnet build` or `dotnet build -r {rid}`
112  will behave identically (save you from typing it).
113  note: not the case if you use `RuntimeIdentifiers` (notice the 's')
114* It is [recommended](https://docs.microsoft.com/en-us/nuget/create-packages/native-packages)
115  to add the tag `native` to the
116  [nuget package tags](https://docs.microsoft.com/en-us/dotnet/core/tools/csproj#packagetags)
117  ```xml
118  <PackageTags>native</PackageTags>
119  ```
120* Specify the output target folder for having the assembly output in
121  `runtimes/{rid}/lib/netstandard2.0` in the nupkg
122  ```xml
123  <BuildOutputTargetFolder>runtimes/$(RuntimeIdentifier)/lib</BuildOutputTargetFolder>
124  ```
125  note: Every files with an extension different from `.dll` will be filter out
126  by nuget. \
127  note: dotnet/cli automatically add the `$(TargetFramework)` (i.e.
128  `netstandard2.0`) to the output path.
129* Add the native shared library to the nuget package in the repository
130  `runtimes/{rib}/native`. e.g. for linux-x64:
131  ```xml
132  <Content Include="*.so">
133    <PackagePath>runtimes/linux-x64/native/%(Filename)%(Extension)</PackagePath>
134    <Pack>true</Pack>
135    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
136  </Content>
137  ```
138* Generate the runtime package to a defined directory (i.e. so later in meta
139  Google.OrTools package we will be able to locate it)
140  ```xml
141  <PackageOutputPath>{...}/packages</PackageOutputPath>
142  ```
143* Generate the Reference Assembly (but don't include it to this runtime nupkg !,
144  see below for explanation) using:
145  ```xml
146  <ProduceReferenceAssembly>true</ProduceReferenceAssembly>
147  ```
148
149Then you can generate the package using:
150```bash
151dotnet pack src/Google.OrTools.runtime.{rid}
152```
153note: this will automatically trigger the `dotnet build`.
154
155If everything good the package (located where your `PackageOutputPath` was
156defined) should have this layout:
157```
158{...}/packages/Google.OrTools.runtime.{rid}.nupkg:
159\- Google.OrTools.runtime.{rid}.nuspec
160\- runtimes
161   \- {rid}
162      \- lib
163         \- {framework}
164            \- Google.OrTools.dll
165      \- native
166         \- *.so / *.dylib / *.dll
167...
168```
169note: `{rid}` could be `linux-x64` and `{framework}` could be `netstandard2.0`
170
171tips: since nuget package are zip archive you can use `unzip -l <package>.nupkg`
172to study their layout.
173
174#### Building local Google.OrTools Package
175
176So now, let's create the local `Google.OrTools.nupkg` nuget package which will
177depend on our previous runtime package.
178
179Here some dev-note concerning this `Google.OrTools.csproj`.
180
181* This package is a meta-package so we don't want to ship an empty assembly file
182  : `xml <IncludeBuildOutput>false</IncludeBuildOutput>`
183* Add the previous package directory: `xml <RestoreSources>{...}/packages;
184  $(RestoreSources)</RestoreSources>`
185* Add dependency (i.e. `PackageReference`) on each runtime package(s) available:
186  `xml <ItemGroup Condition="Exists('{...}/packages/Google.OrTools.runtime.linux-x64.1.0.0.nupkg')">
187  <PackageReference Include="Google.OrTools.runtime.linux-x64" Version="1.0.0" />
188  </ItemGroup>` Thanks to the `RestoreSource` we can work locally with our just
189  builded package without the need to upload it on
190  [nuget.org](https://www.nuget.org/).
191* To expose the .Net Surface API the `Google.OrTools.csproj` must contains at
192  least one
193  [Reference Assembly](https://docs.microsoft.com/en-us/nuget/reference/nuspec#explicit-assembly-references)
194  of the previously rumtime package. `xml <Content
195  Include="../Google.OrTools.runtime.{rid}/bin/$(Configuration)/$(TargetFramework)/{rid}/ref/*.dll">
196  <PackagePath>ref/$(TargetFramework)/%(Filename)%(Extension)</PackagePath>
197  <Pack>true</Pack> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
198  </Content>`
199
200Then you can generate the package using:
201```bash
202dotnet pack src/Google.OrTools
203```
204
205If everything good the package (located where your `PackageOutputPath` was
206defined) should have this layout: `{...}/packages/Google.OrTools.nupkg: \-
207Google.OrTools.nuspec \- ref \- {framework} \- Google.OrTools.dll ...` note:
208`{framework}` could be `netstandard2.0`
209
210### Complete Google.OrTools Package
211
212Let's start with scenario 2: Create a *Complete* `Google.OrTools.nupkg` package
213targeting multiple
214[Runtime Identifier (RID)](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog).
215<br>We would like to build a `Google.OrTools.nupkg` package which depends on several
216`Google.OrTools.runtime.{rid}.nupkg`.
217
218The pipeline should be as follow: \
219note: This pipeline should be run on any architecture, provided you have
220generated the three architecture dependent `Google.OrTools.runtime.{rid}.nupkg`
221nuget packages. ![Full Pipeline](doc/full_pipeline.svg)
222![Legend](doc/legend.svg)
223
224#### Building All runtime Google.OrTools Package
225
226Like in the previous scenario, on each targeted OS Platform you can build the
227corresponding `Google.OrTools.runtime.{rid}.nupkg` package.
228
229Simply run on each platform `bash dotnet build src/Google.OrTools.runtime.{rid}
230dotnet pack src/Google.OrTools.runtime.{rid}` note: replace `{rid}` by the
231Runtime Identifier associated to the current OS platform.
232
233Then on one machine used, you copy all other packages in the `{...}/packages` so
234when building `Google.OrTools.csproj` we can have access to all package...
235
236#### Building Complete Google.OrTools Package
237
238This is the same step than in the previous scenario, since we "see" all runtime
239packages in `{...}/packages`, the project will depends on each of them.
240
241Once copied all runtime package locally, simply run:
242```bash
243dotnet build src/Google.OrTools
244dotnet pack src/Google.OrTools
245```
246
247## Examples
248
249The Test projects show examples of building applications with `netcoreapp3.1`.
250
251The F# example folder shows how to compile against the typical .NET Framework
252installed on machine.
253
254## Appendices
255
256Few links on the subject...
257
258.Net runtime can deduce library extension so don’t use a platform-specific
259library name in the `DllImport` statement.
260Instead, just use the library name itself, without any prefixes or suffixes,
261and rely on the runtime to find the appropriate library at runtime.\
262ref: [Mono `pinvoke#libraryname`](https://www.mono-project.com/docs/advanced/pinvoke/#library-names)
263
264## Resources
265
266Some issue related to this process
267* [`PackageReference` only support `TargetFramework` condition](https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#adding-a-packagereference-condition)
268* [Nuget needs to support dependencies specific to target runtime #1660](https://github.com/NuGet/Home/issues/1660)
269* [Improve documentation on creating native packages #238](https://github.com/NuGet/docs.microsoft.com-nuget/issues/238)
270
271### Runtime IDentifier (RID)
272
273* [.NET Core RID Catalog](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog)
274* [Creating native packages](https://docs.microsoft.com/en-us/nuget/create-packages/native-packages)
275* [Blog on Nuget Rid Graph](https://natemcmaster.com/blog/2016/05/19/nuget3-rid-graph/)
276
277### Target Framework Moniker (TFM)
278
279* [.NET TFM list](https://docs.microsoft.com/en-us/dotnet/standard/frameworks)
280* [.NET Standard implementation support](https://docs.microsoft.com/en-us/dotnet/standard/net-standard)
281
282
283### Reference on .csproj format
284
285* [Common MSBuild project properties](https://docs.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-properties?view=vs-2017)
286* [MSBuild well-known item metadata](https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-well-known-item-metadata?view=vs-2017)
287* [Additions to the csproj format for .NET Core](https://docs.microsoft.com/en-us/dotnet/core/tools/csproj)
288
289## Misc
290
291Image has been generated using [plantuml](http://plantuml.com/):
292```bash
293plantuml -Tpng doc/{file}.dot
294```
295
296So you can find the dot source files in [doc](doc).
297