Skip to content

Commit f52dddf

Browse files
[xabuild] MSBuild assemblies should not "Copy Local"
Mono 2018-04 (or 5.14.x) has some changes to MSBuild assemblies that cause the following failure when using `xabuild.exe`: Mono: The following assembly referenced from monodroid/external/xamarin-android/bin/Debug/bin/Microsoft.Build.Tasks.Core.dll could not be loaded: Assembly: System.Reflection.Metadata (assemblyref_index=7) Version: 1.3.0.0 Public Key: b03f5f7f11d50a3a Currently `xabuild.exe` is referencing various MSBuild assemblies that get copied into `bin/$(Configuration)/bin` and shipped in the OSS zip. This isn't exactly desirable, since we don't really want to ship these assemblies... These assemblies are OS-specific (as far as I can tell), I noticed that these assemblies coming from a zip built on macOS do not work on Windows. So instead, we can use `Private=False` item metadata on all MSBuild references and use custom assembly loading. By using the `AppDomain.AssemblyResolve` event, we can add some code to probe the MSBuild bin directory for assemblies. If not found, we can return `null` and let the runtime do its default behavior.
1 parent 2cae443 commit f52dddf

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

build-tools/scripts/MSBuildReferences.projitems

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,23 @@
77
<ItemGroup>
88
<Reference Include="Microsoft.Build">
99
<HintPath>$(MSBuildReferencePath)\Microsoft.Build.dll</HintPath>
10+
<Private>False</Private>
1011
</Reference>
1112
<Reference Include="Microsoft.Build.Engine">
1213
<HintPath>$(MSBuildReferencePath)\Microsoft.Build.Engine.dll</HintPath>
14+
<Private>False</Private>
1315
</Reference>
1416
<Reference Include="Microsoft.Build.Framework">
1517
<HintPath>$(MSBuildReferencePath)\Microsoft.Build.Framework.dll</HintPath>
18+
<Private>False</Private>
1619
</Reference>
1720
<Reference Include="Microsoft.Build.Tasks.Core">
1821
<HintPath>$(MSBuildReferencePath)\Microsoft.Build.Tasks.Core.dll</HintPath>
22+
<Private>False</Private>
1923
</Reference>
2024
<Reference Include="Microsoft.Build.Utilities.Core">
2125
<HintPath>$(MSBuildReferencePath)\Microsoft.Build.Utilities.Core.dll</HintPath>
26+
<Private>False</Private>
2227
</Reference>
2328
</ItemGroup>
2429
</Project>

tools/xabuild/XABuild.cs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,40 @@
1-
using Microsoft.Build.CommandLine;
2-
using System;
1+
using System;
32
using System.IO;
43
using System.Linq;
4+
using System.Reflection;
55
using System.Threading;
66
using System.Xml;
77

88
namespace Xamarin.Android.Build
99
{
1010
class XABuild
1111
{
12+
static readonly XABuildPaths paths;
13+
14+
static XABuild ()
15+
{
16+
paths = new XABuildPaths ();
17+
18+
//NOTE: we have to do this in a static ctor, because assemblies are getting loaded before Main()
19+
AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => {
20+
var name = new AssemblyName (e.Name);
21+
var path = Path.Combine (paths.MSBuildBin, name.Name + ".dll");
22+
if (File.Exists (path)) {
23+
Console.WriteLine ($"[xabuild] custom assembly resolution '{e.Name}' -> '{path}'");
24+
return Assembly.LoadFrom (path);
25+
}
26+
path = Path.Combine (paths.MSBuildBin, name.Name + ".exe");
27+
if (File.Exists (path)) {
28+
Console.WriteLine ($"[xabuild] custom assembly resolution '{e.Name}' -> '{path}'");
29+
return Assembly.LoadFrom (path);
30+
}
31+
return null; //Let the default runtime behavior occur
32+
};
33+
}
34+
1235
[MTAThread]
1336
static int Main ()
1437
{
15-
var paths = new XABuildPaths ();
1638
try {
1739
if (!Directory.Exists (paths.XamarinAndroidBuildOutput)) {
1840
Console.WriteLine ($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
@@ -45,7 +67,7 @@ static int Main ()
4567
}
4668
}
4769

48-
int exitCode = MSBuildApp.Main ();
70+
int exitCode = MSBuild.Run ();
4971
if (exitCode != 0) {
5072
Console.WriteLine ($"MSBuildApp.Main exited with {exitCode}, xabuild configuration is:");
5173

@@ -165,4 +187,14 @@ static void SetProperty (XmlNode toolsets, string name, string value)
165187
}
166188
}
167189
}
190+
191+
//HACK: While running under Mono, I had to put all MSBuild usage in a second static class.
192+
// Otherwise, I was not getting a chance to wire up AppDomain.Assembly resolve before MSBuild.dll was loaded...
193+
static class MSBuild
194+
{
195+
public static int Run ()
196+
{
197+
return Microsoft.Build.CommandLine.MSBuildApp.Main ();
198+
}
199+
}
168200
}

tools/xabuild/xabuild.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
<ItemGroup>
3838
<Reference Include="MSBuild">
3939
<HintPath>$(MSBuildReferencePath)\MSBuild.$(_MSBuildExtension)</HintPath>
40+
<Private>False</Private>
4041
</Reference>
4142
<Reference Include="System" />
4243
<Reference Include="System.Core" />

0 commit comments

Comments
 (0)