Skip to content
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

Need a way to specify RID-specific dependencies #4552

Closed
ericstj opened this issue Dec 10, 2015 · 18 comments
Closed

Need a way to specify RID-specific dependencies #4552

ericstj opened this issue Dec 10, 2015 · 18 comments
Milestone

Comments

@ericstj
Copy link
Member

ericstj commented Dec 10, 2015

Folks often need to cross compile and use an OS-specific package. Today the only way they can do this is to fork their project.json.

I think we need a "dependencies" section under the RID entry in runtimes.

This is related to NuGet/Home#1660.

@ericstj
Copy link
Member Author

ericstj commented Dec 10, 2015

Dependencies under RID might not be the right design since RID has no impact on the compile graph today, but the basic problem is I need to produce an implementation on Windows that uses windows specific packages (which cannot be used for Unix and will fail to resolve any assets) and vice-versa.

/cc @davidfowl @anurse

@TheRealPiotrP TheRealPiotrP self-assigned this Dec 14, 2015
@brthor brthor assigned ericstj and unassigned TheRealPiotrP Jan 8, 2016
@ericstj
Copy link
Member Author

ericstj commented Jan 9, 2016

Here's a suggestion for how we can represent this: permit a runtime to be nested under framework. When that exists it indicates that we should cross compile for that runtime. In that case we'll use the TFM:RID target (runtime graph) for both the compile items and the runtime items. The runtime listed under framework can have its own dependency section to represent packages dependencies specific for that runtime. Here's a sample of how that might be used:

EG:

"dependencies": {
    "NETStandard.Library": "1.0.0-rc2-23616"
},

"frameworks": {
  "dnxcore50": {
    "runtimes": {
      "win": {
        "compilationOptions": {
          "define": ["WIN"]
        },
        "dependencies": {
          "System.Security.Cryptography.Cng": "4.0.0",
          "System.Net.Http.WinHttpHandler": "4.0.0"
        }
      }
      "unix": {
        "compilationOptions": {
          "define": ["Unix"]
        },
        "dependencies": {
          "System.Security.Cryptography.OpenSsl": "4.0.0",
          "System.Net.Http.CurlHandler": "4.0.0"
        }
      }
    }
  }
}

@davidfowl @anurse: thoughts?

@andyleejordan
Copy link
Member

We are definitely going to need this for an internal project, sooner rather than later.

@davidfowl
Copy link
Member

I'll write something up with how this might work. We have a design in mind

@vors
Copy link

vors commented Jan 26, 2016

I (as a user) think it's a good design.

Also connected scenario: I want to be able to build my dependencies from sources, but at the same time, I want to be able to consume dependencies as packages from nuget. I would love to have it to provide an easier setup for people, who care only about a particular package in the project.

Looks like this feature will allow me to do it as well.

@davidfowl
Copy link
Member

Project file changes

Foo/project.json

{
    "version": "1.0.0-*",
    "frameworks": {
      "netstandard1.3": {
        "dependencies": {
          "System.Console": "4.1.0-rc2-3455"
        }
      },
      "netstandard1.3(win7)": {
        "dependencies": {
          "System.Security.Cryptography.Cng": "4.1.0-rc2-3455",
          "System.Net.Http.WinHttpHandler": "4.1.0-rc2-3455"
        }
      },
      "netstandard1.3(unix)": {
        "dependencies": {
          "System.Security.Cryptography.OpenSsl": "4.1.0-rc2-3455",
          "System.Net.Http.CurlHandler": "4.1.0-rc2-3455"
        }
      }
    }
}

We would infer defines for the RID.

public class Foo
{
    public void Method()
    {
       #if WIN7
          // Do something windows specific
       #elif UNIX && NET451
          // Do something mono specific
       #elif UNIX
         // Do something unix specific
       #endif
    } 
}

Lock file changes

{
    ...
    "targets": {
        "DNXCore,Version=v5.0": { },
        "DNXCore,Version=v5.0(win7)": { },
        "DNXCore,Version=v5.0(unix)": { },
        "DNXCore,Version=v5.0/win7-x86": { },
        "DNXCore,Version=v5.0/win7-x64": { }
    }
    ...
}

Notice the {tfm}({rid}) sections. These are new "compile time graphs".

dotnet/nuget pack changes

Foo.1.0.0.nupkg

    lib/
        netstandard1.3/
            Foo.dll
    runtimes/win7/lib/
        netstandard1.3/
            Foo.dll
    runtimes/unix/lib/
        netstandard1.3/
            Foo.dll
   Foo.nuspec

