Merge remote-tracking branch 'origin/master' into mono-2017-02

This commit is contained in:
Rolf Bjarne Kvinge 2017-03-24 17:58:05 +01:00
Родитель d48d0452e5 9f0fd32330
Коммит 26aa29ebd0
71 изменённых файлов: 5326 добавлений и 1334 удалений

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

@ -0,0 +1,111 @@
Code sharing with user frameworks
=================================
Xamarin.iOS can AOT-compile assemblies into:
* A static object (one static object per assembly).
* A dynamic library (one or more dynamic libraries per assembly).
This is used for incremental builds (in which case it's one dynamic library per assembly).
* A user framework (one or more assemblies per framework).
The last case is interesting, because user frameworks can be used to share
code between extensions and the main app.
Xamarin.iOS will automatically try to enable code sharing for all SDK
assemblies whenever it makes sense (for apps that have extensions), but if for
some reason Xamarin.iOS determines that code sharing can't be enabled (there
are many build options that makes code sharing impossible if they differ
between projects), a warning explaining why will be shown. Code sharing can be
forcefully disabled by passing `--nodevcodeshare` as an additional mtouch
argument (this option can also be used to silence any warnings if extensions
require build options that are incompatible with code sharing and would thus
produce warnings).
If Xamarin.iOS determines that code sharing can occur, then it builds one
framework for all the assemblies in the SDK, and this framework is shared
between extensions and the main app. This significantly reduces total code
size of the app (and the build time, since every assembly is only AOT-compiled
once per architecture).
Additionally, when code sharing is enabled, Xamarin.iOS will also AOT-compile
every assembly (not only SDK assemblies) only once (per architecture), which
greatly speeds up compilation time.
It's also possible to manually specify the assembly build target, by passing
--assembly-build-target to mtouch:
--assembly-build-target=assembly=staticobject|dynamiclibrary|framework[=name]
The assembly name is the name of the assembly without the extension. The
assembly name can also be two special values:
* @all: all assemblies (that aren't already handled by other --assembly-build-target options).
* @sdk: all assemblies in the Xamarin.iOS SDK.
`@sdk` takes precedence over `all`, and any other named assembly takes
precedence over these special values.
If `name` is not specified, then it defaults to the assembly name. `name` can
also be duplicated, which would compile multiple assemblies into a single
framework or dynamic library (but not static object).
Examples:
* --assembly-build-target=@all=dynamiclibrary
This will compile every assembly into a separate dynamic library.
* --assembly-build-target=@all=framework=MyFramework
This will compile all assemblies into one framework named `MyFramework`.
* --assembly-build-target=@sdk=framework=Xamarin.Sdk --assembly-build-target=@all=staticobject
This will compile the Xamarin.iOS SDK into a single framework called
`Xamarin.Sdk`, and all other assemblies into static objects.
* --assembly-build-target=MyAssembly1=framework=MyFramework --assembly-build-target=MyAssembly2=framework=MyFramework --assembly-build-target=@all=framework
This will compile `MyAssembly1.dll` and `MyAssembly2.dll` into a single
framework named `MyFramework`, and all other assemblies will be compiled
into distinct frameworks.
* --assembly-build-target=@sdk=Framework=Xamarin.Sdk --assembly-build-target=@all=dynamiclibrary
This will compile the Xamarin.iOS SDK into a single framework named
`Xamarin.Sdk`, and every other assembly into dynamic libraries (one dynamic
library per assembly).
Restrictions / limitations
--------------------------
* When compiling to static objects, every assembly must be compiled to a separate static object.
* Frameworks and dynamic libraries can't depend on static objects.
An assembly compiled to a framework can't reference an assembly compiled to a static object.
For example:
* --assembly-build-target=mscorlib=staticobject --assembly-build-target=@all=framework
This won't work, because every assembly depends on `mscorlib`, but
`mscorlib` is compiled to a static object.
* Apple will not accept apps with dynamic libraries in the App Store. When
building for release, build for either static object or framework.
* Apple recommends no more than 6 user frameworks in app, otherwise App
Startup Time will suffer (link)[1].
This means that compiling each assembly to a separate framework:
--assembly-build-target=@all=framework
is a bad idea, especially if your app has many assemblies.
* Code sharing between extensions and the main app requires that the main app
targets iOS 8.0 or later (this is because user frameworks was introduced in
iOS 8, and will not work in earlier versions of iOS).
[1]: https://developer.apple.com/videos/play/wwdc2016/406/

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

@ -367,10 +367,70 @@ A last-straw solution would be to use a different version of Xamarin.iOS, one th
<h3><a name="MT0096"/>MT0096: No reference to Xamarin.iOS.dll was found.</h3> <h3><a name="MT0096"/>MT0096: No reference to Xamarin.iOS.dll was found.</h3>
<h3><a name="MT0099"/>Internal error *. Please file a bug report with a test case (http://bugzilla.xamarin.com).</h3> <!-- MT0097: used by mmp -->
<h3><a name="MT0099"/>MT0099: Internal error *. Please file a bug report with a test case (http://bugzilla.xamarin.com).</h3>
This error message is reported when an internal consistency check in Xamarin.iOS fails.
This indicates a bug in Xamarin.iOS; please file a bug report at [http://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=iOS) with a test case. This indicates a bug in Xamarin.iOS; please file a bug report at [http://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=iOS) with a test case.
<h3><a name="MT0100"/>Invalid assembly build target: '*'. Please file a bug report with a test case (http://bugzilla.xamarin.com).</h3>
This error message is reported when an internal consistency check in Xamarin.iOS fails.
This is always a bug in Xamarin.iOS; please file a bug report at [http://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=iOS) with a test case.
<h3><a name="MT0101"/>The assembly '*' is specified multiple times in --assembly-build-target arguments.</h3>
The assembly mentioned in the error message is specified multiple times in --assembly-build-target arguments. Please make sure each assembly is only mentioned once.
<h3><a name="MT0102"/>The assemblies '*' and '*' have the same target name ('*'), but different targets ('*' and '*').</h3>
The assemblies mentioned in the error message have conflicting build targets.
For example:
--assembly-build-target:Assembly1.dll=framework=MyBinary --assembly-build-target:Assembly2.dll=dynamiclibrary=MyBinary
This example is trying to create both a dynamic library and a framework with the same make (`MyBinary`).
<h3><a name="MT0103"/>The static object '*' contains more than one assembly ('*'), but each static object must correspond with exactly one assembly.</h3>
The assemblies mentioned in the error message are all compiled to a single static object. This is not allowed, every assembly must be compiled to a different static object.
For example:
--assembly-build-target:Assembly1.dll=staticobject=MyBinary --assembly-build-target:Assembly2.dll=staticobject=MyBinary
This example tries to build a static object (`MyBinary`) comprised of two assemblies (`Assembly1.dll` and `Assembly2.dll`), which is not allowed.
<h3><a name="MT0105"/>MT0105: No assembly build target was specified for '*'.</h3>
When specifying the assembly build target using --assembly-build-target, every assembly in the app must have a build target assigned.
This error is reported when the assembly mentioned in the error message does not have an assembly build target assigned.
See the documentation about --assembly-build-target for further information.
<h3><a name="MT0106"/>MT0106: The assembly build target name '*' is invalid: the character '*' is not allowed.</h3>
The assembly build target name must be a valid filename.
For example these values will trigger this error:
--assembly-build-target:Assembly1.dll=staticobject=my/path.o
because `my/path.o` is not a valid filename due to the directory separator character.
<h3><a name="MT0108"/>MT0108: The assembly build target '*' did not match any assemblies.</h3>
<h3><a name="MT0109"/>MT0109: The assembly '{0}' was loaded from a different path than the provided path (provided path: {1}, actual path: {2}).</h3>
This is a warning indicating that an assembly referenced by the application was loaded from a different location than requested.
This might mean that the app is referencing multiple assemblies with the same name, but from different locations, which might lead to unexpected results (only the first assembly will be used).
<h3><a name="MT0110"/>MT0110: Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include third-party binding libraries and that compiles to bitcode.</h3> <h3><a name="MT0110"/>MT0110: Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include third-party binding libraries and that compiles to bitcode.</h3>
Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include third-party binding libraries and that compiles to bitcode (tvOS and watchOS projects). Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include third-party binding libraries and that compiles to bitcode (tvOS and watchOS projects).
@ -387,6 +447,81 @@ No action is required on your part, this message is purely informational.
For further information see bug #[51634](https://bugzilla.xamarin.com/show_bug.cgi?id=51634). For further information see bug #[51634](https://bugzilla.xamarin.com/show_bug.cgi?id=51634).
<h3><a name="MT0112"/>MT0112: Native code sharing has been disabled because *</h3>
There are multiple reasons code sharing can be disabled:
* because the container app's deployment target is earlier than iOS 8.0 (it's *)).
Native code sharing requires iOS 8.0 because native code sharing is implemented using user frameworks, which was introduced with iOS 8.0.
* because the container app includes I18N assemblies (*).
Native code sharing is currently not supported if the container app includes I18N assemblies.
* because the container app has custom xml definitions for the managed linker (*).
Native code sharing requires is not supported for projects that use custom xml definitions for the managed linker.
<h3><a name="MT0113"/>MT0113: Native code sharing has been disabled for the extension '*' because *.</h3>
* because the bitcode options differ between the container app (*) and the extension (*).
Native code sharing requires that the bitcode options match between the projects that share code.
* because the --assembly-build-target options are different between the container app (*) and the extension (*).
Native code sharing requires that the --assembly-build-target options are identical between the projects that share code.
This condition can occur if incremental builds are not either enabled or disabled in all the projects.
* because the I18N assemblies are different between the container app (*) and the extension (*).
Native code sharing is currently not supported for extensions that include I18N assemblies.
* because the arguments to the AOT compiler are different between the container app (*) and the extension (*).
Native code sharing requires that the arguments to the AOT compiler do not differ between projects that share code.
* because the other arguments to the AOT compiler are different between the container app (*) and the extension (*).
Native code sharing requires that the arguments to the AOT compiler do not differ between projects that share code.
This condition occurs if the 'Perform all 32-bit float operations as 64-bit float' differs between projects.
+ because LLVM is not enabled or disabled in both the container app (*) and the extension (*).
Native code sharing requires that LLVM is either enabled or disabled for all projects that share code.
* because the managed linker settings are different between the container app (*) and the extension (*).
Native code sharing requires that the managed linker settings are identical for all projects that share code.
* because the skipped assemblies for the managed linker are different between the container app (*) and the extension (*).
Native code sharing requires that the managed linker settings are identical for all projects that share code.
* because the extension has custom xml definitions for the managed linker (*).
Native code sharing requires is not supported for projects that use custom xml definitions for the managed linker.
* because the container app does not build for the ABI * (while the extension is building for this ABI).
Native code sharing requires that the container app builds for all the architectures any app extension builds for.
For instance: this condition occurs when an extension builds for ARM64+ARMv7, but the container app only builds for ARM64.
* because the container app is building for the ABI *, which is not compatible with the extension's ABI (*).
Native code sharing requires that all the projects build for the exact same API.
For instance: this condition occurs when an extension builds for ARMv7+llvm+thumb2, but the container app only builds for ARMv7+llvm.
* because the container app is referencing the assembly '*' from '*', while the extension references it from '*'.
Native code sharing requires that all the projects that share code use the same versions for all assemblies.
<h3><a name="MT0127"/>MT0127: Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include more than one third-party binding libraries.</h3> <h3><a name="MT0127"/>MT0127: Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include more than one third-party binding libraries.</h3>
Incremental builds have been disabled automatically because this version of Xamarin.iOS does not always build projects with multiple third-party binding libraries correctly. Incremental builds have been disabled automatically because this version of Xamarin.iOS does not always build projects with multiple third-party binding libraries correctly.
@ -926,6 +1061,14 @@ To fix this warning, open the project file in a text editor, and remove all `Mto
This means there is an error on the [custom XML linker configuration file](https://developer.xamarin.com/guides/cross-platform/advanced/custom_linking/) you provided, please review your file. This means there is an error on the [custom XML linker configuration file](https://developer.xamarin.com/guides/cross-platform/advanced/custom_linking/) you provided, please review your file.
<h3><a name="MT2018"/>MT2018: The assembly '*' is referenced from two different locations: '*' and '*'.</h3>
The assembly mentioned in the error message is loaded from multiple locations. Make sure to always use the same version of an assembly.
<h3><a name="MT2019"/>MT2019: Can not load the root assembly '*'</h3>
The root assembly could not be loaded. Please verify that the path in the error message refers to an existing file, and that it's a valid .NET assembly.
<h3><a name="MT202x"/>MT202x: Binding Optimizer failed processing `...`.</h3> <h3><a name="MT202x"/>MT202x: Binding Optimizer failed processing `...`.</h3>
Something unexpected occured when trying to optimize generated binding code. The element causing the issue is named in the error message. In order to fix this issue the assembly named (or containing the type or method named) will need to be provided in a [bug report](http://bugzilla.xamarin.com) along with a complete build log with verbosity enabled (i.e. `-v -v -v -v` in the **Additional mtouch arguments**). Something unexpected occured when trying to optimize generated binding code. The element causing the issue is named in the error message. In order to fix this issue the assembly named (or containing the type or method named) will need to be provided in a [bug report](http://bugzilla.xamarin.com) along with a complete build log with verbosity enabled (i.e. `-v -v -v -v` in the **Additional mtouch arguments**).
@ -1297,6 +1440,11 @@ This usually indicates a bug in Xamarin.iOS; please file a bug at [http://bugzil
<h3><a name="MT5104"/>MT5104 Could not find neither the '*' nor the '*' compiler. Please install Xcode 'Command-Line Tools' component</h3> <h3><a name="MT5104"/>MT5104 Could not find neither the '*' nor the '*' compiler. Please install Xcode 'Command-Line Tools' component</h3>
<h3><a name="MT5106"/>MT5106: Could not compile the file(s) '*'. Please file a bug report at http://bugzilla.xamarin.com</h3>
This usually indicates a bug in Xamarin.iOS; please file a bug at [http://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=iOS).
### MT52xx: Linking ### MT52xx: Linking
<!-- <!--
@ -1446,6 +1594,12 @@ There are a few possible solutions:
This is a warning, indicating that a P/Invoke was detected to reference the library in question, but the app is not linking with it. This is a warning, indicating that a P/Invoke was detected to reference the library in question, but the app is not linking with it.
<h3><a name="MT5216"/>MT5216: Native linking failed for *. Please file a bug report at http://bugzilla.xamarin.com</h3>
This error is reported when linking the output from the AOT compiler.
This error most likely indicates a bug in Xamarin.iOS. Please file a bug report at [http://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=iOS).
### MT53xx: Other tools ### MT53xx: Other tools
<!-- <!--

2
external/Touch.Unit поставляемый

@ -1 +1 @@
Subproject commit 71c2c44f926e8f6bcf37c8f5823ed7e841aabc59 Subproject commit 16c5eddc9ed6906a21037c5a4501ba104faba948

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

@ -53,6 +53,8 @@
<CodesignKey>iPhone Developer</CodesignKey> <CodesignKey>iPhone Developer</CodesignKey>
<MtouchUseSGen>true</MtouchUseSGen> <MtouchUseSGen>true</MtouchUseSGen>
<MtouchUseRefCounting>true</MtouchUseRefCounting> <MtouchUseRefCounting>true</MtouchUseRefCounting>
<MtouchFastDev>true</MtouchFastDev>
<MtouchFloat32>true</MtouchFloat32>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
<DebugType>full</DebugType> <DebugType>full</DebugType>
@ -65,6 +67,9 @@
<CodesignKey>iPhone Developer</CodesignKey> <CodesignKey>iPhone Developer</CodesignKey>
<MtouchUseSGen>true</MtouchUseSGen> <MtouchUseSGen>true</MtouchUseSGen>
<MtouchUseRefCounting>true</MtouchUseRefCounting> <MtouchUseRefCounting>true</MtouchUseRefCounting>
<MtouchFloat32>true</MtouchFloat32>
<MtouchUseLlvm>true</MtouchUseLlvm>
<MtouchEnableBitcode>true</MtouchEnableBitcode>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />

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

@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010 # Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyTVApp", "MyTVApp.csproj", "{7BF755AC-EADC-4353-A0CC-4F3AB61681FF}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyTVApp", "MyTVApp.csproj", "{7BF755AC-EADC-4353-A0CC-4F3AB61681FF}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyTVServicesExtension", "..\MyTVServicesExtension\MyTVServicesExtension.csproj", "{0F124570-8B79-4593-B618-A90E51F339DF}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|iPhoneSimulator = Debug|iPhoneSimulator Debug|iPhoneSimulator = Debug|iPhoneSimulator
@ -19,6 +21,14 @@ Global
{7BF755AC-EADC-4353-A0CC-4F3AB61681FF}.Release|iPhone.Build.0 = Release|iPhone {7BF755AC-EADC-4353-A0CC-4F3AB61681FF}.Release|iPhone.Build.0 = Release|iPhone
{7BF755AC-EADC-4353-A0CC-4F3AB61681FF}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator {7BF755AC-EADC-4353-A0CC-4F3AB61681FF}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{7BF755AC-EADC-4353-A0CC-4F3AB61681FF}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator {7BF755AC-EADC-4353-A0CC-4F3AB61681FF}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{0F124570-8B79-4593-B618-A90E51F339DF}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{0F124570-8B79-4593-B618-A90E51F339DF}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{0F124570-8B79-4593-B618-A90E51F339DF}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{0F124570-8B79-4593-B618-A90E51F339DF}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{0F124570-8B79-4593-B618-A90E51F339DF}.Debug|iPhone.ActiveCfg = Debug|iPhone
{0F124570-8B79-4593-B618-A90E51F339DF}.Debug|iPhone.Build.0 = Debug|iPhone
{0F124570-8B79-4593-B618-A90E51F339DF}.Release|iPhone.ActiveCfg = Release|iPhone
{0F124570-8B79-4593-B618-A90E51F339DF}.Release|iPhone.Build.0 = Release|iPhone
EndGlobalSection EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = MyTVApp.csproj StartupItem = MyTVApp.csproj

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

@ -9,6 +9,8 @@
<RootNamespace>MyTVServicesExtension</RootNamespace> <RootNamespace>MyTVServicesExtension</RootNamespace>
<AssemblyName>MyTVServicesExtension</AssemblyName> <AssemblyName>MyTVServicesExtension</AssemblyName>
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix> <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>

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

@ -4,6 +4,7 @@ using TVServices;
namespace MyTVServicesExtension namespace MyTVServicesExtension
{ {
[Register ("ServiceProvider")]
public class ServiceProvider : NSObject, ITVTopShelfProvider public class ServiceProvider : NSObject, ITVTopShelfProvider
{ {
protected ServiceProvider (IntPtr handle) : base (handle) protected ServiceProvider (IntPtr handle) : base (handle)
@ -13,12 +14,16 @@ namespace MyTVServicesExtension
public TVContentItem [] TopShelfItems { public TVContentItem [] TopShelfItems {
[Export ("topShelfItems")] [Export ("topShelfItems")]
get; get {
return new TVContentItem [] { new TVContentItem (new TVContentIdentifier ("identifier", null)) { Title = "title" } };
}
} }
public TVTopShelfContentStyle TopShelfStyle { public TVTopShelfContentStyle TopShelfStyle {
[Export ("topShelfStyle")] [Export ("topShelfStyle")]
get; get {
return TVTopShelfContentStyle.Inset;
}
} }
} }
} }

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

@ -1,5 +1,6 @@
using System.IO; using System.IO;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
namespace Xamarin.iOS.Tasks namespace Xamarin.iOS.Tasks
@ -57,15 +58,21 @@ namespace Xamarin.iOS.Tasks
TestFilesExists (AppBundlePath, ExpectedAppFiles); TestFilesExists (AppBundlePath, ExpectedAppFiles);
TestFilesDoNotExist (AppBundlePath, UnexpectedAppFiles); TestFilesDoNotExist (AppBundlePath, UnexpectedAppFiles);
var coreFiles = GetCoreAppFiles (platform, config, hostAppName + ".exe", hostAppName); string [] coreFiles;
if (IsTVOS) { var basedirs = new List<string> ();
TestFilesExists (platform == "iPhone" ? Path.Combine (AppBundlePath, ".monotouch-64") : AppBundlePath, coreFiles); if (IsWatchOS) {
} else if (IsWatchOS) { basedirs.Add (extensionPath);
coreFiles = GetCoreAppFiles (platform, config, extensionName + ".dll", Path.GetFileNameWithoutExtension (extensionPath)); coreFiles = GetCoreAppFiles (platform, config, extensionName + ".dll", Path.GetFileNameWithoutExtension (extensionPath));
TestFilesExists (platform == "iPhone" ? Path.Combine (extensionPath, ".monotouch-32") : extensionPath, coreFiles);
} else { } else {
TestFilesExists (platform == "iPhone" ? Path.Combine (AppBundlePath, ".monotouch-32") : AppBundlePath, coreFiles); basedirs.Add (AppBundlePath);
if (platform == "iPhone") {
basedirs.Add (Path.Combine (AppBundlePath, ".monotouch-32"));
basedirs.Add (Path.Combine (AppBundlePath, "Frameworks", "Xamarin.Sdk.framework", "MonoBundle"));
basedirs.Add (Path.Combine (AppBundlePath, "Frameworks", "Xamarin.Sdk.framework", "MonoBundle", ".monotouch-32"));
} }
coreFiles = GetCoreAppFiles (platform, config, hostAppName + ".exe", hostAppName);
}
TestFilesExists (basedirs.ToArray (), coreFiles);
if (additionalAsserts != null) if (additionalAsserts != null)
additionalAsserts (mtouchPaths); additionalAsserts (mtouchPaths);

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

@ -79,26 +79,8 @@ namespace Xamarin.iOS.Tasks
TestFilesDoNotExist (AppBundlePath, UnexpectedAppFiles); TestFilesDoNotExist (AppBundlePath, UnexpectedAppFiles);
var coreFiles = GetCoreAppFiles (platform, config, appName + ".exe", appName); var coreFiles = GetCoreAppFiles (platform, config, appName + ".exe", appName);
if (IsTVOS) { var baseDirs = new string [] { Path.Combine (AppBundlePath, ".monotouch-32"), Path.Combine (AppBundlePath, ".monotouch-64"), AppBundlePath };
TestFilesExists (platform == "iPhone" ? Path.Combine (AppBundlePath, ".monotouch-64") : AppBundlePath, coreFiles); TestFilesExists (baseDirs, coreFiles);
} else {
bool exists = false;
var baseDir = Path.Combine (AppBundlePath, ".monotouch-32");
if (Directory.Exists (baseDir)) {
TestFilesExists (baseDir, coreFiles);
exists = true;
}
baseDir = Path.Combine (AppBundlePath, ".monotouch-64");
if (Directory.Exists (baseDir)) {
TestFilesExists (baseDir, coreFiles);
exists = true;
}
if (!exists)
TestFilesExists (AppBundlePath, coreFiles);
}
if (platform == "iPhone") { if (platform == "iPhone") {
var dSYMInfoPlist = Path.Combine (AppBundlePath + ".dSYM", "Contents", "Info.plist"); var dSYMInfoPlist = Path.Combine (AppBundlePath + ".dSYM", "Contents", "Info.plist");

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

@ -55,9 +55,6 @@ namespace Xamarin.iOS.Tasks
if (config == "Debug") if (config == "Debug")
coreFiles.Add (Path.ChangeExtension (managedExe, ".pdb")); coreFiles.Add (Path.ChangeExtension (managedExe, ".pdb"));
if (platform == "iPhone")
coreFiles.Add (Path.Combine ("..", nativeExe));
else
coreFiles.Add (nativeExe); coreFiles.Add (nativeExe);
return coreFiles.ToArray (); return coreFiles.ToArray ();
@ -217,6 +214,17 @@ namespace Xamarin.iOS.Tasks
Assert.IsTrue (File.Exists (v) || Directory.Exists (v), "Expected file: {0} does not exist", v); Assert.IsTrue (File.Exists (v) || Directory.Exists (v), "Expected file: {0} does not exist", v);
} }
public void TestFilesExists (string [] baseDirs, string [] files)
{
if (baseDirs.Length == 1) {
TestFilesExists (baseDirs [0], files);
} else {
foreach (var file in files)
Assert.IsTrue (baseDirs.Select (s => File.Exists (Path.Combine (s, file))).Any (v => v), $"Expected file: {file} does not exist in any of the directories: {string.Join (", ", baseDirs)}");
}
}
public void TestStoryboardC (string path) public void TestStoryboardC (string path)
{ {
Assert.IsTrue (Directory.Exists (path), "Storyboard {0} does not exist", path); Assert.IsTrue (Directory.Exists (path), "Storyboard {0} does not exist", path);

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

@ -75,6 +75,10 @@ MONOTOUCH_LIBS = \
libxamarin.dylib \ libxamarin.dylib \
libxamarin-debug.dylib \ libxamarin-debug.dylib \
MONOTOUCH_FRAMEWORKS = \
Xamarin \
Xamarin-debug \
MONOTOUCH_SOURCE_STEMS = $(patsubst %.s,%,$(patsubst %.m,%,$(SHARED_SOURCES) $(MONOTOUCH_SOURCES))) zlib-helper MONOTOUCH_SOURCE_STEMS = $(patsubst %.s,%,$(patsubst %.m,%,$(SHARED_SOURCES) $(MONOTOUCH_SOURCES))) zlib-helper
MONOTOUCH_I386_SOURCE_STEMS = $(patsubst %.s,%,$(patsubst %.m,%,$(SHARED_I386_SOURCES))) MONOTOUCH_I386_SOURCE_STEMS = $(patsubst %.s,%,$(patsubst %.m,%,$(SHARED_I386_SOURCES)))
MONOTOUCH_X86_64_SOURCE_STEMS = $(patsubst %.s,%,$(patsubst %.m,%,$(SHARED_X86_64_SOURCES))) MONOTOUCH_X86_64_SOURCE_STEMS = $(patsubst %.s,%,$(patsubst %.m,%,$(SHARED_X86_64_SOURCES)))
@ -96,19 +100,28 @@ $(2)_DEVICE_ARCHITECTURES = $(3)
endif endif
$(2)_SIM_ARCHITECTURES = $(4) $(2)_SIM_ARCHITECTURES = $(4)
$(2)_ARCHITECTURES = $$($(2)_DEVICE_ARCHITECTURES) $$($(2)_SIM_ARCHITECTURES) $(2)_ARCHITECTURES = $$($(2)_DEVICE_ARCHITECTURES) $$($(2)_SIM_ARCHITECTURES)
$(2)_FRAMEWORKS = $(MONOTOUCH_FRAMEWORKS)
RUNTIME_$(2)_TARGETS_DIRS += \ RUNTIME_$(2)_TARGETS_DIRS += \
$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/Frameworks/Xamarin.framework \
$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/Frameworks/Xamarin-debug.framework \
$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib \ $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib \
$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/include/xamarin \ $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/include/xamarin \
$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/Frameworks/Xamarin.framework \
$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/Frameworks/Xamarin-debug.framework \
$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/lib \ $(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/lib \
$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/include/xamarin \ $(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/include/xamarin \
RUNTIME_$(2)_TARGETS += \ RUNTIME_$(2)_TARGETS += \
$$(foreach file,$$($(2)_FRAMEWORKS),$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/Frameworks/$$(file).framework/$$(file)) \
$$(foreach file,$$($(2)_FRAMEWORKS),$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/Frameworks/$$(file).framework/Info.plist) \
$$(foreach file,$$($(2)_LIBRARIES),$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib/$$(file)) \ $$(foreach file,$$($(2)_LIBRARIES),$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib/$$(file)) \
$(foreach file,$(SHIPPED_HEADERS),$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/include/$(file)) \ $(foreach file,$(SHIPPED_HEADERS),$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/include/$(file)) \
ifdef INCLUDE_DEVICE ifdef INCLUDE_DEVICE
RUNTIME_$(2)_TARGETS += \ RUNTIME_$(2)_TARGETS += \
$$(foreach file,$$($(2)_FRAMEWORKS),$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/Frameworks/$$(file).framework/$$(file)) \
$$(foreach file,$$($(2)_FRAMEWORKS),$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/Frameworks/$$(file).framework/Info.plist) \
$$(foreach file,$$($(2)_LIBRARIES),$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/lib/$$(file)) \ $$(foreach file,$$($(2)_LIBRARIES),$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/lib/$$(file)) \
$(foreach file,$(SHIPPED_HEADERS),$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/include/$(file)) \ $(foreach file,$(SHIPPED_HEADERS),$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/include/$(file)) \
@ -117,9 +130,39 @@ endif
$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib/%.a: .libs/$(1)/%.a | $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib/%.a: .libs/$(1)/%.a | $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib
$(Q) install -m 0644 $$< $$@ $(Q) install -m 0644 $$< $$@
$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/Frameworks/Xamarin.framework/Xamarin: .libs/$(1)/libxamarin-sim.dylib | $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/Frameworks/Xamarin.framework
$(Q) cp $$< $$@.tmp
$(Q) install_name_tool -id @rpath/$$(notdir $$@).framework/$$(notdir $$@) $$@.tmp
$(Q) install_name_tool -change @rpath/libmonosgen-2.0.dylib @rpath/Mono.framework/Mono $$@.tmp
$(Q) mv $$@.tmp $$@
$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/Frameworks/Xamarin-debug.framework/Xamarin-debug: .libs/$(1)/libxamarin-debug-sim.dylib | $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/Frameworks/Xamarin-debug.framework
$(Q) cp $$< $$@.tmp
$(Q) install_name_tool -id @rpath/$$(notdir $$@).framework/$$(notdir $$@) $$@.tmp
$(Q) install_name_tool -change @rpath/libmonosgen-2.0.dylib @rpath/Mono.framework/Mono $$@.tmp
$(Q) mv $$@.tmp $$@
$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/Frameworks/%.framework/Info.plist: Xamarin.framework-$(1).Info.plist | $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/Frameworks/Xamarin.framework
$(Q) sed 's/@BUNDLE_EXECUTABLE@/$$*/' $$< > $$@
ifdef INCLUDE_DEVICE ifdef INCLUDE_DEVICE
$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/lib/%.a: .libs/$(1)/%.a | $(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/lib $(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/lib/%.a: .libs/$(1)/%.a | $(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/usr/lib
$(Q) install -m 0644 $$< $$@ $(Q) install -m 0644 $$< $$@
$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/Frameworks/Xamarin.framework/Xamarin: .libs/$(1)/libxamarin-dev.dylib | $(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/Frameworks/Xamarin.framework
$(Q) cp $$< $$@.tmp
$(Q) install_name_tool -id @rpath/$$(notdir $$@).framework/$$(notdir $$@) $$@.tmp
$(Q) install_name_tool -change @rpath/libmonosgen-2.0.dylib @rpath/Mono.framework/Mono $$@.tmp
$(Q) mv $$@.tmp $$@
$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/Frameworks/Xamarin-debug.framework/Xamarin-debug: .libs/$(1)/libxamarin-debug-dev.dylib | $(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/Frameworks/Xamarin-debug.framework
$(Q) cp $$< $$@.tmp
$(Q) install_name_tool -id @rpath/$$(notdir $$@).framework/$$(notdir $$@) $$@.tmp
$(Q) install_name_tool -change @rpath/libmonosgen-2.0.dylib @rpath/Mono.framework/Mono $$@.tmp
$(Q) mv $$@.tmp $$@
$(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/Frameworks/%.framework/Info.plist: Xamarin.framework-$(1).Info.plist | $(IOS_DESTDIR)$$(XAMARIN_$(6)OS_SDK)/Frameworks/Xamarin.framework
$(Q) sed 's/@BUNDLE_EXECUTABLE@/$$*/' $$< > $$@
endif endif
$(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib/%.dylib: .libs/$(1)/%-sim.dylib | $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib/%.dylib: .libs/$(1)/%-sim.dylib | $(IOS_DESTDIR)$$(XAMARIN_$(5)SIMULATOR_SDK)/usr/lib

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

@ -0,0 +1,57 @@
<?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>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleIdentifier</key>
<string>xamarin.ios.xamarin-framework</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Xamarin</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>3.12</string>
<key>NSPrincipalClass</key>
<string></string>
<key>CFBundleExecutable</key>
<string>@BUNDLE_EXECUTABLE@</string>
<key>BuildMachineOSBuild</key>
<string>13F34</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>
</array>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>12D508</string>
<key>DTPlatformName</key>
<string>iphoneos</string>
<key>DTPlatformVersion</key>
<string>8.2</string>
<key>DTSDKBuild</key>
<string>12D508</string>
<key>DTSDKName</key>
<string>iphoneos8.2</string>
<key>DTXcode</key>
<string>0620</string>
<key>DTXcodeBuild</key>
<string>6C131e</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
</dict>
</plist>

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

@ -0,0 +1,56 @@
<?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>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleIdentifier</key>
<string>xamarin.ios.xamarin-framework</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Xamarin</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>3.12</string>
<key>NSPrincipalClass</key>
<string></string>
<key>CFBundleExecutable</key>
<string>@BUNDLE_EXECUTABLE@</string>
<key>BuildMachineOSBuild</key>
<string>13F34</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>AppleTVOS</string>
</array>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>12D508</string>
<key>DTPlatformName</key>
<string>appletvos</string>
<key>DTPlatformVersion</key>
<string>9.0</string>
<key>DTSDKBuild</key>
<string>12D508</string>
<key>DTSDKName</key>
<string>appletvos9.0</string>
<key>DTXcode</key>
<string>0620</string>
<key>DTXcodeBuild</key>
<string>6C131e</string>
<key>MinimumOSVersion</key>
<string>9.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>3</integer>
</array>
</dict>
</plist>

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

@ -0,0 +1,56 @@
<?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>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleIdentifier</key>
<string>xamarin.ios.xamarin-framework</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Xamarin</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>3.12</string>
<key>NSPrincipalClass</key>
<string></string>
<key>CFBundleExecutable</key>
<string>@BUNDLE_EXECUTABLE@</string>
<key>BuildMachineOSBuild</key>
<string>13F34</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>WatchOS</string>
</array>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>12D508</string>
<key>DTPlatformName</key>
<string>watchos</string>
<key>DTPlatformVersion</key>
<string>2.0</string>
<key>DTSDKBuild</key>
<string>12D508</string>
<key>DTSDKName</key>
<string>watchos2.2</string>
<key>DTXcode</key>
<string>0620</string>
<key>DTXcodeBuild</key>
<string>6C131e</string>
<key>MinimumOSVersion</key>
<string>2.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>4</integer>
</array>
</dict>
</plist>

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

@ -34,35 +34,39 @@ xamarin_load_aot_data (MonoAssembly *assembly, int size, gpointer user_data, voi
// COOP: This is a callback called by the AOT runtime, I believe we don't have to change the GC mode here (even though it accesses managed memory). // COOP: This is a callback called by the AOT runtime, I believe we don't have to change the GC mode here (even though it accesses managed memory).
*out_handle = NULL; *out_handle = NULL;
const char *name = mono_assembly_name_get_name (mono_assembly_get_name (assembly)); char path [1024];
char *path; char name [1024];
const char *pattern; MonoAssemblyName *assembly_name = mono_assembly_get_name (assembly);
const char *aname = mono_assembly_name_get_name (assembly_name);
xamarin_get_assembly_name_without_extension (aname, name, sizeof (name));
if (xamarin_use_new_assemblies) { // LOG (PRODUCT ": Looking for aot data for assembly '%s'.", name);
pattern = "%s/" ARCH_SUBDIR "/%s.%s.aotdata";
} else { strlcat (name, ".aotdata", sizeof (name));
pattern = "%s/%s.%s.aotdata";
bool found = xamarin_locate_assembly_resource_for_name (assembly_name, name, path, sizeof (path));
if (!found) {
LOG (PRODUCT ": Could not find the aot data for %s.\n", aname)
return NULL;
} }
path = xamarin_strdup_printf (pattern, [[[NSBundle mainBundle] bundlePath] UTF8String], name, xamarin_arch_name);
int fd = open (path, O_RDONLY); int fd = open (path, O_RDONLY);
if (fd < 0) { if (fd < 0) {
LOG (PRODUCT ": Could not load the aot data for %s from %s: %s\n", name, path, strerror (errno)); LOG (PRODUCT ": Could not load the aot data for %s from %s: %s\n", aname, path, strerror (errno));
xamarin_free (path);
return NULL; return NULL;
} }
xamarin_free (path);
void *ptr = mmap (NULL, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); void *ptr = mmap (NULL, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
if (ptr == MAP_FAILED) { if (ptr == MAP_FAILED) {
LOG (PRODUCT ": Could not map the aot file for %s: %s\n", name, strerror (errno)); LOG (PRODUCT ": Could not map the aot file for %s: %s\n", aname, strerror (errno));
close (fd); close (fd);
return NULL; return NULL;
} }
close (fd); close (fd);
//LOG (PRODUCT ": Loaded aot data for %s successfully.\n", name); //LOG (PRODUCT ": Loaded aot data for %s.\n", name);
*out_handle = ptr; *out_handle = ptr;
@ -79,7 +83,7 @@ xamarin_free_aot_data (MonoAssembly *assembly, int size, gpointer user_data, voi
/* /*
This hook avoids the gazillion of filesystem probes we do as part of assembly loading. This hook avoids the gazillion of filesystem probes we do as part of assembly loading.
*/ */
MonoAssembly* static MonoAssembly*
assembly_preload_hook (MonoAssemblyName *aname, char **assemblies_path, void* user_data) assembly_preload_hook (MonoAssemblyName *aname, char **assemblies_path, void* user_data)
{ {
// COOP: This is a callback called by the AOT runtime, I belive we don't have to change the GC mode here. // COOP: This is a callback called by the AOT runtime, I belive we don't have to change the GC mode here.
@ -87,6 +91,9 @@ assembly_preload_hook (MonoAssemblyName *aname, char **assemblies_path, void* us
char path [1024]; char path [1024];
const char *name = mono_assembly_name_get_name (aname); const char *name = mono_assembly_name_get_name (aname);
const char *culture = mono_assembly_name_get_culture (aname); const char *culture = mono_assembly_name_get_culture (aname);
// LOG (PRODUCT ": Looking for assembly '%s' (culture: '%s')\n", name, culture);
int len = strlen (name); int len = strlen (name);
int has_extension = len > 3 && name [len - 4] == '.' && (!strcmp ("exe", name + (len - 3)) || !strcmp ("dll", name + (len - 3))); int has_extension = len > 3 && name [len - 4] == '.' && (!strcmp ("exe", name + (len - 3)) || !strcmp ("dll", name + (len - 3)));
bool dual_check = false; bool dual_check = false;
@ -113,33 +120,21 @@ assembly_preload_hook (MonoAssemblyName *aname, char **assemblies_path, void* us
if (culture == NULL) if (culture == NULL)
culture = ""; culture = "";
do_second_check: bool found = xamarin_locate_assembly_resource_for_name (aname, filename, path, sizeof (path));
if (xamarin_use_new_assemblies) { if (!found && dual_check) {
snprintf (path, sizeof (path), "%s/" ARCH_SUBDIR "/%s/%s", xamarin_get_bundle_path (), culture, filename);
if (xamarin_file_exists (path)) {
// fprintf (stderr, "MonoTouch: loading %s\n", path);
return mono_assembly_open (path, NULL);
}
}
snprintf (path, sizeof (path), "%s/%s/%s", xamarin_get_bundle_path (), culture, filename);
if (xamarin_file_exists (path)) {
// fprintf (stderr, "MonoTouch: loading %s\n", path);
return mono_assembly_open (path, NULL);
}
if (dual_check) {
dual_check = false;
filename [strlen (filename) - 4] = 0; filename [strlen (filename) - 4] = 0;
strlcat (filename, ".exe", sizeof (filename)); strlcat (filename, ".exe", sizeof (filename));
goto do_second_check; found = xamarin_locate_assembly_resource_for_name (aname, filename, path, sizeof (path));
} }
//fprintf (stderr, "MonoTouch: unable to find %s\n", name); if (!found) {
LOG (PRODUCT ": Unable to locate assembly '%s' (culture: '%s')\n", name, culture);
return NULL; return NULL;
}
// LOG (PRODUCT ": Found assembly '%s' (culture: '%s'): %s\n", name, culture, path);
return mono_assembly_open (path, NULL);
} }
#ifdef DEBUG_LAUNCH_TIME #ifdef DEBUG_LAUNCH_TIME

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

@ -139,6 +139,7 @@ struct InitializationOptions {
struct MTRegistrationMap* RegistrationData; struct MTRegistrationMap* RegistrationData;
enum MarshalObjectiveCExceptionMode MarshalObjectiveCExceptionMode; enum MarshalObjectiveCExceptionMode MarshalObjectiveCExceptionMode;
enum MarshalManagedExceptionMode MarshalManagedExceptionMode; enum MarshalManagedExceptionMode MarshalManagedExceptionMode;
struct AssemblyLocations* AssemblyLocations;
}; };
static struct Trampolines trampolines = { static struct Trampolines trampolines = {
@ -806,23 +807,13 @@ xamarin_open_assembly (const char *name)
} }
#endif #endif
if (xamarin_use_new_assemblies) { exists = xamarin_locate_assembly_resource (name, NULL, name, path, sizeof (path));
snprintf (path, sizeof (path), "%s/" ARCH_SUBDIR "/%s", xamarin_get_bundle_path (), name);
exists = xamarin_file_exists (path);
}
if (!exists)
snprintf (path, sizeof (path), "%s/%s", xamarin_get_bundle_path (), name);
#if MONOMAC && DYLIB #if MONOMAC && DYLIB
if (!xamarin_file_exists (path)) { if (!exists) {
// Check if we already have the assembly in memory // Check if we already have the assembly in memory
char path2 [1024]; xamarin_get_assembly_name_without_extension (name, path, sizeof (path));
snprintf (path2, sizeof (path2), "%s", name); MonoAssemblyName *aname = mono_assembly_name_new (path);
// strip off the extension
char *dot = strrchr (path2, '.');
if (strncmp (dot, ".dll", 4) == 0)
*dot = 0;
MonoAssemblyName *aname = mono_assembly_name_new (path2);
assembly = mono_assembly_loaded (aname); assembly = mono_assembly_loaded (aname);
mono_assembly_name_free (aname); mono_assembly_name_free (aname);
if (assembly) if (assembly)
@ -832,7 +823,7 @@ xamarin_open_assembly (const char *name)
} }
#endif #endif
if (!xamarin_file_exists (path)) if (!exists)
xamarin_assertion_message ("Could not find the assembly '%s' in the app. This is usually fixed by cleaning and rebuilding your project; if that doesn't work, please file a bug report: http://bugzilla.xamarin.com", name); xamarin_assertion_message ("Could not find the assembly '%s' in the app. This is usually fixed by cleaning and rebuilding your project; if that doesn't work, please file a bug report: http://bugzilla.xamarin.com", name);
assembly = mono_assembly_open (path, NULL); assembly = mono_assembly_open (path, NULL);
@ -2198,6 +2189,178 @@ xamarin_vprintf (const char *format, va_list args)
[message release]; [message release];
} }
/*
* File/resource lookup for assemblies
*
* Assemblies can be found in several locations:
* 1. If the assembly is compiled to a framework, in the framework's MonoBundle directory.
* For extensions the framework may be in the containing app's Frameworks directory.
* If an extension is sharing code with the main app, then the assemblies whose build target isn't 'framework' will be located in the container app's root directory.
* A framework may contain multiple assemblies, so it's not possible to deduce the framework name from the assembly name.
* 2. If the assembly is not a framework, in the app's root directory.
*
* The platform assembly (Xamarin.[iOS|TVOS|WatchOS].dll) and any assemblies
* the platform assembly references (mscorlib.dll, System.dll) may be in a
* pointer-size subdirectory (ARCH_SUBDIR).
*
* AOT data files will have an arch-specific infix.
*/
void
xamarin_get_assembly_name_without_extension (const char *aname, char *name, int namelen)
{
int len = strlen (aname);
strlcpy (name, aname, namelen);
if (namelen <= 4 || len <= 4)
return;
const char *ext = name + (len - 4);
if (!strncmp (".exe", ext, 4) || !strncmp (".dll", ext, 4))
name [len - 4] = 0; // strip off any extensions.
}
static bool
xamarin_locate_assembly_resource_for_root (const char *root, const char *culture, const char *resource, char *path, int pathlen)
{
if (culture != NULL && *culture != 0) {
// culture-specific directory
if (snprintf (path, pathlen, "%s/%s/%s", root, culture, resource) < 0) {
LOG (PRODUCT ": Failed to construct path for assembly resource (root directory: '%s', culture: '%s', resource: '%s'): %s", root, culture, resource, strerror (errno));
return false;
} else if (xamarin_file_exists (path)) {
return true;
}
}
// arch-specific extension
if (snprintf (path, pathlen, "%s/%s.%s", root, resource, xamarin_arch_name) < 0) {
LOG (PRODUCT ": Failed to construct path for resource: %s (4): %s", resource, strerror (errno));
return false;
} else if (xamarin_file_exists (path)) {
return true;
}
#if !MONOMAC
// pointer-size subdirectory with arch-specific extension
if (snprintf (path, pathlen, "%s/%s/%s.%s", root, ARCH_SUBDIR, resource, xamarin_arch_name) < 0) {
LOG (PRODUCT ": Failed to construct path for resource: %s (5): %s", resource, strerror (errno));
return false;
} else if (xamarin_file_exists (path)) {
return true;
}
// pointer-size subdirectory
if (snprintf (path, pathlen, "%s/%s/%s", root, ARCH_SUBDIR, resource) < 0) {
LOG (PRODUCT ": Failed to construct path for resource: %s (5): %s", resource, strerror (errno));
return false;
} else if (xamarin_file_exists (path)) {
return true;
}
#endif // !MONOMAC
// just the file, no extensions, etc.
if (snprintf (path, pathlen, "%s/%s", root, resource) < 0) {
LOG (PRODUCT ": Failed to construct path for resource: %s (6): %s", resource, strerror (errno));
return false;
} else if (xamarin_file_exists (path)) {
return true;
}
return false;
}
bool
xamarin_locate_assembly_resource_for_name (MonoAssemblyName *assembly_name, const char *resource, char *path, int pathlen)
{
const char *culture = mono_assembly_name_get_culture (assembly_name);
const char *aname = mono_assembly_name_get_name (assembly_name);
return xamarin_locate_assembly_resource (aname, culture, resource, path, pathlen);
}
// #define LOG_RESOURCELOOKUP(...) do { NSLog (@ __VA_ARGS__); } while (0);
#define LOG_RESOURCELOOKUP(...)
bool
xamarin_locate_assembly_resource (const char *assembly_name, const char *culture, const char *resource, char *path, int pathlen)
{
char root [1024];
char aname [256];
const char *app_path;
LOG_RESOURCELOOKUP (PRODUCT ": Locating the resource '%s' for the assembly '%s' (culture: '%s').", resource, assembly_name, culture);
app_path = xamarin_get_bundle_path ();
xamarin_get_assembly_name_without_extension (assembly_name, aname, sizeof (aname));
// First check if the directory is explicitly set. This directory is relative to the app bundle.
// For extensions this might be a relative path that points to container app (../../Frameworks/...).
const char *explicit_location = xamarin_find_assembly_directory (aname);
if (explicit_location) {
snprintf (root, sizeof (root), "%s/%s", app_path, explicit_location);
if (xamarin_locate_assembly_resource_for_root (root, culture, resource, path, pathlen)) {
LOG_RESOURCELOOKUP (PRODUCT ": Located resource '%s' from explicit path '%s': %s\n", resource, explicit_location, path);
return true;
}
// If we have an explicit location, then that's where the assembly must be.
LOG_RESOURCELOOKUP (PRODUCT ": Could not find the resource '%s' for the assembly '%s' (culture: '%s') in the explicit path '%s'.", resource, assembly_name, culture, explicit_location);
return false;
}
// The root app directory
if (xamarin_locate_assembly_resource_for_root (app_path, culture, resource, path, pathlen)) {
LOG_RESOURCELOOKUP (PRODUCT ": Located resource '%s' from app bundle: %s\n", resource, path);
return true;
}
// Then in a framework named as the assembly
snprintf (root, sizeof (root), "%s/Frameworks/%s.framework/%s.framework/MonoBundle", app_path, aname, aname);
if (xamarin_locate_assembly_resource_for_root (root, culture, resource, path, pathlen)) {
LOG_RESOURCELOOKUP (PRODUCT ": Located resource '%s' from framework '%s': %s\n", resource, aname, path);
return true;
}
// Then in the container app's root directory (for extensions)
if (xamarin_is_extension) {
snprintf (root, sizeof (root), "../..");
if (xamarin_locate_assembly_resource_for_root (root, culture, resource, path, pathlen)) {
LOG_RESOURCELOOKUP (PRODUCT ": Located resource '%s' from container app bundle '%s': %s\n", resource, aname, path);
return true;
}
}
return false;
}
void
xamarin_set_assembly_directories (struct AssemblyLocations *directories)
{
if (options.AssemblyLocations)
xamarin_assertion_message ("Assembly directories already set.");
options.AssemblyLocations = directories;
}
static int
compare_assembly_location (const void *key, const void *value)
{
return strcmp ((const char *) key, ((struct AssemblyLocation *) value)->assembly_name);
}
const char *
xamarin_find_assembly_directory (const char *assembly_name)
{
if (options.AssemblyLocations == NULL)
return NULL;
struct AssemblyLocation *entry;
entry = (struct AssemblyLocation *) bsearch (assembly_name, options.AssemblyLocations->locations, options.AssemblyLocations->length, sizeof (struct AssemblyLocation), compare_assembly_location);
return entry ? entry->location : NULL;
}
/* /*
* Object unregistration: * Object unregistration:
* *

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

@ -98,6 +98,16 @@ enum NSObjectFlags {
NSObjectFlagsHasManagedRef = 32, NSObjectFlagsHasManagedRef = 32,
}; };
struct AssemblyLocation {
const char *assembly_name; // base name (without extension) of the assembly
const char *location; // the directory where the assembly is
};
struct AssemblyLocations {
int length;
struct AssemblyLocation *locations;
};
void xamarin_initialize (); void xamarin_initialize ();
void xamarin_assertion_message (const char *msg, ...) __attribute__((__noreturn__)); void xamarin_assertion_message (const char *msg, ...) __attribute__((__noreturn__));
@ -174,6 +184,12 @@ id xamarin_invoke_objc_method_implementation (id self, SEL sel, IMP xamarin_i
bool xamarin_is_managed_exception_marshaling_disabled (); bool xamarin_is_managed_exception_marshaling_disabled ();
const char * xamarin_find_assembly_directory (const char *assembly_name);
void xamarin_set_assembly_directories (struct AssemblyLocations *directories);
void xamarin_get_assembly_name_without_extension (const char *aname, char *name, int namelen);
bool xamarin_locate_assembly_resource_for_name (MonoAssemblyName *assembly_name, const char *resource, char *path, int pathlen);
bool xamarin_locate_assembly_resource (const char *assembly_name, const char *culture, const char *resource, char *path, int pathlen);
// this functions support NSLog/NSString-style format specifiers. // this functions support NSLog/NSString-style format specifiers.
void xamarin_printf (const char *format, ...); void xamarin_printf (const char *format, ...);
void xamarin_vprintf (const char *format, va_list args); void xamarin_vprintf (const char *format, va_list args);

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

@ -103,6 +103,7 @@ namespace XamCore.ObjCRuntime {
IsSimulator = 0x10, IsSimulator = 0x10,
} }
[StructLayout (LayoutKind.Sequential)]
internal unsafe struct InitializationOptions { internal unsafe struct InitializationOptions {
public int Size; public int Size;
public InitializationFlags Flags; public InitializationFlags Flags;
@ -111,6 +112,7 @@ namespace XamCore.ObjCRuntime {
public MTRegistrationMap *RegistrationMap; public MTRegistrationMap *RegistrationMap;
public MarshalObjectiveCExceptionMode MarshalObjectiveCExceptionMode; public MarshalObjectiveCExceptionMode MarshalObjectiveCExceptionMode;
public MarshalManagedExceptionMode MarshalManagedExceptionMode; public MarshalManagedExceptionMode MarshalManagedExceptionMode;
IntPtr AssemblyLocations;
public bool IsSimulator { public bool IsSimulator {
get { get {

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

@ -45,10 +45,18 @@
<Compile Include="ResourcesTest.cs" /> <Compile Include="ResourcesTest.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Welcome.resx" /> <EmbeddedResource Include="Welcome.resx">
<EmbeddedResource Include="Welcome.en-AU.resx" /> <LogicalName>EmbeddedResources.Welcome.resources</LogicalName>
<EmbeddedResource Include="Welcome.es.resx" /> </EmbeddedResource>
<EmbeddedResource Include="Welcome.de.resx" /> <EmbeddedResource Include="Welcome.en-AU.resx">
<LogicalName>EmbeddedResources.Welcome.en-AU.resources</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Welcome.es.resx">
<LogicalName>EmbeddedResources.Welcome.es.resources</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Welcome.de.resx">
<LogicalName>EmbeddedResources.Welcome.de.resources</LogicalName>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
</Project> </Project>

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

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

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

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq;
#if __UNIFIED__
using Foundation;
using ObjCRuntime;
#else
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
#endif
using NUnit.Framework;
using Bindings.Test2;
namespace Xamarin.BindingTests2
{
[TestFixture]
[Preserve (AllMembers = true)]
public class BindingTest
{
[Test]
public void Test ()
{
Assert.AreEqual (42, CFunctions.getIntOfChocolate (), "chocolate");
Assert.AreEqual (42, Bindings.Test.CFunctions.theUltimateAnswer (), "theUltimateAnswer");
}
}
}

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

@ -0,0 +1,10 @@
using System;
using System.Runtime.InteropServices;
namespace Bindings.Test2
{
public static class CFunctions {
[DllImport ("__Internal")]
public static extern int getIntOfChocolate ();
}
}

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

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F88FA3CF-B8EF-4CC7-9A2C-BC59DC7B4F22}</ProjectGuid>
<ProjectTypeGuids>{8FFB629D-F513-41CE-95D2-7ECE97B6EEEC};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<RootNamespace>bindingstest2</RootNamespace>
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
<AssemblyName>bindings-test2</AssemblyName>
<TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\product.snk</AssemblyOriginatorKeyFile>
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)-unified</IntermediateOutputPath>
<DefineConstants>XAMCORE_2_0</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' Or '$(Configuration)' == 'Debug32' Or '$(Configuration)' == 'Debug64' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\Any CPU\$(Configuration)-unified</OutputPath>
<DefineConstants>DO_NOT_REMOVE;DEBUG;;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' Or '$(Configuration)' == 'Release32' Or '$(Configuration)' == 'Release64' Or '$(Configuration)' == 'Release-bitcode' ">
<DebugType>none</DebugType>
<Optimize>True</Optimize>
<OutputPath>bin\Any CPU\$(Configuration)-unified</OutputPath>
<DefineConstants>DO_NOT_REMOVE;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Xamarin.iOS" />
<Reference Include="MonoTouch.NUnitLite" />
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
<ItemGroup>
<ObjcBindingApiDefinition Include="ApiDefinition.cs" />
<ObjcBindingApiDefinition Include="ApiProtocol.cs" />
</ItemGroup>
<ItemGroup>
<ObjcBindingCoreSource Include="StructsAndEnums.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.ObjCBinding.CSharp.targets" />
<ItemGroup>
<ObjcBindingNativeLibrary Include="..\..\tests\test-libraries\.libs\ios\libtest2.a">
<Link>libtest2.a</Link>
</ObjcBindingNativeLibrary>
</ItemGroup>
<ItemGroup>
<Compile Include="libtest2.linkwith.cs">
<DependentUpon>libtest2.a</DependentUpon>
</Compile>
<Compile Include="BindingTest.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\tests\test-libraries\libtest2.m">
<Link>libtest2.m</Link>
</None>
<None Include="..\..\tests\test-libraries\libtest2.h">
<Link>libtest2.h</Link>
</None>
</ItemGroup>
<ItemGroup>
<GeneratedTestInput Include="..\..\tests\test-libraries\*.m" />
<GeneratedTestInput Include="..\..\tests\test-libraries\*.h" />
<GeneratedTestInput Include="..\..\tests\test-libraries\*.cs" />
<GeneratedTestInput Include="..\..\tests\test-libraries\Makefile" />
<GeneratedTestOutput Include="..\..\tests\test-libraries\.libs\ios\libtest2.a" />
</ItemGroup>
<Target Name="BeforeBuild" Inputs="@(GeneratedTestInput)" Outputs="@(GeneratedTestOutput)">
<Exec Command="make -j8 -C ..\..\tests\test-libraries" />
</Target>
<ItemGroup>
<ProjectReference Include="..\bindings-test\bindings-test.csproj">
<Project>{48585BC2-D604-4CF2-A827-D887BEA51FD6}</Project>
<Name>bindings-test</Name>
</ProjectReference>
</ItemGroup>
</Project>

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

@ -0,0 +1,14 @@
using System;
#if __UNIFIED__
using ObjCRuntime;
#else
using MonoTouch.ObjCRuntime;
#endif
using System.Runtime.InteropServices;
[assembly: LinkWith ("libtest2.a", LinkTarget.Simulator | LinkTarget.ArmV6 | LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Arm64 | LinkTarget.Simulator64, SmartLink = true, Frameworks = "Foundation" , LinkerFlags = "-lz")]
public static class LibTest {
[DllImport ("__Internal")]
public static extern int theUltimateAnswer ();
}

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

@ -229,15 +229,37 @@ namespace Xamarin.Tests
} }
} }
public static string SdkRoot {
get {
#if MONOMAC
return SdkRootXM;
#else
return SdkRootXI;
#endif
}
}
public static string SdkRootXI {
get {
return Path.Combine (TargetDirectoryXI, "Library", "Frameworks", "Xamarin.iOS.framework", "Versions", "Current");
}
}
public static string SdkRootXM {
get {
return Path.Combine (TargetDirectoryXM, "Library", "Frameworks", "Xamarin.Mac.framework", "Versions", "Current");
}
}
public static string BinDirXI { public static string BinDirXI {
get { get {
return Path.Combine (TargetDirectoryXI, "Library", "Frameworks", "Xamarin.iOS.framework", "Versions", "Current", "bin"); return Path.Combine (SdkRootXI, "bin");
} }
} }
public static string BinDirXM { public static string BinDirXM {
get { get {
return Path.Combine (TargetDirectoryXM, "Library", "Frameworks", "Xamarin.Mac.framework", "Versions", "Current", "bin"); return Path.Combine (SdkRootXM, "bin");
} }
} }

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

@ -60,7 +60,7 @@ namespace Xamarin.Tests
if (rv != 0) { if (rv != 0) {
if (output.Length > 0) if (output.Length > 0)
Console.WriteLine (output); Console.WriteLine ("\t" + output.ToString ().Replace ("\n", "\n\t"));
} }
ParseMessages (); ParseMessages ();
@ -321,10 +321,7 @@ namespace Xamarin.Tests
if (environmentVariables != null) { if (environmentVariables != null) {
var envs = psi.EnvironmentVariables; var envs = psi.EnvironmentVariables;
foreach (var kvp in environmentVariables) { foreach (var kvp in environmentVariables) {
if (envs.ContainsKey (kvp.Key)) envs [kvp.Key] = kvp.Value;
envs [kvp.Key] += ":" + kvp.Value;
else
envs.Add (kvp.Key, kvp.Value);
} }
} }

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

@ -0,0 +1,19 @@
<?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>TestApp</string>
<key>CFBundleIdentifier</key>
<string>com.xamarin.tests.interdependentbindingprojects</string>
<key>CFBundleName</key>
<string>TestApp</string>
<key>MinimumOSVersion</key>
<string>6.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
</dict>
</plist>

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

@ -0,0 +1,37 @@
using System;
using Foundation;
using UIKit;
using MonoTouch.NUnit.UI;
using NUnit.Framework;
using NUnit.Framework.Internal;
#if !__WATCHOS__
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
UIWindow window;
TouchRunner runner;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
window = new UIWindow (UIScreen.MainScreen.Bounds);
runner = new TouchRunner (window);
runner.Add (System.Reflection.Assembly.GetExecutingAssembly ());
runner.Add (typeof (Xamarin.BindingTests2.BindingTest).Assembly);
runner.Add (typeof (Xamarin.BindingTests.ProtocolTest).Assembly);
window.RootViewController = new UINavigationController (runner.GetViewController ());
window.MakeKeyAndVisible ();
return true;
}
static void Main (string[] args)
{
UIApplication.Main (args, null, typeof (AppDelegate));
}
}
#endif // !__WATCHOS__

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

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{AC6D070F-2ED4-4701-B701-81915B931D1D}</ProjectGuid>
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Exe</OutputType>
<RootNamespace>interdependentbindingprojects</RootNamespace>
<AssemblyName>interdependentbindingprojects</AssemblyName>
<SignAssembly>True</SignAssembly>
<TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)-unified</IntermediateOutputPath>
<DefineConstants>XAMCORE_2_0</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\iPhoneSimulator\$(Configuration)-unified</OutputPath>
<DefineConstants>DEBUG;;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>0</WarningLevel>
<MtouchDebug>True</MtouchDebug>
<MtouchExtraArgs>-v -v -v -v</MtouchExtraArgs>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<MtouchArch>i386, x86_64</MtouchArch>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchLink>None</MtouchLink>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
<DebugType>none</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\iPhoneSimulator\$(Configuration)-unified</OutputPath>
<DefineConstants>MONOTOUCH;;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<MtouchLink>None</MtouchLink>
<MtouchExtraArgs>-v -v -v -v</MtouchExtraArgs>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<MtouchArch>i386, x86_64</MtouchArch>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\iPhone\$(Configuration)-unified</OutputPath>
<DefineConstants>DEBUG;;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>0</WarningLevel>
<MtouchDebug>True</MtouchDebug>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchExtraArgs>-v -v -v -v</MtouchExtraArgs>
<MtouchArch>ARMv7, ARM64</MtouchArch>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<IpaPackageName>
</IpaPackageName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug64|iPhone' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\iPhone\$(Configuration)-unified</OutputPath>
<DefineConstants>DEBUG;;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>0</WarningLevel>
<MtouchDebug>True</MtouchDebug>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchExtraArgs>-v -v -v -v</MtouchExtraArgs>
<MtouchArch>ARM64</MtouchArch>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug32|iPhone' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\iPhone\$(Configuration)-unified</OutputPath>
<DefineConstants>DEBUG;;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>0</WarningLevel>
<MtouchDebug>True</MtouchDebug>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchExtraArgs>-v -v -v -v</MtouchExtraArgs>
<MtouchArch>ARMv7</MtouchArch>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
<DebugType>none</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\iPhone\$(Configuration)-unified</OutputPath>
<DefineConstants>MONOTOUCH;;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchExtraArgs>-v -v -v -v --nosymbolstrip</MtouchExtraArgs>
<MtouchArch>ARMv7, ARM64</MtouchArch>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<MtouchUseLlvm>true</MtouchUseLlvm>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release32|iPhone' ">
<DebugType>none</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\iPhone\$(Configuration)-unified</OutputPath>
<DefineConstants>MONOTOUCH;;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchExtraArgs>-v -v -v -v --nosymbolstrip</MtouchExtraArgs>
<MtouchArch>ARMv7</MtouchArch>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<MtouchUseLlvm>true</MtouchUseLlvm>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release64|iPhone' ">
<DebugType>none</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\iPhone\$(Configuration)-unified</OutputPath>
<DefineConstants>MONOTOUCH;;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchExtraArgs>-v -v -v -v --nosymbolstrip</MtouchExtraArgs>
<MtouchArch>ARM64</MtouchArch>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<MtouchUseLlvm>true</MtouchUseLlvm>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Xamarin.iOS" />
<Reference Include="MonoTouch.NUnitLite" />
</ItemGroup>
<ItemGroup>
<None Include="Info.plist" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\bindings-test2\bindings-test2.csproj">
<Project>{F88FA3CF-B8EF-4CC7-9A2C-BC59DC7B4F22}</Project>
<Name>bindings-test2</Name>
</ProjectReference>
<ProjectReference Include="..\bindings-test\bindings-test.csproj">
<Project>{D6667423-EDD8-4B50-9D98-1AC5D8A8A4EA}</Project>
<Name>bindings-test</Name>
</ProjectReference>
</ItemGroup>
</Project>

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

@ -235,47 +235,50 @@ namespace LinkAll {
Assert.NotNull (system, "System"); Assert.NotNull (system, "System");
} }
string FindAssemblyPath ()
{
var filename = Path.GetFileName (GetType ().Assembly.Location);
var bundlePath = NSBundle.MainBundle.BundlePath;
var isExtension = bundlePath.EndsWith (".appex", StringComparison.Ordinal);
var mainBundlePath = bundlePath;
if (isExtension)
mainBundlePath = Path.GetDirectoryName (Path.GetDirectoryName (bundlePath));
foreach (var filepath in Directory.EnumerateFiles (mainBundlePath, filename, SearchOption.AllDirectories)) {
var fname = Path.GetFileName (filepath);
if (filepath.EndsWith ($"{fname}.framework/{fname}", StringComparison.Ordinal)) {
// This isn't the assembly, but the native AOT'ed executable for the assembly.
continue;
}
if (isExtension) {
return "../../" + filepath.Substring (mainBundlePath.Length + 1);
} else {
return filepath.Substring (mainBundlePath.Length + 1);
}
}
throw new FileNotFoundException ($"Could not find the assembly ${filename} in the bundle {bundlePath}.");
}
[Test] [Test]
public void Assembly_LoadFile () public void Assembly_LoadFile ()
{ {
string filename = Path.GetFileName (GetType ().Assembly.Location); string filename = FindAssemblyPath ();
try {
Assert.NotNull (Assembly.LoadFile (filename), "1"); Assert.NotNull (Assembly.LoadFile (filename), "1");
} }
catch (FileNotFoundException) {
// 2nd chance since FAT 32/64 applications moved the assemblies (but that could prove an issue too)
filename = Path.Combine (IntPtr.Size == 4 ? ".monotouch-32" : ".monotouch-64", filename);
Assert.NotNull (Assembly.LoadFile (filename), "2");
}
}
[Test] [Test]
public void Assembly_LoadFrom () public void Assembly_LoadFrom ()
{ {
string filename = Path.GetFileName (GetType ().Assembly.Location); string filename = FindAssemblyPath ();
try {
Assert.NotNull (Assembly.LoadFrom (filename), "1"); Assert.NotNull (Assembly.LoadFrom (filename), "1");
} }
catch (FileNotFoundException) {
// 2nd chance since FAT 32/64 applications moved the assemblies (but that could prove an issue too)
filename = Path.Combine (IntPtr.Size == 4 ? ".monotouch-32" : ".monotouch-64", filename);
Assert.NotNull (Assembly.LoadFrom (filename), "2");
}
}
[Test] [Test]
public void Assembly_ReflectionOnlyLoadFrom () public void Assembly_ReflectionOnlyLoadFrom ()
{ {
string filename = Path.GetFileName (GetType ().Assembly.Location); string filename = FindAssemblyPath ();
try {
Assert.NotNull (Assembly.ReflectionOnlyLoadFrom (filename), "1"); Assert.NotNull (Assembly.ReflectionOnlyLoadFrom (filename), "1");
} }
catch (FileNotFoundException) {
// 2nd chance since FAT 32/64 applications moved the assemblies (but that could prove an issue too)
filename = Path.Combine (IntPtr.Size == 4 ? ".monotouch-32" : ".monotouch-64", filename);
Assert.NotNull (Assembly.ReflectionOnlyLoadFrom (filename), "2");
}
}
[Test] [Test]
#if __WATCHOS__ #if __WATCHOS__

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

@ -184,12 +184,7 @@ namespace Linker.Shared {
} }
// the optimization is turned off in case of fat apps (32/64 bits) // the optimization is turned off in case of fat apps (32/64 bits)
bool b32 = Directory.Exists (Path.Combine (NSBundle.MainBundle.BundlePath, ".monotouch-32")); if (IsMainExecutableDual ()) {
bool b64 = Directory.Exists (Path.Combine (NSBundle.MainBundle.BundlePath, ".monotouch-64"));
// classic does not use the subdirectories, neither do we for single arch simulator
bool classic_or_sim = !b32 && !b64;
bool single_arch = !(b32 && b64);
if (classic_or_sim || single_arch) {
#if DEBUG #if DEBUG
Assert.Inconclusive ("debug IL code"); Assert.Inconclusive ("debug IL code");
#else #else
@ -200,6 +195,97 @@ namespace Linker.Shared {
Assert.IsFalse (!contains11 && !contains22, "both instructions removed"); Assert.IsFalse (!contains11 && !contains22, "both instructions removed");
} }
/* definitions from: /usr/include/mach-o/fat.h */
const uint FAT_MAGIC = 0xcafebabe;
const uint FAT_CIGAM = 0xbebafeca; /* NXSwapLong(FAT_MAGIC) */
static int ConvertBigEndian (int number)
{
return (((number >> 24) & 0xFF)
| ((number >> 08) & 0xFF00)
| ((number << 08) & 0xFF0000)
| ((number << 24)));
}
static uint ConvertBigEndian (uint number)
{
return (((number >> 24) & 0xFF)
| ((number >> 08) & 0xFF00)
| ((number << 08) & 0xFF0000)
| ((number << 24)));
}
static uint ReadUInt32 (BinaryReader reader, bool is_big_endian)
{
var rv = reader.ReadUInt32 ();
if (is_big_endian)
rv = ConvertBigEndian (rv);
return rv;
}
static int ReadInt32 (BinaryReader reader, bool is_big_endian)
{
var rv = reader.ReadInt32 ();
if (is_big_endian)
rv = ConvertBigEndian (rv);
return rv;
}
// Checks if the main executable has both a 32-bit architecture and a 64-bit architecture.
static bool IsMainExecutableDual ()
{
var path = NSGetExecutablePath ();
using (var reader = new BinaryReader (File.OpenRead (path), System.Text.Encoding.UTF8, false)) {
var header = reader.ReadUInt32 ();
bool is_big_endian;
switch (header) {
case FAT_MAGIC:
is_big_endian = false;
break;
case FAT_CIGAM:
is_big_endian = true;
break;
default:
return false;
}
var nfat_arch = ReadUInt32 (reader, is_big_endian);
var is32bit = false;
var is64bit = false;
for (uint i = 0; i < nfat_arch; i++) {
var cputype = ReadInt32 (reader, is_big_endian);
/*var cpusubtype = */ReadInt32 (reader, is_big_endian);
/*var offset = */ReadUInt32 (reader, is_big_endian);
/*var size = */ReadUInt32 (reader, is_big_endian);
/*var align = */ReadUInt32 (reader, is_big_endian);
const int CPU_ARCH_ABI64 = 0x01000000;
if ((cputype & CPU_ARCH_ABI64) == CPU_ARCH_ABI64) {
is64bit = true;
} else {
is32bit = true;
}
}
return is32bit && is64bit;
}
}
[DllImport ("/usr/lib/system/libdyld.dylib")]
static extern int _NSGetExecutablePath (IntPtr buf, ref int bufsize);
static string NSGetExecutablePath ()
{
IntPtr buf;
int bufsize = 0;
_NSGetExecutablePath (IntPtr.Zero, ref bufsize);
buf = Marshal.AllocHGlobal (bufsize);
try {
if (_NSGetExecutablePath (buf, ref bufsize) != 0)
throw new Exception ("Could not get executable path");
return Marshal.PtrToStringAuto (buf);
} finally {
Marshal.FreeHGlobal (buf);
}
}
[Test] [Test]
public void FinallyTest () public void FinallyTest ()
{ {

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

@ -0,0 +1,14 @@
<linker>
<!-- see LinkExtraDefsTest unit tests -->
<assembly fullname="mscorlib">
<type fullname="System.Security.PermissionSet" />
</assembly>
<assembly fullname="System">
<type fullname="System.Net.Mime.ContentType" >
<method name="ParseValue" />
</type>
</assembly>
<assembly fullname="Xamarin.iOS">
<type fullname="CoreBluetooth.CBUUID" preserve="field" />
</assembly>
</linker>

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

@ -748,7 +748,9 @@
<BundleResource Include="xamvideotest.mp4" /> <BundleResource Include="xamvideotest.mp4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Security\openssl_crt.der" /> <EmbeddedResource Include="Security\openssl_crt.der">
<LogicalName>monotouchtest.Security.openssl_crt.der</LogicalName>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ImageAsset Condition="'$(TargetFrameworkIdentifier)' != 'Xamarin.WatchOS'" Include="Assets.xcassets\AppIcons.appiconset\Contents.json" /> <ImageAsset Condition="'$(TargetFrameworkIdentifier)' != 'Xamarin.WatchOS'" Include="Assets.xcassets\AppIcons.appiconset\Contents.json" />

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

@ -94,7 +94,7 @@ namespace Xamarin
mtouch.AssertExecute (MTouchAction.BuildDev, "third build"); mtouch.AssertExecute (MTouchAction.BuildDev, "third build");
var skipFiles = new string [] { "testApp", "testApp.exe", "testApp.armv7.aotdata", "testApp.arm64.aotdata" }; var skipFiles = new string [] { "testApp", "testApp.exe", "testApp.aotdata.armv7", "testApp.aotdata.arm64" };
checkNotModified (name + "-rebuilt", skipFiles); checkNotModified (name + "-rebuilt", skipFiles);
} }
} }
@ -105,7 +105,6 @@ namespace Xamarin
using (var tool = new MTouchTool ()) { using (var tool = new MTouchTool ()) {
tool.Profile = Profile.iOS; tool.Profile = Profile.iOS;
tool.I18N = I18N.West; tool.I18N = I18N.West;
tool.Verbosity = 5;
tool.Cache = Path.Combine (tool.CreateTemporaryDirectory (), "mtouch-test-cache"); tool.Cache = Path.Combine (tool.CreateTemporaryDirectory (), "mtouch-test-cache");
tool.CreateTemporaryApp (); tool.CreateTemporaryApp ();
@ -131,8 +130,8 @@ namespace Xamarin
mtouch.NoFastSim = true; mtouch.NoFastSim = true;
mtouch.Linker = MTouchLinker.DontLink; mtouch.Linker = MTouchLinker.DontLink;
mtouch.CreateTemporaryApp (); mtouch.CreateTemporaryApp ();
mtouch.Verbosity = 4;
mtouch.CreateTemporaryCacheDirectory (); mtouch.CreateTemporaryCacheDirectory ();
mtouch.Verbosity = 4; // This is required to get the debug output we're testing for
mtouch.AssertExecute (MTouchAction.BuildSim, "build 1"); mtouch.AssertExecute (MTouchAction.BuildSim, "build 1");
mtouch.AssertOutputPattern ("Linking .*/testApp.exe into .*/PreBuild using mode 'None'"); mtouch.AssertOutputPattern ("Linking .*/testApp.exe into .*/PreBuild using mode 'None'");
mtouch.AssertExecute (MTouchAction.BuildSim, "build 2"); mtouch.AssertExecute (MTouchAction.BuildSim, "build 2");
@ -140,6 +139,173 @@ namespace Xamarin
} }
} }
[Test]
[TestCase ("single", "", false, new string [] { } )]
[TestCase ("dual", "armv7,arm64", false, new string [] { })]
[TestCase ("llvm", "armv7+llvm", false, new string [] { })]
[TestCase ("debug", "", true, new string [] { })]
[TestCase ("single-framework", "", false, new string [] { "@sdk=framework=Xamarin.Sdk", "@all=staticobject" })]
public void RebuildTest_WithExtensions (string name, string abi, bool debug, string[] assembly_build_targets)
{
var codeA = "[Foundation.Preserve] public class TestApp1 { static void X () { System.Console.WriteLine (typeof (ObjCRuntime.Runtime).ToString ()); } }";
var codeB = "[Foundation.Preserve] public class TestApp2 { static void X () { System.Console.WriteLine (typeof (ObjCRuntime.Runtime).ToString ()); } }";
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension (extraCode: codeA);
extension.CreateTemporaryCacheDirectory ();
extension.Abi = abi;
extension.Debug = debug;
extension.AssemblyBuildTargets.AddRange (assembly_build_targets);
extension.DSym = false; // faster test
extension.MSym = false; // faster test
extension.NoStrip = true; // faster test
extension.AssertExecute (MTouchAction.BuildDev, "extension build");
using (var mtouch = new MTouchTool ()) {
mtouch.AppExtensions.Add (extension);
mtouch.CreateTemporaryApp (extraCode: codeA);
mtouch.CreateTemporaryCacheDirectory ();
mtouch.Abi = abi;
mtouch.Debug = debug;
mtouch.AssemblyBuildTargets.AddRange (assembly_build_targets);
mtouch.DSym = false; // faster test
mtouch.MSym = false; // faster test
mtouch.NoStrip = true; // faster test
var timestamp = DateTime.MinValue;
Action<string, IEnumerable<string>> assertNotModified = (filename, skip) =>
{
var failed = new List<string> ();
var files = Directory.EnumerateFiles (mtouch.AppPath, "*", SearchOption.AllDirectories);
files = files.Concat (Directory.EnumerateFiles (extension.AppPath, "*", SearchOption.AllDirectories));
foreach (var file in files) {
if (skip != null && skip.Contains (Path.GetFileName (file)))
continue;
var info = new FileInfo (file);
if (info.LastWriteTime > timestamp) {
failed.Add (string.Format ("{0} is modified, timestamp: {1}", file, info.LastWriteTime));
Console.WriteLine ("FAIL: {0} modified: {1}", file, info.LastWriteTime);
} else {
Console.WriteLine ("{0} not modified", file);
}
}
Assert.IsEmpty (failed, filename);
};
Action<string, IEnumerable<string>> assertModified = (testname, modified) =>
{
var failed = new List<string> ();
var files = Directory.EnumerateFiles (mtouch.AppPath, "*", SearchOption.AllDirectories);
files = files.Concat (Directory.EnumerateFiles (extension.AppPath, "*", SearchOption.AllDirectories));
foreach (var file in files) {
if (!modified.Contains (Path.GetFileName (file)))
continue;
var info = new FileInfo (file);
if (info.LastWriteTime < timestamp) {
failed.Add (string.Format ("{0} is not modified, timestamp: {1}", file, info.LastWriteTime));
Console.WriteLine ("FAIL: {0} not modified: {1}", file, info.LastWriteTime);
} else {
Console.WriteLine ("{0} modified as expected", file);
}
}
Assert.IsEmpty (failed, testname);
};
mtouch.AssertExecute (MTouchAction.BuildDev, "first build");
Console.WriteLine ($"{DateTime.Now} **** FIRST BUILD DONE ****");
timestamp = DateTime.Now;
System.Threading.Thread.Sleep (1000); // make sure all new timestamps are at least a second older. HFS+ has a 1s timestamp resolution :(
mtouch.AssertExecute (MTouchAction.BuildDev, "second build");
Console.WriteLine ($"{DateTime.Now} **** SECOND BUILD DONE ****");
assertNotModified (name, null);
// Touch the extension's executable, nothing should change
new FileInfo (extension.RootAssembly).LastWriteTimeUtc = DateTime.UtcNow;
mtouch.AssertExecute (MTouchAction.BuildDev, "touch extension executable");
Console.WriteLine ($"{DateTime.Now} **** TOUCH EXTENSION EXECUTABLE DONE ****");
assertNotModified (name, null);
// Touch the main app's executable, nothing should change
new FileInfo (mtouch.RootAssembly).LastWriteTimeUtc = DateTime.UtcNow;
mtouch.AssertExecute (MTouchAction.BuildDev, "touch main app executable");
Console.WriteLine ($"{DateTime.Now} **** TOUCH MAIN APP EXECUTABLE DONE ****");
assertNotModified (name, null);
// Test that a rebuild (where something changed, in this case the .exe)
// actually work. We compile with custom code to make sure it's different
// from the previous exe we built.
//
// The code change is minimal: only changes the class name (default: 'TestApp1' changed to 'TestApp2') to minimize the related
// changes (there should be no changes in Xamarin.iOS.dll nor mscorlib.dll, even after linking)
// Rebuild the extension's .exe
extension.CreateTemporaryServiceExtension (extraCode: codeB);
mtouch.AssertExecute (MTouchAction.BuildDev, "change extension executable");
Console.WriteLine ($"{DateTime.Now} **** CHANGE EXTENSION EXECUTABLE DONE ****");
assertNotModified (name, new [] { "testServiceExtension", "testServiceExtension.aotdata.armv7", "testServiceExtension.aotdata.arm64", "testServiceExtension.dll" } );
timestamp = DateTime.Now;
System.Threading.Thread.Sleep (1000); // make sure all new timestamps are at least a second older. HFS+ has a 1s timestamp resolution :(
// Rebuild the main app's .exe
mtouch.CreateTemporaryApp (extraCode: codeB);
mtouch.AssertExecute (MTouchAction.BuildDev, "change app executable");
Console.WriteLine ($"{DateTime.Now} **** CHANGE APP EXECUTABLE DONE ****");
assertNotModified (name, new [] { "testApp", "testApp.aotdata.armv7", "testApp.aotdata.arm64", "testApp.exe" });
timestamp = DateTime.Now;
System.Threading.Thread.Sleep (1000); // make sure all new timestamps are at least a second older. HFS+ has a 1s timestamp resolution :(
// Add a config file to the extension. This file should be added to the app, and the AOT-compiler re-executed for the root assembly.
File.WriteAllText (extension.RootAssembly + ".config", "<configuration></configuration>");
mtouch.AssertExecute (MTouchAction.BuildDev, "add config to extension dll");
Console.WriteLine ($"{DateTime.Now} **** ADD CONFIG TO EXTENSION DONE ****");
assertNotModified (name, new [] { "testServiceExtension.dll.config", "testServiceExtension", "testServiceExtension.aotdata.armv7", "testServiceExtension.aotdata.arm64" });
CollectionAssert.Contains (Directory.EnumerateFiles (extension.AppPath, "*", SearchOption.AllDirectories).Select ((v) => Path.GetFileName (v)), "testServiceExtension.dll.config", "extension config added");
timestamp = DateTime.Now;
System.Threading.Thread.Sleep (1000); // make sure all new timestamps are at least a second older. HFS+ has a 1s timestamp resolution :(
// Add a config file to the container. This file should be added to the app, and the AOT-compiler re-executed for the root assembly.
File.WriteAllText (mtouch.RootAssembly + ".config", "<configuration></configuration>");
mtouch.AssertExecute (MTouchAction.BuildDev, "add config to container exe");
Console.WriteLine ($"{DateTime.Now} **** ADD CONFIG TO CONTAINER DONE ****");
assertNotModified (name, new [] { "testApp.exe.config", "testApp", "testApp.aotdata.armv7", "testApp.aotdata.arm64" });
CollectionAssert.Contains (Directory.EnumerateFiles (mtouch.AppPath, "*", SearchOption.AllDirectories).Select ((v) => Path.GetFileName (v)), "testApp.exe.config", "container config added");
timestamp = DateTime.Now;
System.Threading.Thread.Sleep (1000); // make sure all new timestamps are at least a second older. HFS+ has a 1s timestamp resolution :(
{
// Add a satellite to the extension.
var satellite = extension.CreateTemporarySatelliteAssembly ();
mtouch.AssertExecute (MTouchAction.BuildDev, "add satellite to extension");
Console.WriteLine ($"{DateTime.Now} **** ADD SATELLITE TO EXTENSION DONE ****");
assertNotModified (name, new string [] { Path.GetFileName (satellite) });
assertModified (name, new string [] { Path.GetFileName (satellite) });
CollectionAssert.Contains (Directory.EnumerateFiles (extension.AppPath, "*", SearchOption.AllDirectories).Select ((v) => Path.GetFileName (v)), Path.GetFileName (satellite), "extension satellite added");
}
timestamp = DateTime.Now;
System.Threading.Thread.Sleep (1000); // make sure all new timestamps are at least a second older. HFS+ has a 1s timestamp resolution :(
{
// Add a satellite to the container.
var satellite = mtouch.CreateTemporarySatelliteAssembly ();
mtouch.AssertExecute (MTouchAction.BuildDev, "add satellite to container");
Console.WriteLine ($"{DateTime.Now} **** ADD SATELLITE TO CONTAINER DONE ****");
assertNotModified (name, new string [] { Path.GetFileName (satellite) });
assertModified (name, new string [] { Path.GetFileName (satellite) });
CollectionAssert.Contains (Directory.EnumerateFiles (mtouch.AppPath, "*", SearchOption.AllDirectories).Select ((v) => Path.GetFileName (v)), Path.GetFileName (satellite), "container satellite added");
}
}
}
}
[Test] [Test]
// Simulator // Simulator
[TestCase (Target.Sim, Config.Release, PackageMdb.Default, MSym.Default, false, false, "")] [TestCase (Target.Sim, Config.Release, PackageMdb.Default, MSym.Default, false, false, "")]
@ -186,7 +352,8 @@ namespace Xamarin
var appDir = mtouch.AppPath; var appDir = mtouch.AppPath;
var msymDir = appDir + ".mSYM"; var msymDir = appDir + ".mSYM";
if (is_sim) { var is_dual_asm = !is_sim && extra_mtouch_args.Contains ("--abi") && extra_mtouch_args.Contains (",");
if (!is_dual_asm) {
Assert.AreEqual (has_mdb, File.Exists (Path.Combine (appDir, "mscorlib.pdb")), "#pdb"); Assert.AreEqual (has_mdb, File.Exists (Path.Combine (appDir, "mscorlib.pdb")), "#pdb");
} else { } else {
Assert.AreEqual (has_mdb, File.Exists (Path.Combine (appDir, ".monotouch-32", "mscorlib.pdb")), "#pdb"); Assert.AreEqual (has_mdb, File.Exists (Path.Combine (appDir, ".monotouch-32", "mscorlib.pdb")), "#pdb");
@ -227,6 +394,17 @@ namespace Xamarin
} }
} }
[Test]
public void MT0003 ()
{
using (var mtouch = new MTouchTool ()) {
mtouch.CreateTemporaryApp (appName: "mscorlib");
mtouch.Linker = MTouchLinker.DontLink;
mtouch.AssertExecuteFailure (MTouchAction.BuildSim, "build");
mtouch.AssertError (3, "Application name 'mscorlib.exe' conflicts with an SDK or product assembly (.dll) name.");
}
}
[Test] [Test]
public void MT0008 () public void MT0008 ()
{ {
@ -387,6 +565,47 @@ namespace Xamarin
} }
} }
[Test]
public void MT0023 ()
{
using (var mtouch = new MTouchTool ()) {
// Create a library with the same name as the exe
var tmp = mtouch.CreateTemporaryDirectory ();
var dllA = CompileTestAppCode ("library", tmp, "public class X {}");
mtouch.CreateTemporaryApp (code: "public class C { static void Main () { System.Console.WriteLine (typeof (X)); System.Console.WriteLine (typeof (UIKit.UIWindow)); } }", extraArg: "-r:" + Quote (dllA));
mtouch.References = new string [] { dllA };
mtouch.Linker = MTouchLinker.DontLink;
mtouch.AssertExecuteFailure (MTouchAction.BuildSim, "build");
mtouch.AssertErrorPattern (23, "The root assembly .*/testApp.exe conflicts with another assembly (.*/testApp.dll).");
}
}
[Test]
public void MT0023_Extension ()
{
using (var extension = new MTouchTool ()) {
// Create a library with the same name as the root assembly
var tmp = extension.CreateTemporaryDirectory ();
var dll = CompileTestAppCode ("library", tmp, "public class X {}", appName: "testApp");
extension.Linker = MTouchLinker.DontLink; // fastest.
extension.CreateTemporaryServiceExtension (extraArg: $"-r:{Quote (dll)}", extraCode: "class Z { static void Y () { System.Console.WriteLine (typeof (X)); } }", appName: "testApp");
extension.CreateTemporaryCacheDirectory ();
extension.References = new [] { dll };
extension.AssertExecute (MTouchAction.BuildSim, "extension build");
using (var app = new MTouchTool ()) {
app.Linker = MTouchLinker.DontLink; // fastest.
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.AssertExecuteFailure (MTouchAction.BuildSim, "app build");
app.AssertError (23, $"The root assembly {extension.RootAssembly} conflicts with another assembly ({dll}).");
}
}
}
[Test] [Test]
[TestCase (Profile.iOS)] [TestCase (Profile.iOS)]
[TestCase (Profile.watchOS)] [TestCase (Profile.watchOS)]
@ -596,6 +815,409 @@ namespace Xamarin
} }
} }
/* MT0100 is a consistency check, and should never be seen (and as such can never be tested either, since there's no known test cases that would produce it) */
[Test]
public void MT0101 ()
{
using (var mtouch = new MTouchTool ()) {
mtouch.CreateTemporaryApp ();
mtouch.Linker = MTouchLinker.DontLink; // the MT0101 check happens after linking, but before AOT-compiling, so not linking makes the test faster.
mtouch.AssemblyBuildTargets.Add ("mscorlib=framework");
mtouch.AssemblyBuildTargets.Add ("mscorlib=framework");
mtouch.AssertExecuteFailure (MTouchAction.BuildDev, "build");
mtouch.AssertError (101, "The assembly 'mscorlib' is specified multiple times in --assembly-build-target arguments.");
}
}
[Test]
public void MT0102 ()
{
using (var mtouch = new MTouchTool ()) {
mtouch.CreateTemporaryApp ();
mtouch.Linker = MTouchLinker.DontLink; // the MT0102 check happens after linking, but before AOT-compiling, so not linking makes the test faster.
mtouch.AssemblyBuildTargets.Add ("mscorlib=framework=MyBinary");
mtouch.AssemblyBuildTargets.Add ("System=dynamiclibrary=MyBinary");
mtouch.AssemblyBuildTargets.Add ("@all=dynamiclibrary");
mtouch.AssertExecuteFailure (MTouchAction.BuildDev, "build");
mtouch.AssertError (102, "The assemblies 'mscorlib' and 'System' have the same target name ('MyBinary'), but different targets ('Framework' and 'DynamicLibrary').");
}
}
[Test]
public void MT0103 ()
{
using (var mtouch = new MTouchTool ()) {
mtouch.CreateTemporaryApp ();
mtouch.Linker = MTouchLinker.DontLink; // the MT0103 check happens after linking, but before AOT-compiling, so not linking makes the test faster.
mtouch.AssemblyBuildTargets.Add ("mscorlib=staticobject=MyBinary");
mtouch.AssemblyBuildTargets.Add ("System=staticobject=MyBinary");
mtouch.AssemblyBuildTargets.Add ("@all=staticobject");
mtouch.AssertExecuteFailure (MTouchAction.BuildDev, "build");
mtouch.AssertError (103, "The static object 'MyBinary' contains more than one assembly ('mscorlib', 'System'), but each static object must correspond with exactly one assembly.");
}
}
[Test]
public void MT0105 ()
{
using (var mtouch = new MTouchTool ()) {
mtouch.CreateTemporaryApp ();
mtouch.Linker = MTouchLinker.DontLink; // the MT0105 check happens after linking, but before AOT-compiling, so not linking makes the test faster.
mtouch.AssemblyBuildTargets.Add ("mscorlib=framework");
mtouch.AssertExecuteFailure (MTouchAction.BuildDev, "build");
mtouch.AssertError (105, "No assembly build target was specified for 'testApp'.");
mtouch.AssertError (105, "No assembly build target was specified for 'System'.");
mtouch.AssertError (105, "No assembly build target was specified for 'System.Xml'.");
mtouch.AssertError (105, "No assembly build target was specified for 'System.Core'.");
mtouch.AssertError (105, "No assembly build target was specified for 'Mono.Dynamic.Interpreter'.");
mtouch.AssertError (105, "No assembly build target was specified for 'Xamarin.iOS'.");
}
}
[Test]
public void MT0106 ()
{
using (var mtouch = new MTouchTool ()) {
mtouch.CreateTemporaryApp ();
mtouch.Linker = MTouchLinker.DontLink; // the MT0106 check happens after linking, but before AOT-compiling, so not linking makes the test faster.
mtouch.AssemblyBuildTargets.Add ("@all=staticobject=a/b");;
mtouch.AssertExecuteFailure (MTouchAction.BuildDev, "build");
mtouch.AssertError (106, "The assembly build target name 'a/b' is invalid: the character '/' is not allowed.");
mtouch.AssemblyBuildTargets.Clear ();
mtouch.AssemblyBuildTargets.Add ("@all=staticobject=d\\e");
mtouch.AssertExecuteFailure (MTouchAction.BuildDev, "build");
mtouch.AssertError (106, "The assembly build target name 'd\\e' is invalid: the character '\\' is not allowed.");
}
}
[Test]
public void MT0108 ()
{
using (var mtouch = new MTouchTool ()) {
mtouch.CreateTemporaryApp ();
mtouch.Linker = MTouchLinker.DontLink; // the MT0108 check happens after linking, but before AOT-compiling, so not linking makes the test faster.
mtouch.AssemblyBuildTargets.Add ("@all=staticobject");
mtouch.AssemblyBuildTargets.Add ("dummy=framework");
mtouch.AssertExecuteFailure (MTouchAction.BuildDev, "build");
mtouch.AssertError (108, "The assembly build target 'dummy' did not match any assemblies.");
}
}
/* MT0109 is tested in other tests (MT2018) */
[Test]
public void MT0112_deploymenttarget ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.TargetVer = "6.0";
app.WarnAsError = new int [] { 112 };
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (112, "Native code sharing has been disabled because the container app's deployment target is earlier than iOS 8.0 (it's 6.0).");
}
}
}
[Test]
public void MT0112_i18n ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.I18N = I18N.CJK;
app.WarnAsError = new int [] { 112 };
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (112, "Native code sharing has been disabled because the container app includes I18N assemblies (CJK).");
}
}
}
[Test]
public void MT0113_bitcode ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.Abi = "arm64+llvm";
app.Bitcode = MTouchBitcode.Full;
app.WarnAsError = new int [] { 113 };
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, "Native code sharing has been disabled for the extension 'testServiceExtension' because the bitcode options differ between the container app (None) and the extension (LLVMOnly).");
}
}
}
[Test]
[TestCase ("framework app", new string [] { "@sdk=framework=Xamarin.Sdk" }, null)]
[TestCase ("framework ext", null, new string [] { "@sdk=framework=Xamarin.Sdk" })]
[TestCase ("fastdev app", new string [] { "@all=dynamiclibrary" }, null)]
[TestCase ("fastdev ext", null, new string [] { "@all=dynamiclibrary" })]
public void MT0113_assemblybuildtarget (string name, string[] extension_abt, string[] app_abt)
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
if (extension_abt != null)
extension.AssemblyBuildTargets.AddRange (extension_abt);
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.WarnAsError = new int [] { 113 };
if (app_abt != null)
app.AssemblyBuildTargets.AddRange (app_abt);
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, $"Native code sharing has been disabled for the extension 'testServiceExtension' because the --assembly-build-target options are different between the container app ({(app_abt == null ? string.Empty : string.Join (", ", app_abt.Select ((v) => "--assembly-build-target:" + v)))}) and the extension ({(extension_abt == null ? string.Empty : string.Join (", ", extension_abt?.Select ((v) => "--assembly-build-target:" + v)))}).");
}
}
}
[Test]
public void MT0113_i18n ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.I18N = I18N.CJK;
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.WarnAsError = new int [] { 113 };
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, "Native code sharing has been disabled for the extension 'testServiceExtension' because the I18N assemblies are different between the container app (None) and the extension (CJK).");
}
}
}
[Test]
public void MT0113_aot ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.WarnAsError = new int [] { 113 };
app.AotArguments = "dwarfdebug"; // doesn't matter exactly what, just that it's different from the extension.
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, "Native code sharing has been disabled for the extension 'testServiceExtension' because the arguments to the AOT compiler are different between the container app (dwarfdebug,static,asmonly,direct-icalls,) and the extension (static,asmonly,direct-icalls,).");
}
}
}
[Test]
public void MT0113_aotother ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.WarnAsError = new int [] { 113 };
app.AotOtherArguments = "--aot-options=-O=float32"; // doesn't matter exactly what, just that it's different from the extension.
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, "Native code sharing has been disabled for the extension 'testServiceExtension' because the other arguments to the AOT compiler are different between the container app (--aot-options=-O=float32 ) and the extension ().");
}
}
}
[Test]
public void MT0113_llvm ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.Abi = "arm64";
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.WarnAsError = new int [] { 113 };
app.Abi = "arm64+llvm";
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, "Native code sharing has been disabled for the extension 'testServiceExtension' because LLVM is not enabled or disabled in both the container app (True) and the extension (False).");
}
}
}
[Test]
public void MT0113_linker ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.Abi = "arm64";
extension.Linker = MTouchLinker.LinkAll;
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.Linker = MTouchLinker.DontLink;
app.WarnAsError = new int [] { 113 };
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, "Native code sharing has been disabled for the extension 'testServiceExtension' because the managed linker settings are different between the container app (None) and the extension (All).");
}
}
}
[Test]
public void MT0113_skipped ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.WarnAsError = new int [] { 113 };
app.LinkSkip = new string [] { "mscorlib.dll" };
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, "Native code sharing has been disabled for the extension 'testServiceExtension' because the skipped assemblies for the managed linker are different between the container app (mscorlib.dll) and the extension ().");
}
}
}
[Test]
public void MT0112_xml ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.WarnAsError = new int [] { 112 };
app.XmlDefinitions = new string [] { "foo.xml" };
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (112, "Native code sharing has been disabled because the container app has custom xml definitions for the managed linker (foo.xml).");
}
}
}
[Test]
public void MT0113_xml ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.XmlDefinitions = new string [] { "foo.xml" };
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.WarnAsError = new int [] { 113 };
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, "Native code sharing has been disabled for the extension 'testServiceExtension' because the extension has custom xml definitions for the managed linker (foo.xml).");
}
}
}
[Test]
[TestCase ("arm64", "armv7", "ARMv7")]
[TestCase ("armv7", "armv7,arm64", "ARM64")]
public void MT0113_abi (string app_abi, string extension_abi, string error_abi)
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.Abi = extension_abi;
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.WarnAsError = new int [] { 113 };
app.Abi = app_abi;
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, $"Native code sharing has been disabled for the extension 'testServiceExtension' because the container app does not build for the ABI {error_abi} (while the extension is building for this ABI).");
}
}
}
[Test]
[TestCase ("armv7+llvm+thumb2", "armv7+llvm", "ARMv7, Thumb, LLVM", "ARMv7, LLVM")]
public void MT0113_incompatible_abi (string app_abi, string extension_abi, string container_error_abi, string extension_error_abi)
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.Abi = extension_abi;
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.WarnAsError = new int [] { 113 };
app.Abi = app_abi;
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, $"Native code sharing has been disabled for the extension 'testServiceExtension' because the container app is building for the ABI {container_error_abi}, which is not compatible with the extension's ABI ({extension_error_abi}).");
}
}
}
[Test]
public void MT0113_refmismatch ()
{
using (var extension = new MTouchTool ()) {
var ext_tmpdir = extension.CreateTemporaryDirectory ();
var ext_dll = CompileTestAppLibrary (ext_tmpdir, @"public class X { }", appName: "testLibrary");
extension.CreateTemporaryServiceExtension (extraCode: "class Y : X {}", extraArg: $"-r:{Quote (ext_dll)}");
extension.CreateTemporaryCacheDirectory ();
extension.References = new string [] { ext_dll };
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
var app_tmpdir = app.CreateTemporaryDirectory ();
var app_dll = Path.Combine (app_tmpdir, Path.GetFileName (ext_dll));
File.Copy (ext_dll, app_dll);
app.CreateTemporaryApp (extraCode: "class Y : X {}", extraArg: $"-r:{Quote (app_dll)}");
app.CreateTemporaryCacheDirectory ();
app.References = new string [] { app_dll };
app.WarnAsError = new int [] { 113 };
app.AssertExecuteFailure (MTouchAction.BuildDev, "build app");
app.AssertError (113, $"Native code sharing has been disabled for the extension 'testServiceExtension' because the container app is referencing the assembly 'testLibrary' from '{app_dll}', while the extension references it from '{ext_dll}'.");
}
}
}
[Test] [Test]
public void MT0127 () public void MT0127 ()
{ {
@ -1095,7 +1717,7 @@ public class TestApp {
public void FastSim (Profile profile) public void FastSim (Profile profile)
{ {
using (var tool = new MTouchTool ()) { using (var tool = new MTouchTool ()) {
tool.Verbosity = 1; tool.Verbosity = 1; // This is required to get the debug output we're testing for.
tool.Profile = profile; tool.Profile = profile;
tool.CreateTemporaryApp (); tool.CreateTemporaryApp ();
tool.Linker = MTouchLinker.DontLink; tool.Linker = MTouchLinker.DontLink;
@ -1207,6 +1829,33 @@ public class TestApp {
} }
} }
[Test]
public void MonoFrameworkArchitectures ()
{
using (var extension = new MTouchTool ()) {
extension.CreateTemporaryServiceExtension ();
extension.CreateTemporaryCacheDirectory ();
extension.Abi = "armv7,arm64";
extension.Linker = MTouchLinker.LinkAll; // faster test
extension.NoStrip = true; // faster test
extension.AssertExecute (MTouchAction.BuildDev, "build extension");
using (var app = new MTouchTool ()) {
app.AppExtensions.Add (extension);
app.CreateTemporaryApp ();
app.CreateTemporaryCacheDirectory ();
app.Abi = "arm64";
app.Linker = MTouchLinker.LinkAll; // faster test
app.NoStrip = true; // faster test
app.AssertExecute (MTouchAction.BuildDev, "build app");
var mono_framework = Path.Combine (app.AppPath, "Frameworks", "Mono.framework", "Mono");
Assert.That (mono_framework, Does.Exist, "mono framework existence");
// Verify that mtouch removed armv7s from the framework.
Assert.That (GetArchitectures (mono_framework), Is.EquivalentTo (new [] { "armv7", "arm64" }), "mono framework architectures");
}
}
}
[Test] [Test]
public void GarbageCollectors () public void GarbageCollectors ()
{ {
@ -1350,6 +1999,7 @@ public class TestApp {
mtouch.RootAssembly = exe; mtouch.RootAssembly = exe;
mtouch.References = new [] { bindingLib }; mtouch.References = new [] { bindingLib };
mtouch.Timeout = TimeSpan.FromMinutes (5);
// each variation is tested twice so that we don't break when everything is found in the cache the second time around. // each variation is tested twice so that we don't break when everything is found in the cache the second time around.
@ -1466,6 +2116,7 @@ public class TestApp {
mtouch.Linker = linker; mtouch.Linker = linker;
mtouch.CreateTemporaryApp (); mtouch.CreateTemporaryApp ();
mtouch.CreateTemporaryCacheDirectory (); mtouch.CreateTemporaryCacheDirectory ();
mtouch.Timeout = TimeSpan.FromMinutes (5);
mtouch.AssertExecute (MTouchAction.BuildDev, "first build"); mtouch.AssertExecute (MTouchAction.BuildDev, "first build");
File.Delete (mtouch.NativeExecutablePath); // This will force the final native link to succeed, while everything before has been cached. File.Delete (mtouch.NativeExecutablePath); // This will force the final native link to succeed, while everything before has been cached.
@ -1672,10 +2323,10 @@ class Test {
mtouch.AssertOutputPattern ("Undefined symbols for architecture arm64:"); mtouch.AssertOutputPattern ("Undefined symbols for architecture arm64:");
mtouch.AssertOutputPattern (".*_OBJC_METACLASS_._Inexistent., referenced from:.*"); mtouch.AssertOutputPattern (".*_OBJC_METACLASS_._Inexistent., referenced from:.*");
mtouch.AssertOutputPattern (".*_OBJC_METACLASS_._Test_Subexistent in registrar.arm64.o.*"); mtouch.AssertOutputPattern (".*_OBJC_METACLASS_._Test_Subexistent in registrar.o.*");
mtouch.AssertOutputPattern (".*_OBJC_CLASS_._Inexistent., referenced from:.*"); mtouch.AssertOutputPattern (".*_OBJC_CLASS_._Inexistent., referenced from:.*");
mtouch.AssertOutputPattern (".*_OBJC_CLASS_._Test_Subexistent in registrar.arm64.o.*"); mtouch.AssertOutputPattern (".*_OBJC_CLASS_._Test_Subexistent in registrar.o.*");
mtouch.AssertOutputPattern (".*objc-class-ref in registrar.arm64.o.*"); mtouch.AssertOutputPattern (".*objc-class-ref in registrar.o.*");
mtouch.AssertOutputPattern (".*ld: symbol.s. not found for architecture arm64.*"); mtouch.AssertOutputPattern (".*ld: symbol.s. not found for architecture arm64.*");
mtouch.AssertOutputPattern (".*clang: error: linker command failed with exit code 1 .use -v to see invocation.*"); mtouch.AssertOutputPattern (".*clang: error: linker command failed with exit code 1 .use -v to see invocation.*");
@ -1751,6 +2402,7 @@ class Test {
mtouch.AppPath = app; mtouch.AppPath = app;
mtouch.RootAssembly = exe; mtouch.RootAssembly = exe;
mtouch.References = new [] { DLL }; mtouch.References = new [] { DLL };
mtouch.Timeout = TimeSpan.FromMinutes (5);
foreach (var test in tests) { foreach (var test in tests) {
mtouch.Abi = test.Abi; mtouch.Abi = test.Abi;
@ -1771,8 +2423,9 @@ class Test {
mtouch.CreateTemporaryCacheDirectory (); mtouch.CreateTemporaryCacheDirectory ();
mtouch.Abi = "armv7,arm64"; mtouch.Abi = "armv7,arm64";
mtouch.AssertExecute (MTouchAction.BuildDev, "build"); mtouch.AssertExecute (MTouchAction.BuildDev, "build");
var ufe = Mono.Unix.UnixFileSystemInfo.GetFileSystemEntry (Path.Combine (mtouch.AppPath, ".monotouch-32", "testApp.exe")); FileAssert.Exists (Path.Combine (mtouch.AppPath, "testApp.exe"));
Assert.IsTrue (ufe.IsSymbolicLink, "testApp.exe IsSymbolicLink"); // Don't check for mscorlib.dll, there might be two versions of it (since Xamarin.iOS.dll depends on it), or there might not.
FileAssert.Exists (Path.Combine (mtouch.AppPath, ".monotouch-32", "Xamarin.iOS.dll"));
} }
} }
@ -1873,7 +2526,6 @@ class Test {
{ {
using (var tool = new MTouchTool ()) { using (var tool = new MTouchTool ()) {
tool.Profile = profile; tool.Profile = profile;
tool.Verbosity = 5;
tool.Cache = Path.Combine (tool.CreateTemporaryDirectory (), "mtouch-test-cache"); tool.Cache = Path.Combine (tool.CreateTemporaryDirectory (), "mtouch-test-cache");
tool.CreateTemporaryApp (code: "using UIKit; class C { static void Main (string[] args) { UIApplication.Main (args); } }"); tool.CreateTemporaryApp (code: "using UIKit; class C { static void Main (string[] args) { UIApplication.Main (args); } }");
tool.FastDev = true; tool.FastDev = true;
@ -1889,8 +2541,6 @@ class Test {
using (var tool = new MTouchTool ()) { using (var tool = new MTouchTool ()) {
tool.Profile = Profile.watchOS; tool.Profile = Profile.watchOS;
tool.CreateTemporaryCacheDirectory (); tool.CreateTemporaryCacheDirectory ();
tool.Verbosity = 5;
tool.Extension = true;
tool.CreateTemporaryWatchKitExtension (); tool.CreateTemporaryWatchKitExtension ();
tool.FastDev = true; tool.FastDev = true;
@ -1944,9 +2594,6 @@ class C {
using (var exttool = new MTouchTool ()) { using (var exttool = new MTouchTool ()) {
exttool.Profile = Profile.watchOS; exttool.Profile = Profile.watchOS;
exttool.CreateTemporaryCacheDirectory (); exttool.CreateTemporaryCacheDirectory ();
exttool.Verbosity = 5;
exttool.Extension = true;
exttool.CreateTemporaryWatchKitExtension (); exttool.CreateTemporaryWatchKitExtension ();
exttool.Frameworks.Add (Path.Combine (Configuration.SourceRoot, "tests/test-libraries/.libs/watchos/XTest.framework")); exttool.Frameworks.Add (Path.Combine (Configuration.SourceRoot, "tests/test-libraries/.libs/watchos/XTest.framework"));
exttool.AssertExecute (MTouchAction.BuildSim, "build extension"); exttool.AssertExecute (MTouchAction.BuildSim, "build extension");
@ -1954,9 +2601,9 @@ class C {
using (var apptool = new MTouchTool ()) { using (var apptool = new MTouchTool ()) {
apptool.Profile = Profile.iOS; apptool.Profile = Profile.iOS;
apptool.CreateTemporaryCacheDirectory (); apptool.CreateTemporaryCacheDirectory ();
apptool.Verbosity = exttool.Verbosity; apptool.Linker = MTouchLinker.DontLink; // faster
apptool.CreateTemporaryApp (); apptool.CreateTemporaryApp ();
apptool.AppExtensions.Add (exttool.AppPath); apptool.AppExtensions.Add (exttool);
apptool.AssertExecute (MTouchAction.BuildSim, "build app"); apptool.AssertExecute (MTouchAction.BuildSim, "build app");
Assert.IsFalse (Directory.Exists (Path.Combine (apptool.AppPath, "Frameworks", "XTest.framework")), "framework inexistence"); Assert.IsFalse (Directory.Exists (Path.Combine (apptool.AppPath, "Frameworks", "XTest.framework")), "framework inexistence");
@ -1973,19 +2620,18 @@ class C {
using (var exttool = new MTouchTool ()) { using (var exttool = new MTouchTool ()) {
exttool.Profile = Profile.iOS; exttool.Profile = Profile.iOS;
exttool.CreateTemporaryCacheDirectory (); exttool.CreateTemporaryCacheDirectory ();
exttool.Verbosity = 5; exttool.Linker = MTouchLinker.DontLink; // faster
exttool.Extension = true; exttool.CreateTemporaryServiceExtension ();
exttool.CreateTemporararyServiceExtension ();
exttool.Frameworks.Add (Path.Combine (Configuration.SourceRoot, "tests/test-libraries/.libs/ios/XTest.framework")); exttool.Frameworks.Add (Path.Combine (Configuration.SourceRoot, "tests/test-libraries/.libs/ios/XTest.framework"));
exttool.AssertExecute (MTouchAction.BuildSim, "build extension"); exttool.AssertExecute (MTouchAction.BuildSim, "build extension");
using (var apptool = new MTouchTool ()) { using (var apptool = new MTouchTool ()) {
apptool.Profile = Profile.iOS; apptool.Profile = Profile.iOS;
apptool.CreateTemporaryCacheDirectory (); apptool.CreateTemporaryCacheDirectory ();
apptool.Verbosity = exttool.Verbosity;
apptool.CreateTemporaryApp (); apptool.CreateTemporaryApp ();
apptool.AppExtensions.Add (exttool.AppPath); apptool.AppExtensions.Add (exttool);
apptool.Linker = MTouchLinker.DontLink; // faster
apptool.AssertExecute (MTouchAction.BuildSim, "build app"); apptool.AssertExecute (MTouchAction.BuildSim, "build app");
Assert.IsTrue (Directory.Exists (Path.Combine (apptool.AppPath, "Frameworks", "XTest.framework")), "framework exists"); Assert.IsTrue (Directory.Exists (Path.Combine (apptool.AppPath, "Frameworks", "XTest.framework")), "framework exists");
@ -2002,14 +2648,13 @@ class C {
using (var exttool = new MTouchTool ()) { using (var exttool = new MTouchTool ()) {
exttool.Profile = Profile.iOS; exttool.Profile = Profile.iOS;
exttool.CreateTemporaryCacheDirectory (); exttool.CreateTemporaryCacheDirectory ();
exttool.Verbosity = 5; exttool.Linker = MTouchLinker.DontLink; // faster
exttool.Extension = true;
exttool.References = new string [] exttool.References = new string []
{ {
GetFrameworksBindingLibrary (exttool.Profile), GetFrameworksBindingLibrary (exttool.Profile),
}; };
exttool.CreateTemporararyServiceExtension (code: @"using UserNotifications; exttool.CreateTemporaryServiceExtension (code: @"using UserNotifications;
[Foundation.Register (""NotificationService"")] [Foundation.Register (""NotificationService"")]
public partial class NotificationService : UNNotificationServiceExtension public partial class NotificationService : UNNotificationServiceExtension
{ {
@ -2023,9 +2668,8 @@ public partial class NotificationService : UNNotificationServiceExtension
using (var apptool = new MTouchTool ()) { using (var apptool = new MTouchTool ()) {
apptool.Profile = Profile.iOS; apptool.Profile = Profile.iOS;
apptool.CreateTemporaryCacheDirectory (); apptool.CreateTemporaryCacheDirectory ();
apptool.Verbosity = exttool.Verbosity;
apptool.CreateTemporaryApp (); apptool.CreateTemporaryApp ();
apptool.AppExtensions.Add (exttool.AppPath); apptool.AppExtensions.Add (exttool);
apptool.AssertExecute (MTouchAction.BuildSim, "build app"); apptool.AssertExecute (MTouchAction.BuildSim, "build app");
Assert.IsTrue (Directory.Exists (Path.Combine (apptool.AppPath, "Frameworks", "XTest.framework")), "framework exists"); Assert.IsTrue (Directory.Exists (Path.Combine (apptool.AppPath, "Frameworks", "XTest.framework")), "framework exists");
@ -2096,7 +2740,6 @@ public partial class NotificationService : UNNotificationServiceExtension
using (var mtouch = new MTouchTool ()) { using (var mtouch = new MTouchTool ()) {
mtouch.Profile = Profile.watchOS; mtouch.Profile = Profile.watchOS;
mtouch.CreateTemporaryWatchKitExtension (); mtouch.CreateTemporaryWatchKitExtension ();
mtouch.Extension = true;
mtouch.HttpMessageHandler = "HttpClientHandler"; mtouch.HttpMessageHandler = "HttpClientHandler";
mtouch.AssertExecute (MTouchAction.BuildSim); mtouch.AssertExecute (MTouchAction.BuildSim);
@ -2112,6 +2755,87 @@ public partial class NotificationService : UNNotificationServiceExtension
} }
} }
[Test]
public void MT2018_a ()
{
using (var mtouch = new MTouchTool ()) {
// Create a library, copy it to a different directory, and then
// pass both as -r:.. to mtouch. Due to assembly resolution being cached,
// this will *not* show the MT2018 error (in fact I don't know if it's possible
// to run into MT2018 at all).
var tmpA = mtouch.CreateTemporaryDirectory ();
var dllA = CompileTestAppCode ("library", tmpA, "public class X {}", appName: "testLib");
var tmpB = mtouch.CreateTemporaryDirectory ();
var dllB = Path.Combine (tmpB, Path.GetFileName (dllA));
File.Copy (dllA, dllB);
mtouch.CreateTemporaryApp (code: "public class C { static void Main () { System.Console.WriteLine (typeof (X)); System.Console.WriteLine (typeof (UIKit.UIWindow)); } }", extraArg: "-r:" + Quote (dllA));
mtouch.References = new string [] { dllA, dllB };
mtouch.Linker = MTouchLinker.DontLink;
mtouch.AssertExecute (MTouchAction.BuildSim, "build");
mtouch.AssertWarningPattern (109, "The assembly 'testLib.dll' was loaded from a different path than the provided path .provided path: .*/testLib.dll, actual path: .*/testLib.dll..");
}
}
[Test]
public void MT2018_b ()
{
using (var mtouch = new MTouchTool ()) {
// Create a library named as an SDK assembly, and then
// pass both as -r:.. to mtouch, this library being the first one.
// Due to assembly resolution being cached,
// this will *not* show the MT2018 error (in fact I don't know if it's possible
// to run into MT2018 at all).
var tmpA = mtouch.CreateTemporaryDirectory ();
var dllA = CompileTestAppCode ("library", tmpA, "public class X {}", appName: "System.Net.Http");
var dllB = Path.Combine (Configuration.SdkRootXI, "lib", "mono", "Xamarin.iOS", Path.GetFileName (dllA));
mtouch.CreateTemporaryApp (code: "public class C { static void Main () { System.Console.WriteLine (typeof (X)); System.Console.WriteLine (typeof (UIKit.UIWindow)); } }", extraArg: "-r:" + Quote (dllA));
mtouch.References = new string [] { dllA, dllB };
// Without the linker we'll just copy the references, and not actually run into problems if we copy one that doesn't work
mtouch.Linker = MTouchLinker.DontLink;
mtouch.AssertExecute (MTouchAction.BuildSim, "build");
mtouch.AssertWarningPattern (109, "The assembly 'System.Net.Http.dll' was loaded from a different path than the provided path .provided path: .*/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.iOS/System.Net.Http.dll, actual path: .*CreateTemporaryDirectory.*/System.Net.Http.dll..");
// With the linker, we'll find out that we've loaded the right one.
mtouch.Linker = MTouchLinker.LinkSdk;
mtouch.AssertExecute (MTouchAction.BuildSim, "build");
mtouch.AssertWarningPattern (109, "The assembly 'System.Net.Http.dll' was loaded from a different path than the provided path .provided path: .*/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/Xamarin.iOS/System.Net.Http.dll, actual path: .*CreateTemporaryDirectory.*/System.Net.Http.dll..");
}
}
[Test]
public void MT2018_c ()
{
using (var mtouch = new MTouchTool ()) {
// Create a library named as an SDK assembly, and then
// pass both as -r:.. to mtouch, the SDK library being the first one.
// Due to assembly resolution being cached,
// this will *not* show the MT2018 error (in fact I don't know if it's possible
// to run into MT2018 at all).
var tmpA = mtouch.CreateTemporaryDirectory ();
var dllA = CompileTestAppCode ("library", tmpA, "public class X {}", appName: "System.Net.Http");
var dllB = Path.Combine (Configuration.SdkRootXI, "lib", "mono", "Xamarin.iOS", Path.GetFileName (dllA));
mtouch.CreateTemporaryApp (code: "public class C { static void Main () { System.Console.WriteLine (typeof (X)); System.Console.WriteLine (typeof (UIKit.UIWindow)); } }", extraArg: "-r:" + Quote (dllA));
mtouch.References = new string [] { dllB, dllA };
// Without the linker we'll just copy the references, and not actually run into problems if we copy one that doesn't work
mtouch.Linker = MTouchLinker.DontLink;
mtouch.AssertExecute (MTouchAction.BuildSim, "build");
mtouch.AssertWarningPattern (109, "The assembly 'System.Net.Http.dll' was loaded from a different path than the provided path .provided path: .*CreateTemporaryDirectory.*/System.Net.Http.dll, actual path: .*/Library/Frameworks/Xamarin.iOS.framework/Versions/.*/lib/mono/Xamarin.iOS/System.Net.Http.dll..");
// With the linker, we'll find out that the loaded reference doesn't work.
mtouch.Linker = MTouchLinker.LinkSdk;
mtouch.AssertExecuteFailure (MTouchAction.BuildSim, "build");
mtouch.AssertError (2002, "Failed to resolve \"X\" reference from \"System.Net.Http, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null\"");
}
}
[Test] [Test]
public void AutoLinkWithSqlite () public void AutoLinkWithSqlite ()
{ {
@ -2141,17 +2865,19 @@ public class TestApp {
} }
#region Helper functions #region Helper functions
public static string CompileTestAppExecutable (string targetDirectory, string code = null, string extraArg = "", Profile profile = Profile.iOS, string appName = "testApp") public static string CompileTestAppExecutable (string targetDirectory, string code = null, string extraArg = "", Profile profile = Profile.iOS, string appName = "testApp", string extraCode = null)
{ {
if (code == null) if (code == null)
code = "public class TestApp { static void Main () { System.Console.WriteLine (typeof (ObjCRuntime.Runtime).ToString ()); } }"; code = "public class TestApp { static void Main () { System.Console.WriteLine (typeof (ObjCRuntime.Runtime).ToString ()); } }";
if (extraCode != null)
code += extraCode;
return CompileTestAppCode ("exe", targetDirectory, code, extraArg, profile, appName); return CompileTestAppCode ("exe", targetDirectory, code, extraArg, profile, appName);
} }
public static string CompileTestAppLibrary (string targetDirectory, string code, string extraArg = null, Profile profile = Profile.iOS) public static string CompileTestAppLibrary (string targetDirectory, string code, string extraArg = null, Profile profile = Profile.iOS, string appName = "testApp")
{ {
return CompileTestAppCode ("library", targetDirectory, code, extraArg, profile); return CompileTestAppCode ("library", targetDirectory, code, extraArg, profile, appName);
} }
public static string CompileTestAppCode (string target, string targetDirectory, string code, string extraArg = "", Profile profile = Profile.iOS, string appName = "testApp") public static string CompileTestAppCode (string target, string targetDirectory, string code, string extraArg = "", Profile profile = Profile.iOS, string appName = "testApp")
@ -2389,7 +3115,7 @@ public class TestApp {
public static string Quote (string f) public static string Quote (string f)
{ {
if (f.IndexOf (' ') == -1 && f.IndexOf ('\'') == -1 && f.IndexOf (',') == -1) if (f.IndexOf (' ') == -1 && f.IndexOf ('\'') == -1 && f.IndexOf (',') == -1 && f.IndexOf ('\\') == -1)
return f; return f;
var s = new StringBuilder (); var s = new StringBuilder ();

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

@ -32,6 +32,14 @@ namespace Xamarin
Static, Static,
} }
public enum MTouchBitcode
{
Unspecified,
ASMOnly,
Full, // LLVMOnly
Marker,
}
[Flags] [Flags]
enum I18N enum I18N
{ {
@ -74,22 +82,32 @@ namespace Xamarin
public MTouchRegistrar Registrar; public MTouchRegistrar Registrar;
public I18N I18N; public I18N I18N;
public bool? Extension; public bool? Extension;
public List<string> AppExtensions = new List<string> (); public List<MTouchTool> AppExtensions = new List<MTouchTool> ();
public List<string> Frameworks = new List<string> (); public List<string> Frameworks = new List<string> ();
public string HttpMessageHandler; public string HttpMessageHandler;
public bool? PackageMdb; public bool? PackageMdb;
public bool? MSym; public bool? MSym;
public bool? DSym; public bool? DSym;
public bool? NoStrip;
public string Mono; public string Mono;
public string GccFlags; public string GccFlags;
#pragma warning restore 649
// These are a bit smarter // These are a bit smarter
public Profile Profile = Profile.iOS; public Profile Profile = Profile.iOS;
public bool NoPlatformAssemblyReference; public bool NoPlatformAssemblyReference;
public List<string> AssemblyBuildTargets = new List<string> ();
static XmlDocument device_list_cache; static XmlDocument device_list_cache;
public string LLVMOptimizations; public string LLVMOptimizations;
public string [] CustomArguments; // Sometimes you want to pass invalid arguments to mtouch, in this case this array is used. No processing will be done, if quotes are required, they must be added to the arguments in the array. public string [] CustomArguments; // Sometimes you want to pass invalid arguments to mtouch, in this case this array is used. No processing will be done, if quotes are required, they must be added to the arguments in the array.
public int [] NoWarn; // null array: no passed to mtouch. empty array: pass --nowarn (which means disable all warnings).
public int [] WarnAsError; // null array: no passed to mtouch. empty array: pass --warnaserror (which means makes all warnings errors).
public MTouchBitcode Bitcode;
public string AotArguments;
public string AotOtherArguments;
public string [] LinkSkip;
public string [] XmlDefinitions;
#pragma warning restore 649
public class DeviceInfo public class DeviceInfo
{ {
@ -201,6 +219,9 @@ namespace Xamarin
if (PackageMdb.HasValue) if (PackageMdb.HasValue)
sb.Append (" --package-mdb:").Append (PackageMdb.Value ? "true" : "false"); sb.Append (" --package-mdb:").Append (PackageMdb.Value ? "true" : "false");
if (NoStrip.HasValue && NoStrip.Value)
sb.Append (" --nostrip");
if (MSym.HasValue) if (MSym.HasValue)
sb.Append (" --msym:").Append (MSym.Value ? "true" : "false"); sb.Append (" --msym:").Append (MSym.Value ? "true" : "false");
@ -211,7 +232,7 @@ namespace Xamarin
sb.Append (" --extension"); sb.Append (" --extension");
foreach (var appext in AppExtensions) foreach (var appext in AppExtensions)
sb.Append (" --app-extension ").Append (MTouch.Quote (appext)); sb.Append (" --app-extension ").Append (MTouch.Quote (appext.AppPath));
foreach (var framework in Frameworks) foreach (var framework in Frameworks)
sb.Append (" --framework ").Append (MTouch.Quote (framework)); sb.Append (" --framework ").Append (MTouch.Quote (framework));
@ -338,6 +359,50 @@ namespace Xamarin
} }
} }
if (NoWarn != null) {
if (NoWarn.Length > 0) {
sb.Append (" --nowarn:");
foreach (var code in NoWarn)
sb.Append (code).Append (',');
sb.Length--;
} else {
sb.Append (" --nowarn");
}
}
if (WarnAsError != null) {
if (WarnAsError.Length > 0) {
sb.Append (" --warnaserror:");
foreach (var code in WarnAsError)
sb.Append (code).Append (',');
sb.Length--;
} else {
sb.Append (" --warnaserror");
}
}
if (Bitcode != MTouchBitcode.Unspecified)
sb.Append (" --bitcode:").Append (Bitcode.ToString ().ToLower ());
foreach (var abt in AssemblyBuildTargets)
sb.Append (" --assembly-build-target ").Append (MTouch.Quote (abt));
if (!string.IsNullOrEmpty (AotArguments))
sb.Append (" --aot:").Append (MTouch.Quote (AotArguments));
if (!string.IsNullOrEmpty (AotOtherArguments))
sb.Append (" --aot-options:").Append (MTouch.Quote (AotOtherArguments));
if (LinkSkip?.Length > 0) {
foreach (var ls in LinkSkip)
sb.Append (" --linkskip:").Append (MTouch.Quote (ls));
}
if (XmlDefinitions?.Length > 0) {
foreach (var xd in XmlDefinitions)
sb.Append (" --xml:").Append (MTouch.Quote (xd));
}
return sb.ToString (); return sb.ToString ();
} }
@ -453,7 +518,17 @@ namespace Xamarin
return plist; return plist;
} }
public void CreateTemporaryApp (bool hasPlist = false, string appName = "testApp", string code = null) public string CreateTemporarySatelliteAssembly (string culture = "en-AU")
{
var asm_dir = Path.Combine (Path.GetDirectoryName (RootAssembly), culture);
Directory.CreateDirectory (asm_dir);
var asm_name = Path.GetFileNameWithoutExtension (RootAssembly) + ".resources.dll";
// Cheat a bit, by compiling a normal assembly with code instead of creating a resource assembly
return MTouch.CompileTestAppLibrary (asm_dir, "class X {}", appName: Path.GetFileNameWithoutExtension (asm_name));
}
public void CreateTemporaryApp (bool hasPlist = false, string appName = "testApp", string code = null, string extraArg = "", string extraCode = null)
{ {
string testDir; string testDir;
if (RootAssembly == null) { if (RootAssembly == null) {
@ -465,16 +540,22 @@ namespace Xamarin
var app = AppPath ?? Path.Combine (testDir, appName + ".app"); var app = AppPath ?? Path.Combine (testDir, appName + ".app");
Directory.CreateDirectory (app); Directory.CreateDirectory (app);
AppPath = app; AppPath = app;
RootAssembly = MTouch.CompileTestAppExecutable (testDir, code, "", Profile, appName); RootAssembly = MTouch.CompileTestAppExecutable (testDir, code, extraArg, Profile, appName, extraCode);
if (hasPlist) if (hasPlist)
File.WriteAllText (Path.Combine (app, "Info.plist"), CreatePlist (Profile, appName)); File.WriteAllText (Path.Combine (app, "Info.plist"), CreatePlist (Profile, appName));
} }
public void CreateTemporararyServiceExtension (string code = null, string extraArg = null) public void CreateTemporaryServiceExtension (string code = null, string extraCode = null, string extraArg = null, string appName = "testServiceExtension")
{ {
var testDir = CreateTemporaryDirectory (); string testDir;
var app = Path.Combine (testDir, "testApp.appex"); if (RootAssembly == null) {
testDir = CreateTemporaryDirectory ();
} else {
// We're rebuilding an existing executable, so just reuse that
testDir = Path.GetDirectoryName (RootAssembly);
}
var app = AppPath ?? Path.Combine (testDir, $"{appName}.appex");
Directory.CreateDirectory (app); Directory.CreateDirectory (app);
if (code == null) { if (code == null) {
@ -485,11 +566,14 @@ public partial class NotificationService : UNNotificationServiceExtension
protected NotificationService (System.IntPtr handle) : base (handle) {} protected NotificationService (System.IntPtr handle) : base (handle) {}
}"; }";
} }
if (extraCode != null)
code += extraCode;
AppPath = app; AppPath = app;
RootAssembly = MTouch.CompileTestAppLibrary (testDir, code: code, profile: Profile, extraArg: extraArg); Extension = true;
RootAssembly = MTouch.CompileTestAppLibrary (testDir, code: code, profile: Profile, extraArg: extraArg, appName: appName);
File.WriteAllText (Path.Combine (app, "Info.plist"), var info_plist =
@"<?xml version=""1.0"" encoding=""UTF-8""?> @"<?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""> <!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">
<plist version=""1.0""> <plist version=""1.0"">
@ -521,7 +605,10 @@ public partial class NotificationService : UNNotificationServiceExtension
</dict> </dict>
</dict> </dict>
</plist> </plist>
"); ";
var plist_path = Path.Combine (app, "Info.plist");
if (!File.Exists (plist_path) || File.ReadAllText (plist_path) != info_plist)
File.WriteAllText (plist_path, info_plist);
} }
public void CreateTemporaryWatchKitExtension (string code = null) public void CreateTemporaryWatchKitExtension (string code = null)
@ -545,6 +632,7 @@ public partial class NotificationController : WKUserNotificationInterfaceControl
} }
AppPath = app; AppPath = app;
Extension = true;
RootAssembly = MTouch.CompileTestAppLibrary (testDir, code: code, profile: Profile); RootAssembly = MTouch.CompileTestAppLibrary (testDir, code: code, profile: Profile);
File.WriteAllText (Path.Combine (app, "Info.plist"), @"<?xml version=""1.0"" encoding=""UTF-8""?> File.WriteAllText (Path.Combine (app, "Info.plist"), @"<?xml version=""1.0"" encoding=""UTF-8""?>

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

@ -27,7 +27,7 @@ bug-13945:
@$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/mtouch -r:binding.dll app.exe --abi=armv7 -sdk "$(IOS_SDK_VERSION)" -dev:TheApp.app -sdkroot $(XCODE_DEVELOPER_ROOT) --cache=$(shell pwd)/cache -r:$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.iOS/Xamarin.iOS.dll @$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/bin/mtouch -r:binding.dll app.exe --abi=armv7 -sdk "$(IOS_SDK_VERSION)" -dev:TheApp.app -sdkroot $(XCODE_DEVELOPER_ROOT) --cache=$(shell pwd)/cache -r:$(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.iOS/Xamarin.iOS.dll
# this will verify that binding.dll wasn't AOT'ed again - if binding.dll.armv7.s differ then the AOT compiler executed. # this will verify that binding.dll wasn't AOT'ed again - if binding.dll.armv7.s differ then the AOT compiler executed.
@diff -u cache-first/binding.dll.armv7.s cache/binding.dll.armv7.s @diff -u cache-first/armv7/binding.dll.s cache/armv7/binding.dll.s
@echo "$@: Success" @echo "$@: Success"
include $(TOP)/mk/rules.mk include $(TOP)/mk/rules.mk

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

@ -14,12 +14,12 @@
<OutputPath>bin\$(Platform)\$(Configuration)-today</OutputPath> <OutputPath>bin\$(Platform)\$(Configuration)-today</OutputPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'iPhoneSimulator' "> <PropertyGroup Condition=" '$(Platform)' == 'iPhoneSimulator' ">
<MtouchArch>x86_64</MtouchArch> <MtouchArch>x86_64,i386</MtouchArch>
<MtouchLink>None</MtouchLink> <MtouchLink>None</MtouchLink>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'iPhone' "> <PropertyGroup Condition=" '$(Platform)' == 'iPhone' ">
<MtouchArch>ARM64</MtouchArch> <MtouchArch>ARM64,ARMv7</MtouchArch>
<MtouchLink>Full</MtouchLink> <MtouchLink>SdkOnly</MtouchLink>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' Or '$(Configuration)' == 'Debug32' Or '$(Configuration)' == 'Debug64' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' Or '$(Configuration)' == 'Debug32' Or '$(Configuration)' == 'Debug64' ">
<DebugSymbols>True</DebugSymbols> <DebugSymbols>True</DebugSymbols>

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

@ -42,7 +42,7 @@
<InterfaceDefinition Include="TodayView.storyboard" /> <InterfaceDefinition Include="TodayView.storyboard" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Main.cs" /> <Compile Include="TodayExtensionMain.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.AppExtension.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.AppExtension.CSharp.targets" />
</Project> </Project>

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

@ -7,6 +7,7 @@ using UIKit;
using MonoTouch.NUnit.UI; using MonoTouch.NUnit.UI;
using NUnit.Framework; using NUnit.Framework;
using NUnit.Framework.Internal; using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Filters;
[Register ("TodayViewController")] [Register ("TodayViewController")]
public partial class TodayViewController : UIViewController, INCWidgetProviding public partial class TodayViewController : UIViewController, INCWidgetProviding
@ -20,6 +21,7 @@ public partial class TodayViewController : UIViewController, INCWidgetProviding
{ {
runner = new ConsoleRunner (); runner = new ConsoleRunner ();
runner.Add (System.Reflection.Assembly.GetExecutingAssembly ()); runner.Add (System.Reflection.Assembly.GetExecutingAssembly ());
runner.Filter = new NotFilter (new CategoryExpression ("MobileNotWorking,NotOnMac,NotWorking,ValueAdd,CAS,InetAccess,NotWorkingInterpreter").Filter);
System.Threading.ThreadPool.QueueUserWorkItem ((v) => System.Threading.ThreadPool.QueueUserWorkItem ((v) =>
{ {
runner.LoadSync (); runner.LoadSync ();

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

@ -0,0 +1,38 @@
namespace todayextensiontests
open System
open System.Threading
open NotificationCenter
open Foundation
open UIKit
open MonoTouch.NUnit.UI
open NUnit.Framework
open NUnit.Framework.Internal
open NUnit.Framework.Internal.Filters
[<Register ("TodayViewController")>]
type TodayViewController() =
inherit UIViewController()
let mutable runner = Unchecked.defaultof<ConsoleRunner>
[<Export ("widgetPerformUpdateWithCompletionHandler:")>]
member this.WidgetPerformUpdate (completionHandler: Action<NCUpdateResult>) =
runner <- new ConsoleRunner ()
let ce = new CategoryExpression ("MobileNotWorking,NotOnMac,NotWorking,ValueAdd,CAS,InetAccess,NotWorkingInterpreter")
runner.Filter <- new NotFilter (ce.Filter)
let tp = this.GetType ()
runner.Add (tp.Assembly)
ThreadPool.QueueUserWorkItem (fun v ->
runner.LoadSync ()
this.BeginInvokeOnMainThread (fun x ->
runner.AutoStart <- true
runner.AutoRun ()
)
)
|> ignore
completionHandler.Invoke (NCUpdateResult.NewData)
interface INCWidgetProviding

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

@ -40,6 +40,7 @@ $(2)_TARGETS = \
.libs/$(1)/XStaticObjectTest.framework/XStaticObjectTest \ .libs/$(1)/XStaticObjectTest.framework/XStaticObjectTest \
.libs/$(1)/XStaticArTest.framework/XStaticArTest \ .libs/$(1)/XStaticArTest.framework/XStaticArTest \
.libs/$(1)/libtest.dylib \ .libs/$(1)/libtest.dylib \
.libs/$(1)/libtest2.a \
.libs/$(1)/libtest.a \ .libs/$(1)/libtest.a \
.libs/$(1)/libtest-object.a \ .libs/$(1)/libtest-object.a \
.libs/$(1)/libtest-ar.a \ .libs/$(1)/libtest-ar.a \
@ -67,6 +68,10 @@ EXTRA_DEPENDENCIES = libtest.h $(GENERATED_FILES)
$(Q) rm -f $$@ $(Q) rm -f $$@
$$(call Q_2,LIPO [$(1)]) $(XCODE_DEVELOPER_ROOT)/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo $$^ -create -output $$@ $$(call Q_2,LIPO [$(1)]) $(XCODE_DEVELOPER_ROOT)/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo $$^ -create -output $$@
.libs/$(1)/libtest2.a: $$(foreach arch,$(3),.libs/$(1)/libtest2.$$(arch).a)
$(Q) rm -f $$@
$$(call Q_2,LIPO [$(1)]) $(XCODE_DEVELOPER_ROOT)/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo $$^ -create -output $$@
.libs/$(1)/libtest-object.a: $$(foreach arch,$(3),.libs/$(1)/libtest-object.$$(arch).a) .libs/$(1)/libtest-object.a: $$(foreach arch,$(3),.libs/$(1)/libtest-object.$$(arch).a)
$(Q) rm -f $$@ $(Q) rm -f $$@
$$(call Q_2,LIPO [$(1)]) $(XCODE_DEVELOPER_ROOT)/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo $$^ -create -output $$@ $$(call Q_2,LIPO [$(1)]) $(XCODE_DEVELOPER_ROOT)/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo $$^ -create -output $$@

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

@ -0,0 +1,10 @@
#ifdef __cplusplus
extern "C" {
#endif
int getIntOfChocolate ();
#ifdef __cplusplus
} /* extern "C" */
#endif

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

@ -0,0 +1,7 @@
#include "libtest.h"
#include "libtest2.h"
int getIntOfChocolate ()
{
return theUltimateAnswer ();
}

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

@ -39,6 +39,7 @@ namespace xharness
public string AppPath; public string AppPath;
public TestExecutingResult Result { get; private set; } public TestExecutingResult Result { get; private set; }
public string FailureMessage { get; private set; }
string appName; string appName;
string appPath; string appPath;
@ -735,6 +736,59 @@ namespace xharness
} else { } else {
Result = TestExecutingResult.Failed; Result = TestExecutingResult.Failed;
} }
// Check crash reports to see if any of them explains why the test run crashed.
if (!success.Value) {
int pid = 0;
string crash_reason = null;
foreach (var crash in crash_reports.Logs) {
try {
if (pid == 0) {
// Find the pid
using (var log_reader = main_log.GetReader ()) {
string line;
while ((line = log_reader.ReadLine ()) != null) {
const string str = "was launched with pid '";
var idx = line.IndexOf (str, StringComparison.Ordinal);
if (idx > 0) {
idx += str.Length;
var next_idx = line.IndexOf ('\'', idx);
if (next_idx > idx)
int.TryParse (line.Substring (idx, next_idx - idx), out pid);
}
if (pid != 0)
break;
}
}
}
using (var crash_reader = crash.GetReader ()) {
var text = crash_reader.ReadToEnd ();
var reader = System.Runtime.Serialization.Json.JsonReaderWriterFactory.CreateJsonReader (Encoding.UTF8.GetBytes (text), new XmlDictionaryReaderQuotas ());
var doc = new XmlDocument ();
doc.Load (reader);
foreach (XmlNode node in doc.SelectNodes ($"/root/processes/item[pid = '" + pid + "']")) {
Console.WriteLine (node?.InnerXml);
Console.WriteLine (node?.SelectSingleNode ("reason")?.InnerText);
crash_reason = node?.SelectSingleNode ("reason")?.InnerText;
}
}
if (crash_reason != null)
break;
} catch (Exception e) {
Console.WriteLine ("Failed to process crash report {1}: {0}", e.Message, crash.Description);
}
}
if (!string.IsNullOrEmpty (crash_reason)) {
if (crash_reason == "per-process-limit") {
FailureMessage = "Killed due to using too much memory (per-process-limit).";
} else {
FailureMessage = $"Killed by the OS ({crash_reason})";
}
}
}
return success.Value ? 0 : 1; return success.Value ? 0 : 1;
} }

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

@ -276,27 +276,27 @@ namespace xharness
void AutoConfigureMac () void AutoConfigureMac ()
{ {
var test_suites = new string[] { "apitest", "dontlink-mac" }; var test_suites = new [] { new { ProjectFile = "apitest", Name = "apitest" }, new { ProjectFile = "dontlink-mac", Name = "dont link" } };
foreach (var p in test_suites) foreach (var p in test_suites)
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".csproj")))); MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, p.ProjectFile + "/" + p.ProjectFile + ".csproj"))) { Name = p.Name });
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "introspection", "Mac", "introspection-mac.csproj")), skipXMVariations : true)); MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "introspection", "Mac", "introspection-mac.csproj")), skipXMVariations : true));
var hard_coded_test_suites = new string[] { "mmptest", "msbuild-mac", "xammac_tests" }; var hard_coded_test_suites = new [] { new { ProjectFile = "mmptest", Name = "mmptest" }, new { ProjectFile = "msbuild-mac", Name = "MSBuild tests" }, new { ProjectFile = "xammac_tests", Name = "xammac tests" } };
foreach (var p in hard_coded_test_suites) foreach (var p in hard_coded_test_suites)
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".csproj")), generateVariations: false)); MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, p.ProjectFile + "/" + p.ProjectFile + ".csproj")), generateVariations: false) { Name = p.Name });
var bcl_suites = new string[] { "mscorlib", "System", "System.Core", "System.Data", "System.Net.Http", "System.Numerics", "System.Runtime.Serialization", "System.Transactions", "System.Web.Services", "System.Xml", "System.Xml.Linq", "Mono.Security", "System.ComponentModel.DataAnnotations", "System.Json", "System.ServiceModel.Web", "Mono.Data.Sqlite" }; var bcl_suites = new string[] { "mscorlib", "System", "System.Core", "System.Data", "System.Net.Http", "System.Numerics", "System.Runtime.Serialization", "System.Transactions", "System.Web.Services", "System.Xml", "System.Xml.Linq", "Mono.Security", "System.ComponentModel.DataAnnotations", "System.Json", "System.ServiceModel.Web", "Mono.Data.Sqlite" };
foreach (var p in bcl_suites) { foreach (var p in bcl_suites) {
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "bcl-test/" + p + "/" + p + "-Mac.csproj")), generateVariations: false)); MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "bcl-test/" + p + "/" + p + "-Mac.csproj")), generateVariations: false) { Name = p });
MacBclTests.Add (new MacBCLTest (p)); MacBclTests.Add (new MacBCLTest (p));
} }
} }
void AutoConfigureIOS () void AutoConfigureIOS ()
{ {
var test_suites = new string [] { "monotouch-test", "framework-test", "mini" }; var test_suites = new string [] { "monotouch-test", "framework-test", "mini", "interdependent-binding-projects" };
var library_projects = new string [] { "BundledResources", "EmbeddedResources", "bindings-test", "bindings-framework-test" }; var library_projects = new string [] { "BundledResources", "EmbeddedResources", "bindings-test", "bindings-test2", "bindings-framework-test" };
var fsharp_test_suites = new string [] { "fsharp" }; var fsharp_test_suites = new string [] { "fsharp" };
var fsharp_library_projects = new string [] { "fsharplibrary" }; var fsharp_library_projects = new string [] { "fsharplibrary" };
var bcl_suites = new string [] { "mscorlib", "System", "System.Core", "System.Data", "System.Net.Http", "System.Numerics", "System.Runtime.Serialization", "System.Transactions", "System.Web.Services", "System.Xml", "System.Xml.Linq", "Mono.Security", "System.ComponentModel.DataAnnotations", "System.Json", "System.ServiceModel.Web", "Mono.Data.Sqlite" }; var bcl_suites = new string [] { "mscorlib", "System", "System.Core", "System.Data", "System.Net.Http", "System.Numerics", "System.Runtime.Serialization", "System.Transactions", "System.Web.Services", "System.Xml", "System.Xml.Linq", "Mono.Security", "System.ComponentModel.DataAnnotations", "System.Json", "System.ServiceModel.Web", "Mono.Data.Sqlite" };

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

@ -183,6 +183,20 @@ namespace xharness
foreach (var task in rv) foreach (var task in rv)
task.Variation = "Debug"; task.Variation = "Debug";
var assembly_build_targets = new []
{
/* we don't add --assembly-build-target=@all=staticobject because that's the default in all our test projects */
new { Variation = "AssemblyBuildTarget: dylib (debug)", MTouchExtraArgs = "--assembly-build-target=@all=dynamiclibrary", Debug = true, Profiling = false },
new { Variation = "AssemblyBuildTarget: SDK framework (debug)", MTouchExtraArgs = "--assembly-build-target=@sdk=framework=Xamarin.Sdk --assembly-build-target=@all=staticobject", Debug = true, Profiling = false },
new { Variation = "AssemblyBuildTarget: dylib (debug, profiling)", MTouchExtraArgs = "--assembly-build-target=@all=dynamiclibrary", Debug = true, Profiling = true },
new { Variation = "AssemblyBuildTarget: SDK framework (debug, profiling)", MTouchExtraArgs = "--assembly-build-target=@sdk=framework=Xamarin.Sdk --assembly-build-target=@all=staticobject", Debug = true, Profiling = true },
new { Variation = "Release", MTouchExtraArgs = "", Debug = false, Profiling = false },
new { Variation = "AssemblyBuildTarget: SDK framework (release)", MTouchExtraArgs = "--assembly-build-target=@sdk=framework=Xamarin.Sdk --assembly-build-target=@all=staticobject", Debug = false, Profiling = false },
};
// Don't build in the original project directory // Don't build in the original project directory
// We can build multiple projects in parallel, and if some of those // We can build multiple projects in parallel, and if some of those
// projects have the same project dependencies, then we may end up // projects have the same project dependencies, then we may end up
@ -196,6 +210,43 @@ namespace xharness
device_test.TestProject = clone; device_test.TestProject = clone;
} }
foreach (var task in rv)
task.Variation = "Debug";
foreach (var task in rv.ToArray ()) {
foreach (var test_data in assembly_build_targets) {
var variation = test_data.Variation;
var mtouch_extra_args = test_data.MTouchExtraArgs;
var configuration = test_data.Debug ? task.ProjectConfiguration : task.ProjectConfiguration.Replace ("Debug", "Release");
var debug = test_data.Debug;
var profiling = test_data.Profiling;
var clone = task.TestProject.Clone ();
var clone_task = Task.Run (async () =>
{
await task.BuildTask.InitialTask; // this is the project cloning above
await clone.CreateCopyAsync (task);
if (!string.IsNullOrEmpty (mtouch_extra_args))
clone.Xml.AddExtraMtouchArgs (mtouch_extra_args, task.ProjectPlatform, configuration);
clone.Xml.SetNode ("MTouchProfiling", profiling ? "True" : "False", task.ProjectPlatform, configuration);
if (!debug)
clone.Xml.SetMtouchUseLlvm (true, task.ProjectPlatform, configuration);
clone.Xml.Save (clone.Path);
});
var build = new XBuildTask
{
Jenkins = this,
TestProject = clone,
ProjectConfiguration = configuration,
ProjectPlatform = task.ProjectPlatform,
Platform = task.Platform,
InitialTask = clone_task,
};
rv.Add (new RunDeviceTask (build, task.Candidates) { Variation = variation, Ignored = task.Ignored });
}
}
return rv; return rv;
} }
@ -404,7 +455,8 @@ namespace xharness
TestExecutable = Path.Combine (Harness.RootDirectory, "..", "packages", "NUnit.Runners.2.6.4", "tools", "nunit-console.exe"), TestExecutable = Path.Combine (Harness.RootDirectory, "..", "packages", "NUnit.Runners.2.6.4", "tools", "nunit-console.exe"),
WorkingDirectory = Path.Combine (Harness.RootDirectory, "..", "packages", "NUnit.Runners.2.6.4", "tools", "lib"), WorkingDirectory = Path.Combine (Harness.RootDirectory, "..", "packages", "NUnit.Runners.2.6.4", "tools", "lib"),
Platform = TestPlatform.iOS, Platform = TestPlatform.iOS,
TestName = "MSBuild tests - iOS", TestName = "MSBuild tests",
Mode = "iOS",
Timeout = TimeSpan.FromMinutes (30), Timeout = TimeSpan.FromMinutes (30),
Ignored = !IncludeiOSMSBuild, Ignored = !IncludeiOSMSBuild,
}; };
@ -438,7 +490,8 @@ namespace xharness
var exec = new MacExecuteTask (build) var exec = new MacExecuteTask (build)
{ {
Ignored = ignored || !IncludeClassicMac, Ignored = ignored || !IncludeClassicMac,
BCLTest = project.IsBclTest BCLTest = project.IsBclTest,
TestName = project.Name,
}; };
Tasks.Add (exec); Tasks.Add (exec);
@ -527,6 +580,7 @@ namespace xharness
return new MacExecuteTask (build) return new MacExecuteTask (build)
{ {
Ignored = ignore, Ignored = ignore,
TestName = build.TestName,
}; };
} }
@ -597,11 +651,107 @@ namespace xharness
var response = context.Response; var response = context.Response;
var arguments = System.Web.HttpUtility.ParseQueryString (request.Url.Query); var arguments = System.Web.HttpUtility.ParseQueryString (request.Url.Query);
try { try {
var allTasks = Tasks.SelectMany ((v) =>
{
var rv = new List<TestTask> ();
var runsim = v as AggregatedRunSimulatorTask;
if (runsim != null)
rv.AddRange (runsim.Tasks);
rv.Add (v);
return rv;
});
switch (request.Url.LocalPath) { switch (request.Url.LocalPath) {
case "/": case "/":
response.ContentType = System.Net.Mime.MediaTypeNames.Text.Html; response.ContentType = System.Net.Mime.MediaTypeNames.Text.Html;
GenerateReportImpl (response.OutputStream); GenerateReportImpl (response.OutputStream);
break; break;
case "/select":
case "/deselect":
response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain;
using (var writer = new StreamWriter (response.OutputStream)) {
foreach (var task in allTasks) {
bool? is_match = null;
if (!(task.Ignored || task.NotStarted))
continue;
switch (request.Url.Query) {
case "?all":
is_match = true;
break;
case "?all-device":
is_match = task is RunDeviceTask;
break;
case "?all-simulator":
is_match = task is RunSimulatorTask;
break;
case "?all-ios":
switch (task.Platform) {
case TestPlatform.iOS:
case TestPlatform.iOS_TodayExtension64:
case TestPlatform.iOS_Unified:
case TestPlatform.iOS_Unified32:
case TestPlatform.iOS_Unified64:
is_match = true;
break;
default:
if (task.Platform.ToString ().StartsWith ("iOS", StringComparison.Ordinal))
throw new NotImplementedException ();
break;
}
break;
case "?all-tvos":
switch (task.Platform) {
case TestPlatform.tvOS:
is_match = true;
break;
default:
if (task.Platform.ToString ().StartsWith ("tvOS", StringComparison.Ordinal))
throw new NotImplementedException ();
break;
}
break;
case "?all-watchos":
switch (task.Platform) {
case TestPlatform.watchOS:
is_match = true;
break;
default:
if (task.Platform.ToString ().StartsWith ("watchOS", StringComparison.Ordinal))
throw new NotImplementedException ();
break;
}
break;
case "?all-mac":
switch (task.Platform) {
case TestPlatform.Mac:
case TestPlatform.Mac_Classic:
case TestPlatform.Mac_Unified:
case TestPlatform.Mac_Unified32:
case TestPlatform.Mac_UnifiedXM45:
case TestPlatform.Mac_UnifiedXM45_32:
is_match = true;
break;
default:
if (task.Platform.ToString ().StartsWith ("Mac", StringComparison.Ordinal))
throw new NotImplementedException ();
break;
}
break;
default:
writer.WriteLine ("unknown query: {0}", request.Url.Query);
break;
}
if (request.Url.LocalPath == "/select") {
if (is_match.HasValue && is_match.Value)
task.Ignored = false;
} else if (request.Url.LocalPath == "/deselect") {
if (is_match.HasValue && is_match.Value)
task.Ignored = true;
}
}
writer.WriteLine ("OK");
}
break;
case "/runalltests": case "/runalltests":
response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain; response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain;
using (var writer = new StreamWriter (response.OutputStream)) { using (var writer = new StreamWriter (response.OutputStream)) {
@ -621,6 +771,37 @@ namespace xharness
writer.WriteLine ("OK"); writer.WriteLine ("OK");
} }
break; break;
case "/runselected":
response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain;
using (var writer = new StreamWriter (response.OutputStream)) {
// We want to randomize the order the tests are added, so that we don't build first the test for one device,
// then for another, since that would not take advantage of running tests on several devices in parallel.
var rnd = new Random ((int) DateTime.Now.Ticks);
foreach (var task in allTasks.Where ((v) => !v.Ignored).OrderBy (v => rnd.Next ())) {
if (task.InProgress || task.Waiting) {
writer.WriteLine ($"Test '{task.TestName}' is already executing.");
} else {
task.Reset ();
task.RunAsync ();
writer.WriteLine ($"Started '{task.TestName}'.");
}
}
}
break;
case "/runfailed":
response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain;
using (var writer = new StreamWriter (response.OutputStream)) {
foreach (var task in allTasks.Where ((v) => v.Failed)) {
if (task.InProgress || task.Waiting) {
writer.WriteLine ($"Test '{task.TestName}' is already executing.");
} else {
task.Reset ();
task.RunAsync ();
writer.WriteLine ($"Started '{task.TestName}'.");
}
}
}
break;
case "/runtest": case "/runtest":
response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain; response.ContentType = System.Net.Mime.MediaTypeNames.Text.Plain;
using (var writer = new StreamWriter (response.OutputStream)) { using (var writer = new StreamWriter (response.OutputStream)) {
@ -661,6 +842,11 @@ namespace xharness
} }
server.Stop (); server.Stop ();
break; break;
case "/favicon.ico":
var favicon = File.ReadAllBytes (Path.Combine (Harness.RootDirectory, "xharness", "favicon.ico"));
response.OutputStream.Write (favicon, 0, favicon.Length);
response.OutputStream.Close ();
break;
default: default:
var path = Path.Combine (LogDirectory, request.Url.LocalPath.Substring (1)); var path = Path.Combine (LogDirectory, request.Url.LocalPath.Substring (1));
if (File.Exists (path)) { if (File.Exists (path)) {
@ -853,6 +1039,62 @@ namespace xharness
.expander { display: table-cell; height: 100%; padding-right: 6px; text-align: center; vertical-align: middle; min-width: 10px; } .expander { display: table-cell; height: 100%; padding-right: 6px; text-align: center; vertical-align: middle; min-width: 10px; }
.runall { font-size: 75%; margin-left: 3px; } .runall { font-size: 75%; margin-left: 3px; }
.logs { padding-bottom: 10px; padding-top: 10px; padding-left: 30px; } .logs { padding-bottom: 10px; padding-top: 10px; padding-left: 30px; }
#nav {
display: inline-block;
width: 200px;
}
#nav > * {
display: inline;
width: 200px;
}
#nav ul {
background: #ffffff;
list-style: none;
position: absolute;
left: -9999px;
padding: 10px;
z-index: 2;
width: 200px;
border-style: ridge;
border-width: thin;
}
#nav li {
margin-right: 10px;
position: relative;
}
#nav a {
display: block;
padding: 5px;
text-decoration: none;
}
#nav a:hover {
text-decoration: underline;
}
#nav ul li {
padding-top: 0;
padding-bottom: 0;
padding-left: 0;
}
#nav ul a {
white-space: nowrap;
}
#nav li:hover ul {
left: 0;
}
#nav li:hover a {
text-decoration: underline;
}
#nav li:hover ul a {
text-decoration:none;
}
#nav li:hover ul li a:hover {
text-decoration: underline;
}
</style> </style>
</head>"); </head>");
writer.WriteLine ("<title>Test results</title>"); writer.WriteLine ("<title>Test results</title>");
@ -1035,26 +1277,63 @@ function oninitialload ()
var headerColor = "black"; var headerColor = "black";
if (failedTests.Any ()) { if (failedTests.Any ()) {
headerColor = "red"; headerColor = "red";
} else if (passedTests.Count () != allTasks.Count) { } else if (passedTests.Any ()) {
headerColor = "gray";
} else {
headerColor = "green"; headerColor = "green";
} else {
headerColor = "gray";
} }
writer.Write ($"<span id='x{id_counter++}' class='autorefreshable'>"); writer.Write ($"<span id='x{id_counter++}' class='autorefreshable'>");
if (allTasks.Count == 0) { if (allTasks.Count == 0) {
writer.Write ($"<h2 style='color: {headerColor}'>Loading tests..."); writer.Write ($"<h2 style='color: {headerColor}'>Loading tests...");
} else if (unfinishedTests.Any ()) { } else if (unfinishedTests.Any ()) {
writer.Write ($"<h2 style='color: {headerColor}'>Test run in progress ({failedTests.Count ()} tests failed, {passedTests.Count ()} tests passed, {unfinishedTests.Count ()} tests left)"); writer.Write ($"<h2>Test run in progress (");
var list = new List<string> ();
var grouped = allTasks.GroupBy ((v) => v.ExecutionResult).OrderBy ((v) => (int) v.Key);
foreach (var @group in grouped)
list.Add ($"<span style='color: {GetTestColor (@group)}'>{@group.Key.ToString ()}: {@group.Count ()}</span>");
writer.Write (string.Join (", ", list));
writer.Write (")");
} else if (failedTests.Any ()) { } else if (failedTests.Any ()) {
writer.Write ($"<h2 style='color: {headerColor}'>{failedTests.Count ()} tests failed, {passedTests.Count ()} tests passed."); writer.Write ($"<h2 style='color: {headerColor}'>{failedTests.Count ()} tests failed, {passedTests.Count ()} tests passed.");
} else if (passedTests.Any ()) {
writer.Write ($"<h2 style='color: {headerColor}'>All {passedTests.Count ()} tests passed");
} else { } else {
writer.Write ($"<h2 style='color: {headerColor}'>All tests passed"); writer.Write ($"<h2 style='color: {headerColor}'>No tests selected.");
} }
if (IsServerMode && allTasks.Count > 0) { if (IsServerMode && allTasks.Count > 0) {
writer.Write ("<small>"); writer.WriteLine (@"</h2></span>
writer.Write (" <a href='javascript:runalltests()'>Run all tests</a>"); <ul id='nav'>
writer.WriteLine ("</small>"); <li id=""adminmenu"">Select
<ul>
<li class=""adminitem""><a href='javascript:sendrequest (""select?all"");'>All tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""select?all-device"");'>All device tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""select?all-simulator"");'>All simulator tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""select?all-ios"");'>All iOS tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""select?all-tvos"");'>All tvOS tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""select?all-watchos"");'>All watchOS tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""select?all-mac"");'>All Mac tests</a></li>
</ul>
</li>
<li id=""adminmenu"">Deselect
<ul>
<li class=""adminitem""><a href='javascript:sendrequest (""deselect?all"");'>All tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""deselect?all-device"");'>All device tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""deselect?all-simulator"");'>All simulator tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""deselect?all-ios"");'>All iOS tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""deselect?all-tvos"");'>All tvOS tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""deselect?all-watchos"");'>All watchOS tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""deselect?all-mac"");'>All Mac tests</a></li>
</ul>
</li>
<li id=""adminmenu"">Run
<ul>
<li class=""adminitem""><a href='javascript:runalltests ();'>All tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""runselected"");'>All selected tests</a></li>
<li class=""adminitem""><a href='javascript:sendrequest (""runfailed"");'>All failed tests</a></li>
</ul>
</li>
</ul>");
} }
writer.WriteLine ("</h2></span>"); writer.WriteLine ("</h2></span>");
@ -1109,8 +1388,7 @@ function oninitialload ()
if (resources.Any ()) { if (resources.Any ()) {
writer.WriteLine ($"<h3>Devices:</h3>"); writer.WriteLine ($"<h3>Devices:</h3>");
foreach (var dr in resources.OrderBy ((v) => v.Description, StringComparer.OrdinalIgnoreCase)) { foreach (var dr in resources.OrderBy ((v) => v.Description, StringComparer.OrdinalIgnoreCase)) {
var plural = dr.Users != 1 ? "s" : string.Empty; writer.WriteLine ($"{dr.Description} - {dr.Users}/{dr.MaxConcurrentUsers} users - {dr.QueuedUsers} in queue<br />");
writer.WriteLine ($"{dr.Description} - {dr.Users} user{plural} - {dr.QueuedUsers} in queue<br />");
} }
} }
} }
@ -1218,6 +1496,14 @@ function oninitialload ()
} }
if (test.Duration.Ticks > 0) if (test.Duration.Ticks > 0)
writer.WriteLine ($"Run duration: {test.Duration} <br />"); writer.WriteLine ($"Run duration: {test.Duration} <br />");
var runDeviceTest = runTest as RunDeviceTask;
if (runDeviceTest?.Device != null) {
if (runDeviceTest.CompanionDevice != null) {
writer.WriteLine ($"Device: {runDeviceTest.Device.Name} ({runDeviceTest.CompanionDevice.Name}) <br />");
} else {
writer.WriteLine ($"Device: {runDeviceTest.Device.Name} <br />");
}
}
} else { } else {
if (test.Duration.Ticks > 0) if (test.Duration.Ticks > 0)
writer.WriteLine ($"Duration: {test.Duration} <br />"); writer.WriteLine ($"Duration: {test.Duration} <br />");
@ -1236,20 +1522,31 @@ function oninitialload ()
log_target = "_self"; log_target = "_self";
break; break;
} }
writer.WriteLine ("<a href='{0}' type='{2}' target='{3}'>{1}</a><br />", System.Web.HttpUtility.UrlPathEncode (log.FullPath.Substring (LogDirectory.Length + 1)), log.Description, log_type, log_target); writer.WriteLine ("<a href='{0}' type='{2}' target='{3}'>{1}</a><br />", LinkEncode (log.FullPath.Substring (LogDirectory.Length + 1)), log.Description, log_type, log_target);
if (log.Description == "Test log" || log.Description == "Execution log") { if (log.Description == "Test log" || log.Description == "Execution log") {
var summary = string.Empty; string summary;
var fails = new List<string> (); List<string> fails;
try { try {
using (var reader = log.GetReader ()) { using (var reader = log.GetReader ()) {
Tuple<long, object> data;
if (!log_data.TryGetValue (log, out data) || data.Item1 != reader.BaseStream.Length) {
summary = string.Empty;
fails = new List<string> ();
while (!reader.EndOfStream) { while (!reader.EndOfStream) {
string line = reader.ReadLine ().Trim (); string line = reader.ReadLine ()?.Trim ();
if (line == null)
continue;
if (line.StartsWith ("Tests run:", StringComparison.Ordinal)) { if (line.StartsWith ("Tests run:", StringComparison.Ordinal)) {
summary = line; summary = line;
} else if (line.StartsWith ("[FAIL]", StringComparison.Ordinal)) { } else if (line.StartsWith ("[FAIL]", StringComparison.Ordinal)) {
fails.Add (line); fails.Add (line);
} }
} }
} else {
var data_tuple = (Tuple<string, List<string>>) data.Item2;
summary = data_tuple.Item1;
fails = data_tuple.Item2;
}
} }
if (fails.Count > 0) { if (fails.Count > 0) {
writer.WriteLine ("<div style='padding-left: 15px;'>"); writer.WriteLine ("<div style='padding-left: 15px;'>");
@ -1263,17 +1560,26 @@ function oninitialload ()
writer.WriteLine ("<span style='padding-left: 15px;'>Could not parse log file: {0}</span><br />", System.Web.HttpUtility.HtmlEncode (ex.Message)); writer.WriteLine ("<span style='padding-left: 15px;'>Could not parse log file: {0}</span><br />", System.Web.HttpUtility.HtmlEncode (ex.Message));
} }
} else if (log.Description == "Build log") { } else if (log.Description == "Build log") {
var errors = new HashSet<string> (); HashSet<string> errors;
try { try {
using (var reader = log.GetReader ()) { using (var reader = log.GetReader ()) {
Tuple<long, object> data;
if (!log_data.TryGetValue (log, out data) || data.Item1 != reader.BaseStream.Length) {
errors = new HashSet<string> ();
while (!reader.EndOfStream) { while (!reader.EndOfStream) {
string line = reader.ReadLine ()?.Trim (); string line = reader.ReadLine ()?.Trim ();
if (line == null)
continue;
// Sometimes we put error messages in pull request descriptions // Sometimes we put error messages in pull request descriptions
// Then Jenkins create environment variables containing the pull request descriptions (and other pull request data) // Then Jenkins create environment variables containing the pull request descriptions (and other pull request data)
// So exclude any lines matching 'ghprbPull', to avoid reporting those environment variables as build errors. // So exclude any lines matching 'ghprbPull', to avoid reporting those environment variables as build errors.
if (line.Contains (": error") && !line.Contains ("ghprbPull")) if (line.Contains (": error") && !line.Contains ("ghprbPull"))
errors.Add (line); errors.Add (line);
} }
log_data [log] = new Tuple<long, object> (reader.BaseStream.Length, errors);
} else {
errors = (HashSet<string>) data.Item2;
}
} }
if (errors.Count > 0) { if (errors.Count > 0) {
writer.WriteLine ("<div style='padding-left: 15px;'>"); writer.WriteLine ("<div style='padding-left: 15px;'>");
@ -1301,6 +1607,12 @@ function oninitialload ()
writer.WriteLine ("</html>"); writer.WriteLine ("</html>");
} }
} }
Dictionary<Log, Tuple<long, object>> log_data = new Dictionary<Log, Tuple<long, object>> ();
static string LinkEncode (string path)
{
return System.Web.HttpUtility.UrlEncode (path).Replace ("%2f", "/").Replace ("+", "%20");
}
string RenderTextStates (IEnumerable<TestTask> tests) string RenderTextStates (IEnumerable<TestTask> tests)
{ {
@ -1477,12 +1789,12 @@ function oninitialload ()
ExecutionResult = (ExecutionResult & ~TestExecutingResult.StateMask) | TestExecutingResult.InProgress; ExecutionResult = (ExecutionResult & ~TestExecutingResult.StateMask) | TestExecutingResult.InProgress;
try {
if (InitialTask != null) if (InitialTask != null)
await InitialTask; await InitialTask;
duration.Start (); duration.Start ();
try {
execute_task = ExecuteAsync (); execute_task = ExecuteAsync ();
await execute_task; await execute_task;
@ -1627,7 +1939,13 @@ function oninitialload ()
get { return Platform.ToString (); } get { return Platform.ToString (); }
set { throw new NotSupportedException (); } set { throw new NotSupportedException (); }
} }
}
public virtual Task CleanAsync ()
{
Console.WriteLine ("Clean is not implemented for {0}", GetType ().Name);
return Task.CompletedTask;
}
}
class MdtoolTask : BuildToolTask class MdtoolTask : BuildToolTask
{ {
@ -1747,6 +2065,46 @@ function oninitialload ()
} }
} }
} }
async Task CleanProjectAsync (Log log, string project_file, string project_platform, string project_configuration)
{
// Don't require the desktop resource here, this shouldn't be that resource sensitive
using (var xbuild = new Process ()) {
xbuild.StartInfo.FileName = "xbuild";
var args = new StringBuilder ();
args.Append ("/verbosity:diagnostic ");
if (project_platform != null)
args.Append ($"/p:Platform={project_platform} ");
if (project_configuration != null)
args.Append ($"/p:Configuration={project_configuration} ");
args.Append (Harness.Quote (project_file)).Append (" ");
args.Append ("/t:Clean ");
xbuild.StartInfo.Arguments = args.ToString ();
Jenkins.MainLog.WriteLine ("Cleaning {0} ({1}) - {2}", TestName, Mode, project_file);
SetEnvironmentVariables (xbuild);
foreach (string key in xbuild.StartInfo.EnvironmentVariables.Keys)
log.WriteLine ("{0}={1}", key, xbuild.StartInfo.EnvironmentVariables [key]);
log.WriteLine ("{0} {1}", xbuild.StartInfo.FileName, xbuild.StartInfo.Arguments);
var timeout = TimeSpan.FromMinutes (1);
await xbuild.RunAsync (log, true, timeout);
log.WriteLine ("Clean timed out after {0} seconds.", timeout.TotalSeconds);
Jenkins.MainLog.WriteLine ("Cleaned {0} ({1})", TestName, Mode);
}
}
public async override Task CleanAsync ()
{
var log = Logs.CreateStream (LogDirectory, $"clean-{Platform}-{Timestamp}.txt", "Clean log");
await CleanProjectAsync (log, ProjectFile, SpecifyPlatform ? ProjectPlatform : null, SpecifyConfiguration ? ProjectConfiguration : null);
// Iterate over all the project references as well.
var doc = new System.Xml.XmlDocument ();
doc.LoadWithoutNetworkAccess (ProjectFile);
foreach (var pr in doc.GetProjectReferences ()) {
var path = pr.Replace ('\\', '/');
await CleanProjectAsync (log, path, SpecifyPlatform ? ProjectPlatform : null, SpecifyConfiguration ? ProjectConfiguration : null);
}
}
} }
class NUnitExecuteTask : RunTestTask class NUnitExecuteTask : RunTestTask
@ -1775,10 +2133,10 @@ function oninitialload ()
public override string Mode { public override string Mode {
get { get {
return "NUnit"; return base.Mode ?? "NUnit";
} }
set { set {
throw new NotSupportedException (); base.Mode = value;
} }
} }
@ -1863,17 +2221,17 @@ function oninitialload ()
get { get {
switch (Platform) { switch (Platform) {
case TestPlatform.Mac: case TestPlatform.Mac:
return TestName; return "Mac";
case TestPlatform.Mac_Classic: case TestPlatform.Mac_Classic:
return "Classic"; return "Mac Classic";
case TestPlatform.Mac_Unified: case TestPlatform.Mac_Unified:
return "Unified"; return "Mac Unified";
case TestPlatform.Mac_Unified32: case TestPlatform.Mac_Unified32:
return "Unified 32-bit"; return "Mac Unified 32-bit";
case TestPlatform.Mac_UnifiedXM45: case TestPlatform.Mac_UnifiedXM45:
return "Unified XM45"; return "Mac Unified XM45";
case TestPlatform.Mac_UnifiedXM45_32: case TestPlatform.Mac_UnifiedXM45_32:
return "Unified XM45 32-bit"; return "Mac Unified XM45 32-bit";
default: default:
throw new NotImplementedException (); throw new NotImplementedException ();
} }
@ -2214,9 +2572,9 @@ function oninitialload ()
if (!uninstall_result.Succeeded) { if (!uninstall_result.Succeeded) {
FailureMessage = $"Uninstall failed, exit code: {uninstall_result.ExitCode}."; FailureMessage = $"Uninstall failed, exit code: {uninstall_result.ExitCode}.";
ExecutionResult = TestExecutingResult.Failed; ExecutionResult = TestExecutingResult.Failed;
return;
} }
if (!Failed) {
// Install the app // Install the app
lock (lock_obj) lock (lock_obj)
this.install_log = install_log; this.install_log = install_log;
@ -2226,17 +2584,21 @@ function oninitialload ()
if (!install_result.Succeeded) { if (!install_result.Succeeded) {
FailureMessage = $"Install failed, exit code: {install_result.ExitCode}."; FailureMessage = $"Install failed, exit code: {install_result.ExitCode}.";
ExecutionResult = TestExecutingResult.Failed; ExecutionResult = TestExecutingResult.Failed;
return;
} }
} finally { } finally {
lock (lock_obj) lock (lock_obj)
this.install_log = null; this.install_log = null;
} }
}
if (!Failed) {
// Run the app // Run the app
runner.MainLog = Logs.CreateStream (LogDirectory, $"run-{Device.UDID}-{Timestamp}.log", "Run log"); runner.MainLog = Logs.CreateStream (LogDirectory, $"run-{Device.UDID}-{Timestamp}.log", "Run log");
await runner.RunAsync (); await runner.RunAsync ();
if (!string.IsNullOrEmpty (runner.FailureMessage))
FailureMessage = runner.FailureMessage;
if (runner.Result == TestExecutingResult.Succeeded && Platform == TestPlatform.iOS_TodayExtension64) { if (runner.Result == TestExecutingResult.Succeeded && Platform == TestPlatform.iOS_TodayExtension64) {
// For the today extension, the main app is just a single test. // For the today extension, the main app is just a single test.
// This is because running the today extension will not wake up the device, // This is because running the today extension will not wake up the device,
@ -2256,16 +2618,25 @@ function oninitialload ()
}; };
additional_runner = todayRunner; additional_runner = todayRunner;
await todayRunner.RunAsync (); await todayRunner.RunAsync ();
foreach (var log in todayRunner.Logs.Where ((v) => !v.Description.StartsWith ("Extension ", StringComparison.Ordinal)))
log.Description = "Extension " + log.Description [0].ToString ().ToLower () + log.Description.Substring (1);
ExecutionResult = todayRunner.Result; ExecutionResult = todayRunner.Result;
if (!string.IsNullOrEmpty (todayRunner.FailureMessage))
FailureMessage = todayRunner.FailureMessage;
} else { } else {
ExecutionResult = runner.Result; ExecutionResult = runner.Result;
} }
}
} finally { } finally {
// Uninstall again, so that we don't leave junk behind and fill up the device. // Uninstall again, so that we don't leave junk behind and fill up the device.
runner.MainLog = uninstall_log; runner.MainLog = uninstall_log;
var uninstall_result = await runner.UninstallAsync (); var uninstall_result = await runner.UninstallAsync ();
if (!uninstall_result.Succeeded) if (!uninstall_result.Succeeded)
MainLog.WriteLine ($"Post-run uninstall failed, exit code: {uninstall_result.ExitCode} (this won't affect the test result)"); MainLog.WriteLine ($"Post-run uninstall failed, exit code: {uninstall_result.ExitCode} (this won't affect the test result)");
// Also clean up after us locally.
await BuildTask.CleanAsync ();
} }
} }
} }
@ -2474,6 +2845,14 @@ function oninitialload ()
public int Users => users; public int Users => users;
public int QueuedUsers => queue.Count + exclusive_queue.Count; public int QueuedUsers => queue.Count + exclusive_queue.Count;
public int MaxConcurrentUsers {
get {
return max_concurrent_users;
}
set {
max_concurrent_users = value;
}
}
public Resource (string name, int max_concurrent_users = 1, string description = null) public Resource (string name, int max_concurrent_users = 1, string description = null)
{ {

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

@ -228,7 +228,7 @@ namespace xharness
} }
} }
public static void AddCompileInclude (this XmlDocument csproj, string link, string include) public static void AddCompileInclude (this XmlDocument csproj, string link, string include, bool prepend = false)
{ {
var compile_node = csproj.SelectSingleNode ("//*[local-name() = 'Compile']"); var compile_node = csproj.SelectSingleNode ("//*[local-name() = 'Compile']");
var item_group = compile_node.ParentNode; var item_group = compile_node.ParentNode;
@ -240,6 +240,9 @@ namespace xharness
var linkElement = csproj.CreateElement ("Link", MSBuild_Namespace); var linkElement = csproj.CreateElement ("Link", MSBuild_Namespace);
linkElement.InnerText = link; linkElement.InnerText = link;
node.AppendChild (linkElement); node.AppendChild (linkElement);
if (prepend)
item_group.PrependChild (node);
else
item_group.AppendChild (node); item_group.AppendChild (node);
} }
@ -381,7 +384,13 @@ namespace xharness
public static void FixTestLibrariesReferences (this XmlDocument csproj, string platform) public static void FixTestLibrariesReferences (this XmlDocument csproj, string platform)
{ {
var nodes = csproj.SelectNodes ("//*[local-name() = 'ObjcBindingNativeLibrary' or local-name() = 'ObjcBindingNativeFramework']"); var nodes = csproj.SelectNodes ("//*[local-name() = 'ObjcBindingNativeLibrary' or local-name() = 'ObjcBindingNativeFramework']");
var test_libraries = new string [] { "libtest.a", "XTest.framework", "XStaticArTest.framework", "XStaticObjectTest.framework" }; var test_libraries = new string [] {
"libtest.a",
"libtest2.a",
"XTest.framework",
"XStaticArTest.framework",
"XStaticObjectTest.framework"
};
foreach (XmlNode node in nodes) { foreach (XmlNode node in nodes) {
var includeAttribute = node.Attributes ["Include"]; var includeAttribute = node.Attributes ["Include"];
if (includeAttribute != null) { if (includeAttribute != null) {
@ -641,6 +650,7 @@ namespace xharness
"AssemblyOriginatorKeyFile", "AssemblyOriginatorKeyFile",
"CodesignEntitlements", "CodesignEntitlements",
"TestLibrariesDirectory", "TestLibrariesDirectory",
"HintPath",
}; };
var attributes_with_paths = new string [] [] var attributes_with_paths = new string [] []
{ {
@ -662,6 +672,10 @@ namespace xharness
new string [] { "ObjcBindingNativeLibrary", "Include" }, new string [] { "ObjcBindingNativeLibrary", "Include" },
new string [] { "ObjcBindingNativeFramework", "Include" }, new string [] { "ObjcBindingNativeFramework", "Include" },
}; };
var nodes_with_variables = new string []
{
"MtouchExtraArgs",
};
Func<string, string> convert = (input) => Func<string, string> convert = (input) =>
{ {
if (input [0] == '/') if (input [0] == '/')
@ -678,6 +692,12 @@ namespace xharness
foreach (var node in nodes) foreach (var node in nodes)
node.InnerText = convert (node.InnerText); node.InnerText = convert (node.InnerText);
} }
foreach (var key in nodes_with_variables) {
var nodes = csproj.SelectElementNodes (key);
foreach (var node in nodes) {
node.InnerText = node.InnerText.Replace ("${ProjectDir}", Harness.Quote (System.IO.Path.GetDirectoryName (project_path)));
}
}
foreach (var kvp in attributes_with_paths) { foreach (var kvp in attributes_with_paths) {
var element = kvp [0]; var element = kvp [0];
var attrib = kvp [1]; var attrib = kvp [1];

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

@ -12,6 +12,7 @@ namespace xharness
XmlDocument xml; XmlDocument xml;
public string Path; public string Path;
public string Name;
public bool IsExecutableProject; public bool IsExecutableProject;
public bool GenerateVariations = true; public bool GenerateVariations = true;

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

@ -50,7 +50,7 @@ namespace xharness
info_plist.LoadWithoutNetworkAccess (Path.Combine (Harness.TodayContainerTemplate, "Info.plist")); info_plist.LoadWithoutNetworkAccess (Path.Combine (Harness.TodayContainerTemplate, "Info.plist"));
info_plist.SetCFBundleIdentifier (BundleIdentifier); info_plist.SetCFBundleIdentifier (BundleIdentifier);
info_plist.SetCFBundleName (Name); info_plist.SetCFBundleName (Name);
info_plist.SetMinimumOSVersion ("6.0"); info_plist.SetMinimumOSVersion ("8.0");
Harness.Save (info_plist, target_info_plist); Harness.Save (info_plist, target_info_plist);
} }
@ -66,7 +66,7 @@ namespace xharness
csproj.SetOutputType ("Library"); csproj.SetOutputType ("Library");
csproj.AddAdditionalDefines ("XAMCORE_2_0;XAMCORE_3_0"); csproj.AddAdditionalDefines ("XAMCORE_2_0;XAMCORE_3_0");
var ext = IsFSharp ? "fs" : "cs"; var ext = IsFSharp ? "fs" : "cs";
csproj.AddCompileInclude ("Main." + ext, Path.Combine (Harness.TodayExtensionTemplate, "Main." + ext)); csproj.AddCompileInclude ("TodayExtensionMain." + ext, Path.Combine (Harness.TodayExtensionTemplate, "TodayExtensionMain." + ext), true);
csproj.AddInterfaceDefinition (Path.Combine (Harness.TodayExtensionTemplate, "TodayView.storyboard").Replace ('/', '\\')); csproj.AddInterfaceDefinition (Path.Combine (Harness.TodayExtensionTemplate, "TodayView.storyboard").Replace ('/', '\\'));
csproj.SetExtraLinkerDefs ("extra-linker-defs" + Suffix + ".xml"); csproj.SetExtraLinkerDefs ("extra-linker-defs" + Suffix + ".xml");
csproj.FixProjectReferences ("-today"); csproj.FixProjectReferences ("-today");

Двоичные данные
tests/xharness/favicon.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.2 KiB

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

@ -20,6 +20,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType> <DebugType>full</DebugType>

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

@ -35,7 +35,7 @@ namespace Xamarin.Bundler {
public partial class Application public partial class Application
{ {
public Cache Cache = new Cache (); public Cache Cache;
public string AppDirectory = "."; public string AppDirectory = ".";
public bool DeadStrip = true; public bool DeadStrip = true;
public bool EnableDebug; public bool EnableDebug;
@ -60,12 +60,23 @@ namespace Xamarin.Bundler {
public MarshalManagedExceptionMode MarshalManagedExceptions; public MarshalManagedExceptionMode MarshalManagedExceptions;
public bool IsDefaultMarshalManagedExceptionMode; public bool IsDefaultMarshalManagedExceptionMode;
public string RootAssembly; public string RootAssembly;
public List<Application> SharedCodeApps = new List<Application> (); // List of appexes we're sharing code with.
public string RegistrarOutputLibrary; public string RegistrarOutputLibrary;
public static int Concurrency => Driver.Concurrency; public static int Concurrency => Driver.Concurrency;
public Version DeploymentTarget; public Version DeploymentTarget;
public Version SdkVersion; public Version SdkVersion;
public Application (string[] arguments)
{
Cache = new Cache (arguments);
}
// This is just a name for this app to show in log/error messages, etc.
public string Name {
get { return Path.GetFileNameWithoutExtension (AppDirectory); }
}
public bool RequiresPInvokeWrappers { public bool RequiresPInvokeWrappers {
get { get {
#if MTOUCH #if MTOUCH

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

@ -1,4 +1,5 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@ -40,6 +41,18 @@ namespace Xamarin.Bundler {
} }
} }
public string FileName { get { return Path.GetFileName (FullPath); } } public string FileName { get { return Path.GetFileName (FullPath); } }
public string Identity { get { return GetIdentity (FullPath); } }
public static string GetIdentity (AssemblyDefinition ad)
{
return Path.GetFileNameWithoutExtension (ad.MainModule.FileName);
}
public static string GetIdentity (string path)
{
return Path.GetFileNameWithoutExtension (path);
}
public bool EnableCxx; public bool EnableCxx;
public bool NeedsGccExceptionHandling; public bool NeedsGccExceptionHandling;
public bool ForceLoad; public bool ForceLoad;
@ -464,4 +477,93 @@ namespace Xamarin.Bundler {
} }
} }
} }
public class AssemblyCollection : IEnumerable<Assembly>
{
Dictionary<string, Assembly> HashedAssemblies = new Dictionary<string, Assembly> (StringComparer.OrdinalIgnoreCase);
public void Add (Assembly assembly)
{
Assembly other;
if (HashedAssemblies.TryGetValue (assembly.Identity, out other))
throw ErrorHelper.CreateError (2018, "The assembly '{0}' is referenced from two different locations: '{1}' and '{2}'.", assembly.Identity, other.FullPath, assembly.FullPath);
HashedAssemblies.Add (assembly.Identity, assembly);
}
public void AddRange (AssemblyCollection assemblies)
{
foreach (var a in assemblies)
Add (a);
}
public int Count {
get {
return HashedAssemblies.Count;
}
}
public IDictionary<string, Assembly> Hashed {
get { return HashedAssemblies; }
}
public bool TryGetValue (string identity, out Assembly assembly)
{
return HashedAssemblies.TryGetValue (identity, out assembly);
}
public bool ContainsKey (string identity)
{
return HashedAssemblies.ContainsKey (identity);
}
public void Remove (string identity)
{
HashedAssemblies.Remove (identity);
}
public void Remove (Assembly assembly)
{
Remove (assembly.Identity);
}
public Assembly this [string key] {
get { return HashedAssemblies [key]; }
set { HashedAssemblies [key] = value; }
}
public void Update (Target target, IEnumerable<AssemblyDefinition> assemblies)
{
// This function will remove any assemblies not in 'assemblies', and add any new assemblies.
var current = new HashSet<string> (HashedAssemblies.Keys, HashedAssemblies.Comparer);
foreach (var assembly in assemblies) {
var identity = Assembly.GetIdentity (assembly);
if (!current.Remove (identity)) {
// new assembly
var asm = new Assembly (target, assembly);
Add (asm);
Driver.Log (1, "The linker added the assembly '{0}' to '{1}' to satisfy a reference.", asm.Identity, target.App.Name);
} else {
this [identity].AssemblyDefinition = assembly;
}
}
foreach (var removed in current) {
Driver.Log (1, "The linker removed the assembly '{0}' from '{1}' since there is no more reference to it.", this [removed].Identity, target.App.Name);
Remove (removed);
}
}
#region Interface implementations
IEnumerator IEnumerable.GetEnumerator ()
{
return GetEnumerator ();
}
public IEnumerator<Assembly> GetEnumerator ()
{
return HashedAssemblies.Values.GetEnumerator ();
}
#endregion
}
} }

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

@ -1,55 +1,319 @@
// #define LOG_TASK
using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Xamarin.Bundler namespace Xamarin.Bundler
{ {
// This contains all the tasks that has to be done to create the final output.
// Intermediate tasks do not have to be in this list (as long as they're in another task's dependencies),
// but it doesn't hurt if they're here either.
// This is a directed graph, where the top nodes represent the input, and the leaf nodes the output.
// Each node (BuildTask) will build its dependencies before building itself, so at build time
// we only have to iterate over the leaf nodes to build the whole graph.
public class BuildTasks : List<BuildTask> public class BuildTasks : List<BuildTask>
{ {
static void Execute (List<BuildTask> added, BuildTask v) SemaphoreSlim semaphore;
public BuildTasks ()
{ {
var next = v.Execute (); semaphore = new SemaphoreSlim (Driver.Concurrency, Driver.Concurrency);
if (next != null) { Driver.Log (2, $"Created task scheduler with concurrency {Driver.Concurrency}.");
lock (added)
added.AddRange (next);
}
} }
public void ExecuteInParallel () public async Task AcquireSemaphore ()
{
await semaphore.WaitAsync ();
}
public void ReleaseSemaphore ()
{
semaphore.Release ();
}
void ExecuteBuildTasks (SingleThreadedSynchronizationContext context, List<Exception> exceptions)
{
Task [] tasks = new Task [Count];
for (int i = 0; i < Count; i++)
tasks [i] = this [i].Execute (this);
Task.Factory.StartNew (async () =>
{
try {
await Task.WhenAll (tasks);
} catch (Exception e) {
exceptions.Add (e);
} finally {
context.SetCompleted ();
}
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext ());
}
public void Execute ()
{ {
if (Count == 0) if (Count == 0)
return; return;
var build_list = new List<BuildTask> (this); var savedContext = SynchronizationContext.Current;
var added = new List<BuildTask> (); var exceptions = new List<Exception> ();
while (build_list.Count > 0) { try {
added.Clear (); var context = new SingleThreadedSynchronizationContext ();
Parallel.ForEach (build_list, new ParallelOptions () { MaxDegreeOfParallelism = Driver.Concurrency }, (v) => SynchronizationContext.SetSynchronizationContext (context);
{ ExecuteBuildTasks (context, exceptions);
Execute (added, v); context.Run ();
}); } finally {
build_list.Clear (); SynchronizationContext.SetSynchronizationContext (savedContext);
build_list.AddRange (added); }
if (exceptions.Count > 0)
throw new AggregateException (exceptions);
} }
Clear (); public void Dot (string file)
{
var nodes = new HashSet<string> ();
var queue = new Queue<BuildTask> (this);
var input_nodes = new HashSet<string> ();
var action_nodes = new HashSet<string> ();
var output_nodes = new HashSet<string> ();
var all_nodes = new HashSet<string> ();
var circular_ref_nodes = new HashSet<string> ();
var render_file = new Func<string, string> ((v) =>
{
if (Path.GetDirectoryName (v).EndsWith (".framework", StringComparison.Ordinal))
return Path.GetFileName (Path.GetDirectoryName (v));
return Path.GetFileName (v);
});
var processed = new HashSet<BuildTask> ();
while (queue.Count > 0) {
var task = queue.Dequeue ();
var action_node = $"\"{task.GetType ().Name}{task.ID}\"";
if (processed.Contains (task)) {
Console.WriteLine ($"Already processed: {action_node}");
continue;
}
processed.Add (task);
foreach (var d in task.Dependencies)
queue.Enqueue (d);
nodes.Add ($"{action_node} [label=\"{task.GetType ().Name.Replace ("Task", "")}\", shape=box]");
all_nodes.Add ($"X{task.ID}");
action_nodes.Add (action_node);
var inputs = task.Inputs.ToArray ();
for (int i = 0; i < inputs.Length; i++) {
var node = $"\"{render_file (inputs [i])}\"";
all_nodes.Add (node);
input_nodes.Add (node);
nodes.Add ($"{node} -> {action_node}");
}
var outputs = task.Outputs.ToArray ();
for (int i = 0; i < outputs.Length; i++) {
var node = $"\"{render_file (outputs [i])}\"";
all_nodes.Add (node);
output_nodes.Add (node);
nodes.Add ($"{action_node} -> {node}");
}
}
using (var writer = new StreamWriter (file)) {
writer.WriteLine ("digraph build {");
writer.WriteLine ("\trankdir=LR;");
foreach (var node in nodes)
writer.WriteLine ("\t{0};", node);
// make all the final nodes a different color
foreach (var end_node in output_nodes.Except (input_nodes))
writer.WriteLine ($"\t{end_node} [fillcolor = \"lightblue\"; style = \"filled\"; ];");
foreach (var node in circular_ref_nodes)
writer.WriteLine ($"\t{node} [fillcolor = \"red\"; style = \"filled\"; ];");
writer.WriteLine ("}");
}
Driver.Log ("Created dot file: {0}", file);
} }
} }
public abstract class BuildTask public abstract class BuildTask
{ {
public IEnumerable<BuildTask> NextTasks; static int counter;
public readonly int ID = counter++;
protected abstract void Build (); TaskCompletionSource<bool> started_task = new TaskCompletionSource<bool> ();
TaskCompletionSource<bool> completed_task = new TaskCompletionSource<bool> (); // The value determines whether the target was rebuilt (not up-to-date) or not.
List<BuildTask> dependencies = new List<BuildTask> ();
public IEnumerable<BuildTask> Execute () [System.Diagnostics.Conditional ("LOG_TASK")]
void Log (string format, params object [] args)
{ {
Build (); Console.WriteLine ($"{ID} {GetType ().Name}: {string.Format (format, args)}");
return NextTasks;
} }
public virtual bool IsUptodate () // A list of input files (not a list of all the dependencies that would make this task rebuild).
public abstract IEnumerable<string> Inputs { get; }
public bool Rebuilt {
get {
if (!completed_task.Task.IsCompleted)
throw ErrorHelper.CreateError (99, "Internal error: Can't rebuild a task that hasn't completed. Please file a bug report with a test case (http://bugzilla.xamarin.com).");
return completed_task.Task.Result;
}
}
public virtual bool IsUptodate {
get {
return Application.IsUptodate (FileDependencies, Outputs);
}
}
// A list of all the files that causes the task to rebuild.
// This should at least include all the 'Inputs', and potentially other files as well.
public virtual IEnumerable<string> FileDependencies {
get {
return Inputs;
}
}
// A list of files that this task outputs.
public abstract IEnumerable<string> Outputs { get; }
public IEnumerable<BuildTask> Dependencies {
get {
return dependencies;
}
}
public Task CompletedTask {
get {
return completed_task.Task;
}
}
public void AddDependency (params BuildTask [] dependencies)
{ {
return false; if (dependencies == null)
return;
this.dependencies.AddRange (dependencies.Where ((v) => v != null));
}
public void AddDependency (IEnumerable<BuildTask> dependencies)
{
if (dependencies == null)
return;
this.dependencies.AddRange (dependencies.Where ((v) => v != null));
}
public async Task Execute (BuildTasks build_tasks)
{
if (started_task.TrySetResult (true)) {
var watch = new System.Diagnostics.Stopwatch ();
try {
Log ("Launching task");
var deps = Dependencies.ToArray ();
var dep_tasks = new Task [deps.Length];
for (int i = 0; i < deps.Length; i++)
dep_tasks [i] = deps [i].Execute (build_tasks);
Log ("Waiting for dependencies to complete.");
await Task.WhenAll (dep_tasks);
Log ("Done waiting for dependencies.");
// We can only check if we're up-to-date after executing dependencies.
if (IsUptodate) {
if (Outputs.Count () > 1) {
Driver.Log (3, "Targets '{0}' are up-to-date.", string.Join ("', '", Outputs.ToArray ()));
} else {
Driver.Log (3, "Target '{0}' is up-to-date.", Outputs.First () );
}
completed_task.SetResult (false);
} else {
Driver.Log (3, "Target(s) {0} must be rebuilt.", string.Join (", ", Outputs.ToArray ()));
Log ("Dependencies are complete.");
await build_tasks.AcquireSemaphore ();
try {
Log ("Executing task");
watch.Start ();
await ExecuteAsync ();
watch.Stop ();
Log ("Completed task {0} s", watch.Elapsed.TotalSeconds);
completed_task.SetResult (true);
} finally {
build_tasks.ReleaseSemaphore ();
}
}
} catch (Exception e) {
Log ("Completed task in {0} s with exception: {1}", watch.Elapsed.TotalSeconds, e.Message);
completed_task.SetException (e);
throw;
}
} else {
Log ("Waiting for started task");
await completed_task.Task;
Log ("Waited for started task");
}
}
// Derived tasks must override either ExecuteAsync or Execute.
// If ExecuteAsync is not overridden, then Execute is called on
// a background thread.
protected virtual Task ExecuteAsync ()
{
return Task.Run (() => Execute ());
}
protected virtual void Execute ()
{
throw ErrorHelper.CreateError (99, "Internal error: 'Either Execute or ExecuteAsync must be overridden'. Please file a bug report with a test case (http://bugzilla.xamarin.com).");
}
public override string ToString ()
{
return GetType ().Name;
}
}
class SingleThreadedSynchronizationContext : SynchronizationContext
{
readonly BlockingCollection<Tuple<SendOrPostCallback, object>> queue = new BlockingCollection<Tuple<SendOrPostCallback, object>> ();
public override void Post (SendOrPostCallback d, object state)
{
queue.Add (new Tuple<SendOrPostCallback, object> (d, state));
}
public override void Send (SendOrPostCallback d, object state)
{
d (state);
}
public int Run ()
{
int counter = 0;
while (!queue.IsCompleted) {
var item = queue.Take ();
counter++;
item.Item1 (item.Item2);
}
return counter;
}
public void SetCompleted ()
{
queue.CompleteAdding ();
} }
} }
} }

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

@ -19,6 +19,7 @@ namespace Xamarin.Utils
public HashSet<string> OtherFlags; // X public HashSet<string> OtherFlags; // X
public HashSet<string> Defines; // -DX public HashSet<string> Defines; // -DX
public HashSet<string> UnresolvedSymbols; // -u X public HashSet<string> UnresolvedSymbols; // -u X
public HashSet<string> SourceFiles; // X, added to Inputs
// Here we store a list of all the file-system based inputs // Here we store a list of all the file-system based inputs
// to the compiler. This is used when determining if the // to the compiler. This is used when determining if the
@ -26,6 +27,24 @@ namespace Xamarin.Utils
// tracking). // tracking).
public List<string> Inputs; public List<string> Inputs;
public CompilerFlags (Target target)
{
if (target == null)
throw new ArgumentNullException (nameof (target));
this.Target = target;
}
public HashSet<string> AllLibraries {
get {
var rv = new HashSet<string> ();
if (LinkWithLibraries != null)
rv.UnionWith (LinkWithLibraries);
if (ForceLoadLibraries != null)
rv.UnionWith (ForceLoadLibraries);
return rv;
}
}
public void ReferenceSymbol (string symbol) public void ReferenceSymbol (string symbol)
{ {
if (UnresolvedSymbols == null) if (UnresolvedSymbols == null)
@ -73,6 +92,13 @@ namespace Xamarin.Utils
AddLinkWith (lib, force_load); AddLinkWith (lib, force_load);
} }
public void AddSourceFile (string file)
{
if (SourceFiles == null)
SourceFiles = new HashSet<string> ();
SourceFiles.Add (file);
}
public void AddOtherFlag (string flag) public void AddOtherFlag (string flag)
{ {
if (OtherFlags == null) if (OtherFlags == null)
@ -92,29 +118,38 @@ namespace Xamarin.Utils
public void LinkWithMono () public void LinkWithMono ()
{ {
// link with the exact path to libmono var mode = Target.App.LibMonoLinkMode;
if (Application.UseMonoFramework.Value) { switch (mode) {
AddFramework (Path.Combine (Driver.GetProductFrameworksDirectory (Application), "Mono.framework")); case AssemblyBuildTarget.DynamicLibrary:
} else { case AssemblyBuildTarget.StaticObject:
AddLinkWith (Path.Combine (Driver.GetMonoTouchLibDirectory (Application), Application.LibMono)); AddLinkWith (Application.GetLibMono (mode));
break;
case AssemblyBuildTarget.Framework:
AddFramework (Application.GetLibMono (mode));
break;
default:
throw ErrorHelper.CreateError (100, "Invalid assembly build target: '{0}'. Please file a bug report with a test case (http://bugzilla.xamarin.com).", mode);
} }
} }
public void LinkWithXamarin () public void LinkWithXamarin ()
{ {
AddLinkWith (Path.Combine (Driver.GetMonoTouchLibDirectory (Application), Application.LibXamarin)); var mode = Target.App.LibXamarinLinkMode;
switch (mode) {
case AssemblyBuildTarget.DynamicLibrary:
case AssemblyBuildTarget.StaticObject:
AddLinkWith (Application.GetLibXamarin (mode));
break;
case AssemblyBuildTarget.Framework:
AddFramework (Application.GetLibXamarin (mode));
break;
default:
throw ErrorHelper.CreateError (100, "Invalid assembly build target: '{0}'. Please file a bug report with a test case (http://bugzilla.xamarin.com).", mode);
}
AddFramework ("Foundation"); AddFramework ("Foundation");
AddOtherFlag ("-lz"); AddOtherFlag ("-lz");
} }
public void LinkWithPInvokes (Abi abi)
{
if (!Application.FastDev || !Application.RequiresPInvokeWrappers)
return;
AddOtherFlag (Driver.Quote (Path.Combine (Application.Cache.Location, "libpinvokes." + abi.AsArchString () + ".dylib")));
}
public void AddFramework (string framework) public void AddFramework (string framework)
{ {
if (Frameworks == null) if (Frameworks == null)
@ -212,6 +247,13 @@ namespace Xamarin.Utils
foreach (var symbol in UnresolvedSymbols) foreach (var symbol in UnresolvedSymbols)
args.Append (" -u ").Append (Driver.Quote ("_" + symbol)); args.Append (" -u ").Append (Driver.Quote ("_" + symbol));
} }
if (SourceFiles != null) {
foreach (var src in SourceFiles) {
args.Append (' ').Append (Driver.Quote (src));
AddInput (src);
}
}
} }
void ProcessFrameworksForArguments (StringBuilder args) void ProcessFrameworksForArguments (StringBuilder args)
@ -234,7 +276,7 @@ namespace Xamarin.Utils
args.Append (" -Xlinker -rpath -Xlinker @executable_path/../../Frameworks"); args.Append (" -Xlinker -rpath -Xlinker @executable_path/../../Frameworks");
} }
if (Application.FastDev) if (Application.HasAnyDynamicLibraries)
args.Append (" -Xlinker -rpath -Xlinker @executable_path"); args.Append (" -Xlinker -rpath -Xlinker @executable_path");
} }
@ -256,5 +298,12 @@ namespace Xamarin.Utils
WriteArguments (args); WriteArguments (args);
return args.ToString (); return args.ToString ();
} }
public void PopulateInputs ()
{
var args = new StringBuilder ();
Inputs = new List<string> ();
WriteArguments (args);
}
} }
} }

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

@ -11,7 +11,6 @@ namespace Xamarin.Tuner
{ {
internal StaticRegistrar StaticRegistrar; internal StaticRegistrar StaticRegistrar;
Dictionary<string, List<MemberReference>> required_symbols; Dictionary<string, List<MemberReference>> required_symbols;
List<MethodDefinition> marshal_exception_pinvokes;
Dictionary<string, TypeDefinition> objectivec_classes; Dictionary<string, TypeDefinition> objectivec_classes;
// SDK candidates - they will be preserved only if the application (not the SDK) uses it // SDK candidates - they will be preserved only if the application (not the SDK) uses it
@ -65,14 +64,6 @@ namespace Xamarin.Tuner
} }
} }
public List<MethodDefinition> MarshalExceptionPInvokes {
get {
if (marshal_exception_pinvokes == null)
marshal_exception_pinvokes = new List<MethodDefinition> ();
return marshal_exception_pinvokes;
}
}
public Dictionary<string, TypeDefinition> ObjectiveCClasses { public Dictionary<string, TypeDefinition> ObjectiveCClasses {
get { get {
if (objectivec_classes == null) if (objectivec_classes == null)

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

@ -12,6 +12,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks;
using Xamarin.Utils; using Xamarin.Utils;
using XamCore.ObjCRuntime; using XamCore.ObjCRuntime;
@ -228,6 +229,11 @@ namespace Xamarin.Bundler {
return 0; return 0;
} }
public static Task<int> RunCommandAsync (string path, string args, string [] env = null, StringBuilder output = null, bool suppressPrintOnErrors = false)
{
return Task.Run (() => RunCommand (path, args, env, output, suppressPrintOnErrors));
}
#if !MMP_TEST #if !MMP_TEST
static void FileMove (string source, string target) static void FileMove (string source, string target)
{ {
@ -265,6 +271,7 @@ namespace Xamarin.Bundler {
try { try {
if (!File.Exists (path)) { if (!File.Exists (path)) {
Directory.CreateDirectory (Path.GetDirectoryName (path));
File.WriteAllText (path, contents); File.WriteAllText (path, contents);
Log (3, "File '{0}' does not exist, creating it.", path); Log (3, "File '{0}' does not exist, creating it.", path);
return; return;

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

@ -34,7 +34,7 @@ using PlatformLinkContext = MonoMac.Tuner.MonoMacLinkContext;
namespace Xamarin.Bundler { namespace Xamarin.Bundler {
public partial class Target { public partial class Target {
public Application App; public Application App;
public List<Assembly> Assemblies = new List<Assembly> (); public AssemblyCollection Assemblies = new AssemblyCollection (); // The root assembly is not in this list.
public PlatformLinkContext LinkContext; public PlatformLinkContext LinkContext;
public LinkerOptions LinkerOptions; public LinkerOptions LinkerOptions;
@ -62,9 +62,9 @@ namespace Xamarin.Bundler {
a.ExtractNativeLinkInfo (); a.ExtractNativeLinkInfo ();
#if MTOUCH #if MTOUCH
if (App.FastDev && a.HasLinkWithAttributes && App.EnableBitCode) { if (a.HasLinkWithAttributes && App.EnableBitCode && !App.OnlyStaticLibraries) {
ErrorHelper.Warning (110, "Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include third-party binding libraries and that compiles to bitcode."); ErrorHelper.Warning (110, "Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include third-party binding libraries and that compiles to bitcode.");
App.FastDev = false; App.ClearAssemblyBuildTargets (); // the default is to compile to static libraries, so just revert to the default.
} }
#endif #endif
} catch (Exception e) { } catch (Exception e) {
@ -73,9 +73,9 @@ namespace Xamarin.Bundler {
} }
#if MTOUCH #if MTOUCH
if (App.FastDev && Assemblies.Count ((v) => v.HasLinkWithAttributes) > 1) { if (!App.OnlyStaticLibraries && Assemblies.Count ((v) => v.HasLinkWithAttributes) > 1) {
ErrorHelper.Warning (127, "Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include more than one third-party binding libraries."); ErrorHelper.Warning (127, "Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include more than one third-party binding libraries.");
App.FastDev = false; App.ClearAssemblyBuildTargets (); // the default is to compile to static libraries, so just revert to the default.
} }
#endif #endif
} }

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

@ -18,6 +18,12 @@ public class Cache {
string cache_dir; string cache_dir;
bool temporary_cache; bool temporary_cache;
string[] arguments;
public Cache (string[] arguments)
{
this.arguments = arguments;
}
public bool IsCacheTemporary { public bool IsCacheTemporary {
get { return temporary_cache; } get { return temporary_cache; }
@ -63,11 +69,6 @@ public class Cache {
Directory.CreateDirectory (Location); Directory.CreateDirectory (Location);
} }
public bool Exists (string file)
{
return File.Exists (Path.Combine (Location, file));
}
public static bool CompareFiles (string a, string b, bool ignore_cache = false) public static bool CompareFiles (string a, string b, bool ignore_cache = false)
{ {
if (Driver.Force && !ignore_cache) { if (Driver.Force && !ignore_cache) {
@ -166,10 +167,10 @@ public class Cache {
} while (true); } while (true);
} }
static string GetArgumentsForCacheData () string GetArgumentsForCacheData ()
{ {
var sb = new StringBuilder (); var sb = new StringBuilder ();
var args = new List<string> (Environment.GetCommandLineArgs ()); var args = new List<string> (arguments);
sb.Append ("# Version: ").Append (Constants.Version).Append ('.').Append (Constants.Revision).AppendLine (); sb.Append ("# Version: ").Append (Constants.Version).Append ('.').Append (Constants.Revision).AppendLine ();
if (args.Count > 0) if (args.Count > 0)
@ -196,7 +197,7 @@ public class Cache {
return sb.ToString (); return sb.ToString ();
} }
bool IsCacheValid () public bool IsCacheValid ()
{ {
var name = "arguments"; var name = "arguments";
var pcache = Path.Combine (Location, name); var pcache = Path.Combine (Location, name);
@ -210,9 +211,9 @@ public class Cache {
} }
// Check if mtouch/mmp has been modified. // Check if mtouch/mmp has been modified.
var mtouch = Path.Combine (Driver.DriverBinDirectory, NAME); var executable = System.Reflection.Assembly.GetExecutingAssembly ().Location;
if (!Application.IsUptodate (mtouch, pcache)) { if (!Application.IsUptodate (executable, pcache)) {
Driver.Log (3, "A full rebuild will be performed because mtouch has been modified."); Driver.Log (3, "A full rebuild will be performed because " + NAME + " has been modified.");
return false; return false;
} }

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

@ -68,7 +68,7 @@ namespace Xamarin.Bundler {
} }
public static partial class Driver { public static partial class Driver {
internal static Application App = new Application (); internal static Application App = new Application (Environment.GetCommandLineArgs ());
static Target BuildTarget = new Target (App); static Target BuildTarget = new Target (App);
static List<string> references = new List<string> (); static List<string> references = new List<string> ();
static List<string> resources = new List<string> (); static List<string> resources = new List<string> ();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -11,26 +11,54 @@ using Mono.Cecil;
using Xamarin.Utils; using Xamarin.Utils;
namespace Xamarin.Bundler { namespace Xamarin.Bundler {
public enum AssemblyBuildTarget
{
StaticObject,
DynamicLibrary,
Framework,
}
public class AotInfo
{
public AOTTask Task;
public LinkTask LinkTask;
public List<string> BitcodeFiles = new List<string> (); // .bc files produced by the AOT compiler
public List<string> AsmFiles = new List<string> (); // .s files produced by the AOT compiler.
public List<string> AotDataFiles = new List<string> (); // .aotdata files produced by the AOT compiler
public List<string> ObjectFiles = new List<string> (); // .o files produced by the AOT compiler
}
public partial class Assembly public partial class Assembly
{ {
List<string> dylibs; public AssemblyBuildTarget BuildTarget;
public string Dylib; public string BuildTargetName;
public bool IsCodeShared;
public List<string> AotDataFiles = new List<string> (); public Dictionary<Abi, AotInfo> AotInfos = new Dictionary<Abi, AotInfo> ();
HashSet<string> dependencies; HashSet<string> dependency_map;
bool has_dependency_map;
public IEnumerable<string> Dylibs { public bool HasDependencyMap {
get { return dylibs; } get {
return has_dependency_map;
}
}
public HashSet<string> DependencyMap {
get {
return dependency_map;
}
} }
// Recursively list all the assemblies the specified assembly depends on. // Recursively list all the assemblies the specified assembly depends on.
HashSet<string> ComputeDependencies (List<Exception> warnings) HashSet<string> ComputeDependencies (List<Exception> warnings)
{ {
if (dependencies != null) if (dependency_map != null)
return dependencies; return dependency_map;
dependencies = new HashSet<string> (); dependency_map = new HashSet<string> ();
has_dependency_map = true;
foreach (var ar in AssemblyDefinition.MainModule.AssemblyReferences) { foreach (var ar in AssemblyDefinition.MainModule.AssemblyReferences) {
var found = false; var found = false;
@ -45,33 +73,48 @@ namespace Xamarin.Bundler {
if (a.AssemblyDefinition.Name.Name == ar.Name) { if (a.AssemblyDefinition.Name.Name == ar.Name) {
// gotcha // gotcha
if (!dependencies.Contains (a.FullPath)) { if (!dependency_map.Contains (a.FullPath)) {
dependencies.Add (a.FullPath); dependency_map.Add (a.FullPath);
dependencies.UnionWith (a.ComputeDependencies (warnings)); dependency_map.UnionWith (a.ComputeDependencies (warnings));
} }
found = true; found = true;
break; break;
} }
} }
if (!found) if (!found) {
warnings.Add (new MonoTouchException (3005, false, "The dependency '{0}' of the assembly '{1}' was not found. Please review the project's references.", warnings.Add (new MonoTouchException (3005, false, "The dependency '{0}' of the assembly '{1}' was not found. Please review the project's references.",
ar.FullName, AssemblyDefinition.FullName)); ar.FullName, AssemblyDefinition.FullName));
has_dependency_map = false;
}
} }
return dependencies; return dependency_map;
}
public void ComputeDependencyMap (List<Exception> exceptions)
{
ComputeDependencies (exceptions);
} }
// returns false if the assembly was not copied (because it was already up-to-date). // returns false if the assembly was not copied (because it was already up-to-date).
public bool CopyAssembly (string source, string target, bool copy_mdb = true) public bool CopyAssembly (string source, string target, bool copy_mdb = true, bool strip = false)
{ {
var copied = false; var copied = false;
try { try {
if (!Application.IsUptodate (source, target) && !Cache.CompareAssemblies (source, target)) { if (!Application.IsUptodate (source, target) && (strip || !Cache.CompareAssemblies (source, target))) {
copied = true; copied = true;
if (strip) {
Driver.FileDelete (target);
Directory.CreateDirectory (Path.GetDirectoryName (target));
MonoTouch.Tuner.Stripper.Process (source, target);
} else {
Application.CopyFile (source, target); Application.CopyFile (source, target);
} }
} else {
Driver.Log (3, "Target '{0}' is up-to-date.", target);
}
// Update the debug symbols file even if the assembly didn't change. // Update the debug symbols file even if the assembly didn't change.
if (copy_mdb) { if (copy_mdb) {
@ -133,8 +176,12 @@ namespace Xamarin.Bundler {
} }
} }
// returns false if the assembly was not copied (because it was already up-to-date). // this will copy (and optionally strip) the assembly and all the related files:
public bool CopyToDirectory (string directory, bool reload = true, bool check_case = false, bool only_copy = false, bool copy_mdb = true) // * debug file (.mdb)
// * config file (.config)
// * satellite assemblies (<language id>/.dll)
// * aot data
public void CopyToDirectory (string directory, bool reload = true, bool check_case = false, bool only_copy = false, bool copy_mdb = true, bool strip = false)
{ {
var target = Path.Combine (directory, FileName); var target = Path.Combine (directory, FileName);
@ -145,11 +192,9 @@ namespace Xamarin.Bundler {
target = Path.Combine (directory, assemblyName + Path.GetExtension (FileName)); target = Path.Combine (directory, assemblyName + Path.GetExtension (FileName));
} }
var copied = false;
// our Copy code deletes the target (so copy'ing over itself is a bad idea) // our Copy code deletes the target (so copy'ing over itself is a bad idea)
if (directory != Path.GetDirectoryName (FullPath)) if (directory != Path.GetDirectoryName (FullPath))
copied = CopyAssembly (FullPath, target, copy_mdb: copy_mdb); CopyAssembly (FullPath, target, copy_mdb: copy_mdb, strip: strip);
CopySatellitesToDirectory (directory); CopySatellitesToDirectory (directory);
@ -161,205 +206,76 @@ namespace Xamarin.Bundler {
} }
} }
return copied; foreach (var aotdata in AotInfos.Values.SelectMany ((info) => info.AotDataFiles))
Application.UpdateFile (aotdata, Path.Combine (directory, Path.GetFileName (aotdata)));
} }
IEnumerable<BuildTask> CreateCompileTasks (string s, string asm_infile, string llvm_infile, Abi abi) /*
* Runs the AOT compiler, creating one of the following:
* [not llvm] => .s + .aotdata
* [is llvm-only] => .bc + .aotdata
* [is llvm] =>
* [is llvm creating assembly code] => .s + -llvm.s + .aotdata
* [is llvm creating object code] => .s + -llvm.o + .aotdata
*/
public void CreateAOTTask (Abi abi)
{ {
var compile_tasks = new BuildTasks (); // Check if we've already created the AOT tasks.
if (asm_infile != null) { if (AotInfos.ContainsKey (abi))
var task = CreateCompileTask (s, asm_infile, abi); return;
if (task != null)
compile_tasks.Add (task);
}
if (llvm_infile != null) { var assembly_path = FullPath;
var taskllvm = CreateCompileTask (s, llvm_infile, abi); var build_dir = Path.GetDirectoryName (assembly_path);
if (taskllvm != null)
compile_tasks.Add (taskllvm);
}
return compile_tasks.Count > 0 ? compile_tasks : null;
}
IEnumerable<BuildTask> CreateManagedToAssemblyTasks (string s, Abi abi, string build_dir)
{
var arch = abi.AsArchString (); var arch = abi.AsArchString ();
var asm_dir = App.Cache.Location; var asm_dir = Path.Combine (App.Cache.Location, arch);
var asm = Path.Combine (asm_dir, Path.GetFileName (s)) + "." + arch + ".s"; var asm = Path.Combine (asm_dir, Path.GetFileName (assembly_path)) + ".s";
var llvm_asm = Path.Combine (asm_dir, Path.GetFileName (s)) + "." + arch + "-llvm.s"; var data = Path.Combine (asm_dir, Path.GetFileNameWithoutExtension (assembly_path)) + ".aotdata" + "." + arch;
var data = Path.Combine (asm_dir, Path.GetFileNameWithoutExtension (s)) + "." + arch + ".aotdata"; var llvm_aot_ofile = "";
string llvm_ofile, llvm_aot_ofile = ""; var asm_output = "";
var is_llvm = (abi & Abi.LLVM) == Abi.LLVM; var is_llvm = (abi & Abi.LLVM) == Abi.LLVM;
bool assemble_llvm = is_llvm && Driver.GetLLVMAsmWriter (App);
if (!File.Exists (s)) Directory.CreateDirectory (asm_dir);
throw new MonoTouchException (3004, true, "Could not AOT the assembly '{0}' because it doesn't exist.", s);
HashSet<string> dependencies = null; if (!File.Exists (assembly_path))
List<string> deps = null; throw new MonoTouchException (3004, true, "Could not AOT the assembly '{0}' because it doesn't exist.", assembly_path);
List<string> outputs = new List<string> ();
var warnings = new List<Exception> ();
dependencies = ComputeDependencies (warnings); var aotInfo = new AotInfo ();
AotInfos.Add (abi, aotInfo);
if (warnings.Count > 0) {
ErrorHelper.Show (warnings);
ErrorHelper.Warning (3006, "Could not compute a complete dependency map for the project. This will result in slower build times because Xamarin.iOS can't properly detect what needs to be rebuilt (and what does not need to be rebuilt). Please review previous warnings for more details.");
} else {
deps = new List<string> (dependencies.ToArray ());
deps.Add (s);
deps.Add (Driver.GetAotCompiler (App, Target.Is64Build));
}
if (App.EnableLLVMOnlyBitCode) { if (App.EnableLLVMOnlyBitCode) {
//
// In llvm-only mode, the AOT compiler emits a .bc file and no .s file for JITted code // In llvm-only mode, the AOT compiler emits a .bc file and no .s file for JITted code
// llvm_aot_ofile = Path.Combine (asm_dir, Path.GetFileName (assembly_path)) + ".bc";
llvm_ofile = Path.Combine (asm_dir, Path.GetFileName (s)) + "." + arch + ".bc"; aotInfo.BitcodeFiles.Add (llvm_aot_ofile);
outputs.Add (llvm_ofile); } else if (is_llvm) {
llvm_aot_ofile = llvm_ofile; if (Driver.GetLLVMAsmWriter (App)) {
llvm_aot_ofile = Path.Combine (asm_dir, Path.GetFileName (assembly_path)) + "-llvm.s";
aotInfo.AsmFiles.Add (llvm_aot_ofile);
} else { } else {
llvm_ofile = Path.Combine (asm_dir, Path.GetFileName (s)) + "." + arch + "-llvm.o"; llvm_aot_ofile = Path.Combine (asm_dir, Path.GetFileName (assembly_path)) + "-llvm.o";
outputs.Add (asm); aotInfo.ObjectFiles.Add (llvm_aot_ofile);
}
if (is_llvm) { asm_output = asm;
if (assemble_llvm) {
llvm_aot_ofile = llvm_asm;
} else { } else {
llvm_aot_ofile = llvm_ofile; asm_output = asm;
Target.LinkWith (llvm_ofile);
}
outputs.Add (llvm_aot_ofile);
}
} }
if (deps != null && Application.IsUptodate (deps, outputs)) { if (!string.IsNullOrEmpty (asm_output))
Driver.Log (3, "Target {0} is up-to-date.", asm); aotInfo.AsmFiles.Add (asm_output);
if (App.EnableLLVMOnlyBitCode) aotInfo.AotDataFiles.Add (data);
return CreateCompileTasks (s, null, llvm_ofile, abi);
else
return CreateCompileTasks (s, asm, assemble_llvm ? llvm_asm : null, abi);
} else {
Application.TryDelete (asm); // otherwise the next task might not detect that it will have to rebuild.
Application.TryDelete (llvm_asm);
Application.TryDelete (llvm_ofile);
Driver.Log (3, "Target {0} needs to be rebuilt.", asm);
}
var aotCompiler = Driver.GetAotCompiler (App, Target.Is64Build); var aotCompiler = Driver.GetAotCompiler (App, Target.Is64Build);
var aotArgs = Driver.GetAotArguments (App, s, abi, build_dir, asm, llvm_aot_ofile, data); var aotArgs = Driver.GetAotArguments (App, assembly_path, abi, build_dir, asm_output, llvm_aot_ofile, data);
Driver.Log (3, "Aot compiler: {0} {1}", aotCompiler, aotArgs); var task = new AOTTask
AotDataFiles.Add (data);
IEnumerable<BuildTask> nextTasks;
if (App.EnableLLVMOnlyBitCode)
nextTasks = CreateCompileTasks (s, null, llvm_ofile, abi);
else
nextTasks = CreateCompileTasks (s, asm, assemble_llvm ? llvm_asm : null, abi);
return new BuildTask [] { new AOTTask ()
{ {
AssemblyName = s, Assembly = this,
AddBitcodeMarkerSection = App.FastDev && App.EnableMarkerOnlyBitCode, AssemblyName = assembly_path,
AddBitcodeMarkerSection = BuildTarget != AssemblyBuildTarget.StaticObject && App.EnableMarkerOnlyBitCode,
AssemblyPath = asm, AssemblyPath = asm,
ProcessStartInfo = Driver.CreateStartInfo (App, aotCompiler, aotArgs, Path.GetDirectoryName (s)), ProcessStartInfo = Driver.CreateStartInfo (App, aotCompiler, aotArgs, Path.GetDirectoryName (assembly_path)),
NextTasks = nextTasks AotInfo = aotInfo,
}
};
}
// The input file is either a .s or a .bc file
BuildTask CreateCompileTask (string assembly_name, string infile_path, Abi abi)
{
var ext = App.FastDev ? "dylib" : "o";
var ofile = Path.ChangeExtension (infile_path, ext);
var install_name = string.Empty;
if (App.FastDev) {
if (dylibs == null)
dylibs = new List<string> ();
dylibs.Add (ofile);
install_name = "lib" + Path.GetFileName (assembly_name) + ".dylib";
} else {
Target.LinkWith (ofile);
}
if (Application.IsUptodate (new string [] { infile_path, App.CompilerPath }, new string [] { ofile })) {
Driver.Log (3, "Target {0} is up-to-date.", ofile);
return null;
} else {
Application.TryDelete (ofile); // otherwise the next task might not detect that it will have to rebuild.
Driver.Log (3, "Target {0} needs to be rebuilt.", ofile);
}
var compiler_flags = new CompilerFlags () { Target = Target };
BuildTask bitcode_task = null;
BuildTask link_task = null;
string link_task_input, link_language = "";
if (App.EnableAsmOnlyBitCode) {
link_task_input = infile_path + ".ll";
link_language = "";
// linker_flags.Add (" -fembed-bitcode");
bitcode_task = new BitCodeify () {
Input = infile_path,
OutputFile = link_task_input,
Platform = App.Platform,
Abi = abi,
DeploymentTarget = App.DeploymentTarget,
};
} else {
link_task_input = infile_path;
if (infile_path.EndsWith (".s", StringComparison.Ordinal))
link_language = "assembler";
}
if (App.FastDev) {
compiler_flags.AddFrameworks (Frameworks, WeakFrameworks);
compiler_flags.AddLinkWith (LinkWith, ForceLoad);
compiler_flags.LinkWithMono ();
compiler_flags.LinkWithXamarin ();
compiler_flags.AddOtherFlags (LinkerFlags);
if (Target.GetEntryPoints ().ContainsKey ("UIApplicationMain"))
compiler_flags.AddFramework ("UIKit");
compiler_flags.LinkWithPInvokes (abi);
if (HasLinkWithAttributes && !App.EnableBitCode)
compiler_flags.ReferenceSymbols (Target.GetRequiredSymbols (this, true));
}
if (App.EnableLLVMOnlyBitCode) {
// The AOT compiler doesn't optimize the bitcode so clang will do it
compiler_flags.AddOtherFlag ("-fexceptions");
var optimizations = App.GetLLVMOptimizations (this);
if (optimizations == null) {
compiler_flags.AddOtherFlag ("-O2");
} else if (optimizations.Length > 0) {
compiler_flags.AddOtherFlag (optimizations);
}
}
link_task = new LinkTask ()
{
Target = Target,
AssemblyName = assembly_name,
Abi = abi,
InputFile = link_task_input,
OutputFile = ofile,
InstallName = install_name,
CompilerFlags = compiler_flags,
SharedLibrary = App.FastDev,
Language = link_language,
}; };
if (bitcode_task != null) { aotInfo.Task = task;
bitcode_task.NextTasks = new BuildTask[] { link_task };
return bitcode_task;
}
return link_task;
} }
public bool CanSymLinkForApplication () public bool CanSymLinkForApplication ()
@ -402,20 +318,6 @@ namespace Xamarin.Bundler {
return symlink_failed; return symlink_failed;
} }
public void CreateCompilationTasks (BuildTasks tasks, string build_dir, IEnumerable<Abi> abis)
{
var assembly = Path.Combine (build_dir, FileName);
if (App.FastDev)
Dylib = Path.Combine (App.AppDirectory, "lib" + Path.GetFileName (FullPath) + ".dylib");
foreach (var abi in abis) {
var task = CreateManagedToAssemblyTasks (assembly, abi, build_dir);
if (task != null)
tasks.AddRange (task);
}
}
public void LoadAssembly (string filename) public void LoadAssembly (string filename)
{ {
try { try {

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

@ -116,6 +116,11 @@ namespace MonoTouch.Tuner {
return assembly; return assembly;
} }
public void Add (AssemblyDefinition assembly)
{
cache [Path.GetFileNameWithoutExtension (assembly.MainModule.FileName)] = assembly;
}
public AssemblyDefinition Resolve (string fullName) public AssemblyDefinition Resolve (string fullName)
{ {
return Resolve (AssemblyNameReference.Parse (fullName), null); return Resolve (AssemblyNameReference.Parse (fullName), null);

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

@ -5,6 +5,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using Xamarin.MacDev; using Xamarin.MacDev;
using Xamarin.Utils; using Xamarin.Utils;
@ -31,6 +32,11 @@ namespace Xamarin.Bundler
} }
} }
protected Task<int> StartAsync ()
{
return Task.Run (() => Start ());
}
protected int Start () protected int Start ()
{ {
if (Driver.Verbosity > 0) if (Driver.Verbosity > 0)
@ -73,160 +79,153 @@ namespace Xamarin.Bundler
GC.Collect (); // Workaround for: https://bugzilla.xamarin.com/show_bug.cgi?id=43462#c14 GC.Collect (); // Workaround for: https://bugzilla.xamarin.com/show_bug.cgi?id=43462#c14
if (p.ExitCode != 0)
return p.ExitCode;
if (Driver.Verbosity >= 2 && Output.Length > 0) if (Driver.Verbosity >= 2 && Output.Length > 0)
Console.Error.WriteLine (Output.ToString ()); Console.Error.WriteLine (Output.ToString ());
}
return 0; return p.ExitCode;
}
} }
} }
internal class MainTask : CompileTask class GenerateMainTask : BuildTask
{ {
public static void Create (List<BuildTask> tasks, Target target, Abi abi, IEnumerable<Assembly> assemblies, string assemblyName, IList<string> registration_methods) public Target Target;
public Abi Abi;
public string MainM;
public IList<string> RegistrationMethods;
public override IEnumerable<string> Inputs {
get {
foreach (var asm in Target.Assemblies)
yield return asm.FullPath;
}
}
public override IEnumerable<string> Outputs {
get {
yield return MainM;
}
}
protected override void Execute ()
{ {
var app = target.App; Driver.GenerateMain (Target.App, Target.Assemblies, Target.App.AssemblyName, Abi, MainM, RegistrationMethods);
var arch = abi.AsArchString (); }
var ofile = Path.Combine (app.Cache.Location, "main." + arch + ".o");
var ifile = Path.Combine (app.Cache.Location, "main." + arch + ".m");
var files = assemblies.Select (v => v.FullPath);
if (!Application.IsUptodate (files, new string [] { ifile })) {
Driver.GenerateMain (target.App, assemblies, assemblyName, abi, ifile, registration_methods);
} else {
Driver.Log (3, "Target '{0}' is up-to-date.", ifile);
} }
if (!Application.IsUptodate (ifile, ofile)) { class CompileMainTask : CompileTask
var main = new MainTask ()
{ {
Target = target, protected override void CompilationFailed (int exitCode)
Abi = abi,
AssemblyName = assemblyName,
InputFile = ifile,
OutputFile = ofile,
SharedLibrary = false,
Language = "objective-c++",
};
main.CompilerFlags.AddDefine ("MONOTOUCH");
tasks.Add (main);
} else {
Driver.Log (3, "Target '{0}' is up-to-date.", ofile);
}
target.LinkWith (ofile);
}
protected override void Build ()
{ {
if (Compile () != 0) throw ErrorHelper.CreateError (5103, "Failed to compile the file(s) '{0}'. Please file a bug report at http://bugzilla.xamarin.com", string.Join ("', '", CompilerFlags.SourceFiles.ToArray ()));
throw new MonoTouchException (5103, true, "Failed to compile the file '{0}'. Please file a bug report at http://bugzilla.xamarin.com", InputFile);
} }
} }
internal class PinvokesTask : CompileTask class PinvokesTask : CompileTask
{ {
public static void Create (List<BuildTask> tasks, IEnumerable<Abi> abis, Target target, string ifile) protected override void CompilationFailed (int exitCode)
{ {
foreach (var abi in abis) throw ErrorHelper.CreateError (4002, "Failed to compile the generated code for P/Invoke methods. Please file a bug report at http://bugzilla.xamarin.com");
Create (tasks, abi, target, ifile); }
} }
public static void Create (List<BuildTask> tasks, Abi abi, Target target, string ifile) class RunRegistrarTask : BuildTask
{ {
var arch = abi.AsArchString (); public Target Target;
var ext = target.App.FastDev ? ".dylib" : ".o"; public string RegistrarCodePath;
var ofile = Path.Combine (target.App.Cache.Location, "lib" + Path.GetFileNameWithoutExtension (ifile) + "." + arch + ext); public string RegistrarHeaderPath;
if (!Application.IsUptodate (ifile, ofile)) { public override IEnumerable<string> Inputs {
var task = new PinvokesTask () get {
foreach (var asm in Target.Assemblies)
yield return asm.FullPath;
}
}
public override IEnumerable<string> Outputs {
get {
yield return RegistrarHeaderPath;
yield return RegistrarCodePath;
}
}
protected override void Execute ()
{ {
Target = target, Target.StaticRegistrar.Generate (Target.Assemblies.Select ((a) => a.AssemblyDefinition), RegistrarHeaderPath, RegistrarCodePath);
Abi = abi,
InputFile = ifile,
OutputFile = ofile,
SharedLibrary = target.App.FastDev,
Language = "objective-c++",
};
if (target.App.FastDev) {
task.InstallName = "lib" + Path.GetFileNameWithoutExtension (ifile) + ext;
task.CompilerFlags.AddFramework ("Foundation");
task.CompilerFlags.LinkWithXamarin ();
} }
tasks.Add (task);
} else {
Driver.Log (3, "Target '{0}' is up-to-date.", ofile);
} }
target.LinkWith (ofile); class CompileRegistrarTask : CompileTask
target.LinkWithAndShip (ofile);
}
protected override void Build ()
{ {
if (Compile () != 0) public string RegistrarCodePath;
throw new MonoTouchException (4002, true, "Failed to compile the generated code for P/Invoke methods. Please file a bug report at http://bugzilla.xamarin.com"); public string RegistrarHeaderPath;
public override IEnumerable<string> Inputs {
get {
yield return RegistrarHeaderPath;
yield return RegistrarCodePath;
} }
} }
internal class RegistrarTask : CompileTask protected override void CompilationFailed (int exitCode)
{ {
public static void Create (List<BuildTask> tasks, IEnumerable<Abi> abis, Target target, string ifile) throw ErrorHelper.CreateError (4109, "Failed to compile the generated registrar code. Please file a bug report at http://bugzilla.xamarin.com");
{
foreach (var abi in abis)
Create (tasks, abi, target, ifile);
}
public static void Create (List<BuildTask> tasks, Abi abi, Target target, string ifile)
{
var app = target.App;
var arch = abi.AsArchString ();
var ofile = Path.Combine (app.Cache.Location, Path.GetFileNameWithoutExtension (ifile) + "." + arch + ".o");
if (!Application.IsUptodate (ifile, ofile)) {
tasks.Add (new RegistrarTask ()
{
Target = target,
Abi = abi,
InputFile = ifile,
OutputFile = ofile,
SharedLibrary = false,
Language = "objective-c++",
});
} else {
Driver.Log (3, "Target '{0}' is up-to-date.", ofile);
}
target.LinkWith (ofile);
}
protected override void Build ()
{
if (Driver.IsUsingClang (App)) {
// This is because iOS has a forward declaration of NSPortMessage, but no actual declaration.
// They still use NSPortMessage in other API though, so it can't just be removed from our bindings.
CompilerFlags.AddOtherFlag ("-Wno-receiver-forward-class");
}
if (Compile () != 0)
throw new MonoTouchException (4109, true, "Failed to compile the generated registrar code. Please file a bug report at http://bugzilla.xamarin.com");
} }
} }
public class AOTTask : ProcessTask public class AOTTask : ProcessTask
{ {
public Assembly Assembly;
public string AssemblyName; public string AssemblyName;
public bool AddBitcodeMarkerSection; public bool AddBitcodeMarkerSection;
public string AssemblyPath; // path to the .s file. public string AssemblyPath; // path to the .s file.
List<string> inputs;
public AotInfo AotInfo;
// executed with Parallel.ForEach public override IEnumerable<string> Outputs {
protected override void Build () get {
return AotInfo.AotDataFiles
.Union (AotInfo.AsmFiles)
.Union (AotInfo.BitcodeFiles)
.Union (AotInfo.ObjectFiles);
}
}
public override IEnumerable<string> Inputs {
get {
yield return Assembly.FullPath;
}
}
public override IEnumerable<string> FileDependencies {
get {
if (inputs == null) {
inputs = new List<string> ();
if (Assembly.HasDependencyMap)
inputs.AddRange (Assembly.DependencyMap);
inputs.Add (AssemblyName);
inputs.Add (Driver.GetAotCompiler (Assembly.App, Assembly.Target.Is64Build));
var mdb = Assembly.FullPath + ".mdb";
if (File.Exists (mdb))
inputs.Add (mdb);
var config = Assembly.FullPath + ".config";
if (File.Exists (config))
inputs.Add (config);
}
return inputs;
}
}
public override bool IsUptodate {
get {
// We can only check dependencies if we know the assemblies this assembly depend on (otherwise always rebuild).
return Assembly.HasDependencyMap && base.IsUptodate;
}
}
protected async override Task ExecuteAsync ()
{ {
var exit_code = base.Start (); var exit_code = await StartAsync ();
if (exit_code == 0) { if (exit_code == 0) {
if (AddBitcodeMarkerSection) if (AddBitcodeMarkerSection)
@ -253,10 +252,83 @@ namespace Xamarin.Bundler
throw new MonoTouchException (3001, true, "Could not AOT the assembly '{0}'", AssemblyName); throw new MonoTouchException (3001, true, "Could not AOT the assembly '{0}'", AssemblyName);
} }
public override string ToString ()
{
return Path.GetFileName (AssemblyName);
}
}
public class NativeLinkTask : BuildTask
{
public Target Target;
public string OutputFile;
public CompilerFlags CompilerFlags;
public override IEnumerable<string> Inputs {
get {
CompilerFlags.PopulateInputs ();
return CompilerFlags.Inputs;
}
}
public override IEnumerable<string> Outputs {
get {
yield return OutputFile;
}
}
protected override async Task ExecuteAsync ()
{
// always show the native linker warnings since many of them turn out to be very important
// and very hard to diagnose otherwise when hidden from the build output. Ref: bug #2430
var linker_errors = new List<Exception> ();
var output = new StringBuilder ();
var code = await Driver.RunCommandAsync (Target.App.CompilerPath, CompilerFlags.ToString (), null, output);
Application.ProcessNativeLinkerOutput (Target, output.ToString (), CompilerFlags.AllLibraries, linker_errors, code != 0);
if (code != 0) {
// if the build failed - it could be because of missing frameworks / libraries we identified earlier
foreach (var assembly in Target.Assemblies) {
if (assembly.UnresolvedModuleReferences == null)
continue;
foreach (var mr in assembly.UnresolvedModuleReferences) {
// TODO: add more diagnose information on the warnings
var name = Path.GetFileNameWithoutExtension (mr.Name);
linker_errors.Add (new MonoTouchException (5215, false, "References to '{0}' might require additional -framework=XXX or -lXXX instructions to the native linker", name));
}
}
// mtouch does not validate extra parameters given to GCC when linking (--gcc_flags)
if (!String.IsNullOrEmpty (Target.App.UserGccFlags))
linker_errors.Add (new MonoTouchException (5201, true, "Native linking failed. Please review the build log and the user flags provided to gcc: {0}", Target.App.UserGccFlags));
linker_errors.Add (new MonoTouchException (5202, true, "Native linking failed. Please review the build log.", Target.App.UserGccFlags));
}
ErrorHelper.Show (linker_errors);
// the native linker can prefer private (and existing) over public (but non-existing) framework when weak_framework are used
// on an iOS target version where the framework does not exists, e.g. targeting iOS6 for JavaScriptCore added in iOS7 results in
// /System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore instead of
// /System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore
// more details in https://bugzilla.xamarin.com/show_bug.cgi?id=31036
if (Target.WeakFrameworks.Count > 0)
Target.AdjustDylibs ();
Driver.Watch ("Native Link", 1);
}
public override string ToString ()
{
return Path.GetFileName (OutputFile);
}
} }
public class LinkTask : CompileTask public class LinkTask : CompileTask
{ {
protected override void CompilationFailed (int exitCode)
{
throw ErrorHelper.CreateError (5216, "Native linking failed for '{0}'. Please file a bug report at http://bugzilla.xamarin.com", OutputFile);
}
} }
public class CompileTask : BuildTask public class CompileTask : BuildTask
@ -264,16 +336,41 @@ namespace Xamarin.Bundler
public Target Target; public Target Target;
public Application App { get { return Target.App; } } public Application App { get { return Target.App; } }
public bool SharedLibrary; public bool SharedLibrary;
public string InputFile;
public string OutputFile; public string OutputFile;
public Abi Abi; public Abi Abi;
public string AssemblyName;
public string InstallName; public string InstallName;
public string Language; public string Language;
public override IEnumerable<string> Inputs {
get {
CompilerFlags.PopulateInputs ();
return CompilerFlags.Inputs;
}
}
public override IEnumerable<string> Outputs {
get {
yield return OutputFile;
}
}
public bool IsAssembler {
get {
return Language == "assembler";
}
}
public string InputFile {
set {
// This is an accumulative setter-only property,
// to make it possible add dependencies using object initializers.
CompilerFlags.AddSourceFile (value);
}
}
CompilerFlags compiler_flags; CompilerFlags compiler_flags;
public CompilerFlags CompilerFlags { public CompilerFlags CompilerFlags {
get { return compiler_flags ?? (compiler_flags = new CompilerFlags () { Target = Target }); } get { return compiler_flags ?? (compiler_flags = new CompilerFlags (Target)); }
set { compiler_flags = value; } set { compiler_flags = value; }
} }
@ -297,12 +394,12 @@ namespace Xamarin.Bundler
flags.AddOtherFlag ("-mthumb"); flags.AddOtherFlag ("-mthumb");
} }
public static void GetCompilerFlags (Application app, CompilerFlags flags, string ifile, string language = null) public static void GetCompilerFlags (Application app, CompilerFlags flags, bool is_assembler, string language = null)
{ {
if (string.IsNullOrEmpty (ifile) || !ifile.EndsWith (".s", StringComparison.Ordinal)) if (!is_assembler)
flags.AddOtherFlag ("-gdwarf-2"); flags.AddOtherFlag ("-gdwarf-2");
if (!string.IsNullOrEmpty (ifile) && !ifile.EndsWith (".s", StringComparison.Ordinal)) { if (!is_assembler) {
if (string.IsNullOrEmpty (language) || !language.Contains ("++")) { if (string.IsNullOrEmpty (language) || !language.Contains ("++")) {
// error: invalid argument '-std=c99' not allowed with 'C++/ObjC++' // error: invalid argument '-std=c99' not allowed with 'C++/ObjC++'
flags.AddOtherFlag ("-std=c99"); flags.AddOtherFlag ("-std=c99");
@ -313,9 +410,9 @@ namespace Xamarin.Bundler
flags.AddOtherFlag ("-Qunused-arguments"); // don't complain about unused arguments (clang reports -std=c99 and -Isomething as unused). flags.AddOtherFlag ("-Qunused-arguments"); // don't complain about unused arguments (clang reports -std=c99 and -Isomething as unused).
} }
public static void GetSimulatorCompilerFlags (CompilerFlags flags, string ifile, Application app, string language = null) public static void GetSimulatorCompilerFlags (CompilerFlags flags, bool is_assembler, Application app, string language = null)
{ {
GetCompilerFlags (app, flags, ifile, language); GetCompilerFlags (app, flags, is_assembler, language);
string sim_platform = Driver.GetPlatformDirectory (app); string sim_platform = Driver.GetPlatformDirectory (app);
string plist = Path.Combine (sim_platform, "Info.plist"); string plist = Path.Combine (sim_platform, "Info.plist");
@ -344,9 +441,9 @@ namespace Xamarin.Bundler
flags.AddDefine (defines.Replace (" ", String.Empty)); flags.AddDefine (defines.Replace (" ", String.Empty));
} }
void GetDeviceCompilerFlags (CompilerFlags flags, string ifile) void GetDeviceCompilerFlags (CompilerFlags flags, bool is_assembler)
{ {
GetCompilerFlags (App, flags, ifile, Language); GetCompilerFlags (App, flags, is_assembler, Language);
flags.AddOtherFlag ($"-m{Driver.GetTargetMinSdkName (App)}-version-min={App.DeploymentTarget.ToString ()}"); flags.AddOtherFlag ($"-m{Driver.GetTargetMinSdkName (App)}-version-min={App.DeploymentTarget.ToString ()}");
} }
@ -357,10 +454,10 @@ namespace Xamarin.Bundler
throw new ArgumentNullException (nameof (install_name)); throw new ArgumentNullException (nameof (install_name));
flags.AddOtherFlag ("-shared"); flags.AddOtherFlag ("-shared");
if (!App.EnableMarkerOnlyBitCode) if (!App.EnableMarkerOnlyBitCode && !App.EnableAsmOnlyBitCode)
flags.AddOtherFlag ("-read_only_relocs suppress"); flags.AddOtherFlag ("-read_only_relocs suppress");
flags.LinkWithMono (); flags.LinkWithMono ();
flags.AddOtherFlag ("-install_name " + Driver.Quote ($"@rpath/{install_name}")); flags.AddOtherFlag ("-install_name " + Driver.Quote (install_name));
flags.AddOtherFlag ("-fapplication-extension"); // fixes this: warning MT5203: Native linking warning: warning: linking against dylib not safe for use in application extensions: [..]/actionextension.dll.arm64.dylib flags.AddOtherFlag ("-fapplication-extension"); // fixes this: warning MT5203: Native linking warning: warning: linking against dylib not safe for use in application extensions: [..]/actionextension.dll.arm64.dylib
} }
@ -374,18 +471,24 @@ namespace Xamarin.Bundler
flags.AddOtherFlag (App.EnableMarkerOnlyBitCode ? "-fembed-bitcode-marker" : "-fembed-bitcode"); flags.AddOtherFlag (App.EnableMarkerOnlyBitCode ? "-fembed-bitcode-marker" : "-fembed-bitcode");
} }
protected override void Build () protected override async Task ExecuteAsync ()
{ {
if (Compile () != 0) int exitCode = await CompileAsync ();
throw new MonoTouchException (3001, true, "Could not AOT the assembly '{0}'", AssemblyName); if (exitCode != 0)
CompilationFailed (exitCode);
} }
public int Compile () protected virtual void CompilationFailed (int exitCode)
{
throw ErrorHelper.CreateError (5106, "Could not compile the file(s) '{0}'. Please file a bug report at http://bugzilla.xamarin.com", string.Join ("', '", CompilerFlags.SourceFiles.ToArray ()));
}
protected async Task<int> CompileAsync ()
{ {
if (App.IsDeviceBuild) { if (App.IsDeviceBuild) {
GetDeviceCompilerFlags (CompilerFlags, InputFile); GetDeviceCompilerFlags (CompilerFlags, IsAssembler);
} else { } else {
GetSimulatorCompilerFlags (CompilerFlags, InputFile, App, Language); GetSimulatorCompilerFlags (CompilerFlags, IsAssembler, App, Language);
} }
if (App.EnableBitCode) if (App.EnableBitCode)
@ -406,15 +509,22 @@ namespace Xamarin.Bundler
if (!string.IsNullOrEmpty (Language)) if (!string.IsNullOrEmpty (Language))
CompilerFlags.AddOtherFlag ($"-x {Language}"); CompilerFlags.AddOtherFlag ($"-x {Language}");
CompilerFlags.AddOtherFlag (Driver.Quote (InputFile)); Directory.CreateDirectory (Path.GetDirectoryName (OutputFile));
var rv = Driver.RunCommand (App.CompilerPath, CompilerFlags.ToString (), null, null); var rv = await Driver.RunCommandAsync (App.CompilerPath, CompilerFlags.ToString (), null, null);
return rv; return rv;
} }
public override string ToString ()
{
if (compiler_flags == null || compiler_flags.SourceFiles == null)
return Path.GetFileName (OutputFile);
return string.Join (", ", compiler_flags.SourceFiles.Select ((arg) => Path.GetFileName (arg)).ToArray ());
}
} }
public class BitCodeify : BuildTask public class BitCodeifyTask : BuildTask
{ {
public string Input { get; set; } public string Input { get; set; }
public string OutputFile { get; set; } public string OutputFile { get; set; }
@ -422,9 +532,26 @@ namespace Xamarin.Bundler
public Abi Abi { get; set; } public Abi Abi { get; set; }
public Version DeploymentTarget { get; set; } public Version DeploymentTarget { get; set; }
protected override void Build () public override IEnumerable<string> Inputs {
get {
yield return Input;
}
}
public override IEnumerable<string> Outputs {
get {
yield return OutputFile;
}
}
protected override void Execute ()
{ {
new BitcodeConverter (Input, OutputFile, Platform, Abi, DeploymentTarget).Convert (); new BitcodeConverter (Input, OutputFile, Platform, Abi, DeploymentTarget).Convert ();
} }
public override string ToString ()
{
return Path.GetFileName (Input);
}
} }
} }

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

@ -20,6 +20,8 @@ namespace MonoTouch.Tuner {
// 6.3.x requires mono 3.0.x to be installed so the path will be valid // 6.3.x requires mono 3.0.x to be installed so the path will be valid
// using /usr/bin/mono-cil-strip is not always safe, e.g. bug #12459 // using /usr/bin/mono-cil-strip is not always safe, e.g. bug #12459
Driver.Log (1, "Stripping assembly {0} to {1}", assembly_file, output_file);
string tool = "/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5/mono-cil-strip.exe"; string tool = "/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5/mono-cil-strip.exe";
string cmd = tool + " " + Driver.Quote (assembly_file) + " " + Driver.Quote (output_file); string cmd = tool + " " + Driver.Quote (assembly_file) + " " + Driver.Quote (output_file);
if (Driver.RunCommand ("/Library/Frameworks/Mono.framework/Versions/Current/bin/mono", cmd) != 0) if (Driver.RunCommand ("/Library/Frameworks/Mono.framework/Versions/Current/bin/mono", cmd) != 0)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -17,7 +17,7 @@ using Xamarin.Tuner;
namespace MonoTouch.Tuner { namespace MonoTouch.Tuner {
public class LinkerOptions { public class LinkerOptions {
public AssemblyDefinition MainAssembly { get; set; } public IEnumerable<AssemblyDefinition> MainAssemblies { get; set; }
public string OutputDirectory { get; set; } public string OutputDirectory { get; set; }
public LinkMode LinkMode { get; set; } public LinkMode LinkMode { get; set; }
public AssemblyResolver Resolver { get; set; } public AssemblyResolver Resolver { get; set; }
@ -61,11 +61,12 @@ namespace MonoTouch.Tuner {
class Linker { class Linker {
public static void Process (LinkerOptions options, out MonoTouchLinkContext context, out List<string> assemblies) public static void Process (LinkerOptions options, out MonoTouchLinkContext context, out List<AssemblyDefinition> assemblies)
{ {
var pipeline = CreatePipeline (options); var pipeline = CreatePipeline (options);
pipeline.PrependStep (new MobileResolveMainAssemblyStep (options.MainAssembly)); foreach (var ad in options.MainAssemblies)
pipeline.PrependStep (new MobileResolveMainAssemblyStep (ad));
context = CreateLinkContext (options, pipeline); context = CreateLinkContext (options, pipeline);
context.Resolver.AddSearchDirectory (options.OutputDirectory); context.Resolver.AddSearchDirectory (options.OutputDirectory);
@ -192,24 +193,19 @@ namespace MonoTouch.Tuner {
return pipeline; return pipeline;
} }
static List<string> ListAssemblies (MonoTouchLinkContext context) static List<AssemblyDefinition> ListAssemblies (MonoTouchLinkContext context)
{ {
var list = new List<string> (); var list = new List<AssemblyDefinition> ();
foreach (var assembly in context.GetAssemblies ()) { foreach (var assembly in context.GetAssemblies ()) {
if (context.Annotations.GetAction (assembly) == AssemblyAction.Delete) if (context.Annotations.GetAction (assembly) == AssemblyAction.Delete)
continue; continue;
list.Add (GetFullyQualifiedName (assembly)); list.Add (assembly);
} }
return list; return list;
} }
static string GetFullyQualifiedName (AssemblyDefinition assembly)
{
return assembly.MainModule.FileName;
}
static ResolveFromXmlStep GetResolveStep (string filename) static ResolveFromXmlStep GetResolveStep (string filename)
{ {
filename = Path.GetFullPath (filename); filename = Path.GetFullPath (filename);

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

@ -106,8 +106,34 @@ namespace Xamarin.Bundler {
// MT0097 <used by mmp> // MT0097 <used by mmp>
// MT0098 <used by mmp> // MT0098 <used by mmp>
// MT0099 Internal error {0}. Please file a bug report with a test case (http://bugzilla.xamarin.com). // MT0099 Internal error {0}. Please file a bug report with a test case (http://bugzilla.xamarin.com).
// MT0100 Invalid assembly build target: '{0}'. Please file a bug report with a test case (http://bugzilla.xamarin.com).
// MT0101 The assembly '*' is specified multiple times in --assembly-build-target arguments.
// MT0102 The assemblies '*' and '*' have the same target name ('*'), but different targets ('*' and '*').
// MT0103 The static object '*' contains more than one assembly ('*'), but each static object must correspond with exactly one assembly.
// MT0105 No assembly build target was specified for '{0}'.
// MT0106 The assembly build target name '{0}' is invalid: the character '{1}' is not allowed.
// MT0107 The assemblies '{0}' have different custom LLVM optimizations ({1}), which is not allowed when they are all compiled to a single binary.
// MT0108 The assembly build target '{0}' did not match any assemblies.
// Warning MT0109 The assembly '{0}' was loaded from a different path than the provided path (provided path: {1}, actual path: {2}).
// Warning MT0110 Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include third-party binding libraries and that compiles to bitcode. // Warning MT0110 Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include third-party binding libraries and that compiles to bitcode.
// Warning MT0111 Bitcode has been enabled because this version of Xamarin.iOS does not support building watchOS projects using LLVM without enabling bitcode. // Warning MT0111 Bitcode has been enabled because this version of Xamarin.iOS does not support building watchOS projects using LLVM without enabling bitcode.
// Warning MT0112 Native code sharing has been disabled because {0}
// the container app's deployment target is earlier than iOS 8.0 (its {0})).
// the container app includes I18N assemblies ({0}).
// the container app has custom xml definitions for the managed linker ({0}).
// Warning MT0113 Native code sharing has been disabled for the extension '{0}' because {1}
// the bitcode options differ between the container app ({0}) and the extension ({1}).
// the --assembly-build-target options are different between the container app ({1}) and the extension ({2}).
// the I18N assemblies are different between the container app ({1}) and the extension ({2}).
// the arguments to the AOT compiler are different between the container app ({1}) and the extension ({2}).
// the other arguments to the AOT compiler are different between the container app ({1}) and the extension ({2}).
// LLVM is not enabled or disabled in both the container app ({1}) and the extension ({2}).
// the managed linker settings are different between the container app ({1}) and the extension ({2}).
// the skipped assemblies for the managed linker are different between the container app ({1}) and the extension ({2}).
// the extension has custom xml definitions for the managed linker ({1}).
// the container app does not build for the ABI {1} (while the extension is building for this ABI).
// the container app is building for the ABI {1}, which is not compatible with the extension's ABI ({2}).
// the container app is referencing the assembly '{1}' from '{2}', while the extension references it from '{3}'.
// Warning MT0127 Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include more than one third-party binding libraries. // Warning MT0127 Incremental builds have been disabled because this version of Xamarin.iOS does not support incremental builds in projects that include more than one third-party binding libraries.
// MT1xxx file copy / symlinks (project related) // MT1xxx file copy / symlinks (project related)
// MT10xx installer.cs / mtouch.cs // MT10xx installer.cs / mtouch.cs
@ -215,6 +241,8 @@ namespace Xamarin.Bundler {
// Warning MT2015 Invalid HttpMessageHandler `{0}` for watchOS. The only valid value is NSUrlSessionHandler. // Warning MT2015 Invalid HttpMessageHandler `{0}` for watchOS. The only valid value is NSUrlSessionHandler.
// Warning MT2016 Invalid TlsProvider `{0}` option. The only valid value `{1}` will be used. // Warning MT2016 Invalid TlsProvider `{0}` option. The only valid value `{1}` will be used.
// MT2017 Could not process XML description: {0} // MT2017 Could not process XML description: {0}
// MT2018 The assembly '{0}' is referenced from two different locations: '{1}' and '{2}'.
// MT2019 Can not load the root assembly '{0}'.
// MT202x Binding Optimizer failed processing `...`. // MT202x Binding Optimizer failed processing `...`.
// MT203x Removing User Resources failed processing `...`. // MT203x Removing User Resources failed processing `...`.
// MT204x Default HttpMessageHandler setter failed processing `...`. // MT204x Default HttpMessageHandler setter failed processing `...`.
@ -313,6 +341,7 @@ namespace Xamarin.Bundler {
// MT5103 Failed to compile the file '{0}'. Please file a bug report at http://bugzilla.xamarin.com // MT5103 Failed to compile the file '{0}'. Please file a bug report at http://bugzilla.xamarin.com
// MT5104 Could not find neither the '{0}' nor the '{1}' compiler. Please install Xcode 'Command-Line Tools' component // MT5104 Could not find neither the '{0}' nor the '{1}' compiler. Please install Xcode 'Command-Line Tools' component
// MT5105 ** reserved Xamarin.Mac ** // MT5105 ** reserved Xamarin.Mac **
// MT5106 Could not compile the file(s) '{0}'. Please file a bug report at http://bugzilla.xamarin.com
// MT52xx linking // MT52xx linking
// MT5201 Native linking failed. Please review the build log and the user flags provided to gcc: {0} // MT5201 Native linking failed. Please review the build log and the user flags provided to gcc: {0}
// MT5202 Native linking failed. Please review the build log. // MT5202 Native linking failed. Please review the build log.
@ -325,6 +354,7 @@ namespace Xamarin.Bundler {
// MT5213 Duplicate symbol in: {0} (Location related to previous error) // MT5213 Duplicate symbol in: {0} (Location related to previous error)
// MT5214 Native linking failed, undefined symbol: {0}. This symbol was referenced by the managed member {1}.{2}. Please verify that all the necessary frameworks have been referenced and native libraries linked. // MT5214 Native linking failed, undefined symbol: {0}. This symbol was referenced by the managed member {1}.{2}. Please verify that all the necessary frameworks have been referenced and native libraries linked.
// Warning MT5215 References to '{0}' might require additional -framework=XXX or -lXXX instructions to the native linker // Warning MT5215 References to '{0}' might require additional -framework=XXX or -lXXX instructions to the native linker
// MT5216 Native linking failed for {0}. Please file a bug report at http://bugzilla.xamarin.com
// MT53xx other tools // MT53xx other tools
// MT5301 Missing 'strip' tool. Please install Xcode 'Command-Line Tools' component // MT5301 Missing 'strip' tool. Please install Xcode 'Command-Line Tools' component
// MT5302 Missing 'dsymutil' tool. Please install Xcode 'Command-Line Tools' component // MT5302 Missing 'dsymutil' tool. Please install Xcode 'Command-Line Tools' component

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

@ -118,11 +118,18 @@ namespace Xamarin.Bundler
// //
// Output generation // Output generation
static bool force = false; static bool force = false;
static bool dot;
static string cross_prefix = Environment.GetEnvironmentVariable ("MONO_CROSS_PREFIX"); static string cross_prefix = Environment.GetEnvironmentVariable ("MONO_CROSS_PREFIX");
static string extra_args = Environment.GetEnvironmentVariable ("MTOUCH_ENV_OPTIONS"); static string extra_args = Environment.GetEnvironmentVariable ("MTOUCH_ENV_OPTIONS");
static int verbose = GetDefaultVerbosity (); static int verbose = GetDefaultVerbosity ();
public static bool Dot {
get {
return dot;
}
}
// //
// We need to put a hard dep on Mono.Cecil.Mdb.dll so that it get's mkbundled // We need to put a hard dep on Mono.Cecil.Mdb.dll so that it get's mkbundled
// //
@ -170,7 +177,7 @@ namespace Xamarin.Bundler
set { force = value; } set { force = value; }
} }
static string GetPlatform (Application app) public static string GetPlatform (Application app)
{ {
switch (app.Platform) { switch (app.Platform) {
case ApplePlatform.iOS: case ApplePlatform.iOS:
@ -549,6 +556,8 @@ namespace Xamarin.Bundler
var assembly_externs = new StringBuilder (); var assembly_externs = new StringBuilder ();
var assembly_aot_modules = new StringBuilder (); var assembly_aot_modules = new StringBuilder ();
var register_assemblies = new StringBuilder (); var register_assemblies = new StringBuilder ();
var assembly_location = new StringBuilder ();
var assembly_location_count = 0;
var enable_llvm = (abi & Abi.LLVM) != 0; var enable_llvm = (abi & Abi.LLVM) != 0;
register_assemblies.AppendLine ("\tguint32 exception_gchandle = 0;"); register_assemblies.AppendLine ("\tguint32 exception_gchandle = 0;");
@ -566,11 +575,37 @@ namespace Xamarin.Bundler
} }
} }
if ((abi & Abi.SimulatorArchMask) == 0) {
var frameworks = assemblies.Where ((a) => a.BuildTarget == AssemblyBuildTarget.Framework)
.OrderBy ((a) => a.Identity, StringComparer.Ordinal);
foreach (var asm_fw in frameworks) {
var asm_name = asm_fw.Identity;
if (asm_fw.BuildTargetName == asm_name)
continue; // this is deduceable
if (app.IsExtension && asm_fw.IsCodeShared) {
assembly_location.AppendFormat ("\t{{ \"{0}\", \"../../Frameworks/{1}.framework/MonoBundle\" }},\n", asm_name, asm_fw.BuildTargetName);
} else {
assembly_location.AppendFormat ("\t{{ \"{0}\", \"Frameworks/{1}.framework/MonoBundle\" }},\n", asm_name, asm_fw.BuildTargetName);
}
assembly_location_count++;
}
}
try { try {
StringBuilder sb = new StringBuilder (); StringBuilder sb = new StringBuilder ();
using (var sw = new StringWriter (sb)) { using (var sw = new StringWriter (sb)) {
sw.WriteLine ("#include \"xamarin/xamarin.h\""); sw.WriteLine ("#include \"xamarin/xamarin.h\"");
if (assembly_location.Length > 0) {
sw.WriteLine ();
sw.WriteLine ("struct AssemblyLocation assembly_location_entries [] = {");
sw.WriteLine (assembly_location);
sw.WriteLine ("};");
sw.WriteLine ();
sw.WriteLine ("struct AssemblyLocations assembly_locations = {{ {0}, assembly_location_entries }};", assembly_location_count);
}
sw.WriteLine (); sw.WriteLine ();
sw.WriteLine (assembly_externs); sw.WriteLine (assembly_externs);
@ -614,6 +649,9 @@ namespace Xamarin.Bundler
if (app.EnableLLVMOnlyBitCode) if (app.EnableLLVMOnlyBitCode)
sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY);"); sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY);");
if (assembly_location.Length > 0)
sw.WriteLine ("\txamarin_set_assembly_directories (&assembly_locations);");
if (registration_methods != null) { if (registration_methods != null) {
for (int i = 0; i < registration_methods.Count; i++) { for (int i = 0; i < registration_methods.Count; i++) {
sw.Write ("\t"); sw.Write ("\t");
@ -775,6 +813,11 @@ namespace Xamarin.Bundler
new FileInfo (filename).LastWriteTime = timestamp.Value; new FileInfo (filename).LastWriteTime = timestamp.Value;
} }
public static void Touch (params string [] filenames)
{
Touch ((IEnumerable<string>) filenames);
}
public static string Quote (string f) public static string Quote (string f)
{ {
if (f.IndexOf (' ') == -1 && f.IndexOf ('\'') == -1 && f.IndexOf (',') == -1 && f.IndexOf ('$') == -1) if (f.IndexOf (' ') == -1 && f.IndexOf ('\'') == -1 && f.IndexOf (',') == -1 && f.IndexOf ('$') == -1)
@ -981,7 +1024,7 @@ namespace Xamarin.Bundler
static Application ParseArguments (string [] args, out Action a) static Application ParseArguments (string [] args, out Action a)
{ {
var action = Action.None; var action = Action.None;
var app = new Application (); var app = new Application (args);
var assemblies = new List<string> (); var assemblies = new List<string> ();
if (extra_args != null) { if (extra_args != null) {
@ -1021,6 +1064,7 @@ namespace Xamarin.Bundler
{ "h|?|help", "Displays the help", v => SetAction (Action.Help) }, { "h|?|help", "Displays the help", v => SetAction (Action.Help) },
{ "version", "Output version information and exit.", v => SetAction (Action.Version) }, { "version", "Output version information and exit.", v => SetAction (Action.Version) },
{ "f|force", "Forces the recompilation of code, regardless of timestamps", v=>force = true }, { "f|force", "Forces the recompilation of code, regardless of timestamps", v=>force = true },
{ "dot:", "Generate a dot file to visualize the build tree.", v => dot = true },
{ "cache=", "Specify the directory where object files will be cached", v => app.Cache.Location = v }, { "cache=", "Specify the directory where object files will be cached", v => app.Cache.Location = v },
{ "aot=", "Arguments to the static compiler", { "aot=", "Arguments to the static compiler",
v => app.AotArguments = v + (v.EndsWith (",", StringComparison.Ordinal) ? String.Empty : ",") + app.AotArguments v => app.AotArguments = v + (v.EndsWith (",", StringComparison.Ordinal) ? String.Empty : ",") + app.AotArguments
@ -1038,6 +1082,7 @@ namespace Xamarin.Bundler
{ "time", v => watch_level++ }, { "time", v => watch_level++ },
{ "executable=", "Specifies the native executable name to output", v => app.ExecutableName = v }, { "executable=", "Specifies the native executable name to output", v => app.ExecutableName = v },
{ "nofastsim", "Do not run the simulator fast-path build", v => app.NoFastSim = true }, { "nofastsim", "Do not run the simulator fast-path build", v => app.NoFastSim = true },
{ "nodevcodeshare", "Do not share native code between extensions and main app.", v => app.NoDevCodeShare = true },
{ "nolink", "Do not link the assemblies", v => app.LinkMode = LinkMode.None }, { "nolink", "Do not link the assemblies", v => app.LinkMode = LinkMode.None },
{ "nodebugtrack", "Disable debug tracking of object resurrection bugs", v => app.DebugTrack = false }, { "nodebugtrack", "Disable debug tracking of object resurrection bugs", v => app.DebugTrack = false },
{ "debugtrack:", "Enable debug tracking of object resurrection bugs (enabled by default for the simulator)", v => { app.DebugTrack = ParseBool (v, "--debugtrack"); } }, { "debugtrack:", "Enable debug tracking of object resurrection bugs (enabled by default for the simulator)", v => { app.DebugTrack = ParseBool (v, "--debugtrack"); } },
@ -1164,7 +1209,7 @@ namespace Xamarin.Bundler
{ "enable-repl:", "Enable REPL support (simulator and not linking only)", v => { app.EnableRepl = ParseBool (v, "enable-repl"); }, true /* this is a hidden option until we've actually used it and made sure it works as expected */ }, { "enable-repl:", "Enable REPL support (simulator and not linking only)", v => { app.EnableRepl = ParseBool (v, "enable-repl"); }, true /* this is a hidden option until we've actually used it and made sure it works as expected */ },
{ "pie:", "Enable (default) or disable PIE (Position Independent Executable).", v => { app.EnablePie = ParseBool (v, "pie"); }}, { "pie:", "Enable (default) or disable PIE (Position Independent Executable).", v => { app.EnablePie = ParseBool (v, "pie"); }},
{ "compiler=", "Specify the Objective-C compiler to use (valid values are gcc, g++, clang, clang++ or the full path to a GCC-compatible compiler).", v => { app.Compiler = v; }}, { "compiler=", "Specify the Objective-C compiler to use (valid values are gcc, g++, clang, clang++ or the full path to a GCC-compatible compiler).", v => { app.Compiler = v; }},
{ "fastdev", "Build an app that supports fastdev (this app will only work when launched using Xamarin Studio)", v => { app.FastDev = true; }}, { "fastdev", "Build an app that supports fastdev (this app will only work when launched using Xamarin Studio)", v => { app.AddAssemblyBuildTarget ("@all=dynamiclibrary"); }},
{ "force-thread-check", "Keep UI thread checks inside (even release) builds", v => { app.ThreadCheck = true; }}, { "force-thread-check", "Keep UI thread checks inside (even release) builds", v => { app.ThreadCheck = true; }},
{ "disable-thread-check", "Remove UI thread checks inside (even debug) builds", v => { app.ThreadCheck = false; }}, { "disable-thread-check", "Remove UI thread checks inside (even debug) builds", v => { app.ThreadCheck = false; }},
{ "debug:", "Generate debug code in Mono for the specified assembly (set to 'all' to generate debug code for all assemblies, the default is to generate debug code for user assemblies only)", { "debug:", "Generate debug code in Mono for the specified assembly (set to 'all' to generate debug code for all assemblies, the default is to generate debug code for user assemblies only)",
@ -1287,6 +1332,13 @@ namespace Xamarin.Bundler
}, },
{ "tls-provider=", "Specify the default TLS provider", v => { tls_provider = v; }}, { "tls-provider=", "Specify the default TLS provider", v => { tls_provider = v; }},
{ "xamarin-framework-directory=", "The framework directory", v => { mtouch_dir = v; }, true }, { "xamarin-framework-directory=", "The framework directory", v => { mtouch_dir = v; }, true },
{ "assembly-build-target=", "Specifies how to compile assemblies to native code. Possible values: 'staticobject' (default), 'dynamiclibrary' and 'framework'. " +
"Each option also takes an assembly and a potential name (defaults to the name of the assembly). Example: --assembly-build-target=mscorlib.dll=framework[=name]." +
"There also two special names: '@all' and '@sdk': --assembly-build-target=@all|@sdk=framework[=name].", v =>
{
app.AddAssemblyBuildTarget (v);
}
},
}; };
AddSharedOptions (app, os); AddSharedOptions (app, os);
@ -1446,14 +1498,7 @@ namespace Xamarin.Bundler
throw ErrorHelper.CreateError (99, "Internal error: Extension build action is '{0}' when it should be 'Build'. Please file a bug report with a test case (http://bugzilla.xamarin.com).", app_action); throw ErrorHelper.CreateError (99, "Internal error: Extension build action is '{0}' when it should be 'Build'. Please file a bug report with a test case (http://bugzilla.xamarin.com).", app_action);
} }
foreach (var appex in app.AppExtensions) { app.BuildAll ();
Log ("Building {0}...", appex.BundleId);
appex.Build ();
}
if (app.AppExtensions.Count > 0)
Log ("Building {0}...", app.BundleId);
app.Build ();
} }
} else { } else {
throw ErrorHelper.CreateError (99, "Internal error: Invalid action: {0}. Please file a bug report with a test case (http://bugzilla.xamarin.com).", action); throw ErrorHelper.CreateError (99, "Internal error: Invalid action: {0}. Please file a bug report with a test case (http://bugzilla.xamarin.com).", action);

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

@ -9,6 +9,7 @@
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<AssemblyName>mtouch</AssemblyName> <AssemblyName>mtouch</AssemblyName>
<RootNamespace>mtouch</RootNamespace> <RootNamespace>mtouch</RootNamespace>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols> <DebugSymbols>True</DebugSymbols>