dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.7k stars 1.06k forks source link

.NET Core MSBuild should not generate an empty assembly when building a meta-package project #1021

Open daxian-dbw opened 7 years ago

daxian-dbw commented 7 years ago

I have a .NET Core meta-package project defined in project.json. It contains no code but just references to a few other sub-projects and some packages. This meta-package project exists for 2 purposes:

  1. A NuGet meta-package can be produced that references to the NuGet packages of those sub-projects.
  2. The top-level project can reference only to this meta-package project to chain the dependency to those sub-projects.

This works fine with project.json -- when building the meta-package project, all referenced sub-projects get built and the meta-package project itself doesn't produce anything. Now with .NET Core SDK 1.0, I'm migrating from project.json to .csproj via dotnet migrate, and I find the behavior has changed -- building the meta-package project still get the referenced sub-projects built, but itself starts to produce an empty assembly.

This causes an empty meta-package.dll to appear in the publish folder of the top-level project, and I cannot simply remove it with an after-build target because it's also recorded in the generated .deps.json file, which makes it part of the TPA (trusted platform assemblies). So simply removing the empty assembly will cause the application to crash at startup.

Note that I have set <IncludeBuildOutput>false</IncludeBuildOutput> in the meta-package project file. It does help to make the empty assembly not included in the NuGet package produced out of the meta-package project, but the empty assembly still gets produced, and that causes the empty assembly to be published and put in the deps.json file when building the top-level project.

The project.json file and the corresponding .csproj file are attached. It's part of the powershell core project, and you can see the whole project at https://github.com/PowerShell/PowerShell/tree/master/src. The Microsoft.PowerShell.SDK meta-package project is referenced by powershell-unix\project.json, powershell-win-core\project.json and powershell-win-full\project.json.

project.json.txt Microsoft.PowerShell.SDK.csproj.txt

/cc: @eerhardt

daxian-dbw commented 7 years ago

Quoted from an email from @eerhardt regarding this issue:

I spent some time investigating this scenario today. It looks like it currently isn’t possible with .NET Core 1.0 SDK that ships in VS 2017 RTM.

I tried doing this by setting <CopyBuildOutputToOutputDirectory>false</CopyBuildOutputToOutputDirectory> In the “metapackage” .csproj. But that leads to CSC compile errors.

So then in the referencing projects I added: <ProjectReference Include="..\metapackage \metapackage.csproj" ReferenceOutputAssembly="false" /> But then I hit a bug in the .NET Core SDK: #1020

eerhardt commented 7 years ago

I looked into the project.json support for this. We had checks when compiling the application, packing, creating the .deps.json, and publishing that if a project didn't have any source files, we just skipped the assembly for that project.

See

I'm not sure if we should add similar logic to MSBuild (check for source files), or have a single master switch that says "Don't care about the assembly for this project".

dasMulli commented 7 years ago

i'd be interested to see a "proper" nuget project type - no built assemblies, maybe even no target frameworks - just references, maybe content (> msbuild props/targets files)

dasMulli commented 7 years ago

^ That would also be extremely useful for packaging native assets. (since nuspec + nuget pack requires windows)

craigb commented 7 years ago

So is this an issue that belongs to dotnet/project-system?

eerhardt commented 7 years ago

@craigb - no this is the correct repo for this issue, IMO.

@livarcocc @nguerrera @dsplaisted - to take a look and triage

iSazonov commented 5 years ago

Can we get any progress in .Net Core 3.0?

eerhardt commented 5 years ago

Note, you can accomplish this in the project by setting the following properties:

    <NoBuild>true</NoBuild>
    <IncludeBuildOutput>false</IncludeBuildOutput>
    <IncludeSymbols>false</IncludeSymbols>

Then you can just run the Pack target on that project, which can be set to the default target at the top:

<Project Sdk="Microsoft.NET.Sdk" DefaultTargets="Pack">

Now when you call MSBuild on that project, it will pack the nuget package, but you won't get an empty assembly built or included in the package.

iSazonov commented 5 years ago

@eerhardt Thanks! I am not sure that <NoBuild>true</NoBuild> will works for us because we use the meta csproj to build dependences.

nguerrera commented 5 years ago

Maybe ReferenceOutputAssembly="false" on all project references to meta project? I think that will keep it out of .deps. But not sure if it will break getting the transitive refs through it.

iSazonov commented 5 years ago

I can not compile with ReferenceOutputAssembly="false" because this broke dependencies. Current structure: powershell-win-core.csproj -> Microsoft.PowerShell.SDK.csproj (meta project) - other csproj-s

Our goal is not to create a dll for Microsoft.PowerShell.SDK.csproj, but dependencies should work at the compilation stage like at Core 1.0 time. Is it possible?

nguerrera commented 5 years ago

I don't think it is possible. I think we probably would need to introduce a feature of some kind to support that.

iSazonov commented 5 years ago

@daxian-dbw Is still important for us to have the meta project since we moved on .Net Core 3.0 and could use other features to resolve dependencies and load assemblies?

TomEdwardsEnscape commented 1 year ago

When building with .Net 7, you can add these properties to your project to keep build output etc. out of your output and publish directories:

<GenerateDependencyFile>false</GenerateDependencyFile>

<CopyBuildOutputToOutputDirectory>false</CopyBuildOutputToOutputDirectory>
<CopyOutputSymbolsToOutputDirectory>false</CopyOutputSymbolsToOutputDirectory>
<CopyDocumentationFileToOutputDirectory>false</CopyDocumentationFileToOutputDirectory>

<CopyBuildOutputToPublishDirectory>false</CopyBuildOutputToPublishDirectory>
<CopyOutputSymbolsToPublishDirectory>false</CopyOutputSymbolsToPublishDirectory>

I found these properties in these files: