159
Vote

Add 1st class support for assembly platform (x86, x64, ARM, Any CPU)

description

I have a number of 3rd party assemblies that I would like to use nuget with but they have native platform dependencies. Currently the only solution is to create multiple packages specifying the platform in the name, or, not use the lib directory and work some PowerShell magic so the package can contain multiple assemblies with different platform targets. "Multiple packages" is not an actual workaround since I wouldn't be able to take a dependency on a platform-specific package from an "Any CPU" package.

I would like nuget to support multiple assemblies from the lib folder based on the project's current platform target. For example, something like this would work:

lib{framework name}{version}{platform}
lib.NetFramework 2.0\x86\
lib.NetFramework 2.0\x64\

One approach that may work with nuget is to specify the MSBUILD $(Platform) variable in the project's reference hint path. For example:

<Reference Include="sbclient, Version=6.6.0.0, Culture=neutral, PublicKeyToken=371d4a7d6f5d7853">
<HintPath>..\lib.NetFramework 2.0\sbclient\$(Platform)\sbclient.dll</HintPath>
</Reference>

comments

otac0n wrote Jun 7, 2011 at 8:24 PM

This is a blocker for IronJS right now.

tusbar wrote Jul 2, 2011 at 2:34 PM

I don't think that the platform folders should be inside the lib directory but there should be a nuget directory tree for each platform:

lib\ # <== shared between platforms
x86\lib\ # <== x86 specific, etc.
x86\content\
x64\lib\
x64\content\
x64\tools\
etc..

takekazuomi wrote Jul 14, 2011 at 2:49 AM

What about native code library in nuget package ?

mistachkin wrote Sep 29, 2011 at 2:28 AM

This is also a blocker for System.Data.SQLite right now.

WayneBrantley wrote Jan 3, 2012 at 2:50 PM

Maybe at the same time, support for release/debug builds could be put in.
http://nuget.codeplex.com/discussions/284030

TripleEmcoder wrote Jan 3, 2012 at 4:41 PM

@tusbar What would be the use case for platform-specific content?

WayneBrantley wrote Jan 3, 2012 at 6:07 PM

Not my case, but first paragraph above shows use case?

TripleEmcoder wrote Jan 3, 2012 at 9:02 PM

Sorry, I wasn't clear enough. Of course I know why we need platform-specific lib folders. I was asking about content as in "content" folder: x86\content vs. x86\lib - from @tusbar's post.

JeffHandley wrote Mar 8, 2012 at 8:58 PM

mistachkin wrote Mar 12, 2012 at 7:13 AM

Also, it would be very nice to have an option (bool perhaps?) for either copying the platform specific files to the output directory (e.g. "bin\Debug") or to platform specific sub-directories of the output directory (e.g. "bin\Debug\x86" and "bin\Debug\x64"), based on the value of the option.

JeffHandley wrote Mar 16, 2012 at 9:20 PM

Related to other target framework work items that have been cut from 1.8 and moved to 1.9.

dotnetjunky wrote Apr 30, 2012 at 9:13 PM

@tusbar: Why do you think it's better to have lib/content/tools inside 'x86' and 'x64'? Can you list out the reasons?

tusbar wrote May 1, 2012 at 8:14 AM

@dotnetjunky I do not have any specific examples.

I just repeated the whole directory structure of a nuget package within the platform dependent folders.

tusbar wrote May 2, 2012 at 5:16 AM

@dotnetjunky, I misread your question :

You're probably aware that some packages contain native DLLs within the content directory (often within content/lib, e.g http://nuget.org/packages/Sendgrid).

We sort of follow the same practice for our internal package repository and we find ourselves having to create a nuget package for each platform.

JeffHandley wrote May 17, 2012 at 9:59 PM

We considered this as part of the target framework version changes we are making but decided not to take it at this time. Moved to the backlog.

yzorg wrote Jun 14, 2012 at 1:57 PM

It's been a year since this issue was touched. Is the convention to use content\x86\lib the SOP? Do the maintainers ever expect first-class support for native library platform, or is this SOP expected to continue indefinitely?

bhuijben wrote Jul 4, 2012 at 4:22 PM

I could really use this support for SharpSvn.

The SharpSvn project provides a SharpSvn.dll, that contains a lot of native code.

Side by side it also delivers a few platform specific native DLLs that provide optional extra features.

Currently I have to create separate packages and even then I see problems when using the UI to add a reference because I can't mark the managed dlls as no-assembly.
(They are defined as managed resources of the main assembly to make MSBuild copy the dlls with the primary assembly).

See the SharpSvn packages on the nuget site for some examples on how this works.

alski wrote Sep 5, 2012 at 9:13 AM

Please reassign as a higher priority. The lack of this feature is teh only thing stopping from adopting nuget for our own internal packaging.
Thanks.

