[xabuild] Use a temp file for MSBuild config (#969)
Context: https://github.com/xamarin/xamarin-android/pull/954 Context: https://github.com/xamarin/xamarin-android/pull/964 Context: https://github.com/xamarin/xamarin-android/pull/967 The `Xamarin.Android.Build.Tests` unit tests run `xabuild.exe` in parallel, which causes all manner of "weirdness" as the multiple `xabuild.exe` process all attempt to overwrite the *same* config file used by the `MSBuildApp` class. Fix this by creating *unique* per-process config files, stored in `Path.GetTempFileName()`, and overriding the `$MSBUILD_EXE_PATH` environment variable to refer to the per-process config file -- which is what the [MSBuild Unit Tests use][msbuild-tests] to override the `msbuild.exe.config` file used at runtime -- allowing each `xabuild.exe` process to sanely provide separate config files without conflicting with each other. [msbuild-tests]: https://github.com/Microsoft/msbuild/blob/080ef97/src/Build.UnitTests/BuildEnvironmentHelper_Tests.cs#L47
This commit is contained in:
Родитель
14ad71b1bf
Коммит
9324d4dea0
|
@ -1,8 +1,10 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Build.Framework;
|
||||
using NUnit.Framework;
|
||||
|
@ -2078,6 +2080,26 @@ namespace UnnamedProject {
|
|||
StringAssert.Contains ($"warning XA4", builder.LastBuildOutput, "warning XA4212");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RunXABuildInParallel ()
|
||||
{
|
||||
var xabuild = new ProjectBuilder ("temp/RunXABuildInParallel").XABuildExe;
|
||||
var psi = new ProcessStartInfo (xabuild, "/version") {
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
UseShellExecute = false,
|
||||
};
|
||||
|
||||
Parallel.For (0, 10, i => {
|
||||
using (var p = Process.Start (psi)) {
|
||||
p.WaitForExit ();
|
||||
Assert.AreEqual (0, p.ExitCode);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,23 +11,32 @@ namespace Xamarin.Android.Build
|
|||
static int Main ()
|
||||
{
|
||||
var paths = new XABuildPaths ();
|
||||
if (!Directory.Exists (paths.XamarinAndroidBuildOutput)) {
|
||||
Console.WriteLine ($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Create a custom xabuild.exe.config
|
||||
CreateConfig (paths);
|
||||
|
||||
//Create link to .NETFramework and .NETPortable directory
|
||||
foreach (var dir in Directory.GetDirectories(paths.SystemProfiles)) {
|
||||
var name = Path.GetFileName(dir);
|
||||
if (!SymbolicLink.Create(Path.Combine(paths.FrameworksDirectory, name), dir)) {
|
||||
try {
|
||||
if (!Directory.Exists (paths.XamarinAndroidBuildOutput)) {
|
||||
Console.WriteLine ($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return MSBuildApp.Main ();
|
||||
//Create a custom xabuild.exe.config
|
||||
CreateConfig (paths);
|
||||
|
||||
//Create link to .NETFramework and .NETPortable directory
|
||||
foreach (var dir in Directory.GetDirectories (paths.SystemProfiles)) {
|
||||
var name = Path.GetFileName (dir);
|
||||
if (!SymbolicLink.Create (Path.Combine (paths.FrameworksDirectory, name), dir)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return MSBuildApp.Main ();
|
||||
} finally {
|
||||
//NOTE: these are temporary files
|
||||
foreach (var file in new [] { paths.MSBuildExeTempPath, paths.XABuildConfig }) {
|
||||
if (File.Exists (file)) {
|
||||
File.Delete (file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CreateConfig (XABuildPaths paths)
|
||||
|
@ -79,6 +88,8 @@ namespace Xamarin.Android.Build
|
|||
}
|
||||
|
||||
xml.Save (paths.XABuildConfig);
|
||||
|
||||
Environment.SetEnvironmentVariable ("MSBUILD_EXE_PATH", paths.MSBuildExeTempPath, EnvironmentVariableTarget.Process);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Xamarin.Android.Build
|
|||
public string XABuildDirectory { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to xabuild.exe.config, on Unix it seems to use MSBuild.dll.config instead
|
||||
/// Path to xabuild.exe's config file, this is now a temporary file based on MSBuildExeTempPath
|
||||
/// </summary>
|
||||
public string XABuildConfig { get; private set; }
|
||||
|
||||
|
@ -45,6 +45,11 @@ namespace Xamarin.Android.Build
|
|||
/// </summary>
|
||||
public string MSBuildBin { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Temporary file used for MSBUILD_EXE_PATH
|
||||
/// </summary>
|
||||
public string MSBuildExeTempPath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to MSBuild's App.config file
|
||||
/// </summary>
|
||||
|
@ -110,7 +115,6 @@ namespace Xamarin.Android.Build
|
|||
MSBuildConfig = Path.Combine (MSBuildBin, "MSBuild.exe.config");
|
||||
ProjectImportSearchPaths = new [] { MSBuildPath, "$(MSBuildProgramFiles32)\\MSBuild" };
|
||||
SystemProfiles = Path.Combine (programFiles, "Reference Assemblies", "Microsoft", "Framework");
|
||||
XABuildConfig = Path.Combine (XABuildDirectory, "xabuild.exe.config");
|
||||
SearchPathsOS = "windows";
|
||||
} else {
|
||||
string mono = IsMacOS ? "/Library/Frameworks/Mono.framework/Versions/Current/lib/mono" : "/usr/lib/mono";
|
||||
|
@ -120,7 +124,6 @@ namespace Xamarin.Android.Build
|
|||
MSBuildConfig = Path.Combine (MSBuildBin, "MSBuild.dll.config");
|
||||
ProjectImportSearchPaths = new [] { MSBuildPath, Path.Combine (mono, "xbuild"), Path.Combine (monoExternal, "xbuild") };
|
||||
SystemProfiles = Path.Combine (mono, "xbuild-frameworks");
|
||||
XABuildConfig = Path.Combine (XABuildDirectory, "MSBuild.dll.config");
|
||||
SearchPathsOS = IsMacOS ? "osx" : "unix";
|
||||
}
|
||||
|
||||
|
@ -129,6 +132,8 @@ namespace Xamarin.Android.Build
|
|||
MonoAndroidToolsDirectory = Path.Combine (prefix, "xbuild", "Xamarin", "Android");
|
||||
AndroidSdkDirectory = Path.Combine (userProfile, "android-toolchain", "sdk");
|
||||
AndroidNdkDirectory = Path.Combine (userProfile, "android-toolchain", "ndk");
|
||||
MSBuildExeTempPath = Path.GetTempFileName ();
|
||||
XABuildConfig = MSBuildExeTempPath + ".config";
|
||||
}
|
||||
|
||||
[DllImport ("libc")]
|
||||
|
|
Загрузка…
Ссылка в новой задаче