-
由 Jason Malinowski 提交于
When we build VisualStudioSetup.csproj, we include a bunch of assemblies from other projects into the VSIX. This is done through ProjectReferences to the other projects that produce each binary. It turns out this worked via some more magic than we expected: when we had a ProjectReference, we typically had the following metadata: <ProjectReference Include="..\..\Compilers\Core\Portable\CodeAnalysis.csproj"> <Project>{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}</Project> <Name>CodeAnalysis</Name> <IncludeOutputGroupsInVSIX>BuiltProjectOutputGroup</IncludeOutputGroupsInVSIX> </ProjectReference> When the VSIX targets run, they would collect all the files that need to be put into the VSIX. When it would encounter this ProjectReference, it would actually try to include the output twice. One copy (call it Copy A) would come from the Binaries folder simply by virtue that the binary was a reference from the VisualStudioSetup project and must be copied local. The other copy (Copy B) was coming from the obj directory, because the VSIX targets see us specifying the BuiltProject- OutputGroup and that output group's items point to obj. (There is metadata that points to the Binaries folder but that is getting ignored by the VSIX targets.) The VSIX packaging task would realize we were adding two copies of a file, it'd arbitrarily pick the first one, which happened to be the one in the Binaries folder. This magic blows up in one very special case. If the project's binary happens to be also found in the GAC, the default behavior of MSBuild is to no longer count that binary as CopyLocal. Thus, when the VSIX tried to include a binary that was in the GAC (in this case, Microsoft.Build.Tasks.CodeAnalysis.dll), it'd decide it didn't need to copy it local at all. Thus Copy A in the earlier description didn't exist, and so the VSIX packager would fall back to using Copy B, the copy of the assembly from the obj folder. When we're doing a signed build, Copy A and Copy B are actually different -- one is signed, one isn't, and so a lack of Copy A being given to the VSIX packager meant that we'd end up including unsigned assemblies in our (supposedly) fully signed VSIX. The "fun" part is during non-signed builds Copy A is included, since the locally-built binary (with version 42.42.42.42) isn't in the GAC. Thus if you try to reproduce the strange MSBuild behavior on a regular build you don't see it and you don't understand why. There are two quick fixes: 1. Un-GAC Microsoft.Build.Tasks.CodeAnalysis on any machines that need to do a proper signed build. 2. Force the DLL to be copied local. We take this approach since it's best to not be subject to the whims of the GAC if we can be. Long term, we probably should fix the VSIX targets to never look in the obj folder. They found the obj folder by looking at the items from the BuiltProjectOutputGroup, but didn't look at the appropriate metadata that would have let it realize it should really copy from Binaries. This Copy A vs. Copy B fight happens with any VSIX project, and it'd be best to avoid that.
f3662578