diff --git a/runtime/launcher.m b/runtime/launcher.m index 39ffeb79d7..d5d4bd337e 100644 --- a/runtime/launcher.m +++ b/runtime/launcher.m @@ -311,6 +311,7 @@ update_environment (xamarin_initialize_data *data) // 3) Ensure the following environment variables are set: [...] NSString *res_dir = [data->app_dir stringByAppendingPathComponent: @"Contents/Resources"]; + NSString *monobundle_dir = [data->app_dir stringByAppendingPathComponent: @"Contents/MonoBundle"]; #ifdef DYNAMIC_MONO_RUNTIME NSString *bin_dir = [data->app_dir stringByAppendingPathComponent: @"Contents/MacOS"]; @@ -357,6 +358,8 @@ update_environment (xamarin_initialize_data *data) // So route through MONO_DEBUG setenv ("MONO_DEBUG", "no-gdb-backtrace", 0); } + + setenv ("MONO_CFG_DIR", [monobundle_dir UTF8String], 0); } static void diff --git a/src/AppKit/NSApplication.cs b/src/AppKit/NSApplication.cs index 98c34a3597..2eada1d5da 100644 --- a/src/AppKit/NSApplication.cs +++ b/src/AppKit/NSApplication.cs @@ -68,6 +68,10 @@ namespace XamCore.AppKit { // that don't call Main. NSApplication.mainThread = Thread.CurrentThread; + // Launcher sets this to work around https://bugzilla.xamarin.com/show_bug.cgi?id=45279 + // But can affect child xbuild processes, so unset + Environment.SetEnvironmentVariable ("MONO_CFG_DIR", ""); + // TODO: // Install hook to register dynamically loaded assemblies } diff --git a/tests/common/mac/MacTestMain.cs b/tests/common/mac/MacTestMain.cs index c141ae33b6..44d5e49aa4 100644 --- a/tests/common/mac/MacTestMain.cs +++ b/tests/common/mac/MacTestMain.cs @@ -23,11 +23,12 @@ namespace Xamarin.Mac.Tests static void RunTests() { TestRunner.MainLoop = new NSRunLoopIntegration(); - TestRunner.Main(new[] { - typeof(MainClass).Assembly.Location, - "-labels", - "-noheader" - }); + string testName = System.Environment.GetEnvironmentVariable ("XM_TEST_NAME"); + string [] args = testName != null ? + new [] { typeof(MainClass).Assembly.Location, "-labels", "-noheader", string.Format ("-test={0}", testName) } : + new [] { typeof(MainClass).Assembly.Location, "-labels", "-noheader" }; + + TestRunner.Main (args); } class NSRunLoopIntegration : NSObject, IMainLoopIntegration diff --git a/tests/common/mac/ProjectTestHelpers.cs b/tests/common/mac/ProjectTestHelpers.cs index e96a766e86..878d9c8041 100644 --- a/tests/common/mac/ProjectTestHelpers.cs +++ b/tests/common/mac/ProjectTestHelpers.cs @@ -85,9 +85,9 @@ namespace Xamarin.MMP.Tests int compileResult = Xamarin.Bundler.Driver.RunCommand (exe, args != null ? args.ToString() : string.Empty, MonoDevelopLike, output, suppressPrintOnErrors: shouldFail); Func getInfo = () => getAdditionalFailInfo != null ? getAdditionalFailInfo() : ""; if (!shouldFail) - Assert.AreEqual (0, compileResult, stepName + " failed: '" + output + "' " + exe + " " + args + getInfo ()); + Assert.AreEqual (0, compileResult, stepName + " failed:\n\n'" + output + "' " + exe + " " + args + getInfo ()); else - Assert.AreNotEqual (0, compileResult, stepName + " did not fail as expected: '" + output + "' " + exe + " " + args + getInfo ()); + Assert.AreNotEqual (0, compileResult, stepName + " did not fail as expected:\n\n'" + output + "' " + exe + " " + args + getInfo ()); return output.ToString (); } @@ -111,11 +111,17 @@ namespace Xamarin.MMP.Tests buildArgs.Append (csprojTarget); + Func getBuildProjectErrorInfo = () => { + string csprojText = "\n\n\n\tCSProj: \n" + File.ReadAllText (csprojTarget); + string csprojLocation = Path.GetDirectoryName (csprojTarget); + string fileList = "\n\n\tFiles: " + String.Join (" ", Directory.GetFiles (csprojLocation).Select (x => x.Replace (csprojLocation + "/", ""))); + return csprojText + fileList; + }; if (isUnified) - return RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/xbuild", buildArgs, "Compile", shouldFail, () => File.ReadAllText (csprojTarget)); + return RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/xbuild", buildArgs, "Compile", shouldFail, getBuildProjectErrorInfo); else - return RunAndAssert ("/Applications/Xamarin Studio.app/Contents/MacOS/mdtool", buildArgs, "Compile", shouldFail, () => File.ReadAllText (csprojTarget)); + return RunAndAssert ("/Applications/Xamarin Studio.app/Contents/MacOS/mdtool", buildArgs, "Compile", shouldFail, getBuildProjectErrorInfo); } static string ProjectTextReplacement (UnifiedTestConfig config, string text) diff --git a/tests/mmptest/src/MMPTest.cs b/tests/mmptest/src/MMPTest.cs index 2e3bb7ba31..aa85d7eb8f 100644 --- a/tests/mmptest/src/MMPTest.cs +++ b/tests/mmptest/src/MMPTest.cs @@ -16,6 +16,10 @@ namespace Xamarin.MMP.Tests { string tmpDir = Path.Combine (Path.GetTempPath (), "mmp-test-dir"); try { + // Clean out any existing build there first to prevent strange behavior + if (Directory.Exists (tmpDir)) + Directory.Delete (tmpDir, true); + Directory.CreateDirectory (tmpDir); test (tmpDir); } @@ -380,5 +384,86 @@ namespace Xamarin.MMP.Tests Assert.IsTrue (File.Exists (Path.Combine (tmpDir, "bin/Debug/XM45Example.app/Contents/MonoBundle/Mono.Posix.dll"))); Assert.IsTrue (File.Exists (Path.Combine (tmpDir, "bin/Debug/XM45Example.app/Contents/MonoBundle/libMonoPosixHelper.dylib"))); } -} + + + const string machineConfigMobileLocation = "bin/Debug/UnifiedExample.app/Contents/MonoBundle/mono/4.5/machine.config"; + const string machineConfigXM45Location = "bin/Debug/XM45Example.app/Contents/MonoBundle/mono/4.5/machine.config"; + + [Test] + public void Unified_ShouldNotGenerateMachineConfigInBundle_WithoutOption () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir); + // Mobile + TI.TestUnifiedExecutable (test); + + Assert.IsFalse (File.Exists (Path.Combine (tmpDir, machineConfigMobileLocation))); + + // XM45 + test.XM45 = true; + TI.TestUnifiedExecutable (test); + + Assert.IsFalse (File.Exists (Path.Combine (tmpDir, machineConfigXM45Location))); + }); + } + + [Test] + public void Unified_InvalidMachineConfigInBundle_ThrowsError () + { + RunMMPTest (tmpDir => { + string invalidConfigPath = Path.Combine (tmpDir, "nonexistant/machine.config"); + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { + CSProjConfig = string.Format ("--machine-config={0}", invalidConfigPath) + }; + string buildOutput = TI.TestUnifiedExecutable (test, shouldFail : true).BuildOutput; + Assert.IsTrue (buildOutput.Contains ("can not be found"), "Unified_InvalidMachineConfigInBundle_ThrowsError did not error as expected (1):\n\n", buildOutput); + Assert.IsTrue (buildOutput.Contains ("97"), "Unified_InvalidMachineConfigInBundle_ThrowsError did not error as expected (2):\n\n", buildOutput); + }); + } + + [Test] + public void Unified_ShouldGenerateMachineConfigInBundle_WithEmptyOption () + { + RunMMPTest (tmpDir => { + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { + CSProjConfig = "--machine-config=\"\"" + }; + TI.TestUnifiedExecutable (test); + Assert.IsTrue (File.Exists (Path.Combine (tmpDir, machineConfigMobileLocation))); + + test.XM45 = true; + TI.TestUnifiedExecutable (test); + Assert.IsTrue (File.Exists (Path.Combine (tmpDir, machineConfigXM45Location))); + }); + } + + [Test] + public void Unified_ShouldGenerateMachineConfigInBundle_WhenPassedIn () + { + RunMMPTest (tmpDir => { + const string configText = "THIS_IS_NOT_A_REAL_CONFIG_FILE"; + string configPath = Path.Combine (tmpDir, "machine.config"); + File.WriteAllLines (configPath, new string [] { configText }); + + TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) { + CSProjConfig = string.Format ("--machine-config={0}", configPath) + }; + + // Mobile + TI.TestUnifiedExecutable (test); + + Assert.IsTrue (File.Exists (Path.Combine (tmpDir, machineConfigMobileLocation))); + string [] text = File.ReadAllLines (Path.Combine (tmpDir, machineConfigMobileLocation)); + Assert.IsTrue (text.Length == 1 && text[0] == configText); + + // XM45 + test.XM45 = true; + TI.TestUnifiedExecutable (test); + + Assert.IsTrue (File.Exists (Path.Combine (tmpDir, machineConfigXM45Location))); + text = File.ReadAllLines (Path.Combine (tmpDir, machineConfigXM45Location)); + Assert.IsTrue (text.Length == 1 && text[0] == configText); + }); + } + } } diff --git a/tools/mmp/driver.cs b/tools/mmp/driver.cs index 960c013edb..ee69ce40ff 100644 --- a/tools/mmp/driver.cs +++ b/tools/mmp/driver.cs @@ -81,6 +81,7 @@ namespace Xamarin.Bundler { static string link_flags = null; static LinkerOptions linker_options; static bool disable_lldb_attach = false; + static string machine_config_path = null; static bool arch_set = false; static string arch = "i386"; @@ -287,7 +288,8 @@ namespace Xamarin.Bundler { { "http-message-handler=", "Specify the default HTTP Message Handler", v => { http_message_provider = v; }}, { "extension", "Specifies an app extension", v => is_extension = true }, { "allow-unsafe-gac-resolution", "Allow MSBuild to resolve from the System GAC", v => {} , true }, // Used in Xamarin.Mac.XM45.targets and must be ignored here. Hidden since it is a total hack. If you can use it, you don't need support - { "disable-lldb-attach=", "Disable automatic lldb attach on crash", v => disable_lldb_attach = ParseBool (v, "disable_lldb_attach")}, + { "disable-lldb-attach=", "Disable automatic lldb attach on crash", v => disable_lldb_attach = ParseBool (v, "disable-lldb-attach")}, + { "machine-config=", "Custom machine.config file to copy into MonoBundle/mono/4.5/machine.config. Pass \"\" to copy in a valid \"empty\" config file.", v => machine_config_path = v }, }; AddSharedOptions (os); @@ -1498,6 +1500,21 @@ namespace Xamarin.Bundler { CopyResourceFile ("config", "config"); } + + if (machine_config_path != null) { + string machineConfigDestDir = Path.Combine (mmp_dir, "mono/4.5/"); + string machineConfigDestFile = Path.Combine (machineConfigDestDir, "machine.config"); + + CreateDirectoryIfNeeded (machineConfigDestDir); + if (machine_config_path == String.Empty) { + File.WriteAllLines (machineConfigDestFile, new string [] { "", "", "" }); + } + else { + if (!File.Exists (machine_config_path)) + throw new MonoMacException (97, true, "machine.config file '{0}' can not be found.", machine_config_path); + File.Copy (machine_config_path, machineConfigDestFile); + } + } } static void CopyResourceFile (string streamName, string outputFileName) { diff --git a/tools/mmp/error.cs b/tools/mmp/error.cs index 4cce1d6eed..da5dea4b36 100644 --- a/tools/mmp/error.cs +++ b/tools/mmp/error.cs @@ -35,6 +35,7 @@ namespace Xamarin.Bundler { // Warning MT0080 Disabling NewRefCount, --new-refcount:false, is deprecated. // MM0088 ** Reserved mtouch ** // MM0089 ** Reserved mtouch ** + // MM0097 machine.config file '{0}' can not be found. // MM1xxx file copy / symlinks (project related) // MM14xx Product assemblies // MM1401 The required '{0}' assembly is missing from the references diff --git a/tools/mtouch/error.cs b/tools/mtouch/error.cs index ce9f1b53a2..ea330830bd 100644 --- a/tools/mtouch/error.cs +++ b/tools/mtouch/error.cs @@ -103,6 +103,7 @@ namespace Xamarin.Bundler { // Warning MT0094 Both profiling (--profiling) and incremental builds (--fastdev) are currently not supported when building for {0}, and incremental builds have been disabled (this will be fixed in a future release). // MT0095 Aot files could not be copied to the destination directory. // MT0096 No reference to Xamarin.iOS.dll was found. + // MT0097 // MT1xxx file copy / symlinks (project related) // MT10xx installer.cs / mtouch.cs // MT1001 Could not find an application at the specified directory: {0}