[macos] Fix target framework detection issues in mmp (#2096)
- Also detect mismatches between referenced XM.dll and target framework selected
This commit is contained in:
Родитель
a6cf8c5edc
Коммит
0be72f3c13
|
@ -92,6 +92,8 @@ The easiest way to get exact version information is to use the **Xamarin Studio*
|
|||
|
||||
<h3><a name="MM1406">MM1406: Target framework '{0}' is invalid when targetting Xamarin.Mac 4.5 .NET framwork.</h3>
|
||||
|
||||
<h3><a name="MM1407">MM1407: Mismatch between Xamarin.Mac reference '{0}' and target framework selected '{1}'.</h3>
|
||||
|
||||
## MM15xx: Assembly gathering (not requiring linker) errors
|
||||
|
||||
<h3><a name="MM1501">MM1501: Can not resolve reference: {0}</h3>
|
||||
|
|
|
@ -977,6 +977,8 @@ Things to try to solve this:
|
|||
* Reboot the Mac.
|
||||
* Synchronize the device with iTunes (this will remove any crash reports from the device).
|
||||
|
||||
<!--- 1407 used by mmp -->
|
||||
|
||||
### MT16xx: MachO
|
||||
|
||||
<!--
|
||||
|
|
|
@ -113,9 +113,11 @@ namespace Xamarin.Mac.Tasks
|
|||
args.AddQuoted ("/name:" + ApplicationName);
|
||||
|
||||
if (TargetFrameworkIdentifier == "Xamarin.Mac")
|
||||
args.Add ("/profile:Xamarin.Mac");
|
||||
else if (TargetFrameworkVersion.StartsWith ("v", StringComparison.Ordinal))
|
||||
args.Add ("/profile:" + TargetFrameworkVersion.Substring (1));
|
||||
args.Add ("/profile:Xamarin.Mac,Version=v2.0,Profile=Mobile");
|
||||
else if (UseXamMacFullFramework)
|
||||
args.Add ($"/profile:Xamarin.Mac,Version={TargetFrameworkVersion},Profile=Full");
|
||||
else
|
||||
args.Add ($"/profile:Xamarin.Mac,Version={TargetFrameworkVersion},Profile=System");
|
||||
|
||||
XamMacArch arch;
|
||||
if (!Enum.TryParse (Architecture, true, out arch))
|
||||
|
|
|
@ -85,11 +85,6 @@ namespace Xamarin.MMP.Tests
|
|||
}
|
||||
|
||||
public static string RunAndAssert (string exe, string args, string stepName, bool shouldFail = false, Func<string> getAdditionalFailInfo = null)
|
||||
{
|
||||
return RunAndAssert (exe, new StringBuilder (args), stepName, shouldFail, getAdditionalFailInfo);
|
||||
}
|
||||
|
||||
public static string RunAndAssert (string exe, StringBuilder args, string stepName, bool shouldFail = false, Func<string> getAdditionalFailInfo = null)
|
||||
{
|
||||
StringBuilder output = new StringBuilder ();
|
||||
Environment.SetEnvironmentVariable ("MONO_PATH", null);
|
||||
|
@ -103,6 +98,11 @@ namespace Xamarin.MMP.Tests
|
|||
return output.ToString ();
|
||||
}
|
||||
|
||||
public static string RunAndAssert (string exe, StringBuilder args, string stepName, bool shouldFail = false, Func<string> getAdditionalFailInfo = null)
|
||||
{
|
||||
return RunAndAssert (exe, args.ToString (), stepName, shouldFail, getAdditionalFailInfo);
|
||||
}
|
||||
|
||||
// In most cases we generate projects in tmp and this is not needed. But nuget and test projects can make that hard
|
||||
public static void CleanUnifiedProject (string csprojTarget, bool useMSBuild = false)
|
||||
{
|
||||
|
@ -156,14 +156,13 @@ namespace Xamarin.MMP.Tests
|
|||
{
|
||||
// Assert that the program actually runs and returns our guid
|
||||
Assert.IsTrue (File.Exists (path), string.Format ("{0} did not generate an exe?", path));
|
||||
string output = RunAndAssert (path, (StringBuilder)null, "Run");
|
||||
string output = RunAndAssert (path, (string)null, "Run");
|
||||
|
||||
string guidPath = Path.Combine (tmpDir, guid.ToString ());
|
||||
Assert.IsTrue(File.Exists (guidPath), "Generated program did not create expected guid file: " + output);
|
||||
|
||||
// Let's delete the guid file so re-runs inside same tests are accurate
|
||||
File.Delete (guidPath);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
<Link>unit\aot.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="src\FrameworkLinksTests.cs" />
|
||||
<Compile Include="src\TargetFrameworkDetectionTests.cs" />
|
||||
<Compile Include="src\LinkerTests.cs" />
|
||||
<Compile Include="src\Extensions.cs" />
|
||||
<Compile Include="..\mtouch\Cache.cs">
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Xamarin.MMP.Tests
|
|||
[TestFixture]
|
||||
public partial class MMPTests
|
||||
{
|
||||
void RunMMPTest (Action <string> test)
|
||||
public static void RunMMPTest (Action <string> test)
|
||||
{
|
||||
test (Cache.CreateTemporaryDirectory ());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Xamarin.Tests;
|
||||
using Xamarin.Utils;
|
||||
|
||||
namespace Xamarin.MMP.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TargetFrameworkDetectionTests
|
||||
{
|
||||
TargetFramework [] XMTargetFrameworks = { TargetFramework.Xamarin_Mac_2_0_Mobile, TargetFramework.Xamarin_Mac_4_5_Full, TargetFramework.Xamarin_Mac_4_5_System };
|
||||
|
||||
string CreateTestExe (string tmpDir)
|
||||
{
|
||||
string path = Path.Combine (tmpDir, "b.exe");
|
||||
File.WriteAllText (Path.Combine (tmpDir, "b.cs"), "public static class EntryPoint { public static void Main () {} }");
|
||||
TI.RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/mcs", string.Format ("-out:{0} {1}/b.cs", path, tmpDir), "CreateTestExe");
|
||||
return path;
|
||||
}
|
||||
|
||||
string GetTestMMPInvocation (string tmpDir, string libPath, TargetFramework targetFramework, bool correctReference = true)
|
||||
{
|
||||
string xmReference = correctReference ? GetXMReference (targetFramework) : GetWrongXMReference (targetFramework);
|
||||
return $"-v -v -v -v -v --output={tmpDir} --arch=x86_64 --sdkroot {Configuration.xcode_root} --minos 10.7 {libPath} --sdk 10.12 --nolink -p --profile:{targetFramework} -a:{xmReference}";
|
||||
}
|
||||
|
||||
string GetWrongXMReference (TargetFramework target)
|
||||
{
|
||||
if (target.Profile == "Mobile")
|
||||
return GetXMReference (TargetFramework.Xamarin_Mac_4_5_Full);
|
||||
else
|
||||
return GetXMReference (TargetFramework.Xamarin_Mac_2_0_Mobile);
|
||||
}
|
||||
|
||||
string GetXMReference (TargetFramework target)
|
||||
{
|
||||
switch (target.Profile) {
|
||||
case "Mobile":
|
||||
return $"-a:{Configuration.SdkRootXM}/lib/mono/Xamarin.Mac/Xamarin.Mac.dll";
|
||||
case "Full":
|
||||
case "System":
|
||||
return $"-a:{Configuration.SdkRootXM}/lib/mono/4.5/Xamarin.Mac.dll";
|
||||
default:
|
||||
throw new System.InvalidOperationException ();
|
||||
}
|
||||
}
|
||||
|
||||
string MMPPath => TI.FindRootDirectory () + "/Library/Frameworks/Xamarin.Mac.framework/Commands/mmp";
|
||||
|
||||
[Test]
|
||||
public void LongProfileStrings_SelectCorrectProfile ()
|
||||
{
|
||||
MMPTests.RunMMPTest (tmpDir => {
|
||||
foreach (var targetProfile in XMTargetFrameworks) {
|
||||
string libPath = CreateTestExe (tmpDir);
|
||||
string args = GetTestMMPInvocation (tmpDir, libPath, targetProfile);
|
||||
string mmpOutput = TI.RunAndAssert (MMPPath, args, "mmp invoke");
|
||||
|
||||
bool mobile = targetProfile.Profile == "Mobile";
|
||||
string referenceLine = mmpOutput.Split (Environment.NewLine.ToCharArray ()).First (x => x.StartsWith ("Added assembly ", StringComparison.Ordinal) && x.Contains ("Xamarin.Mac.dll"));
|
||||
|
||||
Assert.True (referenceLine.Contains ("mobile") == mobile, "Selected Reference Line Unexpected: {0} with {1}", referenceLine, targetProfile);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LongProfileStrings_ErrorsWhenWrongXMPassedToRightProfile ()
|
||||
{
|
||||
MMPTests.RunMMPTest (tmpDir => {
|
||||
foreach (var targetProfile in XMTargetFrameworks) {
|
||||
string libPath = CreateTestExe (tmpDir);
|
||||
string args = GetTestMMPInvocation (tmpDir, libPath, targetProfile, false);
|
||||
string buildResults = TI.RunAndAssert (MMPPath, args, "mmp invoke with wrong XM", shouldFail:true);
|
||||
Assert.IsTrue (buildResults.Contains ("1407"), "Did not contains 1407 error expected");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -48,7 +48,7 @@ namespace MonoTouchFixtures.ServiceModel {
|
|||
|
||||
TI.BuildProject (testFolder + "/ServiceModel_Test.csproj", true);
|
||||
|
||||
TI.RunAndAssert (testFolder + "/bin/Debug/ServiceModel_Test.app/Contents/MacOS/ServiceModel_Test", (StringBuilder)null, "Run");
|
||||
TI.RunAndAssert (testFolder + "/bin/Debug/ServiceModel_Test.app/Contents/MacOS/ServiceModel_Test", (string)null, "Run");
|
||||
Assert.True (File.Exists (testResults));
|
||||
|
||||
using (TextReader reader = File.OpenText (testResults)) {
|
||||
|
|
|
@ -182,11 +182,11 @@ $(MMP_DIRECTORIES):
|
|||
GENERATE_PART_REGISTRAR = $(Q_GEN) $(SYSTEM_MONO) --debug mmp.exe --xamarin-framework-directory=$(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR) -q --runregistrar:$(abspath $@) --sdkroot $(XCODE_DEVELOPER_ROOT) --sdk $(OSX_SDK_VERSION) $< --registrar:static
|
||||
|
||||
Xamarin.Mac.registrar.mobile.i386.m: $(TOP)/src/build/mac/mobile-32/Xamarin.Mac.dll $(LOCAL_MMP)
|
||||
$(GENERATE_PART_REGISTRAR) --target-framework Xamarin.Mac,v1.0 --arch=i386
|
||||
$(GENERATE_PART_REGISTRAR) --target-framework Xamarin.Mac,Version=v2.0,Profile=Mobile --arch=i386
|
||||
$(Q) touch Xamarin.Mac.registrar.mobile.i386.m Xamarin.Mac.registrar.mobile.i386.h
|
||||
|
||||
Xamarin.Mac.registrar.mobile.x86_64.m: $(TOP)/src/build/mac/mobile-64/Xamarin.Mac.dll $(LOCAL_MMP)
|
||||
$(GENERATE_PART_REGISTRAR) --target-framework Xamarin.Mac,v1.0 --arch=x86_64
|
||||
$(GENERATE_PART_REGISTRAR) --target-framework Xamarin.Mac,Version=v2.0,Profile=Mobile --arch=x86_64
|
||||
$(Q) touch Xamarin.Mac.registrar.mobile.x86_64.m Xamarin.Mac.registrar.mobile.x86_64.h
|
||||
|
||||
Xamarin.Mac.registrar.full.i386.m: $(TOP)/src/build/mac/full-32/Xamarin.Mac.dll $(LOCAL_MMP)
|
||||
|
|
|
@ -409,8 +409,17 @@ namespace Xamarin.Bundler {
|
|||
if (!targetFramework.HasValue)
|
||||
targetFramework = TargetFramework.Default;
|
||||
|
||||
if (TargetFramework.Identifier == TargetFramework.Xamarin_Mac_2_0.Identifier) {
|
||||
// At least once instance of a TargetFramework of Xamarin.Mac,v2.0,(null) was found already. Assume any v2.0 implies a desire for Modern.
|
||||
if (TargetFramework == TargetFramework.Xamarin_Mac_2_0_Mobile || TargetFramework.Version == TargetFramework.Xamarin_Mac_2_0_Mobile.Version) {
|
||||
IsUnifiedMobile = true;
|
||||
} else if (TargetFramework.Identifier == TargetFramework.Xamarin_Mac_4_5_Full.Identifier
|
||||
&& TargetFramework.Profile == TargetFramework.Xamarin_Mac_4_5_Full.Profile) {
|
||||
IsUnifiedFullXamMacFramework = true;
|
||||
TargetFramework = TargetFramework.Net_4_5;
|
||||
} else if (TargetFramework.Identifier == TargetFramework.Xamarin_Mac_4_5_System.Identifier
|
||||
&& TargetFramework.Profile == TargetFramework.Xamarin_Mac_4_5_System.Profile) {
|
||||
IsUnifiedFullSystemFramework = true;
|
||||
TargetFramework = TargetFramework.Net_4_5;
|
||||
} else if (!IsUnifiedFullXamMacFramework && !IsUnifiedFullSystemFramework) {
|
||||
// This is a total hack. Instead of passing in an argument, we walk the refernces looking for
|
||||
// the "right" Xamarin.Mac and assume you are doing something
|
||||
|
@ -472,6 +481,7 @@ namespace Xamarin.Bundler {
|
|||
if (IsUnified == IsClassic || (IsUnified && IsUnifiedCount != 1))
|
||||
throw new Exception ("IsClassic/IsUnified/IsUnifiedMobile/IsUnifiedFullSystemFramework/IsUnifiedFullXamMacFramework logic regression");
|
||||
|
||||
ValidateXamarinMacReference ();
|
||||
if (IsUnifiedFullSystemFramework || IsUnifiedFullXamMacFramework) {
|
||||
switch (App.LinkMode) {
|
||||
case LinkMode.None:
|
||||
|
@ -523,6 +533,23 @@ namespace Xamarin.Bundler {
|
|||
Log ("bundling complete");
|
||||
}
|
||||
|
||||
static void ValidateXamarinMacReference ()
|
||||
{
|
||||
// Many Xamarin.Mac references are technically valid, so whitelisting risks breaking working project
|
||||
// However, passing in Mobile / Xamarin.Mac folders and resolving full/4.5 or vice versa is
|
||||
// far from expected. So catch the common cases if we can
|
||||
string reference = references.FirstOrDefault (x => x.EndsWith ("Xamarin.Mac.dll"));
|
||||
if (reference != null) {
|
||||
bool valid = true;
|
||||
if (IsUnifiedMobile)
|
||||
valid = !reference.Contains ("full/") && !reference.Contains ("4.5/");
|
||||
else if (IsUnifiedFullXamMacFramework || IsUnifiedFullSystemFramework)
|
||||
valid = !reference.Contains ("mobile/") && !reference.Contains ("Xamarin.Mac/");
|
||||
if (!valid)
|
||||
throw ErrorHelper.CreateError (1407, "Mismatch between Xamarin.Mac reference '{0}' and target framework selected '{1}'.", reference, TargetFramework);
|
||||
}
|
||||
}
|
||||
|
||||
static void FixReferences (Func<string, bool> match, Func<string, string> fix)
|
||||
{
|
||||
var assembliesToFix = references.Where (x => match(x)).ToList ();
|
||||
|
@ -1363,7 +1390,7 @@ namespace Xamarin.Bundler {
|
|||
return ret;
|
||||
}
|
||||
|
||||
// check that we have a reference to XamMac.dll and not to MonoMac.dll. Check various DRM license checks
|
||||
// check that we have a reference to XamMac.dll and not to MonoMac.dll.
|
||||
static void CheckReferences ()
|
||||
{
|
||||
List<Exception> exceptions = new List<Exception> ();
|
||||
|
|
Загрузка…
Ссылка в новой задаче