warlock6x3 wrote Oct 25, 2012 at 9:44 AM

I would disagree with "Impact: Low". Is anyone looking at this? It seems to be an ignored work item.

Without first-class cpu-architecture support, it makes NuGet package development for Windows phone and Windows Tablets much more complicated than it needs to be...

nulltoken wrote Apr 12, 2013 at 10:06 AM

goosemanjack wrote May 31, 2013 at 5:34 PM

This is a high impact item, not low. It requires us to use hacks for our internal packages instead of cleanly using nuget for package management.

xen2 wrote Jul 8, 2013 at 5:19 AM

Hopefully It shouldn't only be for processor but for some other platform characteristics (i.e. for our project we ship one version of the core assembly for D3D, another one for OpenGL -- that's something we rather do at compile-time instead of runtime interface for performance reasons).
Then any sample project should be able to reference the main package that contains both version of the assembly.

JeffHandley wrote Jul 8, 2013 at 11:21 PM

What do you folks think about using the \build folder support to include a targets file in your package and have the targets file do the work of grabbing the right bits at build-time, instead of having NuGet get the right bits at package install-time?

xen2 wrote Jul 27, 2013 at 4:28 PM

Yes that's what we're doing now in our custom MSBuild targets, and it's possible we could use it on top of NuGet. I will check into that.

xen2 wrote Jul 27, 2013 at 4:57 PM

BTW, maybe a bit unrelated, but is there a way to execute this "install-time" folder selection (i.e. .NET 4.5 will actually choose "net40" folder) within MSBuild? (i.e. a task that returns "net40" when requesting a specific NuGet package name)
Since we use one csproj (with rules/variables depending on platform/framework), we need this if we want to use NuGet for 3rd party libraries.

xen2 wrote Jul 27, 2013 at 5:02 PM

(to complete previous message, my main concern is when there is for example a portable library, somehow the assembly resolution is much more complex than just checking for net40 or monodroid).

petersunde wrote Oct 3, 2013 at 5:14 PM

I vote for a simplier approach. You can create AnyCpu/x86/x64 packages rather easily if you have a proper build script. A simple quickfix could be nuget switching between x86/x64/AnyCpu packages when you change solution platform (e.g from x86 to x64). So if you are missing the x64 package in a project, you are prompted to install it.
<metadata>
<platforms>
<windows>
<x86>$id.x86</x86>
<x64>$id.x64</x64>
<anycpu>$id.anycpu</anycpu>
</windows>
</platform>
</metadata>
If 1) We cannot do it because we are not sure what platform "you are currently targeting" -> Force us to choose
If 2) We cannot do it because you have a mix of x86 / x64 / anycpu packages -> Display a red prompt that tells us which projects are troublesome for X operation and need to target a different architecture.

GUYS, it does not have to be PERFECT. Seriously just about any "feature" would be a improvement over today's situation as proven by the comments left above.

JeffHandley wrote Oct 3, 2013 at 5:52 PM

@petersunde That approach does seem appealing. @FearTheCowboy has been exploring something like that too.

fearthecowboy wrote Oct 3, 2013 at 6:12 PM

Yes, as @JeffHandley mentioned, I've been working on a solution for NuGet/C++ packages that solves this.

In the C++ side of things, we've always had to generate a .targets file (and now, a .props file too) that intelligently grabs the appropriate files (libs, headers, dlls, etc) and gets the project to reference them correctly.

it's a far more complex version of the same thing as you're seeing here, and so I've altered the package creator for C++ to automatically handle this for all the variations--which for a given package can easily be 70 or more variations.

In this case, it's not entirely insane that you could ship all the versions of the assemblies in the same package (in our case, it was creating packages that were far too large for comfort)

To do this trivially, you may want to just manually include a .props or .targets file that adds the platform specific references in with a condition statement:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Reference Condition="'$(Platform)' == 'x86'"
        Include="$(MSBuildThisFileDirectory)..\..\build\native\net20\x86\somelib.dll" /> 

    <Reference Condition="'$(Platform)' == 'x64'"
        Include="$(MSBuildThisFileDirectory)..\..\build\native\net20\x64\somelib.dll" /> 

    <Reference Condition="'$(Platform)' == 'anycpu'"
        Include="$(MSBuildThisFileDirectory)..\..\build\native\net20\anycpu\somelib.dll" /> 
  
    <!-- etc... ->

</Project>
and then stick the files into \build\<framework>\<platform>\ .. folders

SharpGIS wrote Apr 17 at 4:09 PM

Here's another approach which could handle this beautifully: https://nuget.codeplex.com/discussions/396720

SharpGIS wrote Apr 17 at 5:32 PM

Sorry I meant to add a link to the issue, not the discussion: https://nuget.codeplex.com/workitem/4119