Thoughts on enhancing NuGet's targeting support

Topics: General
May 5, 2012 at 6:38 PM

I have faced exactly the same problems with the C++ project support. This required the distinction between debug, release, builds and also take into account the target achitecture.

The most easiest way I found to solve this was to pack all the addtional information needed in the profile part of the framework name descriptor. This made the integration in the actual structure much easier. For building packages I think it is also much easier to use shallow folder hierachies. You might want to look at some parts of the discution on C++ project support on the subject.

But I guess the bracket naming structure would also be a good way to integrate the C++ project descriptors.

This is all very good news as this will unify some of the changes I had to make to support C++ projects with the handling of normal manged packages.

May 7, 2012 at 2:24 AM

  "  The most easiest way I found to solve this was to pack all the addtional information needed in the profile part of the framework name descriptor. This made the integration in the actual structure much easier. For building packages I think it is also much easier to use shallow folder hierachies. You might want to look at some parts of the discution on C++ project support on the subject. "

 

Great opinion T-jay

 

- Hostgator Promo Codes

May 7, 2012 at 4:54 PM

Great stuff. The other target environment variable I'd like to see supported is the IDE (or not) that the package is being installed into. This way, different content can be targeted at Visual Studio 11 as compared to Web Matrix 2, e.g. This is particularly useful for JavaScript libraries that have meta-data files used to drive IntelliSense (e.g. jQuery) where each IDE supports different features in the meta-data. Obviously there's the case where nuget is running outside the context of an IDE and that would need to be represented too.

May 7, 2012 at 6:00 PM

We are going to add curated feeds for different IDEs (Web Matrix, VS), so I don't think we need to bake that into package structure.

May 11, 2012 at 6:05 AM

dotnetjunky: Curated feeds for different IDEs is only useful for the public NuGet feeds.  What about corporate and machine local feeds? 

May 11, 2012 at 6:21 AM

IMO a hierarchical folder structure doesn't map well to this problem - each new attribute adds another dimension to the folder hierarchy, multiplying the number of folders needed by the number of values for the new attribute.

My preference is that each of these targeting options are configured as metadata in the nuspec, mapped to a directory or file wildcard to indicate which files apply to which targeting options.  This allows the developer to structure their folders in whatever way is meaningful or space efficient. 

This approache also scales with an arbitrarily large set of targeting attributes and values.  While the universe of targeting attributes and values will be large, each project (if the project even needs targeting) will only use a small subset of this universe of possible attributes and values.  (Which highlights why a fixed folder hierarchy is a bad idea.)

The current conventions are still useful - if no targeting is specified in the nuspec, the current conventions are used to deduce targeting attributes.  Make the simple cases simple, and provide a reasonable path for the complex cases.

The multi-value folder names are better than the deep folders IMO; but separating targeting attributes from the folder structure (thereby enabling some flexibility in the folder structure) would be much better.  It makes all the arguments on the "right" way to organize the folders go away.

May 16, 2012 at 2:34 PM

I'd like to take this opportunity to enable support for portable libraries. This will become especially important this year as VS11 ships with portable libraries built-in.

Portable libraries use a moniker like ".NETPortable,Version=v4.0,Profile=Profile1", where the profile determines which platforms the library may run on (each portable library profile maps to a sequence of framework monikers, which may include wildcards).

A portable library should be able to go into a .nupkg with the metadata specifying the list of frameworks it supports. This is difficult to do with a folder naming convention, so I like johncrim's recommendation to use nuspec (and fall back to the folder naming convention for simple projects and backwards compatibility).

Similarly, we should be able to install a nupkg (containing portable libraries) into a portable library project. In this case, the client should determine the platforms the target project may run on, and the "appropriate" portable library from the nupkg will be used. (Where "appropriate" IMO means the most platform restricted / highest platform version instance that supports all target platforms/versions - and we'll have to decide whether "fewer platforms" or "higher platform version" is more "appropriate"... perhaps a "priority" could also be added to the nuspec as a tie-breaker).

We'd also need a simple "refresh" command. Re-targeting portable library projects is simple (and somewhat common), and we'd want a simple way to refresh the "appropriateness logic" for the nupkg installed in that project (or just an uninstall/reinstall-from-cache).

       -Steve

P.S. I think we should also fix work item 1240 while we're working on this. We should be able to do it without backwards compatibility problems.

P.P.S. While we're at it, do we really need to verify all framework identifiers? We're still missing "Xbox", and others may be added in the future. It would be nice if we could specify the new logic in a way that we can work with any framework identifier specified in the nuspec.

May 17, 2012 at 2:08 PM
johncrim wrote:

This approache also scales with an arbitrarily large set of targeting attributes and values.  While the universe of targeting attributes and values will be large, each project (if the project even needs targeting) will only use a small subset of this universe of possible attributes and values.  (Which highlights why a fixed folder hierarchy is a bad idea.)

I agree with the fact that the number of targeting attributes is very large. However I would find it wise to define a fixed set of attributes which can be handled natively in Nuget. To provide support for non standard attribute combinations, could it be an option to use a powershell script to select the correct targeting combination defined in the nuspec ? Should the script be present, the build in mechanism could be used as fallback if the script failed to designate a compatible target framework.

May 17, 2012 at 6:32 PM

We are not adding official support for Portable library as part of this wave, but we do have it on our roadmap. We hope we can do it very soon, so stay tuned.

Keep the discussion coming.

May 18, 2012 at 10:33 AM

In the write-up above, we proposed adding a 'targetFramework' attribute to the <dependency> element to allow setting multiple target frameworks for a dependency:
<dependencies>
<dependency id="jQuery" version="1.0" targetFramework="net40, sl3" />
 </dependencies>

This design is consistent with the <frameworkAssemblyReferences> element. However, it doesn't address an important scenario that you have been asking for: a package wants to depend on, say, jQuery for .net 4.0 or below, but does not for .net 4.5 or higher.

As a result, we are changing the design to this:
 
<dependencies targetFramework="net40">
<dependency id="jQuery" version="1.0" />
<dependency id="EntityFramework" />
<dependencies>

<dependencies targetFramework="sl3">
<dependency id="jQuery" version="1.0" />
<dependencies>

<dependencies targetFramework="net45">
<dependencies>

Notes:
  • The 'targetFramework' attribute is now set at the <dependencies> node. It can only contain exactly one framework.
  • The 'targetFramework' is optional. If omitted, it behaves as the previous versions of nuget.
  • There can now be multiple <dependencies> elements, each contains a set of <dependency> that will be applied together if the project's framework matches the 'targetFramework' attribute. Think of it as the equivalent of a framework folder under lib/content/tools.
  • In the example above, if the package is installed into a net45 project, no dependency will be installed.

What do you think?

Developer
May 18, 2012 at 10:58 AM

That's looking fine! There is some redundancy in the required elements however it's flexible. You can even rely on different dependency versions depending on the target framework. /me likes!

May 25, 2012 at 7:23 AM

@dotnetjunky: Have you made any progress on the definition of the project attribute matching scheme ? I'm eager to hear about that !

Jul 30, 2013 at 7:56 PM
Nice idea! I have been looking for the targeting framework as meta data (part of nuspec).

I like JohnCrim's suggestion to map directory names in the nuspec for each combination of targetting options. +1