Packaging platform-native (C++) code with C# bindings using nuget - c#

So, I've been searching around about the ideal way to build a cross-platform .NET (C#) application that also relies on some native code bits.
Since I couldn't find a de-facto way to build these things together, I turned by attention into the following workflow:
Build native code (c++ -> native "dll"(.dll/.dylib/.so/etc);
(Generate bindings, w/ SWIG or something, or have a project with them);
Package said project into NuGet;
Consume from the cross-platform application.
Now, Microsoft itself has some suggestions about this. But this - and all other - guides I've found so far have the same quirk: include pre-compiled binaries into the folder structure. This bothers me because:
It makes version control hard, because you have hard-copied build artifacts;
It completely breaks CI/CD because you can't just have a matrix of CI machines each one doing their build/package/upload.
It breaks the development workflow because you need to constantly be building + copying files over.
But, looking around in the NuGet Gallery, there seem to be packages more in the direction that I thought of, for example in the SkiaSharp, and Avalonia packages.
My idea is that there should be a series of for-one-platform-only packages (plus eventually an "aggregator" package) that could be transparently consumed.
Is this a possible workflow? If yes, how? If not, what is the currently agreed upon workflow, and how does it tackle the issues I mentioned?
Just to make it clear, I want to develop the native library and consume it in the cross-platform .NET (5/6) application in a simultaneous fashion, it's not that I'm binding a mature library, with periodic releases, that would make the mentioned workflow easy.
Thank you.

Related

Is there any way to share code between UWP apps and WPF apps?

To be clear, I follow the MVVM pattern, and I want to structure my project such that I can share my model code between a UWP app and a standard WPF app. The code I want to share has no UI. I don't relish the thought of finding new tools to replace the ones that I've been using for years that take care of certain tasks like logging, connecting to a document oriented database, etc.
I attempted to start writing a UWP wrapper around some code I already have and reference the model project directly. Visual Studio refused to let that happen, showing me an error message that says "Unable to add a reference to project 'ACK.Model'". The same thing happened when I attempted to put the model in a Universal Library and reference it from a WPF app. I'm not trying to share WPF code. Just the model layer that has no reference to UI libraries.
This is a scary proposition, because it means that if I want to do anything substantial I have to choose to either jump 100% to UWP or stay 100% WPF. NewtonSoft.JSON might have a universal distribution (ASP.NET MVC), but what about ElasticSearch.NET, and other tools needed to make important apps?
I found where the "Portable Class Library" project type was hiding. PCLs will allow me to share my code across WPF and Universal apps as that was one of the options. This solves the simple case of the Model part of my code, but I (still) can't use some of the libraries I want. There are still a large number of libraries that I need that do not have PCL available.
About a year later, with the advent of Visual Studio 2017 there is a more complete solution. If you target your libraries to .Net Standard then the library is compatible with both .Net Core apps and the monolithic .Net targeted app. The support for standard .Net libraries and APIs is fairly complete, as is the support for modern C# language features.
The general advice now is this:
Target .Net Standard for all libraries
Target the appropriate platform for your actual application. (UWP or WPF).
NOTE: if your library has to interact with C libraries or applications, you have to take extra care to make sure you load the correct version.
It appears that there is a solution, but it has to be adopted by the whole tool chain you want to use. When Microsoft introduced Windows Store apps in Windows 8, they also introduced a Portable Class Library (PCL). The purpose of the PCL is to share code between different parts of your application.
When you create a PCL in Visual Studio 2015, you can specify the types of APIs you want it to be accessible from:
Universal Apps
Mono
.Net Core 5
.Net 4.6
This of course, limits the APIs available to you but most of the ones you want to use are OK as long as it's not UI related. There are other limitations as well:
Your project can only be edited in Visual Studio 2015 or greater
You don't have access to special directories from the Environment variable (i.e. user Documents directory, etc.)
You can't link to a library designed for only one of your target platforms (i.e. libgit2sharp, etc.)
There's no way to browse the API for this subset--MSDN needs to get on the stick. MSDN has updated much of the API documentation, but it's still difficult to figure out what applies to your PCL
However, you can link any library designed for a single target platform to your PCL. It's not ideal, but it's better than nothing.
The ASP.NET MVC stack has been ported to using PCLs, so you can use NewtonSoft.JSON directly as well as any other of those libraries used by that application. However, there are several libraries that have not been ported.
This arrangement forces you to think about how you want to integrate better. The .Net Core 5 seems to be stable, but support is in it's infancy. The current generation of Universal Apps as of VS 2015 update 1 uses .Net Core 5 directly.
There are several features from Nuget that are not currently supported even though work is under way:
MS Build extensions (major changes to MSBuild and the project.json structure)
Install/uninstall scripts (related to the removal of the concept of install)
Content (related to install/uninstall, but work is in progress on this)
Content transforms (related to lack of install/uninstall)
I wish I had a more complete answer. But this is as far as I got once I discovered the PCL and how it evolved for the current infrastructure.
I'm in the process of creating a game creation toolkit that incorporates version control right off the bat. I want to be able to deploy a game as a Windows 10 app, or as a standard WPF app, but due to the libraries I'm using to integrate version control I need to create the editor as a standard WPF app. I had to be a bit creative in building the shared code and importing the correct libraries.
First, my project hierarchy:
Project.Model (Portable Class Library)
Project.Model.Versioning (standard C# library)
Mvvm.Toolkit (Portable Class Library)
Editor (Standard WPF application)
I want the core PCL to be able to load a project and deserialize the JSON encoded objects. The PCL did have access to System.IO, but surprisingly it is not the same as the one defined in the standard C# library. Here's how I had to fix things:
After adding the package reference to NewtonSoft.JSON, I had to change the target framework in the packages.config file:
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="portable-net452+win81" />
All projects dependent on my Project.Model class had to install the `system.io.filesystem' package from nuget so that the System.IO.FileInfo etc. objects were the same.
While this is definitely not a panacea, it's also not a dead end. I'm sure there are more gotchas, but this will at least help with some of the problems.
a .NET Standard library could be used to share a Model-View-ViewModel architecture between a WPF project and a UWP project.
https://www.syncfusion.com/ebooks/xamarin-forms-succinctly/sharing-code-among-platforms
https://devblogs.microsoft.com/dotnet/announcing-uwp-support-for-net-standard-2-0/

Xamarin Build Process

I'm learning Xamarin. We have two ways to share our codes across platform, i.e. Shared Project and Portable Class Libraries.
I want to know what is happening, in detail, when I click on the "Play" button in Xamarin Studio. In particular, I'm interested in the build process for Xamarin. I have another related question: Is there a way to modified the build process?
I can not tell you what happens exactly within the build process but I can tell you that both types of sharing code have there advantages as well as down sides. And I personally prefer SharedProjects over Portable Class Libraries (PCLs).
The reason for this is that PCLs provide the minimal common denominator of the platform that your PCL profile support. Which can be sometimes annoying. A PCL is simplified nothing else as an assembly you reference in you project.
A SharedProject on the other side will be compiled into your project to a monolith. You can use compiler switches and such. Simplified it is a better way of linking files between different projects.
Xamarin has a good guide about Code sharing options you should read through.

Multiple solutions working with shared library project in Visual Studio

I have an independent solution with multiple projects including class libraries and control libraries. This solution and all its projects are under TFS source control.
I reference the output of one or more of these libraries in all new projects I develop. References are currently binary rather than project references.
The new projects are also always under source control and now I need to add debugging support for the libraries.
If I reference the library projects from them, the project file is modified and no longer works with the original library solution since source control providers for the library and referencee may be different.
Is there an easy way to accommodate this?
You should package the shared binaries, along with indexed PDB's, into a Nuget package. Nuget was specifically designed to solve these problems.
You can index your PDB's by running an indexing tool. TF Build can automatically index your PDB's.
Nope.
There are some strategies you can use, however. Easiest (possibly, but not in some cases) is to build the project you wish to debug, drop the binaries on top of the application that hosts them, and attach your debugger to the running application. This makes sure you have the correct version of the assembly under debug, but you might have to do unwanted things, such as making sure you're not targeting a specific version of the assembly
Which may be bad news for an assembly under development. It also requires lots of handiwork, which depending on where your application runs may require you run remote debugging, deal with issues transmitting dlls across untrusted networks, etc etc.

obfuscator and linker for .net

I am in need to develop a desktop application which will be quite light-weight but dont want my end users to install full-fledged .net framerwork to run that. I've done a lot of research and my findings are:
1. using some .net linkers, i can achieve this goal. some of them are salamander, spoon.net(not 100% sure about its functionality), rustemsoft etc.
2. I am coming across two tools for this: Obfuscator & linker. Now I know obfuscator basically is used to eliminate the reverse-engineering possibilities of a code and to secure it but i've found that many obfuscators also include .net linker feature
so kindly can anyone enlighten me that for me to achieve my goal: running my .net developed application in end user's Windows (XP to be precise - though its quite defunct), can i use some obfuscators like that of rustemsoft to create a standalone and ready to deploy exe with no dependencies on framework?

Targeting individual platforms with Visual Studio

I am writing an app that would work for both .NET and Mono. However components of it would only be available for one or the other. For example, a modular part of the app use WPF, which is not available in Mono (it would not even build!!!). Another part of the app uses PInvoke on a libpango, which is normally only available on Unix.
Is it possible to target individual platform with Visual Studio with different build parameter for each?
Currently The modular parts are not in their own project file, but I can easily move them to.
#define/#if blocks are one method for doing this. There is also a conditional attribute. You might also want to look into MSBuild targets.
You might also want to think about your class design and whether you can share have shared interfaces that enable more of a provider or "plug-in" model to support different platforms. Microsoft developed a Portable Libraries project type that might help with this.
Conditional compilation can make your code hard to understand and maintain. Personally, I am against it.
My suggestion is that you utilize good design patterns to isolate the platform specific bits,
http://codebetter.com/patricksmacchia/2011/11/07/real-world-feedback-on-a-net-to-mono-migration/
JavaDepend is a Windows Forms project, so its porting experience may help you.
WinForms executable (.exe) -> Platform adapter (.dll) -> Windows (.Windows.dll)
|
--> Other platforms (.Unix.dll)
In this way, you can always compile the whole solution together, package them together. At runtime, the adapter can load correct platform assembly/assemblies after platform detection.
For you case maybe you can use WPF for Windows, then you have to isolate WPF bits from business logic code, and then write UI again for other platforms (GTK# for Linux, MonoMac for OS X). This approach can be visualized as
WinForms/WPF executable (.exe) -> Platform independent biz-logic code (.dll)
^ ^
MonoMac executable ---| |
|
GTK\# executable ------|
In this way, you need to package differently for each platforms, but the core assembly/assemblies can be the same.

Categories