-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
One NuGet for all OSs #19
Comments
I've not done this before myself yet, and most examples I know about only call into different native libraries for each platform, but all of them share a common API already. So I'm wondering if this is possible for SpiderEye - there needs to some smart handling/loading of a specific OS's .dll or the SpiderEye source needs to change to merge all OS-specific source projects and do some good old |
The following <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>$(MSBuildProjectName.Replace('.Packaging', ''))</AssemblyName>
</PropertyGroup>
<Import Project="..\Shared\SpiderEye.Shared.proj" />
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<IncludeBuildOutput>false</IncludeBuildOutput>
<DisableTransitiveFrameworkReferences>true</DisableTransitiveFrameworkReferences>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\**\*.csproj" />
<ProjectReference Remove="$(MSBuildProjectFullPath)" />
</ItemGroup>
<ItemGroup>
<None Include="$(OutputPath)**/*.Core.*" Pack="true" PackagePath="ref/$(TargetFramework);runtimes/linux-x64/lib/$(TargetFramework);runtimes/osx-x64/lib/$(TargetFramework);runtimes/win/lib/$(TargetFramework)" />
<None Include="$(OutputPath)**/*.Linux.*" Pack="true" PackagePath="runtimes/linux-x64/lib/$(TargetFramework)" />
<None Include="$(OutputPath)**/*.Mac.*" Pack="true" PackagePath="runtimes/osx-x64/lib/$(TargetFramework)" />
<None Include="$(OutputPath)**/*.Windows.*" Pack="true" PackagePath="runtimes/win/lib/$(TargetFramework)" />
</ItemGroup>
</Project> The downside to this approach: Each platform project's NuGet dependencies (at this time only the Windows project has one) isn't included properly. I can of course manually add a reference to the package in this new project, and there's probably also some MSBuild logic I can add to add those transitive package references as a direct one instead. However, for now I'm looking into another approach instead: Keep the platform-specific NuGet packages and instead pack them all into a new "meta package" instead. The bigger missing point for either approach is to get the APIs wrapped in a way that does the correct call to the right assembly at runtime. Still looking into that but using Core (or a new project) as the entry point, making that a reference assembly and that then calling into a manually loaded platform-specific assembly should work. |
We do something like this (multiplatform bindings with single nuget) with our RocksDB bindings, if you want to check it out: https://github.com/curiosity-ai/rocksdb-sharp |
Thanks for the suggestion and detailed explanation and examples! I have tried various things to get a single Nuget package but nothing really worked so far. The main reasons I decide against it in the end (other than not working) was
The metapackage sounds like the most promising way to me but doesn't that mean that each platform specific build also contains the DLLs of all platforms? Either way, I'm open to solutions for a single Nuget package as long as separate projects are still possible (for those that need it). @theolivenbaum thank you for the example, always good to see something that works (the docs are a bit sparse on that topic). It's a bit different though from what I'd need here. You include native libs while I need to include .Net libs that should get referenced. |
I think that's what I'm slowly able to confirm works fine for non-native assemblies, too: We just need to put the dlls into
So once we provide our libs via the Note the first sentence of this quote: As soon as we have a single platform-specific assembly in its
I just finished some tests and it looks like NuGet only includes the dlls for the runtime(s) you build for. This matches the behavior of native libs from NuGet allows us to differentiate between the assemblies we want to reference at compile time, and which ones to reference at runtime:
So what this is saying is that we should put the assemblies we want to compile against into
A good summary of all of this can be found here. I just found a pretty good example of this solution! Microsoft.Data.SqlClient does what we want:
The nuspec has a few interesting things to it.
SpiderEye is a bit different when it comes to a few things: We might have an issue with this getting put in our auto-generated nuspec. <frameworkReferences>
<group targetFramework=".NETCoreApp3.0">
<frameworkReference name="Microsoft.WindowsDesktop.App.WindowsForms" />
</group>
</frameworkReferences> This is from the SpiderEye.Windows project, because it uses <Project>
<PropertyGroup>
<TargetsWindows>false</TargetsWindows>
<TargetsWindows Condition="'$(RuntimeIdentifier)' != '' AND $(RuntimeIdentifier.StartsWith('win'))">true</TargetsWindows>
</PropertyGroup>
<Import Condition="!$(TargetsWindows)" Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<Import Condition="$(TargetsWindows)" Project="Sdk.props" Sdk="Microsoft.NET.Sdk.WindowsDesktop" />
<!-- The actual project configuration. -->
<Import Condition="!$(TargetsWindows)" Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<Import Condition="$(TargetsWindows)" Project="Sdk.targets" Sdk="Microsoft.NET.Sdk.WindowsDesktop" />
</Project> The Windows project also uses So with all of this knowledge this is the tl;dr of the solution I think:
The result is a new NuGet package that has Core in Now the only missing piece is the need to define some API somewhere that users can call to initialize the Additionally I want to look into making our own custom SDK to make the above csproj setup a user has to do in their project a single line. I.e. I'm working on this over this weekend, we'll see if this works 😉 |
woah this is amazing 😲 I'm totally on board with
The windows project will soon need a reference to support the chromium edge webview (maybe macOS as well, I haven't looked into that yet). To avoid duplicated reference entries I think it'd be best to have a shared proj file for each platform that lists references and is then imported in both the actual OS project and the unified project. This way you can't forget to add references to both projects and version updates only have to be done once. Having a custom SDK would be the icing on the cake. I didn't even know that it was possible to create a custom one, that's very cool. <ItemGroup>
<EmbeddedResource Include="Angular\dist\**">
<LogicalName>%(RelativeDir)%(Filename)%(Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup> where the include path is configurable of course and maybe a flag to disable this as well. Thank you so much for all that detective work, you got way farther than I did 😄 |
I ran into a few more issues, so it will be a bit until I can get this into a state that hopefully works. Then we can clean it up afterwards 😉 I'll update this issue once I can. |
no worries, I didn't expect it to work without a fight 😄 If you like you can create a WIP pull request if you need any input or a second set of eyes. |
Describe the feature you'd like
Offer one NuGet package, that is multi-targeted and contains the necessary assemblies to support all supported OSs. Then additionally the
<OsName>Application.Init
API can be simplified to do the right call based on a runtime check. This would replace the current packages as it can be a full replacement for consumers of SpiderEye.Reason for this feature request
Currently projects that use SpiderEye on more than one target OS have to be developed with N+1 projects, where N is the number of the OSs. The reason for that is the fact that SpiderEye currently ships support for each OS in a separate NuGet. The remaining project acts as the "core" project that defines most of the logic, while the other projects all just configure the app on startup via the correct
<OsName>Application
API for that OS.With this change a user of SpiderEye would only add a single NuGet package to their project and call a single initialization method. Besides a bigger NuGet package for developers to download this would not result in unnecessary assembly additions for a specific target OS.
Besides simplification for consumers this change would most likely also
The text was updated successfully, but these errors were encountered: