[mtouch] Copy third-party frameworks from extensions to the main app's Frameworks directory. Fixes #45800. (#1069)

The container app may not reference the same third-party frameworks as
extensions, which means that we must make sure the extension's frameworks are
also included in the app bundle.

So when building extensions save a list of all third-party frameworks, and
then read that list and include those frameworks when building the main app.

https://bugzilla.xamarin.com/show_bug.cgi?id=45800
This commit is contained in:
Rolf Bjarne Kvinge 2016-10-31 12:36:06 +01:00 коммит произвёл GitHub
Родитель 612f52bd80
Коммит 0b3ab9cc15
3 изменённых файлов: 113 добавлений и 0 удалений

Просмотреть файл

@ -1986,6 +1986,35 @@ class C {
}
}
[Test]
public void OnlyExtensionWithFramework ()
{
// if an extension references a framework, and the main app does not,
// the framework should still be copied to the main app's Framework directory.
using (var exttool = new MTouchTool ()) {
exttool.Profile = Profile.Unified;
exttool.CreateTemporaryCacheDirectory ();
exttool.Verbosity = 5;
exttool.Extension = true;
exttool.CreateTemporararyServiceExtension ();
exttool.Frameworks.Add (Path.Combine (Configuration.SourceRoot, "tests/test-libraries/.libs/ios/XTest.framework"));
exttool.AssertExecute (MTouchAction.BuildSim, "build extension");
using (var apptool = new MTouchTool ()) {
apptool.Profile = Profile.Unified;
apptool.CreateTemporaryCacheDirectory ();
apptool.Verbosity = exttool.Verbosity;
apptool.CreateTemporaryApp ();
apptool.AppExtensions.Add (exttool.AppPath);
apptool.AssertExecute (MTouchAction.BuildSim, "build app");
Assert.IsTrue (Directory.Exists (Path.Combine (apptool.AppPath, "Frameworks", "XTest.framework")), "framework exists");
Assert.IsFalse (Directory.Exists (Path.Combine (exttool.AppPath, "Frameworks")), "extension framework inexistence");
}
}
}
#region Helper functions
static string CompileUnifiedTestAppExecutable (string targetDirectory, string code = null, string extraArg = "")
{

Просмотреть файл

@ -73,6 +73,8 @@ namespace Xamarin
public MTouchRegistrar Registrar;
public I18N I18N;
public bool? Extension;
public List<string> AppExtensions = new List<string> ();
public List<string> Frameworks = new List<string> ();
#pragma warning restore 649
// These are a bit smarter
@ -118,6 +120,11 @@ namespace Xamarin
return Execute (BuildArguments (action));
}
public void AssertExecute (MTouchAction action, string message = null)
{
NUnit.Framework.Assert.AreEqual (0, Execute (action), message);
}
string BuildArguments (MTouchAction action)
{
var sb = new StringBuilder ();
@ -181,6 +188,12 @@ namespace Xamarin
if (Extension == true)
sb.Append (" --extension");
foreach (var appext in AppExtensions)
sb.Append (" --app-extension ").Append (MTouch.Quote (appext));
foreach (var framework in Frameworks)
sb.Append (" --framework ").Append (MTouch.Quote (framework));
if (Dlsym.HasValue)
sb.Append (" --dlsym:").Append (Dlsym.Value ? "true" : "false");
@ -408,6 +421,59 @@ namespace Xamarin
File.WriteAllText (Path.Combine (app, "Info.plist"), CreatePlist (profile, appName));
}
public void CreateTemporararyServiceExtension (string code = null)
{
var testDir = CreateTemporaryDirectory ();
var app = Path.Combine (testDir, "testApp.appex");
Directory.CreateDirectory (app);
if (code == null) {
code = @"using UserNotifications;
[Foundation.Register (""NotificationService"")]
public partial class NotificationService : UNNotificationServiceExtension
{
protected NotificationService (System.IntPtr handle) : base (handle) {}
}";
}
AppPath = app;
Executable = MTouch.CompileTestAppLibrary (testDir, code: code, profile: Profile);
File.WriteAllText (Path.Combine (app, "Info.plist"),
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">
<plist version=""1.0"">
<dict>
<key>CFBundleDisplayName</key>
<string>serviceextension</string>
<key>CFBundleName</key>
<string>serviceextension</string>
<key>CFBundleIdentifier</key>
<string>com.xamarin.testapp.serviceextension</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>10.0</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key>
<string>NotificationService</string>
</dict>
</dict>
</plist>
");
}
public void CreateTemporaryWatchKitExtension (string code = null)
{
var testDir = CreateTemporaryDirectory ();

Просмотреть файл

@ -1110,6 +1110,17 @@ namespace Xamarin.Bundler {
all_frameworks.Add (Path.Combine (Driver.ProductSdkDirectory, "Frameworks", "Mono.framework"));
}
foreach (var appex in Extensions) {
var f_path = Path.Combine (appex, "..", "frameworks.txt");
if (!File.Exists (f_path))
continue;
foreach (var fw in File.ReadAllLines (f_path)) {
Driver.Log (3, "Copying {0} to the app's Frameworks directory because it's used by the extension {1}", fw, Path.GetFileName (appex));
all_frameworks.Add (fw);
}
}
foreach (var fw in all_frameworks) {
if (!fw.EndsWith (".framework", StringComparison.Ordinal))
continue;
@ -1128,6 +1139,13 @@ namespace Xamarin.Bundler {
Xamarin.MachO.SelectArchitectures (Path.Combine (AppDirectory, "Frameworks", Path.GetFileName (fw), Path.GetFileNameWithoutExtension (fw)), AllArchitectures);
}
}
} else {
if (!IsWatchExtension) {
// In extensions we need to save a list of the frameworks we need so that the main app can get them.
var all_frameworks = Frameworks.Union (WeakFrameworks);
if (all_frameworks.Count () > 0)
Driver.WriteIfDifferent (Path.Combine (Path.GetDirectoryName (AppDirectory), "frameworks.txt"), string.Join ("\n", all_frameworks.ToArray ()));
}
}
if (IsSimulatorBuild || !IsDualBuild) {