Sdk: Project.json's "copyToOutput" isn't transitive

Created on 5 May 2016  路  15Comments  路  Source: dotnet/sdk

Steps to reproduce

Have ProjectA which defines a "copyToOutput" element within its "buildOptions" section in project.json. When compiled, the file or files in the "include" section will be copied to the output, along with ProjectA.dll.
ProjectA
project.json _("include": ["ProgramA.cs"] is just as an example)_

{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true,
    "copyToOutput": {
      "include": ["ProgramA.cs"]
    }
  },
  "dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.0.0-*"
    }
  },
  "frameworks": {
    "netcoreapp1.0": {
      "imports": "dnxcore50"
    }
  }
}

ProgramA.cs

``` C#
using System;
namespace ProjectA
{
public class ClassFromProjectA
{
public int Value { get; set; } = 3;
}
}

Now, have `ProjectB` which includes `ProjectA` as a reference. When compiled, it will produce `ProjectB.dll` as well as `ProjectA.dll` in the output directory.
**ProjectB**
project.json

{
"version": "1.0.0-",
"buildOptions": {
"emitEntryPoint": true
},
"dependencies": {
"ProjectA": "1.0.0-
",
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-*"
}
},
"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50"
}
}
}

ProgramB.cs

``` C#
using System;
using ProjectA;
namespace ProjectB
{
    public class ProgramB
    {
        public static void Main(string[] args)
        {
            var r = new ClassFromProjectA();
            Console.WriteLine($"Value from ProjectA {r.Value}");
        }
    }
}

Expected behavior

The files specified by the "copyToOutput" element of ProjectA show up in the output directory of ProjectB. Furthermore, I expect that the output directory for ProjectA also contains the files.

Actual behavior

The files included by the "copyToOutput" element of ProjectA will not be copied to the output of ProjectB, or the output directory of ProjectA. The files will only be copied to the output when the root compilation project is the one specifying the "copyToOutput" element, and it will only work on the files included by the root compilation project.

Environment data

dotnet --info output:
.NET Command Line Tools (1.0.0-rc2-002659)

Product Information:
Version: 1.0.0-rc2-002659
Commit Sha: 11a001706f

Runtime Environment:
OS Name: Windows
OS Version: 10.0.14295
OS Platform: Windows
RID: win10-x64

enhancement needs design

Most helpful comment

Yeah when will we expect a fix? Need it.

All 15 comments

@davidfowl @anurse @cdmihai @Sridhar-MS @brthor I think this is representative of a bigger design concern. copyToOutput is one example of how the output directory of a project might get mutated. scripts are another. I think that our policy should be to take the full output directory, less publish, and treat it as the set of assets that get copied to p2p references. What are your thoughts?

What does msbuild do?

With MSBuild, it depends on what the user targets implement. Each project type has its own deployment targets with particular deployment logic. MSBuild itself has no knowledge of project models.

Looking into Microsoft.Common.CurrentVersion.targets, I found this Publish target which only applies to ClickOnce apps. It appears to want to copy transitively but doesn't, judging from the comment: https://github.com/Microsoft/msbuild/blob/master/src/XMakeTasks/Microsoft.Common.CurrentVersion.targets#L3994-L4005

So, it depends. It's how the project type wants it to be

Hm, this bug is quite annoying. Most of MSBUILD project types I know are supporting "Content/CopyToOutput" transitively. It makes the copyToOutput currently in project.json completely useless as soon as you use project dependencies.

I created a related issue back in Jan https://github.com/dotnet/cli/issues/1090

@piotrpMSFT @davidfowl Could a fix be part of the RTM for this? This issue should be tagged as a bug, not an enhancement. Building an hybrid ASP.net Core/ConsoleApp and I'm stuck, only workaround is to manually duplicate the files from all my assembly dependencies, and put them as part of the assembly main entrypoint in order to work.

@xoofx I'm in a really similar situation. It's caused me to write cross-platform scripts around dotnet just to distribute files, when it should be able to pick them up automatically. :cry:

I encountered this after having content files (.js etc) in seperate projects and in seperate NuGet packages. Trying to get this content output to my main applications output directory was a pain because the copyToOutput is non transitive, and if the content is in a referenced NuGet package - then you are on your own. The solution I had to go for in the end was to embed all content into assemblies, and use EmbeddedFileProviders to access this content from my application. I hope though that this will be fixed in the future - every project type I have worked with so far works transitively with this setting.

I'm also struggling with this limitation. Milestone of this issue is set to 1.0.0-rtm that will be released on June 27 (according to the ASP.NET roadmap). However, this issue is still in the "open" state. So will this be part of the 1.0.0 release? If not, could you please provide an ETA?

Yeah when will we expect a fix? Need it.

@Joshscorp I think this might not be fixed since project.json will be superseded by a return to msbuild. See the section on msbuild-mitigated issues in the README. FWIW, my workaround is to add the static files I need copied as resources (see buildOptions.embed), then add a static constructor in my library project that simply reads the resource streams and spits out the files into the executing assembly directory. This behaves identically to a properly functioning transitive copyToOutput, at least for my use case.

Just hit the same issue :( :(

It looks like the return to the MSBuild approach will be available in VS2017, and only VS2017.

https://blogs.msdn.microsoft.com/dotnet/2016/11/16/announcing-net-core-tools-msbuild-alpha/

We are working to get the new .NET Core msbuild-based tools finished and at RTM quality as quickly as possible. They will be supported in Visual Studio 2017+ and will be shipped as RTM next year. The changes are significant, including to Visual Studio components, making it very challenging for us to support them in Visual Studio 2015.

As @masaeedu suggested, this issue will not be fixed. We have no further releases planned for project.json-based CLI.

Anyone know if this has been fixed with the msbuild tooling?

Was this page helpful?
0 / 5 - 0 ratings