xamarin-macios/tools/mtouch/Application.cs

2421 строка
82 KiB
C#
Исходник Обычный вид История

// Copyright 2013 Xamarin Inc. All rights reserved.
2016-04-21 15:58:45 +03:00
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml.Linq;
2016-04-21 15:58:45 +03:00
using System.IO;
using System.Text;
using MonoTouch.Tuner;
using Mono.Tuner;
using Xamarin.Linker;
using Xamarin.Utils;
using Xamarin.MacDev;
2016-04-21 15:58:45 +03:00
namespace Xamarin.Bundler {
public enum BitCodeMode {
None = 0,
ASMOnly = 1,
LLVMOnly = 2,
MarkerOnly = 3,
}
public static class AbiExtensions {
public static string AsString (this Abi self)
{
var rv = (self & Abi.ArchMask).ToString ();
if ((self & Abi.LLVM) == Abi.LLVM)
rv += "+LLVM";
if ((self & Abi.Thumb) == Abi.Thumb)
rv += "+Thumb";
return rv;
}
public static string AsArchString (this Abi self)
{
return (self & Abi.ArchMask).ToString ().ToLowerInvariant ();
}
}
public enum RegistrarMode {
Default,
Dynamic,
Static,
}
public enum BuildTarget {
Simulator,
Device,
}
public enum DlsymOptions
{
Default,
All,
None,
Custom,
}
public partial class Application
{
public const string ProductName = "Xamarin.iOS";
public const string Error91LinkerSuggestion = "set the managed linker behaviour to Link Framework SDKs Only in your project's iOS Build Options > Linker Behavior";
2016-04-21 15:58:45 +03:00
public string ExecutableName;
public BuildTarget BuildTarget;
public bool EnableCxx;
public bool EnableProfiling;
bool? package_managed_debug_symbols;
public bool PackageManagedDebugSymbols {
get { return package_managed_debug_symbols.Value; }
set { package_managed_debug_symbols = value; }
2016-04-21 15:58:45 +03:00
}
bool? enable_msym;
public bool EnableMSym {
get { return enable_msym.Value; }
set { enable_msym = value; }
}
public bool EnableRepl;
public bool IsExtension;
public List<string> Extensions = new List<string> (); // A list of the extensions this app contains.
public List<Application> AppExtensions = new List<Application> ();
public Application ContainerApp; // For extensions, this is the containing app
2016-04-21 15:58:45 +03:00
public bool? EnablePie;
public bool NativeStrip = true;
public string SymbolList;
public bool ManagedStrip = true;
public List<string> NoSymbolStrip = new List<string> ();
[mtouch/mmp] Give users more control over optimizations, and share more code between mtouch and mmp. (#3242) * [mtouch/mmp] Give users more control over optimizations, and share more code between mtouch and mmp. 1. Add an --optimize flag to mtouch/mmp that allows users to select which optimizations to apply (or not). This makes it easier to add future optimizations, and allow users to disable any optimization that causes problems without having to disable many other features. 2. Share as much optimization code as possible between mtouch and mmp. This immediately gives a benefit to mmp, which has three new optimizations only mtouch had: NSObject.IsDirectBinding inlining, IntPtr.Size inlining and dead code elimination. This results in ~6kb of disk space saved for a linked Xamarin.Mac app: * link sdk: [Debug][1], [Release][2] * link all: [Debug][3], [Release][4] Testing also verifies that monotouchtest ([Debug][5], [Release][6]) has not changed size at all, which means that no default optimizations have changed inadvertedly. [1]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#link-sdk-mac--debug [2]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#link-sdk-mac--release [3]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#link-all-mac--debug [4]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#link-all-mac--release [5]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#monotouchtest-iphonedebug64 [6]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#monotouchtest-iphonerelease64 * [tools] Don't enable the IsDirectBinding optimization by default for Xamarin.Mac apps, it's not safe. * Fix whitespace issues. * [doc] Document optimizations. * Officially support optimizations by adding them to the Versions.plist. * [linker] Improve IntPtr.Size inliner + dead code eliminatior and add tests. * Properly handle operands for the ldc_i4_s instruction (they're sbyte). * Fix less-than condition to actually do a less-than comparison. * Make sure to look up the bitness in the Target, not the Application, since the Application's value will be incorrect when building fat apps (both Is32Build and Is64Build will be true). * Remove unnecessary checks for the IntPtr.Size inliner: this optimization does not depend on other instructions than the IntPtr.get_Size call, so remove the checks that verify surrounding instructions. This makes the IntPtr.Size inliner kick in in more scenarios (such as the new tests). * Add tests. * [tests] Add mmp tests for optimizations. * [tests] Fix XM optimization tests. * [tests] Fix test build error.
2018-01-23 13:33:48 +03:00
2016-04-21 15:58:45 +03:00
public DlsymOptions DlsymOptions;
public List<Tuple<string, bool>> DlsymAssemblies;
public bool? UseMonoFramework;
public bool? PackageMonoFramework;
public bool NoFastSim;
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
public bool NoDevCodeShare;
public bool IsCodeShared { get; private set; }
// The list of assemblies that we do generate debugging info for.
public bool DebugAll;
public List<string> DebugAssemblies = new List<string> ();
public bool? DebugTrack;
public string Compiler = string.Empty;
public string CompilerPath;
public string AotArguments = "static,asmonly,direct-icalls,";
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
public List<string> AotOtherArguments = null;
public bool? LLVMAsmWriter;
public Dictionary<string, string> LLVMOptimizations = new Dictionary<string, string> ();
Bump to mono:2018-06 (#4277) * Bump to mono:2018-06 * Bump mono * Updates compression to work with the public span * Bump mono * Fixes pointer check logic in Deflater * Bump mono * Fixes pointer check logic in Deflater * Bump mono * Bump Mono * [runtime] always use `mono_jit_set_aot_mode` (#4491) `mono_jit_set_aot_only` is deprecated and accidentally broke with https://github.com/mono/mono/pull/7887 This should fix device tests with `mono-2018-06` * Testing with Zoltan's patch * Include libmono-system-native on Xamarin.Mac * Bump Mono Commit list for mono/mono: * mono/mono@7bcda192a06 Bump llvm to release_60/fc854b8ec5873d294b80afa3e6cf6a88c5c48886. (#9786). (#9804) * mono/mono@23e95ec7ad7 Apply F# portable pdb debug fix for pinvokes & bump (#9797) * mono/mono@295f6d32afd [2018-06] [MacOS] On Mac, use the copyfile API to copy files (#9696) Diff: https://github.com/mono/mono/compare/7d5f4b61366008d47665bb473205f4ae1f716d1f...7bcda192a06267562af565d404c06d159f475c03 * Revert 4bacab3d5c7fa86a0e6437f64bb9f08ea3d0741b, it doesn't fix the ios aot problems. * Bump mono * [tests] Adjust the MT0137 test for mcs change in behavior. Starting with mono 5.16 mcs will now add assembly references when the assembly is only used in attributes (this was already the case for csc in both 5.14 and 5.16, so it seems to be a compatibility change). Adjust the MT0137 test accordingly. * [msbuild] Fix parsing of json parser errors to handle trailing periods in the error message. Fixes this test: 1) Test Failure : Xamarin.iOS.Tasks.Bug60536.TestACToolTaskCatchesJsonException ColumnNumber Expected: 2 But was: 0 * Bump mono * [builds] Install the old llvm binaries into the LLVM36 directory and make the 32 bit builds use that. * Bump mono * Bump mono * [jenkins] Don't give VSTS a fake branch. (#4667) Something in VSTS changed, and now fake branch names don't work anymore. So instead use real branch names (and for pull requests I've created a 'pull-request' branch we can use). * Assembly.LoadFile accepts only absolute path * [linker] Add new Facade (System.Threading.Tasks.Extensions). Fixes these MTouch test failures: 1. Xamarin.Linker.SdkTest.iOS_Unified : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > 2. Xamarin.Linker.SdkTest.tvOS : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > 3. Xamarin.Linker.SdkTest.watchOS : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > * [mono-sdks] Necessary changes to unify the LLVM provisioning for both iOS and Android. (#4732) * Bump Mono * [mtouch] add mixed-mode support (#4751) * [mtouch] add --interp-mixed option When enabling this option, mtouch will AOT compile `mscorlib.dll`. At runtime that means every method that wasn't AOT'd will be executed by the runtime interpreter. * [mtouch] Add support to --interpreter to list the assemblies to (not) interpret. * [msbuild] Simplify interpreter code to use a single variable. * Fix whitespace. * [mtouch] Move mtouch-specific code to mtouch-specific file. * [msbuild] An empty string is a valid value for 'Interpreter', so make it a non-required property. * [mtouch] Add sanity check for aot-compiling interpreted assemblies. * Bump Mono * [linker] Updates SDKs facades list * Bump mono * [msbuild] Adds facades which might override default nuget version to framework list The collision resolver task reads them from here https://github.com/dotnet/sdk/blob/master/src/Tasks/Common/ConflictResolution/FrameworkListReader.cs * Bump to a VSfM version that can build XM Classic projects.
2018-10-10 18:02:28 +03:00
public bool UseInterpreter;
public List<string> InterpretedAssemblies = new List<string> ();
public Dictionary<string, string> EnvironmentVariables = new Dictionary<string, string> ();
2016-04-21 15:58:45 +03:00
//
// Linker config
//
public bool LinkAway = true;
public bool LinkerDumpDependencies { get; set; }
public List<string> References = new List<string> ();
public bool? BuildDSym;
Bump to mono:2018-06 (#4277) * Bump to mono:2018-06 * Bump mono * Updates compression to work with the public span * Bump mono * Fixes pointer check logic in Deflater * Bump mono * Fixes pointer check logic in Deflater * Bump mono * Bump Mono * [runtime] always use `mono_jit_set_aot_mode` (#4491) `mono_jit_set_aot_only` is deprecated and accidentally broke with https://github.com/mono/mono/pull/7887 This should fix device tests with `mono-2018-06` * Testing with Zoltan's patch * Include libmono-system-native on Xamarin.Mac * Bump Mono Commit list for mono/mono: * mono/mono@7bcda192a06 Bump llvm to release_60/fc854b8ec5873d294b80afa3e6cf6a88c5c48886. (#9786). (#9804) * mono/mono@23e95ec7ad7 Apply F# portable pdb debug fix for pinvokes & bump (#9797) * mono/mono@295f6d32afd [2018-06] [MacOS] On Mac, use the copyfile API to copy files (#9696) Diff: https://github.com/mono/mono/compare/7d5f4b61366008d47665bb473205f4ae1f716d1f...7bcda192a06267562af565d404c06d159f475c03 * Revert 4bacab3d5c7fa86a0e6437f64bb9f08ea3d0741b, it doesn't fix the ios aot problems. * Bump mono * [tests] Adjust the MT0137 test for mcs change in behavior. Starting with mono 5.16 mcs will now add assembly references when the assembly is only used in attributes (this was already the case for csc in both 5.14 and 5.16, so it seems to be a compatibility change). Adjust the MT0137 test accordingly. * [msbuild] Fix parsing of json parser errors to handle trailing periods in the error message. Fixes this test: 1) Test Failure : Xamarin.iOS.Tasks.Bug60536.TestACToolTaskCatchesJsonException ColumnNumber Expected: 2 But was: 0 * Bump mono * [builds] Install the old llvm binaries into the LLVM36 directory and make the 32 bit builds use that. * Bump mono * Bump mono * [jenkins] Don't give VSTS a fake branch. (#4667) Something in VSTS changed, and now fake branch names don't work anymore. So instead use real branch names (and for pull requests I've created a 'pull-request' branch we can use). * Assembly.LoadFile accepts only absolute path * [linker] Add new Facade (System.Threading.Tasks.Extensions). Fixes these MTouch test failures: 1. Xamarin.Linker.SdkTest.iOS_Unified : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > 2. Xamarin.Linker.SdkTest.tvOS : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > 3. Xamarin.Linker.SdkTest.watchOS : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > * [mono-sdks] Necessary changes to unify the LLVM provisioning for both iOS and Android. (#4732) * Bump Mono * [mtouch] add mixed-mode support (#4751) * [mtouch] add --interp-mixed option When enabling this option, mtouch will AOT compile `mscorlib.dll`. At runtime that means every method that wasn't AOT'd will be executed by the runtime interpreter. * [mtouch] Add support to --interpreter to list the assemblies to (not) interpret. * [msbuild] Simplify interpreter code to use a single variable. * Fix whitespace. * [mtouch] Move mtouch-specific code to mtouch-specific file. * [msbuild] An empty string is a valid value for 'Interpreter', so make it a non-required property. * [mtouch] Add sanity check for aot-compiling interpreted assemblies. * Bump Mono * [linker] Updates SDKs facades list * Bump mono * [msbuild] Adds facades which might override default nuget version to framework list The collision resolver task reads them from here https://github.com/dotnet/sdk/blob/master/src/Tasks/Common/ConflictResolution/FrameworkListReader.cs * Bump to a VSfM version that can build XM Classic projects.
2018-10-10 18:02:28 +03:00
public bool IsInterpreted (string assembly)
{
// IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both.
if (!UseInterpreter)
return false;
// Go through the list of assemblies to interpret in reverse order,
// so that the last option passed to mtouch takes precedence.
for (int i = InterpretedAssemblies.Count - 1; i >= 0; i--) {
var opt = InterpretedAssemblies [i];
if (opt == "all")
return true;
else if (opt == "-all")
return false;
else if (opt == assembly)
return true;
else if (opt [0] == '-' && opt.Substring (1) == assembly)
return false;
}
// There's an implicit 'all' at the start of the list.
return true;
}
public bool IsAOTCompiled (string assembly)
{
if (!UseInterpreter)
return true;
// IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both:
// - mscorlib will always be processed by the AOT compiler to generate required wrapper functions for the interpreter to work
// - mscorlib might also be fully AOT-compiled (both when the interpreter is enabled and when it's not)
if (assembly == "mscorlib")
return true;
return !IsInterpreted (assembly);
}
// If we're targetting a 32 bit arch.
bool? is32bits;
public bool Is32Build {
get {
if (!is32bits.HasValue)
is32bits = IsArchEnabled (Abi.Arch32Mask);
return is32bits.Value;
}
}
// If we're targetting a 64 bit arch.
bool? is64bits;
public bool Is64Build {
get {
if (!is64bits.HasValue)
is64bits = IsArchEnabled (Abi.Arch64Mask);
return is64bits.Value;
}
}
2016-04-21 15:58:45 +03:00
public bool IsDualBuild { get { return Is32Build && Is64Build; } } // if we're building both a 32 and a 64 bit version.
public bool IsLLVM { get { return IsArchEnabled (Abi.LLVM); } }
bool RequiresXcodeHeaders => LinkMode == LinkMode.None;
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
public List<string> UserGccFlags;
2016-04-21 15:58:45 +03:00
// If we didn't link the final executable because the existing binary is up-to-date.
bool cached_executable {
get {
if (final_build_task == null) {
// symlinked
return false;
}
return !final_build_task.Rebuilt;
}
}
2016-04-21 15:58:45 +03:00
List<Abi> abis;
HashSet<Abi> all_architectures; // all Abis used in the app, including extensions.
[mtouch] Rework how tasks are built. The previous build system kept a forward-pointing single linked list of tasks to execute: task X had a list of subsequent tasks to execute. If task X was up-to-date, it was not created (and the next tasks were directly added to the list of tasks to execute). In this world it became complicated to merge output from tasks (for instance if the output of task X and task Y should be a consumed by a single task producing a single output, since the corresponding task would end up in both X's and Y's list of subsequent tasks). Example: creating a single framework from the aot-compiled output of multiple assemblies. So I've reversed the logic: now we keep track of the final output, and then each task has a list of dependencies that must be built. This makes it trivial to create merging tasks (for the previous example, there could for instance be a CreateFrameworkTask, where its dependencies would be all the corresponding AotTasks). We also always create every task, and then each task decides when its executed whether it should do anything or not. This makes it unnecessary to 'forward- delete' files when creating tasks (say you have three tasks, A, B, C; B depends on A, and C depends on B; if A's output isn't up-to-date, it has to delete its own output if it exists, otherwise B would not detect that it would have to re-execute, because at task *creation* time, B's input hadn't changed). Additionally make it based on async/await, since much of the work happens in externel processes (and we don't need to spin up additional threads just to run external processes). This makes us have less code run on background threads, which makes any issues with thread-safety less likely.
2017-01-26 12:56:55 +03:00
BuildTasks build_tasks;
BuildTask final_build_task; // either lipo or file copy (to final destination)
[mtouch] Rework how tasks are built. The previous build system kept a forward-pointing single linked list of tasks to execute: task X had a list of subsequent tasks to execute. If task X was up-to-date, it was not created (and the next tasks were directly added to the list of tasks to execute). In this world it became complicated to merge output from tasks (for instance if the output of task X and task Y should be a consumed by a single task producing a single output, since the corresponding task would end up in both X's and Y's list of subsequent tasks). Example: creating a single framework from the aot-compiled output of multiple assemblies. So I've reversed the logic: now we keep track of the final output, and then each task has a list of dependencies that must be built. This makes it trivial to create merging tasks (for the previous example, there could for instance be a CreateFrameworkTask, where its dependencies would be all the corresponding AotTasks). We also always create every task, and then each task decides when its executed whether it should do anything or not. This makes it unnecessary to 'forward- delete' files when creating tasks (say you have three tasks, A, B, C; B depends on A, and C depends on B; if A's output isn't up-to-date, it has to delete its own output if it exists, otherwise B would not detect that it would have to re-execute, because at task *creation* time, B's input hadn't changed). Additionally make it based on async/await, since much of the work happens in externel processes (and we don't need to spin up additional threads just to run external processes). This makes us have less code run on background threads, which makes any issues with thread-safety less likely.
2017-01-26 12:56:55 +03:00
Dictionary<string, Tuple<AssemblyBuildTarget, string>> assembly_build_targets = new Dictionary<string, Tuple<AssemblyBuildTarget, string>> ();
public AssemblyBuildTarget LibMonoLinkMode {
get {
if (Embeddinator) {
return AssemblyBuildTarget.StaticObject;
} else if (HasFrameworks || UseMonoFramework.Value) {
return AssemblyBuildTarget.Framework;
} else if (HasDynamicLibraries) {
return AssemblyBuildTarget.DynamicLibrary;
} else {
return AssemblyBuildTarget.StaticObject;
}
}
}
public AssemblyBuildTarget LibXamarinLinkMode {
get {
if (Embeddinator) {
return AssemblyBuildTarget.StaticObject;
} else if (HasFrameworks) {
return AssemblyBuildTarget.Framework;
} else if (HasDynamicLibraries) {
return AssemblyBuildTarget.DynamicLibrary;
} else {
return AssemblyBuildTarget.StaticObject;
}
}
}
public AssemblyBuildTarget LibPInvokesLinkMode => LibXamarinLinkMode;
public AssemblyBuildTarget LibProfilerLinkMode => OnlyStaticLibraries ? AssemblyBuildTarget.StaticObject : AssemblyBuildTarget.DynamicLibrary;
public AssemblyBuildTarget LibMonoNativeLinkMode => HasDynamicLibraries ? AssemblyBuildTarget.DynamicLibrary : AssemblyBuildTarget.StaticObject;
Dictionary<string, BundleFileInfo> bundle_files = new Dictionary<string, BundleFileInfo> ();
public bool OnlyStaticLibraries {
get {
return assembly_build_targets.All ((abt) => abt.Value.Item1 == AssemblyBuildTarget.StaticObject);
}
}
public bool HasDynamicLibraries {
get {
return assembly_build_targets.Any ((abt) => abt.Value.Item1 == AssemblyBuildTarget.DynamicLibrary);
}
}
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
public bool HasAnyDynamicLibraries {
get {
if (LibMonoLinkMode == AssemblyBuildTarget.DynamicLibrary)
return true;
if (LibXamarinLinkMode == AssemblyBuildTarget.DynamicLibrary)
return true;
if (LibPInvokesLinkMode == AssemblyBuildTarget.DynamicLibrary)
return true;
if (LibProfilerLinkMode == AssemblyBuildTarget.DynamicLibrary)
return true;
2018-10-15 22:39:29 +03:00
if (LibMonoNativeLinkMode == AssemblyBuildTarget.DynamicLibrary)
return true;
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
return HasDynamicLibraries;
}
}
public bool HasFrameworks {
get {
return assembly_build_targets.Any ((abt) => abt.Value.Item1 == AssemblyBuildTarget.Framework);
}
}
public void ClearAssemblyBuildTargets ()
{
assembly_build_targets.Clear ();
}
public void AddAssemblyBuildTarget (string value)
{
var eq_index = value.IndexOf ('=');
if (eq_index == -1)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (10, Errors.MX0010, $"--assembly-build-target={value}");
var assembly_name = value.Substring (0, eq_index);
string target, name;
var eq_index2 = value.IndexOf ('=', eq_index + 1);
if (eq_index2 == -1) {
target = value.Substring (eq_index + 1);
if (assembly_name == "@all" || assembly_name == "@sdk") {
name = string.Empty;
} else {
name = assembly_name;
}
} else {
target = value.Substring (eq_index + 1, eq_index2 - eq_index - 1);
name = value.Substring (eq_index2 + 1);
}
int invalid_idx;
if ((invalid_idx = name.IndexOfAny (new char [] { '/', '\\' })) != -1)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (106, Errors.MT0106, name, name [invalid_idx]);
if (assembly_build_targets.ContainsKey (assembly_name))
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (101, Errors.MT0101, assembly_name);
AssemblyBuildTarget build_target;
switch (target) {
case "staticobject":
build_target = AssemblyBuildTarget.StaticObject;
break;
case "dynamiclibrary":
build_target = AssemblyBuildTarget.DynamicLibrary;
break;
case "framework":
build_target = AssemblyBuildTarget.Framework;
if (name.EndsWith (".framework", StringComparison.Ordinal))
name = name.Substring (0, name.Length - ".framework".Length);
break;
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (10, Errors.MX0010, $"--assembly-build-target={value}");
}
assembly_build_targets [assembly_name] = new Tuple<AssemblyBuildTarget, string> (build_target, name);
}
public bool ContainsGroupedSdkAssemblyBuildTargets {
get {
// The logic here must match the default logic in 'SelectAssemblyBuildTargets' (because we will execute this method before 'SelectAssemblyBuildTargets' is executed)
Tuple<AssemblyBuildTarget, string> value;
if (!assembly_build_targets.TryGetValue ("@sdk", out value))
return IsCodeShared;
return !string.IsNullOrEmpty (value.Item2);
}
}
void SelectAssemblyBuildTargets ()
{
Tuple<AssemblyBuildTarget, string> all = null;
Tuple<AssemblyBuildTarget, string> sdk = null;
List<Exception> exceptions = null;
if (IsSimulatorBuild && !Embeddinator) {
if (assembly_build_targets.Count > 0) {
var first = assembly_build_targets.First ();
if (assembly_build_targets.Count == 1 && first.Key == "@all" && first.Value.Item1 == AssemblyBuildTarget.DynamicLibrary && first.Value.Item2 == string.Empty) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (126, Errors.MT0126);
} else {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (125, Errors.MT0125);
}
assembly_build_targets.Clear ();
}
return;
}
if (assembly_build_targets.Count == 0) {
// The logic here must match the logic in 'ContainsGroupedSdkAssemblyBuildTarget' (because we will execute 'ContainsGroupedSdkAssemblyBuildTargets' before this is executed)
assembly_build_targets.Add ("@all", new Tuple<AssemblyBuildTarget, string> (AssemblyBuildTarget.StaticObject, ""));
if (IsCodeShared) {
// If we're sharing code, then we can default to creating a Xamarin.Sdk.framework for SDK assemblies,
// and static objects for the rest of the assemblies.
assembly_build_targets.Add ("@sdk", new Tuple<AssemblyBuildTarget, string> (AssemblyBuildTarget.Framework, "Xamarin.Sdk"));
}
}
assembly_build_targets.TryGetValue ("@all", out all);
assembly_build_targets.TryGetValue ("@sdk", out sdk);
foreach (var target in Targets) {
var asm_build_targets = new Dictionary<string, Tuple<AssemblyBuildTarget, string>> (assembly_build_targets);
foreach (var assembly in target.Assemblies) {
Tuple<AssemblyBuildTarget, string> build_target;
var asm_name = assembly.Identity;
if (asm_build_targets.TryGetValue (asm_name, out build_target)) {
asm_build_targets.Remove (asm_name);
} else if (sdk != null && (Profile.IsSdkAssembly (asm_name) || Profile.IsProductAssembly (asm_name))) {
build_target = sdk;
} else {
build_target = all;
}
if (build_target == null) {
if (exceptions == null)
exceptions = new List<Exception> ();
2020-01-31 23:02:52 +03:00
exceptions.Add (ErrorHelper.CreateError (105, Errors.MT0105, assembly.Identity));
continue;
}
assembly.BuildTarget = build_target.Item1;
// The default build target name is the assembly's filename, including the extension,
// so that for instance for System.dll, we'd end up with a System.dll.framework
// (this way it doesn't clash with the system's System.framework).
assembly.BuildTargetName = string.IsNullOrEmpty (build_target.Item2) ? Path.GetFileName (assembly.FileName) : build_target.Item2;
}
foreach (var abt in asm_build_targets) {
if (abt.Key == "@all" || abt.Key == "@sdk")
continue;
if (exceptions == null)
exceptions = new List<Exception> ();
2020-01-31 23:02:52 +03:00
exceptions.Add (ErrorHelper.CreateError (108, Errors.MT0108, abt.Key));
}
if (exceptions != null)
continue;
var grouped = target.Assemblies.GroupBy ((a) => a.BuildTargetName);
foreach (var @group in grouped) {
var assemblies = @group.AsEnumerable ().ToArray ();
// Check that all assemblies in a group have the same build target
for (int i = 1; i < assemblies.Length; i++) {
if (assemblies [0].BuildTarget != assemblies [i].BuildTarget)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (102, Errors.MT0102,
assemblies [0].Identity, assemblies [1].Identity, assemblies [0].BuildTargetName, assemblies [0].BuildTarget, assemblies [1].BuildTarget);
}
// Check that static objects must consist of only one assembly
if (assemblies.Length != 1 && assemblies [0].BuildTarget == AssemblyBuildTarget.StaticObject)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (103, Errors.MT0103,
assemblies [0].BuildTargetName, string.Join ("', '", assemblies.Select ((a) => a.Identity).ToArray ()));
}
}
if (exceptions != null)
throw new AggregateException (exceptions);
}
public string GetLLVMOptimizations (Assembly assembly)
{
string opt;
if (LLVMOptimizations.TryGetValue (assembly.FileName, out opt))
return opt;
if (LLVMOptimizations.TryGetValue ("all", out opt))
return opt;
return null;
}
public void SetDlsymOption (string asm, bool dlsym)
{
if (DlsymAssemblies == null)
DlsymAssemblies = new List<Tuple<string, bool>> ();
DlsymAssemblies.Add (new Tuple<string, bool> (Path.GetFileNameWithoutExtension (asm), dlsym));
DlsymOptions = DlsymOptions.Custom;
}
2016-04-21 15:58:45 +03:00
public void ParseDlsymOptions (string options)
{
bool dlsym;
if (Driver.TryParseBool (options, out dlsym)) {
DlsymOptions = dlsym ? DlsymOptions.All : DlsymOptions.None;
} else {
DlsymAssemblies = new List<Tuple<string, bool>> ();
var assemblies = options.Split (',');
foreach (var assembly in assemblies) {
var asm = assembly;
if (assembly.StartsWith ("+", StringComparison.Ordinal)) {
2016-04-21 15:58:45 +03:00
dlsym = true;
asm = assembly.Substring (1);
} else if (assembly.StartsWith ("-", StringComparison.Ordinal)) {
2016-04-21 15:58:45 +03:00
dlsym = false;
asm = assembly.Substring (1);
} else {
dlsym = true;
}
DlsymAssemblies.Add (new Tuple<string, bool> (Path.GetFileNameWithoutExtension (asm), dlsym));
}
DlsymOptions = DlsymOptions.Custom;
}
}
public bool UseDlsym (string assembly)
{
string asm;
if (DlsymAssemblies != null) {
asm = Path.GetFileNameWithoutExtension (assembly);
foreach (var tuple in DlsymAssemblies) {
if (string.Equals (tuple.Item1, asm, StringComparison.Ordinal))
return tuple.Item2;
}
}
switch (DlsymOptions) {
case DlsymOptions.All:
return true;
case DlsymOptions.None:
return false;
}
2016-04-21 15:58:45 +03:00
if (EnableLLVMOnlyBitCode)
return false;
// Even if this assembly is aot'ed, if we are using the interpreter we can't yet
// guarantee that code in this assembly won't be executed in interpreted mode,
// which can happen for virtual calls between assemblies, during exception handling
// etc. We make sure we don't strip away symbols needed for pinvoke calls.
// https://github.com/mono/mono/issues/14206
if (UseInterpreter)
return true;
2016-04-21 15:58:45 +03:00
switch (Platform) {
case ApplePlatform.iOS:
return !Profile.IsSdkAssembly (Path.GetFileNameWithoutExtension (assembly));
2016-04-21 15:58:45 +03:00
case ApplePlatform.TVOS:
case ApplePlatform.WatchOS:
return false;
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (71, Errors.MX0071, Platform, "Xamarin.iOS");
2016-04-21 15:58:45 +03:00
}
}
public string MonoGCParams {
get {
// Configure sgen to use a small nursery
string ret = "nursery-size=512k";
if (IsTodayExtension || Platform == ApplePlatform.WatchOS) {
// A bit test shows different behavior
// Sometimes apps are killed with ~100mb allocated,
// but I've seen apps allocate up to 240+mb as well
ret += ",soft-heap-limit=8m";
2016-04-21 15:58:45 +03:00
}
if (EnableSGenConc)
ret += ",major=marksweep-conc";
else
ret += ",major=marksweep";
return ret;
2016-04-21 15:58:45 +03:00
}
}
public bool IsDeviceBuild {
get { return BuildTarget == BuildTarget.Device; }
}
public bool IsSimulatorBuild {
get { return BuildTarget == BuildTarget.Simulator; }
}
public IEnumerable<Abi> Abis {
get { return abis; }
}
public BitCodeMode BitCodeMode { get; set; }
public bool EnableAsmOnlyBitCode { get { return BitCodeMode == BitCodeMode.ASMOnly; } }
public bool EnableLLVMOnlyBitCode { get { return BitCodeMode == BitCodeMode.LLVMOnly; } }
public bool EnableMarkerOnlyBitCode { get { return BitCodeMode == BitCodeMode.MarkerOnly; } }
public bool EnableBitCode { get { return BitCodeMode != BitCodeMode.None; } }
public ICollection<Abi> AllArchitectures {
get {
if (all_architectures == null) {
all_architectures = new HashSet<Abi> ();
foreach (var abi in abis)
all_architectures.Add (abi);
foreach (var ext in AppExtensions) {
foreach (var abi in ext.Abis)
all_architectures.Add (abi);
2016-04-21 15:58:45 +03:00
}
}
return all_architectures;
}
}
public bool IsTodayExtension {
get {
return ExtensionIdentifier == "com.apple.widget-extension";
}
}
public bool IsWatchExtension {
get {
return ExtensionIdentifier == "com.apple.watchkit";
}
}
public bool IsTVExtension {
get {
return ExtensionIdentifier == "com.apple.tv-services";
}
}
public bool HasFrameworksDirectory {
get {
if (!IsExtension)
return true;
if (IsWatchExtension && Platform == ApplePlatform.WatchOS)
return true;
return false;
}
}
2016-04-21 15:58:45 +03:00
public string ExtensionIdentifier {
get {
if (!IsExtension)
return null;
var info_plist = Path.Combine (AppDirectory, "Info.plist");
var plist = Driver.FromPList (info_plist);
var dict = plist.Get<PDictionary> ("NSExtension");
if (dict == null)
return null;
return dict.GetString ("NSExtensionPointIdentifier");
2016-04-21 15:58:45 +03:00
}
}
public string BundleId {
get {
return GetStringFromInfoPList ("CFBundleIdentifier");
}
}
2016-04-21 15:58:45 +03:00
string GetStringFromInfoPList (string key)
{
return GetStringFromInfoPList (AppDirectory, key);
2016-04-21 15:58:45 +03:00
}
string GetStringFromInfoPList (string directory, string key)
{
var info_plist = Path.Combine (directory, "Info.plist");
if (!File.Exists (info_plist))
return null;
var plist = Driver.FromPList (info_plist);
if (!plist.ContainsKey (key))
return null;
return plist.GetString (key);
2016-04-21 15:58:45 +03:00
}
public void SetDefaultAbi ()
{
if (abis == null)
abis = new List<Abi> ();
switch (Platform) {
case ApplePlatform.iOS:
if (abis.Count == 0) {
if (DeploymentTarget == null || DeploymentTarget.Major >= 11) {
abis.Add (IsDeviceBuild ? Abi.ARM64 : Abi.x86_64);
} else {
abis.Add (IsDeviceBuild ? Abi.ARMv7 : Abi.i386);
}
2016-04-21 15:58:45 +03:00
}
break;
case ApplePlatform.WatchOS:
if (abis.Count == 0)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (76, Errors.MT0076, "Xamarin.WatchOS");
2016-04-21 15:58:45 +03:00
break;
case ApplePlatform.TVOS:
if (abis.Count == 0)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (76, Errors.MT0076, "Xamarin.TVOS");
2016-04-21 15:58:45 +03:00
break;
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (71, Errors.MX0071, Platform, "Xamarin.iOS");
2016-04-21 15:58:45 +03:00
}
}
public void ValidateAbi ()
{
var validAbis = new List<Abi> ();
switch (Platform) {
case ApplePlatform.iOS:
if (IsDeviceBuild) {
validAbis.Add (Abi.ARMv7);
validAbis.Add (Abi.ARMv7 | Abi.Thumb);
validAbis.Add (Abi.ARMv7 | Abi.LLVM);
validAbis.Add (Abi.ARMv7 | Abi.LLVM | Abi.Thumb);
validAbis.Add (Abi.ARMv7s);
validAbis.Add (Abi.ARMv7s | Abi.Thumb);
validAbis.Add (Abi.ARMv7s | Abi.LLVM);
validAbis.Add (Abi.ARMv7s | Abi.LLVM | Abi.Thumb);
} else {
validAbis.Add (Abi.i386);
}
if (IsDeviceBuild) {
validAbis.Add (Abi.ARM64);
validAbis.Add (Abi.ARM64 | Abi.LLVM);
} else {
validAbis.Add (Abi.x86_64);
2016-04-21 15:58:45 +03:00
}
break;
case ApplePlatform.WatchOS:
if (IsDeviceBuild) {
validAbis.Add (Abi.ARMv7k);
validAbis.Add (Abi.ARMv7k | Abi.LLVM);
2019-01-10 21:08:41 +03:00
validAbis.Add (Abi.ARM64_32);
validAbis.Add (Abi.ARM64_32 | Abi.LLVM);
} else {
validAbis.Add (Abi.i386);
}
2016-04-21 15:58:45 +03:00
break;
case ApplePlatform.TVOS:
if (IsDeviceBuild) {
validAbis.Add (Abi.ARM64);
validAbis.Add (Abi.ARM64 | Abi.LLVM);
} else {
validAbis.Add (Abi.x86_64);
}
break;
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (71, Errors.MX0071, Platform, "Xamarin.iOS");
2016-04-21 15:58:45 +03:00
}
foreach (var abi in abis) {
if (!validAbis.Contains (abi))
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (75, Errors.MT0075, abi, Platform, string.Join (", ", validAbis.Select ((v) => v.AsString ()).ToArray ()));
2016-04-21 15:58:45 +03:00
}
}
public void ClearAbi ()
{
abis = null;
}
// This is to load the symbols for all assemblies, so that we can give better error messages
// (with file name / line number information).
public void LoadSymbols ()
{
foreach (var t in Targets)
t.LoadSymbols ();
}
public void ParseAbi (string abi)
{
var res = new List<Abi> ();
foreach (var str in abi.Split (new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries)) {
Abi value;
switch (str) {
case "i386":
value = Abi.i386;
break;
case "x86_64":
value = Abi.x86_64;
break;
case "armv7":
value = Abi.ARMv7;
break;
case "armv7+llvm":
value = Abi.ARMv7 | Abi.LLVM;
break;
case "armv7+llvm+thumb2":
value = Abi.ARMv7 | Abi.LLVM | Abi.Thumb;
break;
case "armv7s":
value = Abi.ARMv7s;
break;
case "armv7s+llvm":
value = Abi.ARMv7s | Abi.LLVM;
break;
case "armv7s+llvm+thumb2":
value = Abi.ARMv7s | Abi.LLVM | Abi.Thumb;
break;
case "arm64":
value = Abi.ARM64;
break;
case "arm64+llvm":
value = Abi.ARM64 | Abi.LLVM;
break;
2019-01-10 21:08:41 +03:00
case "arm64_32":
value = Abi.ARM64_32;
break;
case "arm64_32+llvm":
value = Abi.ARM64_32 | Abi.LLVM;
break;
2016-04-21 15:58:45 +03:00
case "armv7k":
value = Abi.ARMv7k;
break;
case "armv7k+llvm":
value = Abi.ARMv7k | Abi.LLVM;
break;
2016-04-21 15:58:45 +03:00
default:
2020-01-31 23:02:52 +03:00
throw new MonoTouchException (15, true, Errors.MT0015, str);
2016-04-21 15:58:45 +03:00
}
// merge this value with any existing ARMv? already specified.
// this is so that things like '--armv7 --thumb' work correctly.
if (abis != null) {
for (int i = 0; i < abis.Count; i++) {
if ((abis [i] & Abi.ArchMask) == (value & Abi.ArchMask)) {
value |= abis [i];
break;
}
}
}
res.Add (value);
}
// We replace any existing abis, to keep the old behavior where '--armv6 --armv7' would
// enable only the last abi specified and disable the rest.
abis = res;
}
public static string GetArchitectures (IEnumerable<Abi> abis)
{
var res = new List<string> ();
foreach (var abi in abis)
res.Add (abi.AsArchString ());
return string.Join (", ", res.ToArray ());
}
public bool IsArchEnabled (Abi arch)
{
return IsArchEnabled (abis, arch);
}
public static bool IsArchEnabled (IEnumerable<Abi> abis, Abi arch)
{
foreach (var abi in abis) {
if ((abi & arch) != 0)
return true;
}
return false;
}
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
public void BuildAll ()
{
var allapps = new List<Application> ();
allapps.Add (this); // We need to build the main app first, so that any extensions sharing code can reference frameworks built in the main app.
allapps.AddRange (AppExtensions);
VerifyCache ();
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
allapps.ForEach ((v) => v.BuildInitialize ());
DetectCodeSharing ();
allapps.ForEach ((v) => v.BuildManaged ());
allapps.ForEach ((v) => v.BuildNative ());
BuildBundle ();
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
allapps.ForEach ((v) => v.BuildEnd ());
}
void VerifyCache ()
2016-04-21 15:58:45 +03:00
{
var valid = true;
// First make sure that all the caches (both for the container app and any app extensions) are valid.
// Due to code sharing it's safest to rebuild everything if any cache ends up out-of-date.
2016-04-21 15:58:45 +03:00
if (Driver.Force) {
Driver.Log (3, $"A full rebuild has been forced by the command line argument -f.");
valid = false;
} else if (!Cache.IsCacheValid ()) {
Driver.Log (3, $"A full rebuild has been forced because the cache for {Name} is not valid.");
valid = false;
[mtouch] Don't set Force when the cache is invalid (as it will be deleted) (#1016) If the cache is invalid we print a warning: > A full rebuild will be performed because the cache is either incomplete or entirely missing. and set `Driver.Force = true;` (in Application.cs). This later means that extracting the native code is done on each target: ``` public static bool IsUptodate (string source, string target) { if (Driver.Force) return false; ``` even if this is identical between 32 and 64 bits (targets). That's inefficient and, for large binding libraries (e.g. > 1GB), has a noticable impact on build time (see timestamps). Considering that the cache is cleaned (when detected as invalid) then this Force condition is not really needed. E.g. in `IsUptodate` * the first time (arch) it's called will have to extract the native library; * if a 2nd arch is built (fat) then it will be found as present and will not be extracted again Removing the `Driver.Force = true;` in this condition let the `-f` option continue to extract it twice, which can be useful in debugging and testing. As such the check is not removed from `IsUptodate` Timestamps (before) Setup: 25 ms Resolve References: 1605 ms Extracted native link info: 10465 ms ... Timestamps (after) Setup: 24 ms Resolve References: 1560 ms Extracted native link info: 5473 ms ... Total build times (from XS) was around 90-100 seconds so 5 seconds is about 10%. The actual savings will depend on how much native code needs to be extracted, but it should help most release builds (almost always fat builds).
2016-11-01 16:10:09 +03:00
} else {
foreach (var appex in AppExtensions) {
if (appex.Cache.IsCacheValid ())
continue;
Driver.Log (3, $"A full rebuild has been forced because the cache for {appex.Name} is not valid.");
valid = false;
break;
}
2016-04-21 15:58:45 +03:00
}
if (valid)
return;
// Something's not valid anymore, so clean everything.
Cache.Clean ();
[mtouch] Set the force flag again when the cache is invalid. Fixes #54973. (#2163) In 11390f119ce745f9d4d2e8362c4befae98cc2a44 we stopped setting the force flag when the cache was invalid, because we'd delete the cache anyway, and it was determined that deleting the cache was enough. Unfortunately it's not, because some output is not in the cache, and might not get correctly updated. Scenario: * User builds app. * User changes some build option (for instance switching off incremental builds). * User does an insignificant change in a source file for the executable process. * User builds app again (without cleaning). This will rebuild the exe, but since the change was insignificant, all the IL, except the MVID, would remain identical. * mtouch would see that the command-line options changed, and invalidate the cache. This would delete the cache, and everything would be rebuilt, including AOT-compiling the assemblies again. * When the time came for mtouch to copy assemblies to the app directory, mtouch would realize that the existing .exe in the app (which was not deleted because it's not in the cache, but the actual output directory) was only insignificantly different (only the MVID was different, which our cache logic knows to ignore when comparing assemblies), so it wouldn't copy the .exe to the .app. * At runtime we'd assert, because the MVID in the aot-compiled code was different from the MVID in the assembly: error: Failed to load AOT module '(null)' while running in aot-only mode: doesn't match assembly. * The exact assert varies depending on which build option changed. Other variations: Failed to load AOT module '(null)' while running in aot-only mode: compiled against GC (4, while the current runtime uses GC sgen) * Assertion at /Users/builder/data/lanes/4691/0719ced1/source/xamarin-macios/external/mono/mono/metadata/metadata.c:1118, condition `idx < t->rows' not met Because of this I'm reverting 11390f119ce745f9d4d2e8362c4befae98cc2a44, and once again setting the force flag when the cache is invalid. It might be overkill, but it's the safest option (cache invalidation is after all the only hard problem in computer science), and bugs are very annoying and timeconsuming to track down. https://bugzilla.xamarin.com/show_bug.cgi?id=54973
2017-06-02 16:23:30 +03:00
// Make sure everything is rebuilt no matter what, the cache is not
// the only location taken into account when determing if something
// needs to be rebuilt.
Driver.Force = true;
AppExtensions.ForEach ((v) => v.Cache.Clean ());
}
void BuildInitialize ()
{
SelectRegistrar ();
2016-04-21 15:58:45 +03:00
Initialize ();
ValidateAbi ();
ExtractNativeLinkInfo ();
SelectNativeCompiler ();
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
}
void BuildManaged ()
{
ProcessAssemblies ();
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
}
[mtouch] Rework how tasks are built. The previous build system kept a forward-pointing single linked list of tasks to execute: task X had a list of subsequent tasks to execute. If task X was up-to-date, it was not created (and the next tasks were directly added to the list of tasks to execute). In this world it became complicated to merge output from tasks (for instance if the output of task X and task Y should be a consumed by a single task producing a single output, since the corresponding task would end up in both X's and Y's list of subsequent tasks). Example: creating a single framework from the aot-compiled output of multiple assemblies. So I've reversed the logic: now we keep track of the final output, and then each task has a list of dependencies that must be built. This makes it trivial to create merging tasks (for the previous example, there could for instance be a CreateFrameworkTask, where its dependencies would be all the corresponding AotTasks). We also always create every task, and then each task decides when its executed whether it should do anything or not. This makes it unnecessary to 'forward- delete' files when creating tasks (say you have three tasks, A, B, C; B depends on A, and C depends on B; if A's output isn't up-to-date, it has to delete its own output if it exists, otherwise B would not detect that it would have to re-execute, because at task *creation* time, B's input hadn't changed). Additionally make it based on async/await, since much of the work happens in externel processes (and we don't need to spin up additional threads just to run external processes). This makes us have less code run on background threads, which makes any issues with thread-safety less likely.
2017-01-26 12:56:55 +03:00
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
void BuildNative ()
{
[mtouch] Rework how tasks are built. The previous build system kept a forward-pointing single linked list of tasks to execute: task X had a list of subsequent tasks to execute. If task X was up-to-date, it was not created (and the next tasks were directly added to the list of tasks to execute). In this world it became complicated to merge output from tasks (for instance if the output of task X and task Y should be a consumed by a single task producing a single output, since the corresponding task would end up in both X's and Y's list of subsequent tasks). Example: creating a single framework from the aot-compiled output of multiple assemblies. So I've reversed the logic: now we keep track of the final output, and then each task has a list of dependencies that must be built. This makes it trivial to create merging tasks (for the previous example, there could for instance be a CreateFrameworkTask, where its dependencies would be all the corresponding AotTasks). We also always create every task, and then each task decides when its executed whether it should do anything or not. This makes it unnecessary to 'forward- delete' files when creating tasks (say you have three tasks, A, B, C; B depends on A, and C depends on B; if A's output isn't up-to-date, it has to delete its own output if it exists, otherwise B would not detect that it would have to re-execute, because at task *creation* time, B's input hadn't changed). Additionally make it based on async/await, since much of the work happens in externel processes (and we don't need to spin up additional threads just to run external processes). This makes us have less code run on background threads, which makes any issues with thread-safety less likely.
2017-01-26 12:56:55 +03:00
// Everything that can be parallelized is put into a list of tasks,
// which are then executed at the end.
build_tasks = new BuildTasks ();
Driver.Watch ("Generating build tasks", 1);
CompilePInvokeWrappers ();
2016-04-21 15:58:45 +03:00
BuildApp ();
[mtouch] Rework how tasks are built. The previous build system kept a forward-pointing single linked list of tasks to execute: task X had a list of subsequent tasks to execute. If task X was up-to-date, it was not created (and the next tasks were directly added to the list of tasks to execute). In this world it became complicated to merge output from tasks (for instance if the output of task X and task Y should be a consumed by a single task producing a single output, since the corresponding task would end up in both X's and Y's list of subsequent tasks). Example: creating a single framework from the aot-compiled output of multiple assemblies. So I've reversed the logic: now we keep track of the final output, and then each task has a list of dependencies that must be built. This makes it trivial to create merging tasks (for the previous example, there could for instance be a CreateFrameworkTask, where its dependencies would be all the corresponding AotTasks). We also always create every task, and then each task decides when its executed whether it should do anything or not. This makes it unnecessary to 'forward- delete' files when creating tasks (say you have three tasks, A, B, C; B depends on A, and C depends on B; if A's output isn't up-to-date, it has to delete its own output if it exists, otherwise B would not detect that it would have to re-execute, because at task *creation* time, B's input hadn't changed). Additionally make it based on async/await, since much of the work happens in externel processes (and we don't need to spin up additional threads just to run external processes). This makes us have less code run on background threads, which makes any issues with thread-safety less likely.
2017-01-26 12:56:55 +03:00
if (Driver.DotFile != null)
build_tasks.Dot (this, Driver.DotFile.Length > 0 ? Driver.DotFile : Path.Combine (Cache.Location, "build.dot"));
[mtouch] Rework how tasks are built. The previous build system kept a forward-pointing single linked list of tasks to execute: task X had a list of subsequent tasks to execute. If task X was up-to-date, it was not created (and the next tasks were directly added to the list of tasks to execute). In this world it became complicated to merge output from tasks (for instance if the output of task X and task Y should be a consumed by a single task producing a single output, since the corresponding task would end up in both X's and Y's list of subsequent tasks). Example: creating a single framework from the aot-compiled output of multiple assemblies. So I've reversed the logic: now we keep track of the final output, and then each task has a list of dependencies that must be built. This makes it trivial to create merging tasks (for the previous example, there could for instance be a CreateFrameworkTask, where its dependencies would be all the corresponding AotTasks). We also always create every task, and then each task decides when its executed whether it should do anything or not. This makes it unnecessary to 'forward- delete' files when creating tasks (say you have three tasks, A, B, C; B depends on A, and C depends on B; if A's output isn't up-to-date, it has to delete its own output if it exists, otherwise B would not detect that it would have to re-execute, because at task *creation* time, B's input hadn't changed). Additionally make it based on async/await, since much of the work happens in externel processes (and we don't need to spin up additional threads just to run external processes). This makes us have less code run on background threads, which makes any issues with thread-safety less likely.
2017-01-26 12:56:55 +03:00
Driver.Watch ("Building build tasks", 1);
build_tasks.Execute ();
}
[mtouch] Rework how tasks are built. The previous build system kept a forward-pointing single linked list of tasks to execute: task X had a list of subsequent tasks to execute. If task X was up-to-date, it was not created (and the next tasks were directly added to the list of tasks to execute). In this world it became complicated to merge output from tasks (for instance if the output of task X and task Y should be a consumed by a single task producing a single output, since the corresponding task would end up in both X's and Y's list of subsequent tasks). Example: creating a single framework from the aot-compiled output of multiple assemblies. So I've reversed the logic: now we keep track of the final output, and then each task has a list of dependencies that must be built. This makes it trivial to create merging tasks (for the previous example, there could for instance be a CreateFrameworkTask, where its dependencies would be all the corresponding AotTasks). We also always create every task, and then each task decides when its executed whether it should do anything or not. This makes it unnecessary to 'forward- delete' files when creating tasks (say you have three tasks, A, B, C; B depends on A, and C depends on B; if A's output isn't up-to-date, it has to delete its own output if it exists, otherwise B would not detect that it would have to re-execute, because at task *creation* time, B's input hadn't changed). Additionally make it based on async/await, since much of the work happens in externel processes (and we don't need to spin up additional threads just to run external processes). This makes us have less code run on background threads, which makes any issues with thread-safety less likely.
2017-01-26 12:56:55 +03:00
void BuildEnd ()
{
[mtouch] Rework how tasks are built. The previous build system kept a forward-pointing single linked list of tasks to execute: task X had a list of subsequent tasks to execute. If task X was up-to-date, it was not created (and the next tasks were directly added to the list of tasks to execute). In this world it became complicated to merge output from tasks (for instance if the output of task X and task Y should be a consumed by a single task producing a single output, since the corresponding task would end up in both X's and Y's list of subsequent tasks). Example: creating a single framework from the aot-compiled output of multiple assemblies. So I've reversed the logic: now we keep track of the final output, and then each task has a list of dependencies that must be built. This makes it trivial to create merging tasks (for the previous example, there could for instance be a CreateFrameworkTask, where its dependencies would be all the corresponding AotTasks). We also always create every task, and then each task decides when its executed whether it should do anything or not. This makes it unnecessary to 'forward- delete' files when creating tasks (say you have three tasks, A, B, C; B depends on A, and C depends on B; if A's output isn't up-to-date, it has to delete its own output if it exists, otherwise B would not detect that it would have to re-execute, because at task *creation* time, B's input hadn't changed). Additionally make it based on async/await, since much of the work happens in externel processes (and we don't need to spin up additional threads just to run external processes). This makes us have less code run on background threads, which makes any issues with thread-safety less likely.
2017-01-26 12:56:55 +03:00
// TODO: make more of the below actions parallelizable
2016-04-21 15:58:45 +03:00
BuildDsymDirectory ();
BuildMSymDirectory ();
StripNativeCode ();
BundleAssemblies ();
WriteNotice ();
2016-04-21 15:58:45 +03:00
GenerateRuntimeOptions ();
if (Cache.IsCacheTemporary) {
// If we used a temporary directory we created ourselves for the cache
// (in which case it's more a temporary location where we store the
// temporary build products than a cache), it will not be used again,
// so just delete it.
try {
Directory.Delete (Cache.Location, true);
} catch {
// Don't care.
}
} else {
// Write the cache data as the last step, so there is no half-done/incomplete (but yet detected as valid) cache.
Cache.ValidateCache ();
}
Console.WriteLine ("{0} built successfully.", AppDirectory);
}
bool no_framework;
2016-04-21 15:58:45 +03:00
public void SetDefaultFramework ()
{
// If no target framework was specified, check if we're referencing Xamarin.iOS.dll.
// It's an error if neither target framework nor Xamarin.iOS.dll is not specified
2016-04-21 15:58:45 +03:00
if (!Driver.HasTargetFramework) {
foreach (var reference in References) {
var name = Path.GetFileName (reference);
switch (name) {
case "Xamarin.iOS.dll":
Driver.TargetFramework = TargetFramework.Xamarin_iOS_1_0;
break;
case "Xamarin.TVOS.dll":
case "Xamarin.WatchOS.dll":
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (86, Errors.MT0086);
2016-04-21 15:58:45 +03:00
}
if (Driver.HasTargetFramework)
break;
}
}
if (!Driver.HasTargetFramework) {
// Set a default target framework to show errors in the least confusing order.
Driver.TargetFramework = TargetFramework.Xamarin_iOS_1_0;
no_framework = true;
2016-04-21 15:58:45 +03:00
}
}
string FormatAssemblyBuildTargets ()
{
var sb = new StringBuilder ();
foreach (var foo in assembly_build_targets) {
if (sb.Length > 0)
sb.Append (" ");
sb.Append ("--assembly-build-target:");
sb.Append (foo.Key);
sb.Append ("=").Append (foo.Value.Item1.ToString ().ToLower ());
if (!string.IsNullOrEmpty (foo.Value.Item2))
sb.Append ("=").Append (foo.Value.Item2);
}
return sb.ToString ();
}
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
void DetectCodeSharing ()
{
if (AppExtensions.Count == 0)
return;
if (!IsDeviceBuild)
return;
if (NoDevCodeShare) {
// This is not a warning because then there would be no way to get a warning-less build if you for some reason wanted
// a configuration that ends up disabling code sharing. In other words: if you want a configuration that causes mtouch
// to disable code sharing, explicitly disabling code sharing will shut up all warnings about it.
Driver.Log (2, "Native code sharing has been disabled in the main app; no code sharing with extensions will occur.");
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
return;
}
if (Platform == ApplePlatform.iOS && DeploymentTarget.Major < 8) {
// This is a limitation it's technically possible to fix (we can build all extensions into frameworks, and the main app to static objects).
// It would make our code a bit more complicated though, and would only be valuable for apps that target iOS 6 or iOS 7 and has more than one extension.
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (112, Errors.MT0112, String.Format (Errors.MT0112_a, DeploymentTarget));
return;
}
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
// No I18N assemblies can be included
if (I18n != Mono.Linker.I18nAssemblies.None) {
// This is a limitation it's technically possible to fix.
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (112, Errors.MT0112, String.Format (Errors.MT0112_b, I18n));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
return;
}
List<Application> candidates = new List<Application> ();
foreach (var appex in AppExtensions) {
if (appex.IsWatchExtension)
continue;
if (appex.NoDevCodeShare) {
// This is not a warning because then there would be no way to get a warning-less build if you for some reason wanted
// a configuration that ends up disabling code sharing. In other words: if you want a configuration that causes mtouch
// to disable code sharing, explicitly disabling code sharing will shut up all warnings about it.
Driver.Log (2, "Native code sharing has been disabled in the extension {0}; no code sharing with the main will occur for this extension.", appex.Name);
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue;
}
if (BitCodeMode != appex.BitCodeMode) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_a, appex.BitCodeMode, BitCodeMode));
continue;
}
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
bool applicable = true;
// The --assembly-build-target arguments must be identical.
// We can probably lift this requirement (at least partially) at some point,
// but for now it makes our code simpler.
if (assembly_build_targets.Count != appex.assembly_build_targets.Count) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113,appex.Name, String.Format (Errors.MT0113_b, FormatAssemblyBuildTargets(), appex.FormatAssemblyBuildTargets()));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue;
}
foreach (var key in assembly_build_targets.Keys) {
Tuple<AssemblyBuildTarget, string> appex_value;
if (!appex.assembly_build_targets.TryGetValue (key, out appex_value)) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_b, FormatAssemblyBuildTargets(), appex.FormatAssemblyBuildTargets()));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
applicable = false;
break;
}
var value = assembly_build_targets [key];
if (value.Item1 != appex_value.Item1 || value.Item2 != appex_value.Item2) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_b, FormatAssemblyBuildTargets(), appex.FormatAssemblyBuildTargets()));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
applicable = false;
break;
}
}
if (!applicable)
continue;
// No I18N assemblies can be included
if (appex.I18n != Mono.Linker.I18nAssemblies.None) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_c, I18n, appex.I18n));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue;
}
// All arguments to the AOT compiler must be identical
if (AotArguments != appex.AotArguments) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_d, AotArguments, appex.AotArguments));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue;
}
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
if (!CompareLists (AotOtherArguments, appex.AotOtherArguments)) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_e, StringUtils.FormatArguments(AotOtherArguments), StringUtils.FormatArguments(appex.AotOtherArguments)));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue;
}
if (IsLLVM != appex.IsLLVM) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_f, IsLLVM, appex.IsLLVM));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue;
}
if (LinkMode != appex.LinkMode) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_g, LinkMode, appex.LinkMode));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue;
}
if (LinkMode != LinkMode.None) {
var linkskipped_same = !LinkSkipped.Except (appex.LinkSkipped).Any () && !appex.LinkSkipped.Except (LinkSkipped).Any ();
if (!linkskipped_same) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_h, string.Join(", ", LinkSkipped), string.Join(", ", appex.LinkSkipped)));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue;
}
if (Definitions.Count > 0) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (112, Errors.MT0112, String.Format (Errors.MT0112_c, string.Join(", ", Definitions)));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue;
}
if (appex.Definitions.Count > 0) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_i, string.Join(", ", appex.Definitions)));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue;
}
}
if (UseInterpreter != appex.UseInterpreter) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_j, (UseInterpreter ? "Enabled" : "Disabled"), (appex.UseInterpreter ? "Enabled" : "Disabled")));
continue;
} else if (UseInterpreter) {
var appAssemblies = new HashSet<string> (InterpretedAssemblies);
var appexAssemblies = new HashSet<string> (appex.InterpretedAssemblies);
if (!appAssemblies.SetEquals (appexAssemblies)) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_k, (InterpretedAssemblies.Count == 0 ? "all assemblies" : string.Join(", ", InterpretedAssemblies)), (appex.InterpretedAssemblies.Count == 0 ? "all assemblies" : string.Join(", ", appex.InterpretedAssemblies))));
continue;
}
}
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
// Check that the Abis are matching
foreach (var abi in appex.Abis) {
var matching = abis.FirstOrDefault ((v) => (v & Abi.ArchMask) == (abi & Abi.ArchMask));
if (matching == Abi.None) {
// Example: extension has arm64+armv7, while the main app has only arm64.
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_l, abi));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
applicable = false;
break;
} else if (matching != abi) {
// Example: extension has arm64+llvm, while the main app has only arm64.
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_m, matching, abi));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
applicable = false;
break;
}
}
// Check that the remove-dynamic-registrar optimizations are identical
if (Optimizations.RemoveDynamicRegistrar != appex.Optimizations.RemoveDynamicRegistrar) {
Func<bool?, string> bool_tostr = (v) => {
if (!v.HasValue)
return "default";
return v.Value ? "true" : "false";
};
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_n, bool_tostr(appex.Optimizations.RemoveDynamicRegistrar), bool_tostr(Optimizations.RemoveDynamicRegistrar)));
continue;
}
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
// Check if there aren't referenced assemblies from different sources
foreach (var target in Targets) {
var appexTarget = appex.Targets.SingleOrDefault ((v) => v.Is32Build == target.Is32Build);
if (appexTarget == null)
continue; // container is fat, appex isn't. This is not a problem.
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
foreach (var kvp in appexTarget.Assemblies.Hashed) {
Assembly asm;
if (!target.Assemblies.TryGetValue (kvp.Key, out asm))
continue; // appex references an assembly the main app doesn't. This is fine.
if (asm.FullPath != kvp.Value.FullPath && !Cache.CompareFiles (asm.FullPath, kvp.Value.FullPath, true)) {
applicable = false; // app references an assembly with the same name as the main app, but from a different location and not identical. This is not fine.
ErrorHelper.Warning (113, Errors.MT0113, appex.Name, String.Format (Errors.MT0113_o, asm.Identity, asm.FullPath, kvp.Value.FullPath));
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
break;
}
}
}
if (!applicable)
continue;
candidates.Add (appex);
appex.IsCodeShared = true;
IsCodeShared = true;
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
Driver.Log (2, "The app '{1}' and the extension '{0}' will share code.", appex.Name, Name);
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
}
if (candidates.Count > 0)
SharedCodeApps.AddRange (candidates);
Driver.Watch ("Detect Code Sharing", 1);
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
}
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
static bool CompareLists (List<string> a, List<string> b)
{
if (a == b)
return true;
if (a == null ^ b == null)
return false;
return a.SequenceEqual (b);
}
2016-04-21 15:58:45 +03:00
void Initialize ()
{
if (UseInterpreter) {
// it's confusing to use different options to get a feature to work (e.g. dynamic, SRE...) on both simulator and device
if (IsSimulatorBuild) {
ErrorHelper.Show (ErrorHelper.CreateWarning (141, Errors.MT0141));
UseInterpreter = false;
}
// FIXME: the interpreter only supports ARM64{,_32} right now
// temporary - without a check here the error happens when deploying
if (!IsSimulatorBuild && (!IsArchEnabled (Abi.ARM64) && !IsArchEnabled (Abi.ARM64_32)))
throw ErrorHelper.CreateError (99, Errors.MX0099, "The interpreter is currently only available for 64 bits");
// needs to be set after the argument validations
// interpreter can use some extra code (e.g. SRE) that is not shipped in the default (AOT) profile
EnableRepl = true;
} else {
if (Platform == ApplePlatform.WatchOS && IsArchEnabled (Abi.ARM64_32) && BitCodeMode != BitCodeMode.LLVMOnly) {
if (IsArchEnabled (Abi.ARMv7k)) {
throw ErrorHelper.CreateError (145, Errors.MT0145);
} else {
ErrorHelper.Warning (146, Errors.MT0146);
UseInterpreter = true;
InterpretedAssemblies.Clear ();
}
}
}
if (EnableDebug && IsLLVM)
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (3003, Errors.MT3003);
if (!IsLLVM && (EnableAsmOnlyBitCode || EnableLLVMOnlyBitCode))
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (3008, Errors.MT3008);
if (IsLLVM && Platform == ApplePlatform.WatchOS && BitCodeMode != BitCodeMode.LLVMOnly) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (111, Errors.MT0111);
BitCodeMode = BitCodeMode.LLVMOnly;
}
if (!DebugTrack.HasValue) {
DebugTrack = false;
} else if (DebugTrack.Value && !EnableDebug) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (32, Errors.MT0032);
}
if (EnableAsmOnlyBitCode)
LLVMAsmWriter = true;
List<Exception> exceptions = null;
foreach (var root in RootAssemblies) {
if (File.Exists (root))
continue;
if (exceptions == null)
exceptions = new List<Exception> ();
if (root [0] == '-' || root [0] == '/') {
2020-01-31 23:02:52 +03:00
exceptions.Add (ErrorHelper.CreateError (18, Errors.MX0018, root));
} else {
2020-01-31 23:02:52 +03:00
exceptions.Add (ErrorHelper.CreateError (7, Errors.MX0007, root));
}
}
if (exceptions?.Count > 0)
throw new AggregateException (exceptions);
if (no_framework)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (96, Errors.MT0096);
2016-04-21 15:58:45 +03:00
// Add a reference to the platform assembly if none has been added, and check that we're not referencing
// any platform assemblies from another platform.
var platformAssemblyReference = false;
foreach (var reference in References) {
var name = Path.GetFileNameWithoutExtension (reference);
if (name == Driver.GetProductAssembly (this)) {
2016-04-21 15:58:45 +03:00
platformAssemblyReference = true;
} else {
switch (name) {
case "Xamarin.iOS":
case "Xamarin.TVOS":
case "Xamarin.WatchOS":
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (41, Errors.MT0041, Path.GetFileName (reference), Driver.TargetFramework.Identifier);
2016-04-21 15:58:45 +03:00
}
}
}
if (!platformAssemblyReference) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (85, Errors.MT0085, Driver.GetProductAssembly (this) + ".dll");
References.Add (Path.Combine (Driver.GetPlatformFrameworkDirectory (this), Driver.GetProductAssembly (this) + ".dll"));
2016-04-21 15:58:45 +03:00
}
((MonoTouchProfile)Profile.Current).SetProductAssembly (Driver.GetProductAssembly (this));
2016-04-21 15:58:45 +03:00
var FrameworkDirectory = Driver.GetPlatformFrameworkDirectory (this);
foreach (var root in RootAssemblies) {
string root_wo_ext = Path.GetFileNameWithoutExtension (root);
if (Profile.IsSdkAssembly (root_wo_ext) || Profile.IsProductAssembly (root_wo_ext))
2020-01-31 23:02:52 +03:00
throw new MonoTouchException (3, true, Errors.MX0003, root_wo_ext);
}
2016-04-21 15:58:45 +03:00
if (IsDualBuild) {
var target32 = new Target (this);
var target64 = new Target (this);
target32.ArchDirectory = Path.Combine (Cache.Location, "32");
target32.TargetDirectory = IsSimulatorBuild ? Path.Combine (AppDirectory, ".monotouch-32") : Path.Combine (target32.ArchDirectory, "Output");
target32.AppTargetDirectory = Path.Combine (AppDirectory, ".monotouch-32");
target32.Resolver.ArchDirectory = Driver.GetArch32Directory (this);
2016-04-21 15:58:45 +03:00
target32.Abis = SelectAbis (abis, Abi.Arch32Mask);
target64.ArchDirectory = Path.Combine (Cache.Location, "64");
target64.TargetDirectory = IsSimulatorBuild ? Path.Combine (AppDirectory, ".monotouch-64") : Path.Combine (target64.ArchDirectory, "Output");
target64.AppTargetDirectory = Path.Combine (AppDirectory, ".monotouch-64");
target64.Resolver.ArchDirectory = Driver.GetArch64Directory (this);
2016-04-21 15:58:45 +03:00
target64.Abis = SelectAbis (abis, Abi.Arch64Mask);
Targets.Add (target64);
Targets.Add (target32);
} else {
var target = new Target (this);
target.TargetDirectory = AppDirectory;
target.AppTargetDirectory = IsSimulatorBuild ? AppDirectory : Path.Combine (AppDirectory, Is64Build ? ".monotouch-64" : ".monotouch-32");
2016-04-21 15:58:45 +03:00
target.ArchDirectory = Cache.Location;
target.Resolver.ArchDirectory = Path.Combine (FrameworkDirectory, "..", "..", Is32Build ? "32bits" : "64bits");
2016-04-21 15:58:45 +03:00
target.Abis = abis;
Targets.Add (target);
// Make sure there aren't any lingering .monotouch-* directories.
if (IsSimulatorBuild) {
var dir = Path.Combine (AppDirectory, ".monotouch-32");
if (Directory.Exists (dir))
Directory.Delete (dir, true);
dir = Path.Combine (AppDirectory, ".monotouch-64");
if (Directory.Exists (dir))
Directory.Delete (dir, true);
}
}
var RootDirectory = Path.GetDirectoryName (Path.GetFullPath (RootAssemblies [0]));
2016-04-21 15:58:45 +03:00
foreach (var target in Targets) {
target.Resolver.FrameworkDirectory = FrameworkDirectory;
2016-04-21 15:58:45 +03:00
target.Resolver.RootDirectory = RootDirectory;
target.Resolver.EnableRepl = EnableRepl;
target.ManifestResolver.EnableRepl = EnableRepl;
target.ManifestResolver.FrameworkDirectory = target.Resolver.FrameworkDirectory;
target.ManifestResolver.RootDirectory = target.Resolver.RootDirectory;
target.ManifestResolver.ArchDirectory = target.Resolver.ArchDirectory;
target.Initialize (target == Targets [0]);
if (!Directory.Exists (target.TargetDirectory))
Directory.CreateDirectory (target.TargetDirectory);
}
if (string.IsNullOrEmpty (ExecutableName)) {
var bundleExecutable = GetStringFromInfoPList ("CFBundleExecutable");
ExecutableName = bundleExecutable ?? Path.GetFileNameWithoutExtension (RootAssemblies [0]);
2016-04-21 15:58:45 +03:00
}
if (ExecutableName != Path.GetFileNameWithoutExtension (AppDirectory))
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (30, Errors.MT0030,
2016-04-21 15:58:45 +03:00
ExecutableName, Path.GetFileName (AppDirectory));
if (IsExtension && Platform == ApplePlatform.iOS && SdkVersion < new Version (8, 0))
2020-01-31 23:02:52 +03:00
throw new MonoTouchException (45, true, Errors.MT0045);
2016-04-21 15:58:45 +03:00
if (IsExtension && Platform != ApplePlatform.iOS && Platform != ApplePlatform.WatchOS && Platform != ApplePlatform.TVOS)
2020-01-31 23:02:52 +03:00
throw new MonoTouchException (72, true, Errors.MT0072, Platform);
2016-04-21 15:58:45 +03:00
if (!IsExtension && Platform == ApplePlatform.WatchOS)
2020-01-31 23:02:52 +03:00
throw new MonoTouchException (77, true, Errors.MT0077);
2016-04-21 15:58:45 +03:00
#if ENABLE_BITCODE_ON_IOS
if (Platform == ApplePlatform.iOS)
DeploymentTarget = new Version (9, 0);
#endif
if (DeploymentTarget == null)
2016-04-21 15:58:45 +03:00
DeploymentTarget = Xamarin.SdkVersions.GetVersion (Platform);
if (Platform == ApplePlatform.iOS && (HasDynamicLibraries || HasFrameworks) && DeploymentTarget.Major < 8) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (78, Errors.MT0078, DeploymentTarget);
[mtouch] Require deployment target to be 8+ for incremental builds. (#805) This is something that changed with 70f1346b: our libxamarin.dylib now requires iOS 8+, which means the app itself must require iOS 8+ when using libxamarin.dylib. This fixes an msbuild failure (Xamarin.iOS.Tasks.IBToolLinking("iPhone").BuildTest): Process exited with code 1, command: /Applications/Xcode73.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -framework Foundation -framework UIKit /Users/builder/data/lanes/1381/5f73edaa/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/SDKs/MonoTouch.iphoneos.sdk/usr/lib/libmonosgen-2.0.dylib /Users/builder/data/lanes/1381/5f73edaa/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/SDKs/MonoTouch.iphoneos.sdk/usr/lib/libxamarin-debug.dylib -lz -isysroot /Applications/Xcode73.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk -Qunused-arguments -miphoneos-version-min=7.0 -arch armv7 -shared -read_only_relocs suppress -install_name @executable_path/libXamarin.iOS.dll.dylib -fapplication-extension -o /Users/builder/data/lanes/1381/5f73edaa/source/xamarin-macios/msbuild/tests/MyIBToolLinkTest/obj/iPhone/Debug/mtouch-cache/Xamarin.iOS.dll.armv7.dylib -x assembler /Users/builder/data/lanes/1381/5f73edaa/source/xamarin-macios/msbuild/tests/MyIBToolLinkTest/obj/iPhone/Debug/mtouch-cache/Xamarin.iOS.dll.armv7.s -DDEBUG ld: warning: embedded dylibs/frameworks only run on iOS 8 or later ld: embedded dylibs/frameworks are only supported on iOS 8.0 and later (@executable_path/libxamarin-debug.dylib) for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)
2016-09-08 16:01:48 +03:00
DeploymentTarget = new Version (8, 0);
2016-04-21 15:58:45 +03:00
}
if (!package_managed_debug_symbols.HasValue) {
package_managed_debug_symbols = EnableDebug;
} else if (package_managed_debug_symbols.Value && IsLLVM) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (3007, Errors.MT3007);
2016-04-21 15:58:45 +03:00
}
if (!enable_msym.HasValue)
enable_msym = !EnableDebug && IsDeviceBuild;
2016-04-21 15:58:45 +03:00
if (!UseMonoFramework.HasValue && DeploymentTarget >= new Version (8, 0)) {
if (IsExtension) {
UseMonoFramework = true;
2017-01-31 14:54:08 +03:00
Driver.Log (2, $"The extension {Name} will automatically link with Mono.framework.");
} else if (Extensions.Count > 0) {
UseMonoFramework = true;
Driver.Log (2, "Automatically linking with Mono.framework because this is an app with extensions");
2016-04-21 15:58:45 +03:00
}
}
if (!UseMonoFramework.HasValue)
UseMonoFramework = false;
if (UseMonoFramework.Value)
Frameworks.Add (Path.Combine (Driver.GetProductFrameworksDirectory (this), "Mono.framework"));
2016-04-21 15:58:45 +03:00
if (!PackageMonoFramework.HasValue) {
if (!IsExtension && Extensions.Count > 0 && !UseMonoFramework.Value) {
// The main app must package the Mono framework if we have extensions, even if it's not linking with
// it. This happens when deployment target < 8.0 for the main app.
PackageMonoFramework = true;
} else {
// Package if we're not an extension and we're using the mono framework.
PackageMonoFramework = UseMonoFramework.Value && !IsExtension;
}
}
if (Frameworks.Count > 0) {
switch (Platform) {
case ApplePlatform.iOS:
if (DeploymentTarget < new Version (8, 0))
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (65, Errors.MT0065, DeploymentTarget, string.Join (", ", Frameworks.ToArray ()));
break;
case ApplePlatform.WatchOS:
if (DeploymentTarget < new Version (2, 0))
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (65, Errors.MT0065_A, DeploymentTarget, string.Join (", ", Frameworks.ToArray ()));
break;
case ApplePlatform.TVOS:
// All versions of tvOS support extensions
break;
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (71, Errors.MX0071, Platform, "Xamarin.iOS");
}
2016-04-21 15:58:45 +03:00
}
if (IsDeviceBuild) {
switch (BitCodeMode) {
case BitCodeMode.ASMOnly:
if (Platform == ApplePlatform.WatchOS)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (83, Errors.MT0083);
2016-04-21 15:58:45 +03:00
break;
case BitCodeMode.LLVMOnly:
case BitCodeMode.MarkerOnly:
break;
case BitCodeMode.None:
// If neither llvmonly nor asmonly is enabled, enable markeronly.
if (Platform == ApplePlatform.TVOS || Platform == ApplePlatform.WatchOS)
BitCodeMode = BitCodeMode.MarkerOnly;
break;
}
}
if (EnableBitCode && IsSimulatorBuild)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (84, Errors.MT0084);
2016-04-21 15:58:45 +03:00
Namespaces.Initialize ();
if (Embeddinator) {
// The assembly we're embedding doesn't necessarily reference our platform assembly, but we still need it.
RootAssemblies.Add (Path.Combine (Driver.GetPlatformFrameworkDirectory (this), Driver.GetProductAssembly (this) + ".dll"));
}
if (Platform == ApplePlatform.iOS) {
if (DeploymentTarget.Major >= 11 && Is32Build) {
var invalidArches = abis.Where ((v) => (v & Abi.Arch32Mask) != 0);
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (116, Errors.MT0116, invalidArches.First ());
}
}
InitializeCommon ();
2016-04-21 15:58:45 +03:00
Driver.Watch ("Resolve References", 1);
}
2018-10-15 22:39:29 +03:00
2016-04-21 15:58:45 +03:00
void SelectRegistrar ()
{
// If the default values are changed, remember to update CanWeSymlinkTheApplication
// and main.m (default value for xamarin_use_old_dynamic_registrar must match).
if (Registrar == RegistrarMode.Default) {
if (IsDeviceBuild) {
Registrar = RegistrarMode.Static;
} else { /* if (app.IsSimulatorBuild) */
Registrar = RegistrarMode.Dynamic;
}
}
}
// Select all abi from the list matching the specified mask.
List<Abi> SelectAbis (IEnumerable<Abi> abis, Abi mask)
{
var rv = new List<Abi> ();
foreach (var abi in abis) {
if ((abi & mask) != 0)
rv.Add (abi);
}
return rv;
}
public string AssemblyName {
get {
return Path.GetFileName (RootAssemblies [0]);
2016-04-21 15:58:45 +03:00
}
}
public string Executable {
get {
if (Embeddinator)
return Path.Combine (AppDirectory, "Frameworks", ExecutableName + ".framework", ExecutableName);
2016-04-21 15:58:45 +03:00
return Path.Combine (AppDirectory, ExecutableName);
}
}
void ProcessAssemblies ()
2016-04-21 15:58:45 +03:00
{
[mtouch] Rework how tasks are built. The previous build system kept a forward-pointing single linked list of tasks to execute: task X had a list of subsequent tasks to execute. If task X was up-to-date, it was not created (and the next tasks were directly added to the list of tasks to execute). In this world it became complicated to merge output from tasks (for instance if the output of task X and task Y should be a consumed by a single task producing a single output, since the corresponding task would end up in both X's and Y's list of subsequent tasks). Example: creating a single framework from the aot-compiled output of multiple assemblies. So I've reversed the logic: now we keep track of the final output, and then each task has a list of dependencies that must be built. This makes it trivial to create merging tasks (for the previous example, there could for instance be a CreateFrameworkTask, where its dependencies would be all the corresponding AotTasks). We also always create every task, and then each task decides when its executed whether it should do anything or not. This makes it unnecessary to 'forward- delete' files when creating tasks (say you have three tasks, A, B, C; B depends on A, and C depends on B; if A's output isn't up-to-date, it has to delete its own output if it exists, otherwise B would not detect that it would have to re-execute, because at task *creation* time, B's input hadn't changed). Additionally make it based on async/await, since much of the work happens in externel processes (and we don't need to spin up additional threads just to run external processes). This makes us have less code run on background threads, which makes any issues with thread-safety less likely.
2017-01-26 12:56:55 +03:00
// This can be parallelized once we determine the linker doesn't use any static state.
2016-04-21 15:58:45 +03:00
foreach (var target in Targets) {
if (target.CanWeSymlinkTheApplication ()) {
target.Symlink ();
} else {
target.ProcessAssemblies ();
}
}
// Deduplicate files from the Build directory. We need to do this before the AOT
// step, so that we can ignore timestamp/GUID in assemblies (the GUID is
// burned into the AOT assembly, so after that we'll need the original assembly.
if (IsDualBuild && IsDeviceBuild) {
2016-04-21 15:58:45 +03:00
// All the assemblies are now in BuildDirectory.
var t1 = Targets [0];
var t2 = Targets [1];
foreach (var f1 in Directory.GetFileSystemEntries (t1.BuildDirectory)) {
var f2 = Path.Combine (t2.BuildDirectory, Path.GetFileName (f1));
if (!File.Exists (f2))
continue;
var ext = Path.GetExtension (f1).ToUpperInvariant ();
var is_assembly = ext == ".EXE" || ext == ".DLL";
if (!is_assembly)
continue;
if (!Cache.CompareAssemblies (f1, f2, true))
continue;
2016-12-12 21:01:26 +03:00
Driver.Log (1, "Targets {0} and {1} found to be identical", f1, f2);
2016-04-21 15:58:45 +03:00
// Don't use symlinks, since it just gets more complicated
// For instance: on rebuild, when should the symlink be updated and when
// should the target of the symlink be updated? And all the usages
// must be audited to ensure the right thing is done...
Driver.CopyAssembly (f1, f2);
}
}
}
void CompilePInvokeWrappers ()
{
foreach (var target in Targets)
target.CompilePInvokeWrappers ();
}
2016-04-21 15:58:45 +03:00
void BuildApp ()
{
SelectAssemblyBuildTargets (); // This must be done after the linker has run, since the linker may bring in more assemblies than only those referenced explicitly.
var link_tasks = new List<NativeLinkTask> ();
2016-04-21 15:58:45 +03:00
foreach (var target in Targets) {
if (target.CanWeSymlinkTheApplication ())
continue;
target.ComputeLinkerFlags ();
target.Compile ();
link_tasks.AddRange (target.NativeLink (build_tasks));
}
if (IsDeviceBuild) {
// If building for the simulator, the executable is written directly into the expected location within the .app, and no lipo/file copying is needed.
if (link_tasks.Count > 1) {
// If we have more than one executable, we must lipo them together.
var lipo_task = new LipoTask {
InputFiles = link_tasks.Select ((v) => v.OutputFile),
OutputFile = Executable,
};
final_build_task = lipo_task;
} else if (link_tasks.Count == 1) {
var copy_task = new FileCopyTask {
InputFile = link_tasks [0].OutputFile,
OutputFile = Executable,
};
final_build_task = copy_task;
}
// no link tasks if we were symlinked
if (final_build_task != null) {
final_build_task.AddDependency (link_tasks);
build_tasks.Add (final_build_task);
}
2016-04-21 15:58:45 +03:00
}
}
void WriteNotice ()
{
if (!IsDeviceBuild || IsExtension)
2016-04-21 15:58:45 +03:00
return;
if (Embeddinator)
return;
WriteNotice (AppDirectory);
}
void WriteNotice (string directory)
{
var path = Path.Combine (directory, "NOTICE");
if (Directory.Exists (path))
2020-01-31 23:02:52 +03:00
throw new MonoTouchException (1016, true, Errors.MT1016);
2016-04-21 15:58:45 +03:00
try {
// write license information inside the .app
StringBuilder sb = new StringBuilder ();
sb.Append ("Xamarin built applications contain open source software. ");
sb.Append ("For detailed attribution and licensing notices, please visit...");
sb.AppendLine ().AppendLine ().Append ("http://xamarin.com/mobile-licensing").AppendLine ();
Driver.WriteIfDifferent (path, sb.ToString ());
2016-04-21 15:58:45 +03:00
} catch (Exception ex) {
2020-01-31 23:02:52 +03:00
throw new MonoTouchException (1017, true, ex, Errors.MT1017, ex.Message);
2016-04-21 15:58:45 +03:00
}
}
public static void CopyMSymData (string src, string dest)
{
if (string.IsNullOrEmpty (src) || string.IsNullOrEmpty (dest))
return;
if (!Directory.Exists (src)) // got no aot data
return;
var p = new Process ();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = "/Library/Frameworks/Mono.framework/Versions/Current/Commands/mono-symbolicate";
p.StartInfo.Arguments = $"store-symbols \"{src}\" \"{dest}\"";
try {
if (p.Start ()) {
var error = p.StandardError.ReadToEnd();
p.WaitForExit ();
if (p.ExitCode == 0)
return;
else {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (95, Errors.MT0095, dest, error);
return;
}
}
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (95, Errors.MT0095_A, dest);
return;
}
catch (Exception e) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (95, e, Errors.MT0095_A, dest);
return;
}
}
void BuildBundle ()
2016-04-21 15:58:45 +03:00
{
Driver.Watch ($"Building app bundle for {Name}", 1);
2016-04-21 15:58:45 +03:00
// First we must build every appex's bundle, otherwise we won't be able
// to copy any frameworks the appex is using to the container app.
foreach (var appex in AppExtensions)
appex.BuildBundle ();
2016-04-21 15:58:45 +03:00
// Make sure we bundle Mono.framework if we need to.
if (PackageMonoFramework == true) {
BundleFileInfo info;
var name = "Frameworks/Mono.framework";
bundle_files [name] = info = new BundleFileInfo ();
info.Sources.Add (GetLibMono (AssemblyBuildTarget.Framework));
}
2016-04-21 15:58:45 +03:00
2018-11-14 21:20:48 +03:00
var require_mono_native = false;
// Collect files to bundle from every target
if (Targets.Count == 1) {
bundle_files = Targets [0].BundleFiles;
require_mono_native = Targets[0].MonoNative.RequireMonoNative;
} else {
foreach (var target in Targets) {
foreach (var kvp in target.BundleFiles) {
BundleFileInfo info;
if (!bundle_files.TryGetValue (kvp.Key, out info))
bundle_files [kvp.Key] = info = new BundleFileInfo () { DylibToFramework = kvp.Value.DylibToFramework };
info.Sources.UnionWith (kvp.Value.Sources);
}
require_mono_native |= target.MonoNative.RequireMonoNative;
2016-04-21 15:58:45 +03:00
}
}
if (require_mono_native && LibMonoNativeLinkMode == AssemblyBuildTarget.DynamicLibrary) {
foreach (var target in Targets) {
BundleFileInfo info;
var lib_native_name = target.GetLibNativeName () + ".dylib";
bundle_files [lib_native_name] = info = new BundleFileInfo ();
var lib_native_path = Path.Combine (Driver.GetMonoTouchLibDirectory (this), lib_native_name);
info.Sources.Add (lib_native_path);
Driver.Log (3, "Adding mono-native library {0} for {1}.", lib_native_name, target.MonoNativeMode);
}
2018-10-15 22:39:29 +03:00
}
// And from ourselves
var all_assemblies = Targets.SelectMany ((v) => v.Assemblies);
var all_frameworks = Frameworks.Concat (all_assemblies.SelectMany ((v) => v.Frameworks));
var all_weak_frameworks = WeakFrameworks.Concat (all_assemblies.SelectMany ((v) => v.WeakFrameworks));
foreach (var fw in all_frameworks.Concat (all_weak_frameworks)) {
BundleFileInfo info;
if (!Path.GetFileName (fw).EndsWith (".framework", StringComparison.Ordinal))
continue;
var key = $"Frameworks/{Path.GetFileName (fw)}";
if (!bundle_files.TryGetValue (key, out info))
bundle_files [key] = info = new BundleFileInfo ();
info.Sources.Add (fw);
}
// We also need to add any frameworks from extensions
foreach (var appex in AppExtensions) {
foreach (var bf in appex.bundle_files.ToList ()) {
if (!Path.GetFileName (bf.Key).EndsWith (".framework", StringComparison.Ordinal) && !bf.Value.DylibToFramework)
continue;
Driver.Log (3, "Copying {0} to the app's Frameworks directory because it's used by the extension {1}", bf.Key, Path.GetFileName (appex.Name));
var appex_info = bf.Value;
BundleFileInfo info;
if (!bundle_files.TryGetValue (bf.Key, out info))
bundle_files [bf.Key] = info = new BundleFileInfo ();
info.Sources.UnionWith (appex_info.Sources);
if (appex_info.DylibToFramework)
info.DylibToFramework = true;
}
}
// Finally copy all the files & directories
foreach (var kvp in bundle_files) {
var name = kvp.Key;
var info = kvp.Value;
var targetPath = Path.Combine (AppDirectory, name);
var files = info.Sources;
var isFramework = Directory.Exists (files.First ());
if (!HasFrameworksDirectory && (isFramework || info.DylibToFramework))
continue; // Don't copy frameworks to app extensions (except watch extensions), they go into the container app.
if (!files.All ((v) => Directory.Exists (v) == isFramework))
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (99, Errors.MX0099, $"'can't process a mix of dylibs and frameworks: {string.Join(", ", files)}'");
if (isFramework) {
// This is a framework
if (files.Count > 1) {
// If we have multiple frameworks, check if they're identical, and remove any duplicates
var firstFile = files.First ();
foreach (var otherFile in files.Where ((v) => v != firstFile).ToArray ()) {
if (Cache.CompareDirectories (firstFile, otherFile, ignore_cache: true)) {
Driver.Log (6, $"Framework '{name}' included from both '{firstFile}' and '{otherFile}', but they are identical, so the latter will be ignored.");
files.Remove (otherFile);
continue;
}
}
}
if (files.Count != 1) {
var exceptions = new List<Exception> ();
var fname = Path.GetFileName (name);
2020-01-31 23:02:52 +03:00
exceptions.Add (ErrorHelper.CreateError (1035, Errors.MT1035, fname));
foreach (var file in files)
2020-01-31 23:02:52 +03:00
exceptions.Add (ErrorHelper.CreateError (1036, Errors.MT1036, fname, file));
throw new AggregateException (exceptions);
}
if (info.DylibToFramework)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (99, Errors.MX0099, $"'can't convert frameworks to frameworks: {files.First()}'");
var framework_src = files.First ();
var framework_filename = Path.Combine (framework_src, Path.GetFileNameWithoutExtension (framework_src));
var dynamic = false;
try {
dynamic = MachO.IsDynamicFramework (framework_filename);
} catch (Exception e) {
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (140, e, Errors.MT0140, framework_filename);
}
if (!dynamic) {
Driver.Log (1, "The framework {0} is a framework of static libraries, and will not be copied to the app.", framework_src);
} else {
var macho_file = Path.Combine (targetPath, Path.GetFileNameWithoutExtension (framework_src));
var macho_info = new FileInfo (macho_file);
var macho_last_write_time = macho_info.LastWriteTimeUtc; // this returns a date in the 17th century if the file doesn't exist.
UpdateDirectory (framework_src, Path.GetDirectoryName (targetPath));
if (IsDeviceBuild) {
// Remove architectures we don't care about.
MachO.SelectArchitectures (macho_file, AllArchitectures);
// Strip bitcode if needed.
macho_info.Refresh ();
if (macho_info.LastWriteTimeUtc > macho_last_write_time) {
// bitcode_strip will always touch the file, but we only want to strip it if it was updated.
StripBitcode (macho_file);
}
}
2016-04-21 15:58:45 +03:00
}
} else {
var targetDirectory = Path.GetDirectoryName (targetPath);
if (!IsUptodate (files, new string [] { targetPath })) {
Directory.CreateDirectory (targetDirectory);
if (files.Count == 1) {
CopyFile (files.First (), targetPath);
} else {
Driver.RunLipo (targetPath, files);
}
if (LibMonoLinkMode == AssemblyBuildTarget.Framework)
Driver.RunInstallNameTool (new [] { "-change", "@rpath/libmonosgen-2.0.dylib", "@rpath/Mono.framework/Mono", targetPath });
// Remove architectures we don't care about.
if (IsDeviceBuild)
MachO.SelectArchitectures (targetPath, AllArchitectures);
} else {
Driver.Log (3, "Target '{0}' is up-to-date.", targetPath);
}
2016-04-21 15:58:45 +03:00
if (info.DylibToFramework) {
var bundleName = Path.GetFileName (name);
CreateFrameworkInfoPList (Path.Combine (targetDirectory, "Info.plist"), bundleName, BundleId + Path.GetFileNameWithoutExtension (bundleName), bundleName);
CreateFrameworkNotice (targetDirectory);
}
}
2016-04-21 15:58:45 +03:00
}
if (Embeddinator) {
if (IsSimulatorBuild) {
var frameworkName = ExecutableName;
var frameworkDirectory = Path.Combine (AppDirectory, "Frameworks", frameworkName + ".framework");
var frameworkExecutable = Path.Combine (frameworkDirectory, frameworkName);
Directory.CreateDirectory (frameworkDirectory);
var allExecutables = Targets.SelectMany ((t) => t.Executables.Values).ToArray ();
if (allExecutables.Length > 1) {
Lipo (frameworkExecutable, allExecutables);
} else {
UpdateFile (allExecutables [0], frameworkExecutable);
}
CreateFrameworkInfoPList (Path.Combine (frameworkDirectory, "Info.plist"), frameworkName, BundleId + frameworkName, frameworkName);
}
2016-04-21 15:58:45 +03:00
}
}
public void StripBitcode (string macho_file)
{
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
var sb = new List<string> ();
sb.Add (macho_file);
switch (BitCodeMode) {
case BitCodeMode.ASMOnly:
case BitCodeMode.LLVMOnly:
// do nothing, since we don't know neither if bitcode is needed (if we're publishing) or if native code is needed (not publishing).
return;
case BitCodeMode.MarkerOnly:
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
sb.Add ("-m");
break;
case BitCodeMode.None:
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
sb.Add ("-r");
break;
}
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
sb.Add ("-o");
sb.Add (macho_file);
Driver.RunBitcodeStrip (sb);
}
// Returns true if is up-to-date
public static bool Lipo (string output, params string [] inputs)
{
if (IsUptodate (inputs, new string [] { output })) {
Driver.Log (3, "Target '{0}' is up-to-date.", output);
return true;
} else {
Driver.RunLipo (output, inputs);
return false;
}
}
2016-04-21 15:58:45 +03:00
public void ExtractNativeLinkInfo ()
{
var exceptions = new List<Exception> ();
foreach (var target in Targets)
target.ExtractNativeLinkInfo (exceptions);
if (exceptions.Count > 0)
throw new AggregateException (exceptions);
Driver.Watch ("Extracted native link info", 1);
}
public void SelectNativeCompiler ()
{
foreach (var t in Targets) {
foreach (var a in t.Assemblies) {
if (a.EnableCxx) {
EnableCxx = true;
break;
}
}
}
Driver.CalculateCompilerPath (this);
Driver.Watch ("Select Native Compiler", 1);
2016-04-21 15:58:45 +03:00
}
public string GetLibMono (AssemblyBuildTarget build_target)
{
switch (build_target) {
case AssemblyBuildTarget.StaticObject:
return Path.Combine (Driver.GetMonoTouchLibDirectory (this), "libmonosgen-2.0.a");
case AssemblyBuildTarget.DynamicLibrary:
return Path.Combine (Driver.GetMonoTouchLibDirectory (this), "libmonosgen-2.0.dylib");
case AssemblyBuildTarget.Framework:
return Path.Combine (Driver.GetProductSdkDirectory (this), "Frameworks", "Mono.framework");
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (100, Errors.MT0100, build_target);
2016-04-21 15:58:45 +03:00
}
}
public string GetLibXamarin (AssemblyBuildTarget build_target)
{
switch (build_target) {
case AssemblyBuildTarget.StaticObject:
return Path.Combine (Driver.GetMonoTouchLibDirectory (this), EnableDebug ? "libxamarin-debug.a" : "libxamarin.a");
case AssemblyBuildTarget.DynamicLibrary:
return Path.Combine (Driver.GetMonoTouchLibDirectory (this), EnableDebug ? "libxamarin-debug.dylib" : "libxamarin.dylib");
case AssemblyBuildTarget.Framework:
return Path.Combine (Driver.GetProductSdkDirectory (this), "Frameworks", EnableDebug ? "Xamarin-debug.framework" : "Xamarin.framework");
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (100, Errors.MT0100, build_target);
2016-04-21 15:58:45 +03:00
}
}
// this will filter/remove warnings that are not helpful (e.g. complaining about non-matching armv6-6 then armv7-6 on fat binaries)
// and turn the remaining of the warnings into MT5203 that MonoDevelop will be able to report as real warnings (not just logs)
// it will also look for symbol-not-found errors and try to provide useful error messages.
public static void ProcessNativeLinkerOutput (Target target, string output, IEnumerable<string> inputs, List<Exception> errors, bool error)
2016-04-21 15:58:45 +03:00
{
List<string> lines = new List<string> (output.Split (new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries));
// filter
for (int i = 0; i < lines.Count; i++) {
string line = lines [i];
if (errors.Count > 100)
return;
if (line.Contains ("ld: warning: ignoring file ") &&
line.Contains ("file was built for") &&
line.Contains ("which is not the architecture being linked") &&
// Only ignore warnings related to the object files we've built ourselves (assemblies, main.m, registrar.m)
inputs.Any ((v) => line.Contains (v))) {
continue;
} else if (line.Contains ("ld: symbol(s) not found for architecture") && errors.Count > 0) {
continue;
} else if (line.Contains ("clang: error: linker command failed with exit code 1")) {
continue;
} else if (line.Contains ("was built for newer iOS version (5.1.1) than being linked (5.1)")) {
continue;
} else if (line.Contains ("was built for newer iOS version (7.0) than being linked (6.0)") &&
line.Contains (Driver.GetProductSdkDirectory (target.App))) {
continue;
} else if (line.Contains ("was built for newer watchOS version (5.1) than being linked (2.0)") &&
line.Contains (Driver.GetProductSdkDirectory (target.App))) {
// We build the arm64_32 slice for watchOS for watchOS 5.1, and the armv7k slice for watchOS 2.0.
// Building for anything less than watchOS 5.1 will trigger this warning for the arm64_32 slice.
continue;
2016-04-21 15:58:45 +03:00
}
if (line.Contains ("Undefined symbols for architecture")) {
while (++i < lines.Count) {
line = lines [i];
if (!line.EndsWith (", referenced from:", StringComparison.Ordinal))
2016-04-21 15:58:45 +03:00
break;
var symbol = line.Replace (", referenced from:", "").Trim ('\"', ' ');
if (symbol.StartsWith ("_OBJC_CLASS_$_", StringComparison.Ordinal)) {
2020-01-31 23:02:52 +03:00
errors.Add (new MonoTouchException (5211, error, Errors.MT5211, symbol.Replace ("_OBJC_CLASS_$_", ""), symbol));
2016-04-21 15:58:45 +03:00
} else {
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
var members = target.GetAllSymbols ().Find (symbol.Substring (1))?.Members;
if (members != null && members.Any ()) {
var member = members.First (); // Just report the first one.
2016-04-21 15:58:45 +03:00
// Neither P/Invokes nor fields have IL, so we can't find the source code location.
2020-01-31 23:02:52 +03:00
errors.Add (new MonoTouchException (5214, error, Errors.MT5214,
2016-04-21 15:58:45 +03:00
symbol, member.DeclaringType.FullName, member.Name));
} else {
2020-01-31 23:02:52 +03:00
errors.Add (new MonoTouchException (5210, error, Errors.MT5210, symbol));
2016-04-21 15:58:45 +03:00
}
}
// skip all subsequent lines related to the same error.
// we skip all subsequent lines with more indentation than the initial line.
var indent = GetIndentation (line);
while (i + 1 < lines.Count) {
line = lines [i + 1];
if (GetIndentation (lines [i + 1]) <= indent)
break;
i++;
}
}
} else if (line.StartsWith ("duplicate symbol", StringComparison.Ordinal) && line.EndsWith (" in:", StringComparison.Ordinal)) {
2016-04-21 15:58:45 +03:00
var symbol = line.Replace ("duplicate symbol ", "").Replace (" in:", "").Trim ();
2020-01-31 23:02:52 +03:00
errors.Add (new MonoTouchException (5212, error, Errors.MT5212, symbol));
2016-04-21 15:58:45 +03:00
var indent = GetIndentation (line);
while (i + 1 < lines.Count) {
line = lines [i + 1];
if (GetIndentation (lines [i + 1]) <= indent)
break;
i++;
2020-01-31 23:02:52 +03:00
errors.Add (new MonoTouchException (5213, error, Errors.MT5213, line.Trim ()));
2016-04-21 15:58:45 +03:00
}
} else {
if (line.StartsWith ("ld: ", StringComparison.Ordinal))
2016-04-21 15:58:45 +03:00
line = line.Substring (4);
line = line.Trim ();
if (error) {
2020-01-31 23:02:52 +03:00
errors.Add (new MonoTouchException (5209, error, Errors.MT5209, line));
2016-04-21 15:58:45 +03:00
} else {
2020-01-31 23:02:52 +03:00
errors.Add (new MonoTouchException (5203, error, Errors.MT5203, line));
2016-04-21 15:58:45 +03:00
}
}
}
}
static int GetIndentation (string line)
{
int rv = 0;
if (line.Length == 0)
return 0;
while (true) {
switch (line [rv]) {
case ' ':
case '\t':
rv++;
break;
default:
return rv;
}
};
}
// return the ids found in a macho file
List<Guid> GetUuids (MachOFile file)
{
var result = new List<Guid> ();
foreach (var cmd in file.load_commands) {
if (cmd is UuidCommand) {
var uuidCmd = cmd as UuidCommand;
result.Add (new Guid (uuidCmd.uuid));
}
}
return result;
}
// This method generates the manifest that is required by the symbolication in order to be able to debug the application,
// The following is an example of the manifest to be generated:
// <mono-debug version=”1”>
// <app-id>com.foo.bar</app-id>
// <build-date>datetime</build-date>
// <build-id>build-id</build-id>
// <build-id>build-id</build-id>
// </mono-debug>
// where:
//
// app-id: iOS/Android/Mac app/package ID. Currently for verification and user info only but in future may be used to find symbols automatically.
// build-date: Local time in DateTime “O” format. For user info only.
// build-id: The build UUID. Needed for HockeyApp to find the mSYM folder matching the app build. There may be more than one, as in the case of iOS multi-arch.
void GenerateMSymManifest (Target target, string target_directory)
{
var manifestPath = Path.Combine (target_directory, "manifest.xml");
if (String.IsNullOrEmpty (target_directory))
throw new ArgumentNullException (nameof (target_directory));
var root = new XElement ("mono-debug",
new XAttribute("version", 1),
new XElement ("app-id", BundleId),
new XElement ("build-date", DateTime.Now.ToString ("O")));
foreach (var executable in target.Executables.Values) {
var file = MachO.Read (executable);
if (file is MachO) {
var mfile = file as MachOFile;
var uuids = GetUuids (mfile);
foreach (var str in uuids) {
root.Add (new XElement ("build-id", str));
}
} else if (file is IEnumerable<MachOFile>) {
var ffile = file as IEnumerable<MachOFile>;
foreach (var fentry in ffile) {
var uuids = GetUuids (fentry);
foreach (var str in uuids) {
root.Add (new XElement ("build-id", str));
}
}
} else {
// do not write a manifest
return;
}
}
// Write only if we need to update the manifest
Driver.WriteIfDifferent (manifestPath, root.ToString ());
}
void CopyAotData (string src, string dest)
{
if (string.IsNullOrEmpty (src) || string.IsNullOrEmpty (dest)) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (95, Errors.MT0095_B, dest);
return;
}
var dir = new DirectoryInfo (src);
if (!dir.Exists) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (95, Errors.MT0095_B, dest);
return;
}
var dirs = dir.GetDirectories ();
if (!Directory.Exists (dest))
Directory.CreateDirectory (dest);
var files = dir.GetFiles ();
foreach (var file in files) {
var tmp = Path.Combine (dest, file.Name);
file.CopyTo (tmp, true);
}
foreach (var subdir in dirs) {
var tmp = Path.Combine (dest, subdir.Name);
CopyAotData (subdir.FullName, tmp);
}
}
2016-04-21 15:58:45 +03:00
public void BuildMSymDirectory ()
{
if (!EnableMSym)
return;
if (IsExtension && IsCodeShared) // we already have the data from the app
return;
var target_directory = string.Format ("{0}.mSYM", AppDirectory);
if (!Directory.Exists (target_directory))
Directory.CreateDirectory (target_directory);
2016-04-21 15:58:45 +03:00
foreach (var target in Targets) {
GenerateMSymManifest (target, target_directory);
var msymdir = Path.Combine (target.BuildDirectory, "Msym");
if (!Directory.Exists (msymdir)) {
2020-01-31 23:02:52 +03:00
ErrorHelper.Warning (118, Errors.MT0118, msymdir);
continue;
}
// copy aot data must be done BEFORE we do copy the msym one
CopyAotData (msymdir, target_directory);
// copy all assemblies under mvid and with the dll and mdb/pdb
var tmpdir = Path.Combine (msymdir, "Msym", "tmp");
if (!Directory.Exists (tmpdir))
Directory.CreateDirectory (tmpdir);
2016-04-21 15:58:45 +03:00
foreach (var asm in target.Assemblies) {
asm.CopyToDirectory (tmpdir, reload: false, only_copy: true);
asm.CopyAotDataFilesToDirectory (tmpdir);
2016-04-21 15:58:45 +03:00
}
// mono-symbolicate knows best
CopyMSymData (target_directory, tmpdir);
2016-04-21 15:58:45 +03:00
}
}
public void BuildDsymDirectory ()
{
if (!BuildDSym.HasValue)
BuildDSym = IsDeviceBuild;
if (!BuildDSym.Value)
return;
string dsym_dir = string.Format ("{0}.dSYM", AppDirectory);
bool cached_dsym = false;
if (cached_executable)
cached_dsym = IsUptodate (new string [] { Executable }, Directory.EnumerateFiles (dsym_dir, "*", SearchOption.AllDirectories));
if (!cached_dsym) {
if (Directory.Exists (dsym_dir))
Directory.Delete (dsym_dir, true);
Driver.CreateDsym (AppDirectory, ExecutableName, dsym_dir);
} else {
Driver.Log (3, "Target '{0}' is up-to-date.", dsym_dir);
}
Driver.Watch ("Linking DWARF symbols", 1);
}
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
IEnumerable<Symbol> GetRequiredSymbols ()
2016-04-21 15:58:45 +03:00
{
foreach (var target in Targets) {
foreach (var symbol in target.GetRequiredSymbols ())
yield return symbol;
}
}
bool WriteSymbolList (string filename)
{
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
var required_symbols = GetRequiredSymbols ();
2016-04-21 15:58:45 +03:00
using (StreamWriter writer = new StreamWriter (filename)) {
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
foreach (var symbol in required_symbols)
writer.WriteLine ("_{0}", symbol.Name);
2016-04-21 15:58:45 +03:00
foreach (var symbol in NoSymbolStrip)
writer.WriteLine ("_{0}", symbol);
writer.Flush ();
return writer.BaseStream.Position > 0;
}
}
void StripNativeCode (string name)
{
if (NativeStrip && IsDeviceBuild && !EnableDebug && string.IsNullOrEmpty (SymbolList)) {
string symbol_file = Path.Combine (Cache.Location, "symbol-file");
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
var args = new List<string> ();
2016-04-21 15:58:45 +03:00
if (WriteSymbolList (symbol_file)) {
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
args.Add ("-i");
args.Add ("-s");
args.Add (symbol_file);
2016-04-21 15:58:45 +03:00
}
if (Embeddinator)
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
args.Add ("-ux");
args.Add (Executable);
Driver.RunStrip (args);
2016-04-21 15:58:45 +03:00
Driver.Watch ("Native Strip", 1);
}
if (!string.IsNullOrEmpty (SymbolList))
WriteSymbolList (SymbolList);
}
public void StripNativeCode ()
{
if (!cached_executable)
StripNativeCode (Executable);
2016-04-21 15:58:45 +03:00
}
public void BundleAssemblies ()
2016-04-21 15:58:45 +03:00
{
Bump to mono:2018-06 (#4277) * Bump to mono:2018-06 * Bump mono * Updates compression to work with the public span * Bump mono * Fixes pointer check logic in Deflater * Bump mono * Fixes pointer check logic in Deflater * Bump mono * Bump Mono * [runtime] always use `mono_jit_set_aot_mode` (#4491) `mono_jit_set_aot_only` is deprecated and accidentally broke with https://github.com/mono/mono/pull/7887 This should fix device tests with `mono-2018-06` * Testing with Zoltan's patch * Include libmono-system-native on Xamarin.Mac * Bump Mono Commit list for mono/mono: * mono/mono@7bcda192a06 Bump llvm to release_60/fc854b8ec5873d294b80afa3e6cf6a88c5c48886. (#9786). (#9804) * mono/mono@23e95ec7ad7 Apply F# portable pdb debug fix for pinvokes & bump (#9797) * mono/mono@295f6d32afd [2018-06] [MacOS] On Mac, use the copyfile API to copy files (#9696) Diff: https://github.com/mono/mono/compare/7d5f4b61366008d47665bb473205f4ae1f716d1f...7bcda192a06267562af565d404c06d159f475c03 * Revert 4bacab3d5c7fa86a0e6437f64bb9f08ea3d0741b, it doesn't fix the ios aot problems. * Bump mono * [tests] Adjust the MT0137 test for mcs change in behavior. Starting with mono 5.16 mcs will now add assembly references when the assembly is only used in attributes (this was already the case for csc in both 5.14 and 5.16, so it seems to be a compatibility change). Adjust the MT0137 test accordingly. * [msbuild] Fix parsing of json parser errors to handle trailing periods in the error message. Fixes this test: 1) Test Failure : Xamarin.iOS.Tasks.Bug60536.TestACToolTaskCatchesJsonException ColumnNumber Expected: 2 But was: 0 * Bump mono * [builds] Install the old llvm binaries into the LLVM36 directory and make the 32 bit builds use that. * Bump mono * Bump mono * [jenkins] Don't give VSTS a fake branch. (#4667) Something in VSTS changed, and now fake branch names don't work anymore. So instead use real branch names (and for pull requests I've created a 'pull-request' branch we can use). * Assembly.LoadFile accepts only absolute path * [linker] Add new Facade (System.Threading.Tasks.Extensions). Fixes these MTouch test failures: 1. Xamarin.Linker.SdkTest.iOS_Unified : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > 2. Xamarin.Linker.SdkTest.tvOS : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > 3. Xamarin.Linker.SdkTest.watchOS : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > * [mono-sdks] Necessary changes to unify the LLVM provisioning for both iOS and Android. (#4732) * Bump Mono * [mtouch] add mixed-mode support (#4751) * [mtouch] add --interp-mixed option When enabling this option, mtouch will AOT compile `mscorlib.dll`. At runtime that means every method that wasn't AOT'd will be executed by the runtime interpreter. * [mtouch] Add support to --interpreter to list the assemblies to (not) interpret. * [msbuild] Simplify interpreter code to use a single variable. * Fix whitespace. * [mtouch] Move mtouch-specific code to mtouch-specific file. * [msbuild] An empty string is a valid value for 'Interpreter', so make it a non-required property. * [mtouch] Add sanity check for aot-compiling interpreted assemblies. * Bump Mono * [linker] Updates SDKs facades list * Bump mono * [msbuild] Adds facades which might override default nuget version to framework list The collision resolver task reads them from here https://github.com/dotnet/sdk/blob/master/src/Tasks/Common/ConflictResolution/FrameworkListReader.cs * Bump to a VSfM version that can build XM Classic projects.
2018-10-10 18:02:28 +03:00
Assembly.StripAssembly strip = ((path) =>
{
if (!ManagedStrip)
return false;
if (!IsDeviceBuild)
return false;
if (EnableDebug)
return false;
if (PackageManagedDebugSymbols)
return false;
/* FIXME: should be `if (IsInterpreted (Assembly.GetIdentity (path)))`.
* The problem is that in mixed mode we can't do the transition
* between "interp"->"aot'd methods using gsharedvt", so we
* fall back to the interp and thus need the IL not to be
* stripped out. Once Mono supports this, we can add back the
* more precise check.
* See https://github.com/mono/mono/issues/11942 */
if (UseInterpreter)
Bump to mono:2018-06 (#4277) * Bump to mono:2018-06 * Bump mono * Updates compression to work with the public span * Bump mono * Fixes pointer check logic in Deflater * Bump mono * Fixes pointer check logic in Deflater * Bump mono * Bump Mono * [runtime] always use `mono_jit_set_aot_mode` (#4491) `mono_jit_set_aot_only` is deprecated and accidentally broke with https://github.com/mono/mono/pull/7887 This should fix device tests with `mono-2018-06` * Testing with Zoltan's patch * Include libmono-system-native on Xamarin.Mac * Bump Mono Commit list for mono/mono: * mono/mono@7bcda192a06 Bump llvm to release_60/fc854b8ec5873d294b80afa3e6cf6a88c5c48886. (#9786). (#9804) * mono/mono@23e95ec7ad7 Apply F# portable pdb debug fix for pinvokes & bump (#9797) * mono/mono@295f6d32afd [2018-06] [MacOS] On Mac, use the copyfile API to copy files (#9696) Diff: https://github.com/mono/mono/compare/7d5f4b61366008d47665bb473205f4ae1f716d1f...7bcda192a06267562af565d404c06d159f475c03 * Revert 4bacab3d5c7fa86a0e6437f64bb9f08ea3d0741b, it doesn't fix the ios aot problems. * Bump mono * [tests] Adjust the MT0137 test for mcs change in behavior. Starting with mono 5.16 mcs will now add assembly references when the assembly is only used in attributes (this was already the case for csc in both 5.14 and 5.16, so it seems to be a compatibility change). Adjust the MT0137 test accordingly. * [msbuild] Fix parsing of json parser errors to handle trailing periods in the error message. Fixes this test: 1) Test Failure : Xamarin.iOS.Tasks.Bug60536.TestACToolTaskCatchesJsonException ColumnNumber Expected: 2 But was: 0 * Bump mono * [builds] Install the old llvm binaries into the LLVM36 directory and make the 32 bit builds use that. * Bump mono * Bump mono * [jenkins] Don't give VSTS a fake branch. (#4667) Something in VSTS changed, and now fake branch names don't work anymore. So instead use real branch names (and for pull requests I've created a 'pull-request' branch we can use). * Assembly.LoadFile accepts only absolute path * [linker] Add new Facade (System.Threading.Tasks.Extensions). Fixes these MTouch test failures: 1. Xamarin.Linker.SdkTest.iOS_Unified : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > 2. Xamarin.Linker.SdkTest.tvOS : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > 3. Xamarin.Linker.SdkTest.watchOS : Facades Expected: But was: < "System.Threading.Tasks.Extensions" > * [mono-sdks] Necessary changes to unify the LLVM provisioning for both iOS and Android. (#4732) * Bump Mono * [mtouch] add mixed-mode support (#4751) * [mtouch] add --interp-mixed option When enabling this option, mtouch will AOT compile `mscorlib.dll`. At runtime that means every method that wasn't AOT'd will be executed by the runtime interpreter. * [mtouch] Add support to --interpreter to list the assemblies to (not) interpret. * [msbuild] Simplify interpreter code to use a single variable. * Fix whitespace. * [mtouch] Move mtouch-specific code to mtouch-specific file. * [msbuild] An empty string is a valid value for 'Interpreter', so make it a non-required property. * [mtouch] Add sanity check for aot-compiling interpreted assemblies. * Bump Mono * [linker] Updates SDKs facades list * Bump mono * [msbuild] Adds facades which might override default nuget version to framework list The collision resolver task reads them from here https://github.com/dotnet/sdk/blob/master/src/Tasks/Common/ConflictResolution/FrameworkListReader.cs * Bump to a VSfM version that can build XM Classic projects.
2018-10-10 18:02:28 +03:00
return false;
return true;
});
var grouped = Targets.SelectMany ((Target t) => t.Assemblies).GroupBy ((Assembly asm) => asm.Identity);
foreach (var @group in grouped) {
var filename = @group.Key;
var assemblies = @group.AsEnumerable ().ToArray ();
var build_target = assemblies [0].BuildTarget;
var size_specific = assemblies.Length > 1 && !Cache.CompareAssemblies (assemblies [0].FullPath, assemblies [1].FullPath, true, true);
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
if (IsExtension && !IsWatchExtension) {
var codeShared = assemblies.Count ((v) => v.IsCodeShared || v.BundleInContainerApp);
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
if (codeShared > 0) {
if (codeShared != assemblies.Length)
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (99, Errors.MX0099, $"all assemblies in a joined build target must have the same code sharing options ({string.Join(", ", assemblies.Select((v) => v.Identity + "=" + v.IsCodeShared))})");
[mtouch] Implement support for sharing code between app extensions and container apps. Implement support for sharing both code and resources between app extensions and their container app: * AOT-compiled code. Each shared assembly is only AOT-compiled once, and if the assembly is built to a framework or dynamic library, it will also only be included once in the final app (as a framework or dynamic library in the container app, referenced directly by the app extension). If the assemblies are built to static objects there won't be any size improvements in the app, but the build will be much faster, because the assemblies will only be AOT- compiled once. * Any resources related to managed assemblies (debug files, config files, satellite assemblies) will be put in the container app only. Since these improvements are significant, code sharing will be enabled by default. Test results ============ For an extreme test project with 7 extensions (embedded-frameworks)[1]: with code sharing cycle 9 difference build time 1m 47s 3m 33s -1m 46s = ~50% faster app size 26 MB 131 MB -105 MB = ~80% smaller For a more normal test project (MyTabbedApplication)[2] - this is a simple application with 1 extension: with code sharing cycle 9 difference build time 0m 44s 0m 48s -4s = ~ 8% faster app size 23 MB 37 MB -15 MB = ~40% smaller Another tvOS app with one extension also show similar gains (MyTVApp)[3]: with code sharing cycle 9 difference build time 0m 22s 0m 48s -26s = ~54% faster app size 22 MB 62 MB -40 MB = ~65% smaller [1]: https://github.com/rolfbjarne/embedded-frameworks [2]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTabbedApplication [3]: https://github.com/xamarin/xamarin-macios/tree/cycle9/msbuild/tests/MyTVApp
2017-01-24 13:10:20 +03:00
continue; // These resources will be found in the main app.
}
}
// Determine where to put the assembly
switch (build_target) {
case AssemblyBuildTarget.StaticObject:
case AssemblyBuildTarget.DynamicLibrary:
if (size_specific) {
assemblies [0].CopyToDirectory (assemblies [0].Target.AppTargetDirectory, copy_debug_symbols: PackageManagedDebugSymbols, strip: strip, only_copy: true);
assemblies [1].CopyToDirectory (assemblies [1].Target.AppTargetDirectory, copy_debug_symbols: PackageManagedDebugSymbols, strip: strip, only_copy: true);
} else {
assemblies [0].CopyToDirectory (AppDirectory, copy_debug_symbols: PackageManagedDebugSymbols, strip: strip, only_copy: true);
}
foreach (var asm in assemblies)
asm.CopyAotDataFilesToDirectory (size_specific ? asm.Target.AppTargetDirectory : AppDirectory);
break;
case AssemblyBuildTarget.Framework:
// Put our resources in a subdirectory in the framework
// But don't use 'Resources', because the app ends up being undeployable:
// "PackageInspectionFailed: Failed to load Info.plist from bundle at path /private/var/installd/Library/Caches/com.apple.mobile.installd.staging/temp.CR0vmK/extracted/testapp.app/Frameworks/TestApp.framework"
var target_name = assemblies [0].BuildTargetName;
var resource_directory = Path.Combine (AppDirectory, "Frameworks", $"{target_name}.framework", "MonoBundle");
if (IsSimulatorBuild)
resource_directory = Path.Combine (resource_directory, "simulator");
if (size_specific) {
assemblies [0].CopyToDirectory (Path.Combine (resource_directory, Path.GetFileName (assemblies [0].Target.AppTargetDirectory)), copy_debug_symbols: PackageManagedDebugSymbols, strip: strip, only_copy: true);
assemblies [1].CopyToDirectory (Path.Combine (resource_directory, Path.GetFileName (assemblies [1].Target.AppTargetDirectory)), copy_debug_symbols: PackageManagedDebugSymbols, strip: strip, only_copy: true);
} else {
assemblies [0].CopyToDirectory (resource_directory, copy_debug_symbols: PackageManagedDebugSymbols, strip: strip, only_copy: true);
}
foreach (var asm in assemblies)
asm.CopyAotDataFilesToDirectory (size_specific ? Path.Combine (resource_directory, Path.GetFileName (asm.Target.AppTargetDirectory)) : resource_directory);
break;
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (100, Errors.MT0100, build_target);
}
2016-04-21 15:58:45 +03:00
}
}
public void GenerateRuntimeOptions ()
{
// only if the linker is disabled
if (LinkMode != LinkMode.None)
return;
RuntimeOptions.Write (AppDirectory);
}
public void CreateFrameworkNotice (string output_path)
{
if (!Embeddinator)
return;
WriteNotice (output_path);
}
public void CreateFrameworkInfoPList (string output_path, string framework_name, string bundle_identifier, string bundle_name)
{
var sb = new StringBuilder ();
sb.AppendLine ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
sb.AppendLine ("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
sb.AppendLine ("<plist version=\"1.0\">");
sb.AppendLine ("<dict>");
sb.AppendLine (" <key>CFBundleDevelopmentRegion</key>");
sb.AppendLine (" <string>en</string>");
sb.AppendLine (" <key>CFBundleIdentifier</key>");
sb.AppendLine ($" <string>{bundle_identifier}</string>");
sb.AppendLine (" <key>CFBundleInfoDictionaryVersion</key>");
sb.AppendLine (" <string>6.0</string>");
sb.AppendLine (" <key>CFBundleName</key>");
sb.AppendLine ($" <string>{bundle_name}</string>");
sb.AppendLine (" <key>CFBundlePackageType</key>");
sb.AppendLine (" <string>FMWK</string>");
sb.AppendLine (" <key>CFBundleShortVersionString</key>");
sb.AppendLine (" <string>1.0</string>");
sb.AppendLine (" <key>CFBundleSignature</key>");
sb.AppendLine (" <string>????</string>");
sb.AppendLine (" <key>CFBundleVersion</key>");
sb.AppendLine (" <string>1.0</string>");
sb.AppendLine (" <key>NSPrincipalClass</key>");
sb.AppendLine (" <string></string>");
sb.AppendLine (" <key>CFBundleExecutable</key>");
sb.AppendLine ($" <string>{framework_name}</string>");
sb.AppendLine (" <key>BuildMachineOSBuild</key>");
sb.AppendLine (" <string>13F34</string>");
sb.AppendLine (" <key>CFBundleSupportedPlatforms</key>");
sb.AppendLine (" <array>");
sb.AppendLine ($" <string>{Driver.GetPlatform (this)}</string>");
sb.AppendLine (" </array>");
sb.AppendLine (" <key>DTCompiler</key>");
sb.AppendLine (" <string>com.apple.compilers.llvm.clang.1_0</string>");
sb.AppendLine (" <key>DTPlatformBuild</key>");
sb.AppendLine (" <string>12D508</string>");
sb.AppendLine (" <key>DTPlatformName</key>");
sb.AppendLine ($" <string>{Driver.GetPlatform (this).ToLowerInvariant ()}</string>");
sb.AppendLine (" <key>DTPlatformVersion</key>");
sb.AppendLine ($" <string>{SdkVersions.GetVersion (Platform)}</string>");
sb.AppendLine (" <key>DTSDKBuild</key>");
sb.AppendLine (" <string>12D508</string>");
sb.AppendLine (" <key>DTSDKName</key>");
sb.AppendLine ($" <string>{Driver.GetPlatform (this)}{SdkVersion}</string>");
sb.AppendLine (" <key>DTXcode</key>");
sb.AppendLine (" <string>0620</string>");
sb.AppendLine (" <key>DTXcodeBuild</key>");
sb.AppendLine (" <string>6C131e</string>");
sb.AppendLine (" <key>MinimumOSVersion</key>");
sb.AppendLine ($" <string>{DeploymentTarget.ToString ()}</string>");
sb.AppendLine (" <key>UIDeviceFamily</key>");
sb.AppendLine (" <array>");
switch (Platform) {
case ApplePlatform.iOS:
sb.AppendLine (" <integer>1</integer>");
sb.AppendLine (" <integer>2</integer>");
break;
case ApplePlatform.TVOS:
sb.AppendLine (" <integer>3</integer>");
break;
case ApplePlatform.WatchOS:
sb.AppendLine (" <integer>4</integer>");
break;
default:
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (71, Errors.MX0071, Platform, "Xamarin.iOS");
}
sb.AppendLine (" </array>");
sb.AppendLine ("</dict>");
sb.AppendLine ("</plist>");
Driver.WriteIfDifferent (output_path, sb.ToString ());
}
2016-04-21 15:58:45 +03:00
}
}