{"id":22254586,"url":"https://github.com/mizux/dotnet-native","last_synced_at":"2025-07-28T07:30:47.584Z","repository":{"id":74261440,"uuid":"144027654","full_name":"Mizux/dotnet-native","owner":"Mizux","description":"Template to build a multi-platforms Native Net 6.0 Nuget package using dotnet cli","archived":false,"fork":false,"pushed_at":"2024-01-29T12:48:01.000Z","size":1278,"stargazers_count":76,"open_issues_count":2,"forks_count":14,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-01-29T14:47:50.270Z","etag":null,"topics":["cmake","dotnet","dotnet-cli","mizux","native-library","netstandard","netstandard2","netstandard20","netstandard21","nuget"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mizux.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null}},"created_at":"2018-08-08T14:44:45.000Z","updated_at":"2024-04-23T13:55:17.800Z","dependencies_parsed_at":"2024-01-29T14:12:45.880Z","dependency_job_id":null,"html_url":"https://github.com/Mizux/dotnet-native","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mizux%2Fdotnet-native","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mizux%2Fdotnet-native/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mizux%2Fdotnet-native/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mizux%2Fdotnet-native/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mizux","download_url":"https://codeload.github.com/Mizux/dotnet-native/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227873180,"owners_count":17832896,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cmake","dotnet","dotnet-cli","mizux","native-library","netstandard","netstandard2","netstandard20","netstandard21","nuget"],"created_at":"2024-12-03T07:31:54.163Z","updated_at":"2024-12-03T07:31:59.565Z","avatar_url":"https://github.com/Mizux.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"Github-CI:\n[![Build Status][amd64_linux_status]][amd64_linux_link]\n[![Build Status][amd64_macos_status]][amd64_macos_link]\n[![Build Status][amd64_windows_status]][amd64_windows_link]\u003cbr\u003e\n\n[![Build Status][amd64_docker_status]][amd64_docker_link]\n\n[amd64_linux_status]: ./../../actions/workflows/amd64_linux.yml/badge.svg\n[amd64_linux_link]: ./../../actions/workflows/amd64_linux.yml\n[amd64_macos_status]: ./../../actions/workflows/amd64_macos.yml/badge.svg\n[amd64_macos_link]: ./../../actions/workflows/amd64_macos.yml\n[amd64_windows_status]: ./../../actions/workflows/amd64_windows.yml/badge.svg\n[amd64_windows_link]: ./../../actions/workflows/amd64_windows.yml\n\n[amd64_docker_status]: ./../../actions/workflows/amd64_docker.yml/badge.svg\n[amd64_docker_link]: ./../../actions/workflows/amd64_docker.yml\n\n# Introduction\n\u003cnav for=\"project\"\u003e |\n\u003ca href=\"#requirement\"\u003eRequirement\u003c/a\u003e |\n\u003ca href=\"#codemap\"\u003eCodemap\u003c/a\u003e |\n\u003ca href=\"#dependencies\"\u003eDependencies\u003c/a\u003e |\n\u003ca href=\"#build-process\"\u003eBuild\u003c/a\u003e |\n\u003ca href=\"ci/README.md\"\u003eCI\u003c/a\u003e |\n\u003ca href=\"#appendices\"\u003eAppendices\u003c/a\u003e |\n\u003ca href=\"#license\"\u003eLicense\u003c/a\u003e |\n\u003c/nav\u003e\n\nThis is an example of how to create a Modern [CMake](https://cmake.org/) C++/.Net Project.\n\nThis project aim to explain how you build a .NetStandard2.0 native (win-x64,\nlinux-x64 and osx-x64) nuget multiple package using\n[`.NET Core CLI`](https://docs.microsoft.com/en-us/dotnet/core/tools/) and the\n[*new* .csproj format](https://docs.microsoft.com/en-us/dotnet/core/tools/csproj).\u003cbr\u003e\ne.g. You have a cross platform C++ library (using a CMake based build) and a .NetStandard2.0 wrapper on it thanks to SWIG.  \nThen you want to provide a cross-platform Nuget package to consume it in a .NetCoreApp3.1 project...\n\n## Requirement\n\nYou'll need:\n\n* \"CMake \u003e= 3.18\".\n* \".Net Core SDK \u003e= 3.1\" to get the dotnet cli.\n\nnote: We won't/can't rely on VS 2019 since we want a portable cross-platform [`dotnet/cli`](https://github.com/dotnet/cli) pipeline.\n\n## Codemap\n\nThe project layout is as follow:\n\n* [CMakeLists.txt](CMakeLists.txt) Top-level for [CMake](https://cmake.org/cmake/help/latest/) based build.\n* [cmake](cmake) Subsidiary CMake files.\n  * [dotnet.cmake](cmake/dotnet.cmake) All internall .Net CMake stuff.\n\n* [ci](ci) Root directory for continuous integration.\n\n* [Foo](Foo) Root directory for `Foo` library.\n  * [CMakeLists.txt](Foo/CMakeLists.txt) for `Foo`.\n  * [include](Foo/include) public folder.\n    * [foo](Foo/include/foo)\n      * [Foo.hpp](Foo/include/foo/Foo.hpp)\n  * [src](Foo/src) private folder.\n    * [src/Foo.cpp](Foo/src/Foo.cpp)\n  * [dotnet](Foo/dotnet)\n    * [CMakeLists.txt](Foo/dotnet/CMakeLists.txt) for `Foo` .Net.\n    * [foo.i](Foo/dotnet/foo.i) SWIG .Net wrapper.\n* [Bar](Bar) Root directory for `Bar` library.\n  * [CMakeLists.txt](Bar/CMakeLists.txt) for `Bar`.\n  * [include](Bar/include) public folder.\n    * [bar](Bar/include/bar)\n      * [Bar.hpp](Bar/include/bar/Bar.hpp)\n  * [src](Bar/src) private folder.\n    * [src/Bar.cpp](Bar/src/Bar.cpp)\n  * [dotnet](Bar/dotnet)\n    * [CMakeLists.txt](Bar/dotnet/CMakeLists.txt) for `Bar` .Net.\n    * [bar.i](Bar/dotnet/bar.i) SWIG .Net wrapper.\n* [FooBar](FooBar) Root directory for `FooBar` library.\n  * [CMakeLists.txt](FooBar/CMakeLists.txt) for `FooBar`.\n  * [include](FooBar/include) public folder.\n    * [foobar](FooBar/include/foobar)\n      * [FooBar.hpp](FooBar/include/foobar/FooBar.hpp)\n  * [src](FooBar/src) private folder.\n    * [src/FooBar.cpp](FooBar/src/FooBar.cpp)\n  * [dotnet](FooBar/dotnet)\n    * [CMakeLists.txt](FooBar/dotnet/CMakeLists.txt) for `FooBar` .Net.\n    * [foobar.i](Bar/dotnet/foobar.i) SWIG .Net wrapper.\n\n* [dotnet](dotnet) Root directory for .Net template files\n  * [`Mizux.DotnetNative.runtime.csproj.in`](dotnet/Mizux.DotnetNative.runtime.csproj.in) csproj template for the .Net \"native\" (i.e. RID dependent) package.\n  * [`Mizux.DotnetNative.csproj.in`](dotnet/Mizux.DotnetNative.csproj.in) csproj template for the .Net package.\n  * [`Test.csproj.in`](dotnet/Test.csproj.in) csproj template for .Net test project.\n  * [`Example.csproj.in`](dotnet/Example.csproj.in) csproj template for .Net example project.\n\n* [tests](tests) Root directory for tests\n  * [CMakeLists.txt](tests/CMakeLists.txt) for `DotnetNative.Test` .Net.\n  * [`FooTests.cs`](tests/FooTests.cs) Code of the Mizux.DotnetNative.FooTests project.\n\n* [examples](examples) Root directory for examples\n  * [CMakeLists.txt](examples/CMakeLists.txt) for `DotnetNative.FooApp` .Net.\n  * [`FooApp.cs`](examples/FooApp.cs) Code of the `DotnetNative.FooApp` app.\n\n## Dependencies\nTo complexify a little, the CMake project is composed of three libraries (Foo, Bar and FooBar)\nwith the following dependencies:  \n```sh\nFoo:\nBar:\nFooBar: PUBLIC Foo PRIVATE Bar\n```\n\n## Build Process\n\nTo Create a native dependent package we will split it in two parts:\n\n* A bunch of `Mizux.DotnetNative.runtime.{rid}.nupkg` packages for each \n[Runtime Identifier (RId)](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog) targeted containing the native libraries.\n* A generic package `Mizux.DotnetNative.nupkg` depending on each runtime packages and\ncontaining the managed .Net code.\n\nActually, You don't need a specific variant of .Net Standard wrapper, simply omit the library extension and .Net magic will pick\nthe correct native library.  \nref: https://www.mono-project.com/docs/advanced/pinvoke/#library-names\n\nnote: [`Microsoft.NetCore.App` packages](https://www.nuget.org/packages?q=Microsoft.NETCore.App)\nfollow this layout.\n\nnote: While Microsoft use `runtime-\u003crid\u003e.Company.Project` for native libraries\nnaming, it is very difficult to get ownership on it, so you should prefer to use\n`Company.Project.runtime-\u003crid\u003e` instead since you can have ownership on\n`Company.*` prefix more easily.\n\nWe have two use case scenario:\n\n1.  Locally, be able to build a Mizux.DotnetNative package which **only** target the\n    local `OS Platform`, i.e. building for only one\n    [Runtime Identifier (RID)](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog).\n    \\\n    note: This is useful since the C++ build is a complex process for Windows,\n    Linux and MacOS. i.e. We don't support cross-compilation for the native\n    library generation.\n\n2.  Be able to create a complete cross-platform (ed. platform as multiple rid)\n    Mizux.DotnetNative package. \\\n    i.e. First you generate each native Nuget package\n    (`Mizux.DotnetNative.runtime.{rid}.nupkg`) on each native architecture, then\n    copy paste these artifacts on one native machine to generate the\n    meta-package `Mizux.DotnetNative`.\n\n### Local Mizux.DotnetNative Package\n\nLet's start with scenario 1: Create a *Local only* `Mizux.DotnetNative.nupkg` package targeting **one**\n[Runtime Identifier (RID)](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog).  \nWe would like to build a `Mizux.DotnetNative.nupkg` package which only depends\non one `Mizux.DotnetNative.runtime.{rid}.nupkg` in order to work locally.\n\nThe pipeline for `linux-x64` should be as follow:\n![Local Pipeline](docs/local_pipeline.svg)\n![Legend](docs/legend.svg)\nnote: The pipeline will be similar for `osx-x64` and `win-x64` architecture,\ndon't hesitate to look at the CI log.\n\n#### Building local runtime Mizux.DotnetNative Package\n\ndisclaimer: In this git repository, we use `CMake` and `SWIG`.  \nThus we have the C++ shared library `libFoo.so` and the SWIG generated .Net wrapper `Foo.cs`.  \nnote: For a C++ CMake cross-platform project sample, take a look at [Mizux/cmake-cpp](https://github.com/Mizux/cmake-cpp).   \nnote: For a C++/Swig CMake cross-platform project sample, take a look at [Mizux/cmake-swig](https://github.com/Mizux/cmake-swig). \n\nSo first let's create the local `Mizux.DotnetNative.runtime.{rid}.nupkg` nuget package.\n\nHere some dev-note concerning this `Mizux.DotnetNative.runtime.{rid}.csproj`.\n* Once you specify a `RuntimeIdentifier` then `dotnet build` or `dotnet build -r {rid}` \nwill behave identically (save you from typing it).\n  * note: it is **NOT** the case if you use `RuntimeIdentifiers` (notice the 's')\n* It is [recommended](https://docs.microsoft.com/en-us/nuget/create-packages/native-packages)\nto add the tag `native` to the \n[nuget package tags](https://docs.microsoft.com/en-us/dotnet/core/tools/csproj#packagetags)\n  ```xml\n  \u003cPackageTags\u003enative\u003c/PackageTags\u003e\n  ```\n* This package is a runtime package so we don't want to ship an empty assembly file:\n  ```xml\n  \u003cIncludeBuildOutput\u003efalse\u003c/IncludeBuildOutput\u003e\n  ```\n* Add the native (i.e. C++) libraries to the nuget package in the repository `runtimes/{rid}/native`. e.g. for linux-x64:\n  ```xml\n  \u003cContent Include=\"*.so\"\u003e\n    \u003cPackagePath\u003eruntimes/linux-x64/native/%(Filename)%(Extension)\u003c/PackagePath\u003e\n    \u003cPack\u003etrue\u003c/Pack\u003e\n    \u003cCopyToOutputDirectory\u003ePreserveNewest\u003c/CopyToOutputDirectory\u003e\n  \u003c/Content\u003e\n  ```\n* Generate the runtime package to a defined directory (i.e. so later in\n  `Mizux.DotnetNative` package we will be able to locate it)\n  ```xml\n  \u003cPackageOutputPath\u003e{...}/packages\u003c/PackageOutputPath\u003e\n  ```\n\nThen you can generate the package using:\n\n```bash\ndotnet pack Mizux.DotnetNative.runtime.{rid}\n```\nnote: this will automatically trigger the `dotnet build`.\n\nIf everything good the package (located where your `PackageOutputPath` was defined) should have this layout:\n\n```\n{...}/packages/Mizux.DotnetNative.runtime.{rid}.nupkg:\n\\- Mizux.DotnetNative.runtime.{rid}.nuspec\n\\- runtimes\n   \\- {rid}\n      \\- native\n         \\- *.so / *.dylib / *.dll\n...\n```\nnote: `{rid}` could be `linux-x64` and `{framework}` could be `netstandard2.0`\n\ntips: since nuget package are zip archive you can use `unzip -l \u003cpackage\u003e.nupkg`\nto study their layout.\n\n#### Building local Mizux.DotnetNative Package\n\nSo now, let's create the local `Mizux.DotnetNative.nupkg` nuget package which will\ndepend on our previous runtime package.\n\nHere some dev-note concerning this `DotnetNative.csproj`.\n* Add the previous package directory:\n  ```xml\n  \u003cRestoreSources\u003e{...}/packages;$(RestoreSources)\u003c/RestoreSources\u003e\n  ```\n* Add dependency (i.e. `PackageReference`) on each runtime package(s) availabe:\n  ```xml\n  \u003cItemGroup\u003e\n    \u003cRuntimeLinux Include=\"{...}/packages/Mizux.DotnetNative.runtime.linux-x64.*.nupkg\"/\u003e\n    \u003cRuntimeOsx   Include=\"{...}/packages/Mizux.DotnetNative.runtime.osx-x64.*.nupkg\"/\u003e\n    \u003cRuntimeWin   Include=\"{...}/packages/Mizux.DotnetNative.runtime.win-x64.*.nupkg\"/\u003e\n    \u003cPackageReference Include=\"Mizux.DotnetNative.runtime.linux-x64\" Version=\"1.0\" Condition=\"Exists('@(RuntimeLinux)')\"/\u003e\n    \u003cPackageReference Include=\"Mizux.DotnetNative.runtime.osx-x64\"   Version=\"1.0\" Condition=\"Exists('@(RuntimeOsx)')\"  /\u003e\n    \u003cPackageReference Include=\"Mizux.DotnetNative.runtime.win-x64\"   Version=\"1.0\" Condition=\"Exists('@(RuntimeWin)')\"  /\u003e\n  \u003c/ItemGroup\u003e\n  ```\n  Thanks to the `RestoreSource` we can work locally we our just builded package\n  without the need to upload it on [nuget.org](https://www.nuget.org/).\n\nThen you can generate the package using:\n\n```bash\ndotnet pack Mizux.DotnetNative\n```\n\nIf everything good the package (located where your `PackageOutputPath` was\ndefined) should have this layout:\n\n```\n{...}/packages/Mizux.DotnetNative.nupkg:\n\\- Mizux.DotnetNative.nuspec\n\\- lib\n   \\- {framework}\n      \\- Mizux.DotnetNative.dll\n...\n```\nnote: `{framework}` could be `netcoreapp3.1` or/and `net6.0`\n\n#### Testing local Mizux.DotnetNative.FooApp Package\n\nWe can test everything is working by using the `Mizux.DotnetNative.FooApp` or `Mizux.DotnetNative.FooTests` project.\n\nFirst you can build it using:\n```\ndotnet build \u003cbuild_dir\u003e/dotnet/FooApp\n```\nnote: Since `Mizux.DotnetNative.FooApp` `PackageReference` Mizux.DotnetNative and add `{...}/packages` to the `RestoreSource`.\nDuring the build of DotnetNative.FooApp you can see that `Mizux.DotnetNative` and\n`Mizux.DotnetNative.runtime.{rid}` are automatically installed in the nuget cache.\n\nThen you can run it using:\n```\ndotnet run --project \u003cbuild_dir\u003e/dotnet/FooApp/FooApp.csproj\n```\nnote: Contrary to `dotnet build` and `dotnet pack` you must use `--project`\nbefore the `.csproj` path (let's call it \"dotnet cli command consistency\")\n\nYou should see:\n```sh\n$ dotnet run --project build/dotnet/FooApp/FooApp.csproj\n[1] Enter DotnetNativeApp\n[2] Enter Foo::staticFunction(int)\n[3] Enter freeFunction(int)\n[3] Exit freeFunction(int)\n[2] Exit Foo::staticFunction(int)\n[1] Exit DotnetNativeApp\n```\n\n### Complete Mizux.DotnetNative Package\n\nLet's start with scenario 2: Create a *Complete* `Mizux.DotnetNative.nupkg` package\ntargeting multiple\n[Runtime Identifier (RID)](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog).  \nWe would like to build a `Mizux.DotnetNative.nupkg` package which depends on several\n`Mizux.DotnetNative.runtime.{rid}.nupkg`.\n\nThe pipeline should be as follow:  \nnote: This pipeline should be run on any architecture,\nprovided you have generated the three architecture dependent `Mizux.DotnetNative.runtime.{rid}.nupkg`\nnuget packages.\n![Full Pipeline](docs/full_pipeline.svg)\n![Legend](docs/legend.svg)\n\n#### Building All runtime Mizux.DotnetNative Package\n\nLike in the previous scenario, on each targeted OS Platform you can build the\ncoresponding `Mizux.DotnetNative.runtime.{rid}.nupkg` package.\n\nSimply run on each platform:\n\n```bash\ncmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release\ncmake --build build --config Release\n```\nnote: replace `{rid}` by the Runtime Identifier associated to the current OS platform.\n\nThen on one machine used, you copy all other packages in the `{...}/packages` so\nwhen building `Mizux.DotnetNative.csproj` we can have access to all package...\n\n#### Building Complete Mizux.DotnetNative Package\n\nThis is the same step than in the previous scenario, since we \"see\" all runtime\npackages in `{...}/packages`, the project will depends on each of them.\n\nOnce copied all runtime package locally, simply run:\n\n```bash\ndotnet build \u003cbuild_dir\u003e/dotnet/Mizux.DotnetNative\ndotnet pack \u003cbuild_dir\u003e/dotnet/Mizux.DotnetNative\n```\n\n#### Testing Complete Mizux.DotnetNative Package\n\nWe can test everything is working by using the `Mizux.DotnetNative.FooApp` or `Mizux.DotnetNative.FooTests` project.\n\nFirst you can build it using:\n```\ndotnet build \u003cbuild_dir\u003e/dotnet/FooApp\n```\nnote: Since Mizux.DotnetNative.FooApp `PackageReference` Mizux.DotnetNative and add `{...}/packages` to the `RestoreSource`.\nDuring the build of Mizux.DotnetNative.FooApp you can see that `Mizux.DotnetNative` and\n`Mizux.DotnetNative.runtime.{rid}` are automatically installed in the nuget cache.\n\nThen you can run it using:\n```\ndotnet run --project \u003cbuild_dir\u003e/dotnet/FooApp/FooApp.csproj\n```\n\nYou should see something like this\n```bash\n$ dotnet run --project build/dotnet/FooApp/FooApp.csproj\n[1] Enter DotnetNativeApp\n[2] Enter Foo::staticFunction(int)\n[3] Enter freeFunction(int)\n[3] Exit freeFunction(int)\n[2] Exit Foo::staticFunction(int)\n[1] Exit DotnetNativeApp\n```\n\n## Appendices\n\nFew links on the subject...\n\n.Net runtime can deduce library extension so don’t use a platform-specific\nlibrary name in the `DllImport` statement.\nInstead, just use the library name itself, without any prefixes or suffixes,\nand rely on the runtime to find the appropriate library at runtime.\\\nref: [Mono `pinvoke#libraryname`](https://www.mono-project.com/docs/advanced/pinvoke/#library-names)\n\n### Resources\n\n#### Project layout\n* [The Pitchfork Layout](https://mizux.github.io/pitchfork/)\n\n#### CMake\n* [CMake Reference Documentation](https://cmake.org/cmake/help/latest/index.html)\n* https://llvm.org/docs/CMakePrimer.html\n* https://cliutils.gitlab.io/modern-cmake/\n* https://cgold.readthedocs.io/en/latest/\n\n#### Target Framework Moniker (TFM)\n\n* [.NET TFM list](https://docs.microsoft.com/en-us/dotnet/standard/frameworks)\n* [.NET Standard implementation support](https://docs.microsoft.com/en-us/dotnet/standard/net-standard)\n\n#### .Net:Runtime IDentifier (RID)\n\n* [.Net Support Policy](https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core)\n* [.NET Core RID Catalog](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog)\n* [Creating native packages](https://docs.microsoft.com/en-us/nuget/create-packages/native-packages)\n* [Blog on Nuget Rid Graph](https://natemcmaster.com/blog/2016/05/19/nuget3-rid-graph/)\n\n#### Reference on .csproj format\n\n* [Common MSBuild project properties](https://docs.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-properties?view=vs-2017)\n* [MSBuild well-known item metadata](https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-well-known-item-metadata?view=vs-2017)\n* [Additions to the csproj format for .NET Core](https://docs.microsoft.com/en-us/dotnet/core/tools/csproj)\n\n### Issues\n\nSome issue related to this process\n* [`PackageReference` only support `TargetFramework` condition](https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#adding-a-packagereference-condition)\n* [Nuget needs to support dependencies specific to target runtime #1660](https://github.com/NuGet/Home/issues/1660)\n* [Improve documentation on creating native packages #238](https://github.com/NuGet/docs.microsoft.com-nuget/issues/238)\n* [Guide for packaging C# library using P/Invoke](https://github.com/NuGet/Home/issues/8623)\n\n### Misc\n\nImage has been generated using [plantuml](http://plantuml.com/):\n\n```bash\nplantuml -Tsvg docs/{file}.dot\n```\nSo you can find the dot source files in [docs](docs).\n\n## License\n\nApache 2. See the LICENSE file for details.\n\n## Disclaimer\n\nThis is not an official Google product, it is just code that happens to be\nowned by Google.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmizux%2Fdotnet-native","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmizux%2Fdotnet-native","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmizux%2Fdotnet-native/lists"}