Foo.nuspec

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
  <metadata minClientVersion="3.4.0">
    <id>Foo</id>
    <version>1.0.0-beta-23504</version>
    <dependencies>
      <group targetFramework=".NETStandard1.3">
        <dependency id="System.Console" version="4.1.0-rc2-3455" />
      </group>
    </dependencies>
    <runtimeDependencies>
      <group targetFramework=".NETStandard1.3" targetRuntime="win7">
        <dependency id="System.Console" version="4.1.0-rc2-3455" />
        <dependency id="System.Security.Cryptography.Cng" version="4.1.0-rc2-3455" />
        <dependency id="System.Net.Http.WinHttpHandler" version="4.1.0-rc2-3455" />
      </group>
      <group targetFramework=".NETStandard1.3" targetRuntime="unix">
        <dependency id="System.Console" version="4.1.0-rc2-3455" />
        <dependency id="System.Security.Cryptography.OpenSsl" version="4.1.0-rc2-3455" />
        <dependency id="System.Net.Http.CurlHandler" version="4.1.0-rc2-3455" />
      </group>
    </runtimeDependencies>
  </metadata>
</package>

The sections DO NOT MERGE. During the runtime graph walk, one of the sections are chosen, just like the TFM graph walk today.

Potential additions

netstandard1.3(win7-x64, win8-x86)

This would be a shortcut for supporting multiple runtimes (if dependencies were shared).

@ericstj
Copy link
Member Author

ericstj commented Jan 26, 2016

What happens if a dependency like this only shows up in the runtime graph?
Since runtime.jsons are only honored if the appear in the compile graph wouldn't the RID specific dependencies be ignored?

Foo is a library that has a Unix and Win build. Unix build depends on Bar. Bar gets listed in Foo's runtime.json.
Bar is a library that has a Linux and OSX build. Linux build depends on Baz. Baz gets listed in Bar's runtime.json.

Foo is consumed by App that is not RID specific. The app's compile graph contains Foo so it gets Bar. The app's compile graph does not contain Bar, so it never gets Bar's runtime.json, and thus never gets Baz when deployed on Linux.

@davidfowl
Copy link
Member

@ericstj We decided to put something in the nuspec. Updated the spec to respect this.

@ericstj
Copy link
Member Author

ericstj commented Jan 27, 2016

LGTM. I'm guessing minClientVersion for this should be 3.4.0 or something.

So when consuming this package

  • compiling anywhere only uses the <group targetFramework=".NETStandard1.3"> section
  • running on win7-x86 it would use the <group targetFramework=".NETStandard1.3" targetRuntime="win7"> section
  • running on win-x86 it would use the <group targetFramework=".NETStandard1.3"> section
  • running on ubuntu.14.04-x64 it'd use the <group targetFramework=".NETStandard1.3" targetRuntime="unix"> section

@davidfowl
Copy link
Member

@ericstj
We need to roll back the change to System.Security.Principal.Windows (WindowsPrincipal) and potentially the System.Windows.Registry until we have this feature because right now we (ASP.NET) are broken. https://github.com/dotnet/corefx/issues/5694

@davidfowl
Copy link
Member

@ericstj That's correct.

@andyleejordan
Copy link
Member

I thought @anurse already had a spec for this.

Specifically this section.

@davidfowl
Copy link
Member

You can assume this supersedes that 😀

@analogrelay
Copy link
Contributor

@andschwa That is not technically related, that is for configuration of corehost. It is derived from this data, but it a different spec.

@ericstj ericstj assigned davidfowl and unassigned ericstj Jan 27, 2016
ericstj referenced this issue in ericstj/corefx Feb 3, 2016
We don't currently have a cross-platform API for folks to use to create
and RSA object https://github.com/dotnet/corefx/issues/2953, and dotnet
cli doesn't yet support folks cross compiling by platform
https://github.com/dotnet/cli/issues/465.

As a result, this package was failing to restore when dotnet CLI
switched to NuGet which will detect missing support at build
time instead of allowing a file-not-found at runtime.

Temporarily unblock installation of this package on Windows so that
folks can consume the package until we have an x-plat API.
@andyleejordan
Copy link
Member

@piotrpMSFT why won't this make it into RTM? It's still blocking us pretty badly. We have to use a LINUX configuration and preprocessor definitions to work-around this. It's ugly.

@baronfel
Copy link
Member

NuGet packages support RID-specific assets now. Closing this as a result.

@PathogenDavid
Copy link
Contributor

@baronfel This isn't about RID-specific assets, it's about RID-specific dependencies.

Unless I missed something in .NET 8, I don't think the latter is supported.

(That being said, maybe NuGet/Home#1660 or NuGet/Home#10571 is a better place to track this anyway?)

@baronfel
Copy link
Member

Ah, good call on both counts. NuGet will need to understand/define something structure for describing these, then probably the SDK's ResolvePackageAssets task will need updating to follow that structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants