dotnet / msbuild

The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.
https://docs.microsoft.com/visualstudio/msbuild/msbuild
MIT License
5.2k stars 1.35k forks source link

msbuild doesn't copy c++ referenced content file into c# output dir #2823

Open levhaikin opened 6 years ago

levhaikin commented 6 years ago

Steps to reproduce

one solution including: one c# project one c++ project x64 solution configuration, including c++ as x64, and c# as Any Cpu (or x64 - doesn't matter) in the csproj file add:

<ProjectReference Include="..\cpplinux\cpplinux.vcxproj">
      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
      <OutputItemType>Content</OutputItemType>
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</ProjectReference>

Command line

msbuild solution.sln /m /t:rebuild /p:configuration=debug /p:platform=x64

Expected behavior

the native dll should be copied over to the output of the c# project

Actual behavior

the native dll is not copied over to the output of the c# project

Environment data

msbuild /version output: Microsoft (R) Build Engine version 15.3.409.57025 for .NET Framework Copyright (C) Microsoft Corporation. All rights reserved.

15.3.409.57025

OS info:

Windows 10, Visual Studio 2017

More info: In visual studio - this works fine. I have reduced my debugging to Microsoft.Common.CurrentVersion.targets, to where QUIRKING FOR DEV10 exists. Seems like adding GetTargetPath to the msbuild task that has the following comment - Build referenced projects when building from the command line. - makes it work. Also, setting DesignTimeBuild to true - solves this, but dependencies are not built in the correct order - so in the end this is not a solution.

levhaikin commented 6 years ago

I changed: Targets="%(_MSBuildProjectReferenceExistent.Targets)" to Targets="%(_MSBuildProjectReferenceExistent.Targets);GetTargetPath"

It seems that it solved it, without doing any other harm (at least nothing I noticed). Could that be the root cause?

levhaikin commented 6 years ago

adding GetTargetPath breaks other things, such as multithreaded build execution. Current solution, that do seem to work is to add: <Targets>Build;BuiltProjectOutputGroup</Targets> to the ProjectReference section.

Is that correct?

DoCode commented 6 years ago

What's going on here? Anybody available from the MSBuild team?

Here an overview:

Alexander-Bartosh commented 5 years ago

You can try this one, it worked for me both from command line and VS (msbuild 15.7.177.53362): ProjectReference in csproj:

    <ProjectReference Include="..\MyVcx\My.vcxproj">
      <Project>{ProjectGuid}</Project>
      <Name>projectname</Name>
    </ProjectReference>

In My.vcxproj: add

  <ItemGroup>
....
    <Content Include="$(TargetPath)" >
      <Link>%(Filename)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
...
  <!-- You can also add this for PDB -->
    <Content Include="$(TargetPath.Replace('.dll', '.pdb'))" >
      <Link>%(Filename)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
Alexei-B commented 5 years ago

@Alexander-Bartosh's solution of adding a <Content> element worked a treat for me.

jeremy-visionaid commented 1 month ago

@levhaikin I just hit this issue too, and came to the same conclusion and a solution as you did. Thanks for reporting it. Shame to see this still isn't fixed upstream!