Added Hot Restart support into the SDK (#12293)
- Added Hot Restart support for net6 - Added Hot Restart content into the Windows iOS pack Co-authored-by: emaf <ema@xamarin.com>
|
@ -1 +1 @@
|
|||
Subproject commit fd29206d98dedbcc08b992916afa2fac1718bf55
|
||||
Subproject commit b7c6c1c971f94e81d934e112278cd882741918d0
|
|
@ -1,5 +1,6 @@
|
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<MessagingVersion>1.3.26</MessagingVersion>
|
||||
<MessagingVersion>1.3.27</MessagingVersion>
|
||||
<HotRestartVersion>1.0.69</HotRestartVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
@ -84,6 +84,10 @@
|
|||
<Delete Files="$(IntermediateOutputPath)ilrepack.txt" Condition="'$(ExitCode)' != '0'" />
|
||||
<Touch AlwaysCreate="true" Files="$(IntermediateOutputPath)ilrepack.txt" Condition="'$(ExitCode)' == '0'" />
|
||||
<Error Text="$(ILRepackOutput)" Condition="'$(ExitCode)' != '0' And '$(ContinueOnError)' != 'true'" />
|
||||
<Delete Files="@(MergedAssemblies -> '$(MSBuildProjectDirectory)\$(OutputPath)%(Filename)%(Extension)')" Condition="Exists('$(MSBuildProjectDirectory)\$(OutputPath)%(Filename)%(Extension)')" />
|
||||
<ItemGroup>
|
||||
<MergedAssembliesToRemove Include="@(MergedAssemblies)" />
|
||||
<MergedAssembliesToRemove Remove="@(ReferenceToPreserve)" />
|
||||
</ItemGroup>
|
||||
<Delete Files="@(MergedAssembliesToRemove -> '$(MSBuildProjectDirectory)\$(OutputPath)%(Filename)%(Extension)')" Condition="Exists('$(MSBuildProjectDirectory)\$(OutputPath)%(Filename)%(Extension)')" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
|
@ -23,6 +23,7 @@ MSBUILD_TASK_ASSEMBLIES =
|
|||
ALL_SOURCES:= $(shell git ls-files | sed 's/ /\\ /g') $(wildcard $(XAMARIN_MACDEV_PATH)/Xamarin.MacDev/*.cs) $(wildcard $(XAMARIN_MACDEV_PATH)/Xamarin.MacDev/*.csproj)
|
||||
CONFIG = Debug
|
||||
TARGETFRAMEWORK = netstandard2.0
|
||||
WINDOWSRUNTIMEIDENTIFIER = win
|
||||
|
||||
##
|
||||
## XI definitions
|
||||
|
@ -38,8 +39,8 @@ IOS_TARGETS = \
|
|||
IOS_WINDOWS_TARGETS = \
|
||||
$(wildcard Xamarin.iOS.Tasks.Windows/Xamarin.*.props) \
|
||||
$(wildcard Xamarin.iOS.Tasks.Windows/Xamarin.*.targets) \
|
||||
$(wildcard Xamarin.iOS.Tasks.Windows/bin/$(CONFIG)/$(TARGETFRAMEWORK)/Xamarin.*.props) \
|
||||
$(wildcard Xamarin.iOS.Tasks.Windows/bin/$(CONFIG)/$(TARGETFRAMEWORK)/Xamarin.*.targets) \
|
||||
$(wildcard Xamarin.iOS.Tasks.Windows/bin/$(CONFIG)/$(TARGETFRAMEWORK)/$(WINDOWSRUNTIMEIDENTIFIER)/Xamarin.*.props) \
|
||||
$(wildcard Xamarin.iOS.Tasks.Windows/bin/$(CONFIG)/$(TARGETFRAMEWORK)/$(WINDOWSRUNTIMEIDENTIFIER)/Xamarin.*.targets) \
|
||||
|
||||
IOS_BINDING_TARGETS = $(wildcard Xamarin.ObjcBinding.Tasks/*.targets)
|
||||
|
||||
|
@ -48,6 +49,8 @@ TRANSLATED_ASSEMBLIES = $(foreach locale,$(LOCALIZATION_LANGUAGES),$(locale)/Xam
|
|||
LOCALIZATION_ASSEMBLIES = Xamarin.Localization.MSBuild
|
||||
IOS_TASK_ASSEMBLIES = Xamarin.iOS.Tasks $(LOCALIZATION_ASSEMBLIES)
|
||||
IOS_WINDOWS_TASK_ASSEMBLIES = Xamarin.iOS.Tasks.Windows
|
||||
IOS_WINDOWS_DEPENDENCIES = Xamarin.iOS.Windows.Client iSign.Core ws2_32 System.Diagnostics.Tracer BouncyCastle.Crypto System.Buffers System.Memory System.Numerics.Vectors System.Runtime.CompilerServices.Unsafe System.Security.Cryptography.ProtectedData System.Security.Cryptography.Pkcs Microsoft.Win32.Registry System.Security.AccessControl System.Security.Principal.Windows
|
||||
IOS_WINDOWS_MOBILEDEVICE_TOOLS = iMobileDevice-net bz2 getopt ideviceactivation idevicebackup idevicebackup2 idevicecrashreport idevicedate idevicedebug idevicedebugserverproxy idevicediagnostics ideviceenterrecovery ideviceimagemounter ideviceinfo ideviceinstaller idevicename idevicenotificationproxy idevicepair ideviceprovision idevicerestore idevicescreenshot idevicesyslog idevice_id imobiledevice-net-lighthouse imobiledevice ios_webkit_debug_proxy iproxy irecovery irecovery libcharset libcurl LIBEAY32 libiconv libusb-1.0 libusb0 libxml2 lzma pcre pcreposix plist plistutil plist_cmp plist_test pthreadVC3 readline SSLEAY32 usbmuxd usbmuxd vcruntime140 zip zlib1
|
||||
|
||||
IOS_DIRECTORIES = \
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.iOS \
|
||||
|
@ -473,12 +476,25 @@ MSBUILD_DIRECTORIES += $(DOTNET_DIRECTORIES)
|
|||
ifdef ENABLE_DOTNET
|
||||
MSBUILD_PRODUCTS += $(DOTNET_TARGETS)
|
||||
|
||||
DOTNET_IOS_WINDOWS_OUTPUT_FILES = $(foreach dll,$(IOS_WINDOWS_TASK_ASSEMBLIES),$(dll).dll $(dll).pdb) Broker.zip Build.zip
|
||||
DOTNET_IOS_WINDOWS_FILES = $(IOS_WINDOWS_TARGETS) $(foreach file,$(DOTNET_IOS_WINDOWS_OUTPUT_FILES),Xamarin.iOS.Tasks.Windows/bin/$(CONFIG)/$(TARGETFRAMEWORK)/$(file))
|
||||
DOTNET_IOS_WINDOWS_OUTPUT_FILES = \
|
||||
$(foreach dll,$(IOS_WINDOWS_TASK_ASSEMBLIES),$(dll).*) \
|
||||
$(foreach dll,$(IOS_WINDOWS_DEPENDENCIES),$(dll).*) \
|
||||
Broker.zip \
|
||||
Build.zip \
|
||||
Xamarin.PreBuilt.iOS.app.zip
|
||||
DOTNET_IOS_WINDOWS_FILES = $(IOS_WINDOWS_TARGETS) $(foreach file,$(DOTNET_IOS_WINDOWS_OUTPUT_FILES),Xamarin.iOS.Tasks.Windows/bin/$(CONFIG)/$(TARGETFRAMEWORK)/$(WINDOWSRUNTIMEIDENTIFIER)/$(file))
|
||||
DOTNET_IOS_WINDOWS_MOBILEDEVICE_TOOLS_X86 = $(foreach file,$(IOS_WINDOWS_MOBILEDEVICE_TOOLS),Xamarin.iOS.Tasks.Windows/bin/$(CONFIG)/$(TARGETFRAMEWORK)/$(WINDOWSRUNTIMEIDENTIFIER)/imobiledevice-x86/$(file).*)
|
||||
DOTNET_IOS_WINDOWS_MOBILEDEVICE_TOOLS_X64 = $(foreach file,$(IOS_WINDOWS_MOBILEDEVICE_TOOLS),Xamarin.iOS.Tasks.Windows/bin/$(CONFIG)/$(TARGETFRAMEWORK)/$(WINDOWSRUNTIMEIDENTIFIER)/imobiledevice-x64/$(file).*)
|
||||
|
||||
# Ensures Xamarin.iOS.Tasks.Windows is built and copies the output files to the Sdk Windows pack
|
||||
.dotnet-windows: .build-stamp | $(DOTNET_DESTDIR)/$(IOS_WINDOWS_NUGET).Sdk/tools/msbuild/iOS
|
||||
.copy-windows-files: .build-stamp
|
||||
$(Q) mkdir -p $(DOTNET_DESTDIR)/$(IOS_WINDOWS_NUGET).Sdk/tools/msbuild/iOS
|
||||
$(Q) $(CP) $(DOTNET_IOS_WINDOWS_FILES) $(DOTNET_DESTDIR)/$(IOS_WINDOWS_NUGET).Sdk/tools/msbuild/iOS/
|
||||
$(Q) mkdir -p $(DOTNET_DESTDIR)/$(IOS_WINDOWS_NUGET).Sdk/tools/msbuild/iOS/imobiledevice-x86
|
||||
$(Q) $(CP) $(DOTNET_IOS_WINDOWS_MOBILEDEVICE_TOOLS_X86) $(DOTNET_DESTDIR)/$(IOS_WINDOWS_NUGET).Sdk/tools/msbuild/iOS/imobiledevice-x86/
|
||||
$(Q) mkdir -p $(DOTNET_DESTDIR)/$(IOS_WINDOWS_NUGET).Sdk/tools/msbuild/iOS/imobiledevice-x64
|
||||
$(Q) $(CP) $(DOTNET_IOS_WINDOWS_MOBILEDEVICE_TOOLS_X64) $(DOTNET_DESTDIR)/$(IOS_WINDOWS_NUGET).Sdk/tools/msbuild/iOS/imobiledevice-x64/
|
||||
|
||||
.dotnet-windows: .build-stamp .copy-windows-files
|
||||
|
||||
all-local:: .dotnet-windows
|
||||
dotnet:: .dotnet-windows
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
{
|
||||
"images": [
|
||||
{
|
||||
"scale": "2x",
|
||||
"size": "20x20",
|
||||
"idiom": "iphone",
|
||||
"filename": "Icon40.png"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"size": "20x20",
|
||||
"idiom": "iphone",
|
||||
"filename": "Icon60.png"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"size": "29x29",
|
||||
"idiom": "iphone",
|
||||
"filename": "Icon58.png"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"size": "29x29",
|
||||
"idiom": "iphone",
|
||||
"filename": "Icon87.png"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"size": "40x40",
|
||||
"idiom": "iphone",
|
||||
"filename": "Icon80.png"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"size": "40x40",
|
||||
"idiom": "iphone",
|
||||
"filename": "Icon120.png"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"size": "60x60",
|
||||
"idiom": "iphone",
|
||||
"filename": "Icon120.png"
|
||||
},
|
||||
{
|
||||
"scale": "3x",
|
||||
"size": "60x60",
|
||||
"idiom": "iphone",
|
||||
"filename": "Icon180.png"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"size": "20x20",
|
||||
"idiom": "ipad",
|
||||
"filename": "Icon20.png"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"size": "20x20",
|
||||
"idiom": "ipad",
|
||||
"filename": "Icon40.png"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"size": "29x29",
|
||||
"idiom": "ipad",
|
||||
"filename": "Icon29.png"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"size": "29x29",
|
||||
"idiom": "ipad",
|
||||
"filename": "Icon58.png"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"size": "40x40",
|
||||
"idiom": "ipad",
|
||||
"filename": "Icon40.png"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"size": "40x40",
|
||||
"idiom": "ipad",
|
||||
"filename": "Icon80.png"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"size": "76x76",
|
||||
"idiom": "ipad",
|
||||
"filename": "Icon76.png"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"size": "76x76",
|
||||
"idiom": "ipad",
|
||||
"filename": "Icon152.png"
|
||||
},
|
||||
{
|
||||
"scale": "2x",
|
||||
"size": "83.5x83.5",
|
||||
"idiom": "ipad",
|
||||
"filename": "Icon167.png"
|
||||
},
|
||||
{
|
||||
"scale": "1x",
|
||||
"size": "1024x1024",
|
||||
"idiom": "ios-marketing",
|
||||
"filename": "Icon1024.png"
|
||||
}
|
||||
],
|
||||
"properties": {},
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "xcode"
|
||||
}
|
||||
}
|
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png
Normal file
После Ширина: | Высота: | Размер: 69 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png
Normal file
После Ширина: | Высота: | Размер: 3.7 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png
Normal file
После Ширина: | Высота: | Размер: 4.6 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png
Normal file
После Ширина: | Высота: | Размер: 4.6 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png
Normal file
После Ширина: | Высота: | Размер: 5.1 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png
Normal file
После Ширина: | Высота: | Размер: 1.3 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png
Normal file
После Ширина: | Высота: | Размер: 845 B |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png
Normal file
После Ширина: | Высота: | Размер: 1.1 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png
Normal file
После Ширина: | Высота: | Размер: 1.7 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png
Normal file
После Ширина: | Высота: | Размер: 2.5 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png
Normal file
После Ширина: | Высота: | Размер: 2.3 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png
Normal file
После Ширина: | Высота: | Размер: 2.4 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png
Normal file
После Ширина: | Высота: | Размер: 2.7 KiB |
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>10.0</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Xamarin.PreBuilt</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.xamarin.Xamarin-PreBuilt</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Xamarin.PreBuilt</string>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
||||
<key>UIStatusBarStyle</key>
|
||||
<string>UIStatusBarStyleLightContent</string>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,38 @@
|
|||
using Foundation;
|
||||
using ObjCRuntime;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UIKit;
|
||||
|
||||
namespace Xamarin.PreBuilt.iOS
|
||||
{
|
||||
public class Applications
|
||||
{
|
||||
static void Main(string[] args)
|
||||
=> Xamarin.iOS.HotRestart.Application.Run(args, (string frameworkPath) => Dlfcn.dlopen(frameworkPath, 0), () => TerminateApplication());
|
||||
|
||||
static void TerminateApplication()
|
||||
{
|
||||
Console.WriteLine("Closing the running application to re-launch...");
|
||||
|
||||
Console.WriteLine("Trying Exit Option 1...");
|
||||
Exit(0);
|
||||
Console.WriteLine("Option 1 failed. Trying Exit Option 2...");
|
||||
NSThread.Exit();
|
||||
Console.WriteLine("Option 2 failed. Trying Exit Option 3...");
|
||||
TerminateWithSuccess();
|
||||
Console.WriteLine("Option 3 failed. Trying Exit Option 4...");
|
||||
throw new Xamarin.iOS.HotRestart.KillApplicationException();
|
||||
}
|
||||
|
||||
[DllImport("__Internal", EntryPoint = "exit")]
|
||||
static extern void Exit(int status);
|
||||
|
||||
static void TerminateWithSuccess()
|
||||
{
|
||||
var selector = new Selector("terminateWithSuccess");
|
||||
|
||||
UIApplication.SharedApplication.PerformSelector(selector, UIApplication.SharedApplication, 0);
|
||||
}
|
||||
}
|
||||
}
|
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Resources/HotRestart-LaunchIcon-568h@2x.png
Normal file
После Ширина: | Высота: | Размер: 8.7 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Resources/HotRestart-LaunchIcon.png
Normal file
После Ширина: | Высота: | Размер: 7.1 KiB |
Двоичные данные
msbuild/Xamarin.HotRestart.PreBuilt/Xamarin.PreBuilt.iOS/Resources/HotRestart-LaunchIcon@2x.png
Normal file
После Ширина: | Высота: | Размер: 8.2 KiB |
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6245" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="X5k-f2-b5h">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6238"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="gAE-YM-kbH">
|
||||
<objects>
|
||||
<viewController id="X5k-f2-b5h" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Y8P-hJ-Z43"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="9ZL-r4-8FZ"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="yd7-JS-zBw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="center" misplaced="YES" image="HotRestart-LaunchIcon.png" translatesAutoresizingMaskIntoConstraints="NO" id="23">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||
<rect key="contentStretch" x="0.0" y="0.0" width="0.0" height="0.0"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.20392156862745098" green="0.59607843137254901" blue="0.85882352941176465" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="23" firstAttribute="centerY" secondItem="yd7-JS-zBw" secondAttribute="centerY" priority="1" id="39"/>
|
||||
<constraint firstItem="23" firstAttribute="centerX" secondItem="yd7-JS-zBw" secondAttribute="centerX" priority="1" id="41"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="XAI-xm-WK6" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="349" y="339"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,32 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-ios</TargetFramework>
|
||||
<RuntimeIdentifier>ios-arm64</RuntimeIdentifier>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ProvisioningType>automatic</ProvisioningType>
|
||||
<DebugType>portable</DebugType>
|
||||
<_LinkMode>None</_LinkMode>
|
||||
<UseInterpreter>true</UseInterpreter>
|
||||
<MtouchExtraArgs>--registrar:dynamic</MtouchExtraArgs>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.iOS.HotRestart.Application" Version="1.1.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="Resources\HotRestart-LaunchIcon-568h%402x.png" />
|
||||
<BundleResource Include="Resources\HotRestart-LaunchIcon.png" />
|
||||
<BundleResource Include="Resources\HotRestart-LaunchIcon%402x.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- For debug only, copies files from a AdditionalFiles directory into the bundle (i.e. an app to be interpreted) -->
|
||||
<!-- <Target Name="ResolveAdditionalReferences">
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="AdditionalReferences\**\*.*" Exclude="AdditionalReferences\Xamarin.Forms.Core.dll" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<Target Name="CopyAdditionalReferences" DependsOnTargets="ResolveAdditionalReferences" AfterTargets="_CalculateCodesignAppBundleInputs" Inputs="@(AdditionalFiles)" Outputs="@(AdditionalFiles -> '$(_AppBundlePath)$(_AppBundleName).content\%(RecursiveDir)%(Filename)%(Extension)')">
|
||||
<Copy SourceFiles="@(AdditionalFiles)" DestinationFiles="@(AdditionalFiles -> '$(_AppBundlePath)$(_AppBundleName).content\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
</Target> -->
|
||||
</Project>
|
|
@ -0,0 +1,81 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29411.138
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.PreBuilt.iOS", "Xamarin.PreBuilt.iOS\Xamarin.PreBuilt.iOS.csproj", "{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
|
||||
Ad-Hoc|iPhone = Ad-Hoc|iPhone
|
||||
Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
|
||||
AppStore|Any CPU = AppStore|Any CPU
|
||||
AppStore|iPhone = AppStore|iPhone
|
||||
AppStore|iPhoneSimulator = AppStore|iPhoneSimulator
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|iPhone = Debug|iPhone
|
||||
Debug|iPhoneSimulator = Debug|iPhoneSimulator
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|iPhone = Release|iPhone
|
||||
Release|iPhoneSimulator = Release|iPhoneSimulator
|
||||
UI Test|Any CPU = UI Test|Any CPU
|
||||
UI Test|iPhone = UI Test|iPhone
|
||||
UI Test|iPhoneSimulator = UI Test|iPhoneSimulator
|
||||
UITEST|Any CPU = UITEST|Any CPU
|
||||
UI-Test|Any CPU = UI-Test|Any CPU
|
||||
UITEST|iPhone = UITEST|iPhone
|
||||
UI-Test|iPhone = UI-Test|iPhone
|
||||
UITEST|iPhoneSimulator = UITEST|iPhoneSimulator
|
||||
UI-Test|iPhoneSimulator = UI-Test|iPhoneSimulator
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Ad-Hoc|Any CPU.ActiveCfg = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Ad-Hoc|Any CPU.Build.0 = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Ad-Hoc|iPhone.ActiveCfg = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Ad-Hoc|iPhone.Build.0 = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.AppStore|Any CPU.ActiveCfg = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.AppStore|Any CPU.Build.0 = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.AppStore|iPhone.ActiveCfg = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.AppStore|iPhone.Build.0 = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.AppStore|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.AppStore|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Debug|iPhone.ActiveCfg = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Debug|iPhone.Build.0 = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Release|iPhone.ActiveCfg = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Release|iPhone.Build.0 = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI Test|Any CPU.ActiveCfg = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI Test|Any CPU.Build.0 = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI Test|iPhone.ActiveCfg = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI Test|iPhone.Build.0 = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI Test|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI Test|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UITEST|Any CPU.ActiveCfg = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UITEST|Any CPU.Build.0 = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI-Test|Any CPU.ActiveCfg = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI-Test|Any CPU.Build.0 = Release|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UITEST|iPhone.ActiveCfg = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UITEST|iPhone.Build.0 = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI-Test|iPhone.ActiveCfg = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI-Test|iPhone.Build.0 = Debug|iPhone
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UITEST|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UITEST|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI-Test|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
|
||||
{CA6E0AA8-7FF0-45DA-BFC9-DBC2B4FB55C0}.UI-Test|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {4F35FA41-BF70-4770-ADFD-D7F760F511B1}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -64,5 +64,35 @@ namespace Xamarin.iOS.Tasks.Windows.Properties {
|
|||
return ResourceManager.GetString("LocalUnzip_Unzipping", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CollectDynamicFrameworks_InvalidFramework {
|
||||
get {
|
||||
return ResourceManager.GetString("CollectDynamicFrameworks_InvalidFramework", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string LocalCodesign_MissingPasswordFile {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalCodesign_MissingPasswordFile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string LocalCodesign_MissingTerminal {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalCodesign_MissingTerminal", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string LocalCodesign_ToolArguments {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalCodesign_ToolArguments", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CompileAppManifest_MissinInfoPList {
|
||||
get {
|
||||
return ResourceManager.GetString("CompileAppManifest_MissinInfoPList", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,4 +21,23 @@
|
|||
<data name="LocalUnzip_Unzipping" xml:space="preserve">
|
||||
<value>Unzipping {0}...</value>
|
||||
</data>
|
||||
<data name="CollectDynamicFrameworks_InvalidFramework" xml:space="preserve">
|
||||
<value>Skipping invalid framework {0}. Reason: {1}</value>
|
||||
<comment>0: framework name; 1: why the framework was skipped</comment>
|
||||
</data>
|
||||
<data name="LocalCodesign_MissingPasswordFile" xml:space="preserve">
|
||||
<value>Could not find the password for the selected Signing Identity, please create a new Certificate from Tools -> Options -> Apple Accounts -> View Team Details.</value>
|
||||
</data>
|
||||
<data name="LocalCodesign_MissingTerminal" xml:space="preserve">
|
||||
<value>Could not find the winiostermial executable {0}</value>
|
||||
<comment>0: path to the terminal</comment>
|
||||
</data>
|
||||
<data name="LocalCodesign_ToolArguments" xml:space="preserve">
|
||||
<value>Started signing tool with arguments: {0}</value>
|
||||
<comment>0: arguments</comment>
|
||||
</data>
|
||||
<data name="CompileAppManifest_MissinInfoPList" xml:space="preserve">
|
||||
<value>Info.plist file does not exist under {0}, please rebuild your project</value>
|
||||
<comment>0: path</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using Xamarin.iOS.Tasks.Windows.Properties;
|
||||
using Xamarin.iOS.Windows;
|
||||
|
||||
namespace Xamarin.iOS.HotRestart.Tasks {
|
||||
public class Codesign : Task, ICancelableTask {
|
||||
CancellationTokenSource cancellationSource;
|
||||
|
||||
#region Inputs
|
||||
|
||||
[Required]
|
||||
public string AppBundlePath { get; set; }
|
||||
|
||||
[Required]
|
||||
public string BundleIdentifier { get; set; }
|
||||
|
||||
[Required]
|
||||
public string CodeSigningPath { get; set; }
|
||||
|
||||
[Required]
|
||||
public string ProvisioningProfilePath { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public override bool Execute ()
|
||||
{
|
||||
try {
|
||||
var hotRestartClient = new HotRestartClient ();
|
||||
var plistArgs = new Dictionary<string, string>
|
||||
{
|
||||
{ "CFBundleIdentifier", BundleIdentifier }
|
||||
};
|
||||
var password = hotRestartClient.CertificatesManager.GetCertificatePassword (certificatePath: CodeSigningPath);
|
||||
|
||||
if (password == null) {
|
||||
throw new Exception (Resources.LocalCodesign_MissingPasswordFile);
|
||||
}
|
||||
|
||||
hotRestartClient.Sign (AppBundlePath, ProvisioningProfilePath, CodeSigningPath, password, plistArgs);
|
||||
} catch (WindowsiOSException ex) {
|
||||
var message = GetFullExceptionMesage (ex);
|
||||
|
||||
Log.LogError (null, ex.ErrorCode, null, null, 0, 0, 0, 0, message);
|
||||
} catch (Exception ex) {
|
||||
Log.LogErrorFromException (ex);
|
||||
}
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
public void Cancel () => cancellationSource?.Cancel ();
|
||||
|
||||
string GetFullExceptionMesage (Exception ex)
|
||||
{
|
||||
var messageBuilder = new StringBuilder ();
|
||||
|
||||
return GetFullExceptionMesage (ex, messageBuilder);
|
||||
}
|
||||
|
||||
string GetFullExceptionMesage (Exception ex, StringBuilder messageBuilder)
|
||||
{
|
||||
messageBuilder.AppendLine (ex.Message);
|
||||
|
||||
if (ex.InnerException != null) {
|
||||
return GetFullExceptionMesage (ex.InnerException, messageBuilder);
|
||||
} else {
|
||||
return messageBuilder.ToString ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Xamarin.iOS.Tasks.Windows.Properties;
|
||||
using Xamarin.iOS.Windows;
|
||||
|
||||
namespace Xamarin.iOS.HotRestart.Tasks {
|
||||
public class CollectDynamicFrameworks : Task {
|
||||
#region Inputs
|
||||
|
||||
[Required]
|
||||
public ITaskItem [] Frameworks { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Outputs
|
||||
|
||||
[Output]
|
||||
public ITaskItem [] DynamicFrameworks { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public override bool Execute ()
|
||||
{
|
||||
var frameworks = new List<ITaskItem> ();
|
||||
var hotRestartClient = new HotRestartClient ();
|
||||
|
||||
foreach (var framework in Frameworks.Where (f => Path.GetExtension (f.ItemSpec.TrimEnd ('\\')) == ".framework")) {
|
||||
framework.ItemSpec = framework.ItemSpec.TrimEnd ('\\');
|
||||
|
||||
if (frameworks.Any (x => x.ItemSpec == framework.ItemSpec)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var frameworkDirName = Path.GetFileName (framework.ItemSpec);
|
||||
|
||||
try {
|
||||
var frameworkPath = Path.Combine (framework.ItemSpec, Path.GetFileNameWithoutExtension (frameworkDirName));
|
||||
|
||||
hotRestartClient.LoadDynamicFramework (frameworkPath);
|
||||
} catch (AppleInvalidFrameworkException frameworkEx) {
|
||||
Log.LogMessage (MessageImportance.Normal, Resources.CollectDynamicFrameworks_InvalidFramework, Path.GetFileName (framework.ItemSpec), frameworkEx.Message);
|
||||
continue;
|
||||
} catch (Exception ex) {
|
||||
Log.LogErrorFromException (ex);
|
||||
break;
|
||||
}
|
||||
|
||||
framework.SetMetadata ("FrameworkDir", $@"{frameworkDirName}\");
|
||||
|
||||
frameworks.Add (framework);
|
||||
}
|
||||
|
||||
DynamicFrameworks = frameworks.ToArray ();
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Xamarin.iOS.Tasks.Windows.Properties;
|
||||
using Xamarin.MacDev;
|
||||
|
||||
namespace Xamarin.iOS.HotRestart.Tasks
|
||||
{
|
||||
public class CompileAppManifest : Task
|
||||
{
|
||||
static readonly string[] IgnorePlistKeys = {
|
||||
"XSAppIconAssets",
|
||||
"CFBundleIconName",
|
||||
"XSLaunchImageAssets",
|
||||
"UIMainStoryboardFile",
|
||||
"UIFileSharingEnabled",
|
||||
"UILaunchStoryboardName",
|
||||
"UIMainStoryboardFile~ipad",
|
||||
"UIMainStoryboardFile~iphone",
|
||||
"CFBundleIdentifier",
|
||||
"CFBundleExecutable"
|
||||
};
|
||||
|
||||
#region Inputs
|
||||
|
||||
[Required]
|
||||
public string AppBundlePath { get; set; }
|
||||
|
||||
[Required]
|
||||
public string AppManifestPath { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
try
|
||||
{
|
||||
var preBuiltInfoPlistPath = Path.Combine(AppBundlePath, "Info.plist");
|
||||
|
||||
if (!File.Exists(preBuiltInfoPlistPath))
|
||||
{
|
||||
throw new Exception(string.Format(Resources.CompileAppManifest_MissinInfoPList, preBuiltInfoPlistPath));
|
||||
}
|
||||
|
||||
var infoPlist = PDictionary.FromFile(AppManifestPath);
|
||||
var preBuiltInfoPlist = PDictionary.FromFile(preBuiltInfoPlistPath);
|
||||
|
||||
foreach (var item in infoPlist)
|
||||
{
|
||||
if (!IgnorePlistKeys.Contains(item.Key))
|
||||
{
|
||||
if (preBuiltInfoPlist.ContainsKey(item.Key))
|
||||
{
|
||||
preBuiltInfoPlist.Remove(item.Key);
|
||||
}
|
||||
|
||||
preBuiltInfoPlist.Add(item.Key, item.Value.Clone());
|
||||
}
|
||||
}
|
||||
|
||||
preBuiltInfoPlist.Save(preBuiltInfoPlistPath, binary: true);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.LogErrorFromException(ex);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,542 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using Xamarin.iOS.Windows;
|
||||
using Xamarin.MacDev;
|
||||
|
||||
namespace Xamarin.iOS.HotRestart.Tasks {
|
||||
public class DetectSigningIdentity : Task {
|
||||
static readonly string ProvisioningPath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData), "Xamarin", "iOS", "Provisioning");
|
||||
static readonly string ProfilesPath = Path.Combine (ProvisioningPath, "Profiles");
|
||||
static readonly string CertificatesPath = Path.Combine (ProvisioningPath, "Certificates");
|
||||
|
||||
const string AutomaticProvision = "Automatic";
|
||||
const string AutomaticAdHocProvision = "Automatic:AdHoc";
|
||||
const string AutomaticAppStoreProvision = "Automatic:AppStore";
|
||||
const string AutomaticInHouseProvision = "Automatic:InHouse";
|
||||
|
||||
protected string PlatformName => "iOS";
|
||||
protected string ApplicationIdentifierKey => "application-identifier";
|
||||
protected string [] DevelopmentPrefixes => IPhoneCertificate.DevelopmentPrefixes;
|
||||
protected string [] AppStoreDistributionPrefixes => IPhoneCertificate.DistributionPrefixes;
|
||||
|
||||
string provisioningProfileName;
|
||||
string codesignCommonName;
|
||||
IHotRestartClient hotRestartClient;
|
||||
|
||||
#region Inputs
|
||||
|
||||
// Single-project property that determines whether other single-project properties should have any effect
|
||||
public bool GenerateApplicationManifest { get; set; }
|
||||
|
||||
// Single-project property that maps to CFBundleIdentifier
|
||||
public string ApplicationId { get; set; }
|
||||
|
||||
// Single-project property that maps to CFBundleDisplayName
|
||||
public string ApplicationTitle { get; set; }
|
||||
|
||||
[Required]
|
||||
public string AppManifest { get; set; }
|
||||
|
||||
public string SigningKey { get; set; }
|
||||
|
||||
public string ProvisioningProfile { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Outputs
|
||||
|
||||
[Output]
|
||||
public string DetectedCodeSigningPath { get; set; }
|
||||
|
||||
[Output]
|
||||
public string DetectedProvisioningProfilePath { get; set; }
|
||||
|
||||
[Output]
|
||||
public string DetectedProvisioningProfileId { get; set; }
|
||||
|
||||
[Output]
|
||||
public string DetectedAppId { get; set; }
|
||||
|
||||
[Output]
|
||||
public string DetectedBundleId { get; set; }
|
||||
|
||||
[Output]
|
||||
public string DetectedAppDisplayName { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public override bool Execute ()
|
||||
{
|
||||
PDictionary plist;
|
||||
IList<MobileProvision> profiles;
|
||||
IList<X509Certificate2> certs;
|
||||
List<CodeSignIdentity> pairs;
|
||||
|
||||
var type = GetProvisioningDistributionType ();
|
||||
var platform = MobileProvisionPlatform.iOS;
|
||||
var identity = new CodeSignIdentity ();
|
||||
|
||||
hotRestartClient = new HotRestartClient ();
|
||||
|
||||
try {
|
||||
plist = PDictionary.FromFile (AppManifest);
|
||||
} catch (Exception ex) {
|
||||
Log.LogError (null, null, null, AppManifest, 0, 0, 0, 0, "Error loading '{0}': {1}", AppManifest, ex.Message);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
identity.BundleId = plist.GetCFBundleIdentifier ();
|
||||
|
||||
if (string.IsNullOrEmpty (identity.BundleId)) {
|
||||
if (GenerateApplicationManifest && !string.IsNullOrEmpty (ApplicationId)) {
|
||||
identity.BundleId = ApplicationId;
|
||||
} else {
|
||||
Log.LogError (null, null, null, AppManifest, 0, 0, 0, 0, "{0} does not define CFBundleIdentifier", AppManifest);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
DetectedBundleId = identity.BundleId;
|
||||
|
||||
var appDisplayName = plist.GetCFBundleDisplayName ();
|
||||
|
||||
if (string.IsNullOrEmpty (appDisplayName)) {
|
||||
if (GenerateApplicationManifest && !string.IsNullOrEmpty (ApplicationTitle)) {
|
||||
appDisplayName = ApplicationTitle;
|
||||
}
|
||||
}
|
||||
|
||||
DetectedAppDisplayName = appDisplayName;
|
||||
|
||||
if (!TryGetSigningCertificates (out certs, false))
|
||||
return false;
|
||||
|
||||
Log.LogMessage (MessageImportance.Low, "Available certificates:");
|
||||
|
||||
foreach (var cert in certs)
|
||||
Log.LogMessage (MessageImportance.Low, " {0}", GetCertificateCommonName (cert));
|
||||
|
||||
if (!IsAutoCodeSignProfile (ProvisioningProfile)) {
|
||||
identity.Profile = MobileProvisionIndex.GetMobileProvision (platform, ProvisioningProfile);
|
||||
|
||||
if (identity.Profile == null) {
|
||||
Log.LogError ("The specified " + PlatformName + " provisioning profile '{0}' could not be found. Please enable Automatic Provisioning from the iOS Bundle Signing page.", ProvisioningProfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
var profile = identity.Profile; // capture ref for lambda
|
||||
|
||||
if (certs.Count > 0) {
|
||||
identity.SigningKey = certs.FirstOrDefault (c => profile.DeveloperCertificates.Any (p => p.Thumbprint == c.Thumbprint));
|
||||
if (identity.SigningKey == null) {
|
||||
Log.LogError ("No " + PlatformName + " signing identities match the specified provisioning profile '{0}'.", ProvisioningProfile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
identity.AppId = ConstructValidAppId (identity.Profile, identity.BundleId);
|
||||
|
||||
if (identity.AppId == null) {
|
||||
Log.LogError (null, null, null, AppManifest, 0, 0, 0, 0, "Project bundle identifier '{0}' does not match specified provisioning profile '{1}'. Please enable Automatic Provisioning from the iOS Bundle Signing page.", identity.BundleId, ProvisioningProfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (identity.SigningKey != null) {
|
||||
codesignCommonName = GetCertificateCommonName (identity.SigningKey);
|
||||
DetectedCodeSigningPath = Path.Combine (CertificatesPath, $"{identity.SigningKey.SerialNumber}.p12");
|
||||
}
|
||||
|
||||
provisioningProfileName = identity.Profile.Name;
|
||||
|
||||
DetectedAppId = identity.AppId;
|
||||
DetectedProvisioningProfileId = identity.Profile.Uuid;
|
||||
DetectedProvisioningProfilePath = Path.Combine (ProfilesPath, $"{DetectedProvisioningProfileId}.mobileprovision");
|
||||
|
||||
ReportDetectedCodesignInfo ();
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
if ((profiles = GetProvisioningProfiles (platform, type, identity, certs)) == null)
|
||||
return false;
|
||||
|
||||
if ((pairs = GetCodeSignIdentityPairs (profiles, certs)) == null)
|
||||
return false;
|
||||
|
||||
identity = GetBestMatch (pairs, identity);
|
||||
|
||||
if (identity.Profile != null && identity.AppId != null) {
|
||||
codesignCommonName = identity.SigningKey != null ? GetCertificateCommonName (identity.SigningKey) : null;
|
||||
provisioningProfileName = identity.Profile.Name;
|
||||
|
||||
DetectedAppId = identity.AppId;
|
||||
DetectedCodeSigningPath = identity.SigningKey != null ? Path.Combine (CertificatesPath, $"{identity.SigningKey.SerialNumber}.p12") : string.Empty;
|
||||
DetectedProvisioningProfileId = identity.Profile.Uuid;
|
||||
DetectedProvisioningProfilePath = Path.Combine (ProfilesPath, $"{DetectedProvisioningProfileId}.mobileprovision");
|
||||
|
||||
ReportDetectedCodesignInfo ();
|
||||
} else {
|
||||
if (identity.SigningKey != null) {
|
||||
Log.LogError ("Bundle identifier '{0}' does not match any installed provisioning profile for selected signing identity '{0}'. Please enable Automatic Provisioning from the iOS Bundle Signing page.", identity.BundleId, identity.SigningKey);
|
||||
} else {
|
||||
Log.LogError ("Bundle identifier '{0}' does not match any installed provisioning profile. Please enable Automatic Provisioning from the iOS Bundle Signing page.", identity.BundleId);
|
||||
}
|
||||
}
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
static bool IsAutoCodeSignProfile (string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty (value))
|
||||
return true;
|
||||
|
||||
switch (value) {
|
||||
case AutomaticAppStoreProvision:
|
||||
case AutomaticAdHocProvision:
|
||||
case AutomaticInHouseProvision:
|
||||
case AutomaticProvision:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string ConstructValidAppId (MobileProvision provision, string bundleId)
|
||||
{
|
||||
int matchLength;
|
||||
|
||||
return ConstructValidAppId (provision, bundleId, out matchLength);
|
||||
}
|
||||
|
||||
string ConstructValidAppId (MobileProvision provision, string bundleId, out int matchLength)
|
||||
{
|
||||
if (!provision.Entitlements.ContainsKey (ApplicationIdentifierKey)) {
|
||||
matchLength = 0;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return ConstructValidAppId (
|
||||
provision.ApplicationIdentifierPrefix [0] + "." + bundleId,
|
||||
((PString) provision.Entitlements [ApplicationIdentifierKey]).Value,
|
||||
out matchLength
|
||||
);
|
||||
}
|
||||
|
||||
static string ConstructValidAppId (string appid, string allowed, out int matchLength)
|
||||
{
|
||||
// The user can't have a wildcard ID as their actual app id
|
||||
if (appid.Contains ("*")) {
|
||||
matchLength = 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Next check if we have an exact match
|
||||
if (allowed == appid) {
|
||||
matchLength = allowed.Length;
|
||||
return appid;
|
||||
}
|
||||
|
||||
// Finally if the profile is a wildcard, ensure that the appid matches it for everything before the '*'
|
||||
int star = allowed.IndexOf ('*');
|
||||
|
||||
if (star != -1 && star + 1 == allowed.Length && appid.Length >= star && appid.StartsWith (allowed.Substring (0, star), StringComparison.Ordinal)) {
|
||||
matchLength = star;
|
||||
return appid;
|
||||
}
|
||||
|
||||
// It does not match
|
||||
matchLength = 0;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void ReportDetectedCodesignInfo ()
|
||||
{
|
||||
Log.LogMessage (MessageImportance.High, "Detected signing identity:");
|
||||
|
||||
if (codesignCommonName != null)
|
||||
Log.LogMessage (MessageImportance.High, " Code Signing Key: \"{0}\" ({1})", codesignCommonName, DetectedCodeSigningPath);
|
||||
if (provisioningProfileName != null)
|
||||
Log.LogMessage (MessageImportance.High, " Provisioning Profile: \"{0}\" ({1})", provisioningProfileName, DetectedProvisioningProfilePath);
|
||||
}
|
||||
|
||||
static bool MatchesAny (string name, string [] names)
|
||||
{
|
||||
for (int i = 0; i < names.Length; i++) {
|
||||
if (name == names [i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool StartsWithAny (string name, string [] prefixes)
|
||||
{
|
||||
foreach (var prefix in prefixes) {
|
||||
if (name.StartsWith (prefix, StringComparison.Ordinal))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TryGetSigningCertificates (out IList<X509Certificate2> certs, string [] prefixes, bool allowZeroCerts)
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
|
||||
certs = new List<X509Certificate2> ();
|
||||
|
||||
foreach (var certificate in GetAllCertificates ()) {
|
||||
var cname = GetCertificateCommonName (certificate);
|
||||
|
||||
if (!StartsWithAny (cname, prefixes)) {
|
||||
Log.LogMessage (MessageImportance.Low, "The certificate '{0}' does not match any of the prefixes '{1}'.", cname, string.Join ("', '", prefixes));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (now >= certificate.NotAfter) {
|
||||
Log.LogMessage (MessageImportance.Low, "The certificate '{0}' has expired ({1})", cname, certificate.NotAfter);
|
||||
continue;
|
||||
}
|
||||
|
||||
certs.Add (certificate);
|
||||
}
|
||||
|
||||
if (certs.Count == 0 && !allowZeroCerts) {
|
||||
var message = "No valid " + PlatformName + " code signing keys found in keychain. Please enable Automatic Provisioning from the iOS Bundle Signing page.";
|
||||
|
||||
Log.LogError (message);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryGetSigningCertificates (out IList<X509Certificate2> certs, string name)
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
|
||||
certs = new List<X509Certificate2> ();
|
||||
|
||||
foreach (var certificate in GetAllCertificates ()) {
|
||||
var cname = GetCertificateCommonName (certificate);
|
||||
|
||||
if (!name.Equals (certificate.Thumbprint, StringComparison.OrdinalIgnoreCase) && name != cname) {
|
||||
Log.LogMessage (MessageImportance.Low, "The certificate '{0}' does not match '{1}'.", cname, name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (now >= certificate.NotAfter) {
|
||||
Log.LogMessage (MessageImportance.Low, "The certificate '{0}' has expired ({1})", cname, certificate.NotAfter);
|
||||
continue;
|
||||
}
|
||||
|
||||
certs.Add (certificate);
|
||||
}
|
||||
|
||||
if (certs.Count == 0) {
|
||||
Log.LogError (PlatformName + " code signing key '{0}' not found in keychain.", SigningKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryGetSigningCertificates (out IList<X509Certificate2> certs, bool allowZeroCerts)
|
||||
{
|
||||
try {
|
||||
if (string.IsNullOrEmpty (SigningKey) || MatchesAny (SigningKey, DevelopmentPrefixes)) {
|
||||
// Note: we treat an empty signing key as "developer automatic".
|
||||
if (!TryGetSigningCertificates (out certs, DevelopmentPrefixes, allowZeroCerts))
|
||||
return false;
|
||||
} else if (MatchesAny (SigningKey, AppStoreDistributionPrefixes)) {
|
||||
if (!TryGetSigningCertificates (out certs, AppStoreDistributionPrefixes, false))
|
||||
return false;
|
||||
} else {
|
||||
// The user has specified an exact name to match...
|
||||
if (!TryGetSigningCertificates (out certs, SigningKey))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
Log.LogError ("{0}", ex.Message);
|
||||
certs = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
IList<MobileProvision> GetProvisioningProfiles (MobileProvisionPlatform platform, MobileProvisionDistributionType type, CodeSignIdentity identity, IList<X509Certificate2> certs)
|
||||
{
|
||||
var failures = new List<string> ();
|
||||
IList<MobileProvision> profiles;
|
||||
|
||||
if (identity.BundleId != null) {
|
||||
if (certs.Count > 0)
|
||||
profiles = MobileProvisionIndex.GetMobileProvisions (platform, identity.BundleId, type, certs, unique: true, failures: failures);
|
||||
else
|
||||
profiles = MobileProvisionIndex.GetMobileProvisions (platform, identity.BundleId, type, unique: true, failures: failures);
|
||||
} else if (certs.Count > 0) {
|
||||
profiles = MobileProvisionIndex.GetMobileProvisions (platform, type, certs, unique: true, failures: failures);
|
||||
} else {
|
||||
profiles = MobileProvisionIndex.GetMobileProvisions (platform, type, unique: true, failures: failures);
|
||||
}
|
||||
|
||||
if (profiles.Count == 0) {
|
||||
foreach (var f in failures)
|
||||
Log.LogMessage (MessageImportance.Low, "{0}", f);
|
||||
|
||||
Log.LogError ($"Could not find any available provisioning profiles for {PlatformName}. Please enable Automatic Provisioning from the iOS Bundle Signing page.");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.LogMessage (MessageImportance.Low, "Available profiles:");
|
||||
|
||||
foreach (var p in profiles)
|
||||
Log.LogMessage (MessageImportance.Low, " {0}", p.Name);
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
List<CodeSignIdentity> GetCodeSignIdentityPairs (IList<MobileProvision> profiles, IList<X509Certificate2> certs)
|
||||
{
|
||||
List<CodeSignIdentity> pairs;
|
||||
|
||||
if (certs.Count > 0) {
|
||||
pairs = (from p in profiles
|
||||
from c in certs
|
||||
where p.DeveloperCertificates.Any (d => {
|
||||
var rv = d.Thumbprint == c.Thumbprint;
|
||||
if (!rv)
|
||||
Log.LogMessage (MessageImportance.Low, "'{0}' doesn't match '{1}'.", d.Thumbprint, c.Thumbprint);
|
||||
return rv;
|
||||
})
|
||||
select new CodeSignIdentity { SigningKey = c, Profile = p }).ToList ();
|
||||
|
||||
if (pairs.Count == 0) {
|
||||
Log.LogError ("No installed provisioning profiles match the installed " + PlatformName + " signing identities. Please enable Automatic Provisioning from the iOS Bundle Signing page.");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
pairs = (from p in profiles select new CodeSignIdentity { Profile = p }).ToList ();
|
||||
}
|
||||
|
||||
return pairs;
|
||||
}
|
||||
|
||||
CodeSignIdentity GetBestMatch (List<CodeSignIdentity> pairs, CodeSignIdentity identity)
|
||||
{
|
||||
var matches = new List<CodeSignIdentity> ();
|
||||
int bestMatchLength = 0;
|
||||
int matchLength;
|
||||
|
||||
// find matching provisioning profiles with compatible appid, keeping only those with the longest matching (wildcard) ids
|
||||
Log.LogMessage (MessageImportance.Low, "Finding matching provisioning profiles with compatible AppID, keeping only those with the longest matching (wildcard) IDs.");
|
||||
|
||||
foreach (var pair in pairs) {
|
||||
var appid = ConstructValidAppId (pair.Profile, identity.BundleId, out matchLength);
|
||||
|
||||
if (appid != null) {
|
||||
if (matchLength >= bestMatchLength) {
|
||||
if (matchLength > bestMatchLength) {
|
||||
bestMatchLength = matchLength;
|
||||
foreach (var previousMatch in matches)
|
||||
Log.LogMessage (MessageImportance.Low, "AppID: {0} was ruled out because we found a better match: {1}.", previousMatch.AppId, appid);
|
||||
matches.Clear ();
|
||||
}
|
||||
|
||||
var match = identity.Clone ();
|
||||
|
||||
match.SigningKey = pair.SigningKey;
|
||||
match.Profile = pair.Profile;
|
||||
match.AppId = appid;
|
||||
|
||||
matches.Add (match);
|
||||
} else {
|
||||
string currentMatches = "";
|
||||
|
||||
foreach (var match in matches)
|
||||
currentMatches += $"{match}; ";
|
||||
|
||||
Log.LogMessage (MessageImportance.Low, "AppID: {0} was ruled out because we already found better matches: {1}.", appid, currentMatches);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matches.Count == 0) {
|
||||
Log.LogWarning (null, null, null, AppManifest, 0, 0, 0, 0, "No installed provisioning profiles match the bundle identifier.");
|
||||
|
||||
return identity;
|
||||
}
|
||||
|
||||
if (matches.Count > 1) {
|
||||
var spaces = new string (' ', 3);
|
||||
|
||||
Log.LogMessage (MessageImportance.Normal, "Multiple provisioning profiles match the bundle identifier; using the first match.");
|
||||
|
||||
matches.Sort (new SigningIdentityComparer ());
|
||||
|
||||
for (int i = 0; i < matches.Count; i++) {
|
||||
Log.LogMessage (MessageImportance.Normal, "{0,3}. Provisioning Profile: \"{1}\" ({2})", i + 1, matches [i].Profile.Name, matches [i].Profile.Uuid);
|
||||
|
||||
if (matches [i].SigningKey != null)
|
||||
Log.LogMessage (MessageImportance.Normal, "{0} Signing Identity: \"{1}\"", spaces, GetCertificateCommonName (matches [i].SigningKey));
|
||||
}
|
||||
}
|
||||
|
||||
return matches [0];
|
||||
}
|
||||
|
||||
MobileProvisionDistributionType GetProvisioningDistributionType ()
|
||||
{
|
||||
if (ProvisioningProfile == AutomaticAppStoreProvision)
|
||||
return MobileProvisionDistributionType.AppStore;
|
||||
else if (ProvisioningProfile == AutomaticInHouseProvision)
|
||||
return MobileProvisionDistributionType.InHouse;
|
||||
else if (ProvisioningProfile == AutomaticAdHocProvision)
|
||||
return MobileProvisionDistributionType.AdHoc;
|
||||
|
||||
return MobileProvisionDistributionType.Any;
|
||||
}
|
||||
|
||||
IEnumerable<X509Certificate2> GetAllCertificates () => hotRestartClient.CertificatesManager.GetInstalledCertificates ();
|
||||
|
||||
string GetCertificateCommonName (X509Certificate2 certificate) => hotRestartClient.CertificatesManager.GetCertificateCommonName (certificate.SerialNumber);
|
||||
|
||||
class CodeSignIdentity {
|
||||
public X509Certificate2 SigningKey { get; set; }
|
||||
public MobileProvision Profile { get; set; }
|
||||
public string BundleId { get; set; }
|
||||
public string AppId { get; set; }
|
||||
|
||||
public CodeSignIdentity Clone ()
|
||||
{
|
||||
return new CodeSignIdentity {
|
||||
SigningKey = SigningKey,
|
||||
Profile = Profile,
|
||||
BundleId = BundleId,
|
||||
AppId = AppId
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class SigningIdentityComparer : IComparer<CodeSignIdentity> {
|
||||
public int Compare (CodeSignIdentity x, CodeSignIdentity y)
|
||||
{
|
||||
// reverse sort by provisioning profile creation date
|
||||
return y.Profile.CreationDate.CompareTo (x.Profile.CreationDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using Xamarin.iOS.Windows;
|
||||
|
||||
namespace Xamarin.iOS.HotRestart.Tasks {
|
||||
public class PrepareAppBundle : Task {
|
||||
#region Inputs
|
||||
|
||||
[Required]
|
||||
public string AppBundleName { get; set; }
|
||||
|
||||
[Required]
|
||||
public string SessionId { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool ShouldExtract { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Outputs
|
||||
|
||||
[Output]
|
||||
public string AppBundlePath { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public override bool Execute ()
|
||||
{
|
||||
AppBundlePath = HotRestartContext.Default.GetAppBundlePath (AppBundleName, SessionId.Substring (0, 8));
|
||||
|
||||
if (!Directory.Exists (AppBundlePath) && ShouldExtract) {
|
||||
var preBuiltAppBundlePath = Path.Combine (
|
||||
Path.GetDirectoryName (typeof (PrepareAppBundle).Assembly.Location),
|
||||
"Xamarin.PreBuilt.iOS.app.zip");
|
||||
|
||||
ZipFile.ExtractToDirectory (preBuiltAppBundlePath, AppBundlePath);
|
||||
File.WriteAllText (Path.Combine (AppBundlePath, "Extracted"), string.Empty);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
using Ionic.Zip;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using Mono.Cecil;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Xamarin.iOS.HotRestart.Tasks {
|
||||
public class UnpackFrameworks : Task {
|
||||
#region Inputs
|
||||
|
||||
[Required]
|
||||
public ITaskItem [] ReferencedAssemblies { get; set; }
|
||||
|
||||
[Required]
|
||||
public string IntermediateOutputPath { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Outputs
|
||||
|
||||
[Output]
|
||||
public ITaskItem [] Frameworks { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public override bool Execute ()
|
||||
{
|
||||
var frameworks = new List<ITaskItem> ();
|
||||
|
||||
Directory.CreateDirectory (Path.Combine (IntermediateOutputPath, "Frameworks"));
|
||||
|
||||
foreach (var assemblyPath in ReferencedAssemblies.Distinct ().Where (x => !IsFrameworkItem (x))) {
|
||||
var assembly = AssemblyDefinition.ReadAssembly (assemblyPath.ItemSpec);
|
||||
|
||||
// We should only get the embedded resources that ends with .framework
|
||||
var embeddedFrameworks = assembly.MainModule.Resources.Where (x => Path.GetExtension (x.Name) == ".framework");
|
||||
|
||||
foreach (var resource in embeddedFrameworks) {
|
||||
var embeddedFramework = resource as EmbeddedResource;
|
||||
|
||||
if (embeddedFramework == null)
|
||||
continue;
|
||||
|
||||
var frameworkPath = Path.Combine (IntermediateOutputPath, "Frameworks", embeddedFramework.Name);
|
||||
var frameworkZipPath = frameworkPath + ".zip";
|
||||
|
||||
// The frameworks are embedded as zip files
|
||||
using (var fileStream = File.OpenWrite (frameworkZipPath)) {
|
||||
embeddedFramework.GetResourceStream ().CopyTo (fileStream);
|
||||
}
|
||||
|
||||
// Unzip the framework
|
||||
using (var zipFile = ZipFile.Read (frameworkZipPath)) {
|
||||
zipFile.ExtractAll (frameworkPath, ExtractExistingFileAction.OverwriteSilently);
|
||||
}
|
||||
|
||||
File.Delete (frameworkZipPath);
|
||||
|
||||
var taskItem = new TaskItem (frameworkPath);
|
||||
|
||||
frameworks.Add (taskItem);
|
||||
}
|
||||
}
|
||||
|
||||
Frameworks = frameworks.ToArray ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsFrameworkItem (ITaskItem item)
|
||||
{
|
||||
return (bool.TryParse (item.GetMetadata ("FrameworkFile"), out var isFrameworkFile) && isFrameworkFile) ||
|
||||
item.GetMetadata ("ResolvedFrom") == "{TargetFrameworkDirectory}" ||
|
||||
item.GetMetadata ("ResolvedFrom") == "ImplicitlyExpandDesignTimeFacades";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<!-- Use single-project MSBuild properties to generate the application manifest by default -->
|
||||
<GenerateApplicationManifest Condition="'$(GenerateApplicationManifest)' == ''">true</GenerateApplicationManifest>
|
||||
|
||||
<HotRestartSignedAppOutputDir>$(TEMP)\Xamarin\HotRestart\Signing\$(_AppBundleName)$(AppBundleExtension)\out\</HotRestartSignedAppOutputDir>
|
||||
<HotRestartPayloadDir>$(HotRestartSignedAppOutputDir)Payload\</HotRestartPayloadDir>
|
||||
<HotRestartSignedAppDir>$(HotRestartPayloadDir)$(_AppBundleName).app\</HotRestartSignedAppDir>
|
||||
<HotRestartContentDir>$(HotRestartSignedAppOutputDir)$(_AppBundleName).content\</HotRestartContentDir>
|
||||
<HotRestartAppContentDir>$(HotRestartSignedAppDir)$(_AppBundleName).content\</HotRestartAppContentDir>
|
||||
<HotRestartContentStampDir>$(HotRestartSignedAppOutputDir)$(_AppBundleName).stamp\</HotRestartContentStampDir>
|
||||
<HotRestartIPAPath>$(HotRestartSignedAppOutputDir)$(_AppBundleName).ipa</HotRestartIPAPath>
|
||||
|
||||
<UnpackHotRestartFrameworks Condition="'$(UnpackHotRestartFrameworks)' == ''">true</UnpackHotRestartFrameworks>
|
||||
|
||||
<_IsHotRestartDefined>$([System.Text.RegularExpressions.Regex]::IsMatch('$(DefineConstants.Trim())', '(^|;)HOTRESTART($|;)'))</_IsHotRestartDefined>
|
||||
<DefineConstants Condition="!$(_IsHotRestartDefined) And '$(IsHotRestartBuild)' == 'true'">HOTRESTART;$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,340 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<UsingTask TaskName="Xamarin.iOS.Tasks.CompileEntitlements" AssemblyFile="Xamarin.iOS.Tasks.dll" />
|
||||
<UsingTask TaskName="Xamarin.iOS.Tasks.UnpackLibraryResources" AssemblyFile="Xamarin.iOS.Tasks.dll" />
|
||||
<UsingTask TaskName="Xamarin.iOS.HotRestart.Tasks.Codesign" AssemblyFile="Xamarin.iOS.Tasks.Windows.dll" />
|
||||
<UsingTask TaskName="Xamarin.iOS.HotRestart.Tasks.CollectDynamicFrameworks" AssemblyFile="Xamarin.iOS.Tasks.Windows.dll" />
|
||||
<UsingTask TaskName="Xamarin.iOS.HotRestart.Tasks.CompileAppManifest" AssemblyFile="Xamarin.iOS.Tasks.Windows.dll" />
|
||||
<UsingTask TaskName="Xamarin.iOS.HotRestart.Tasks.DetectSigningIdentity" AssemblyFile="Xamarin.iOS.Tasks.Windows.dll" />
|
||||
<UsingTask TaskName="Xamarin.iOS.HotRestart.Tasks.PrepareAppBundle" AssemblyFile="Xamarin.iOS.Tasks.Windows.dll" />
|
||||
<UsingTask TaskName="Xamarin.iOS.HotRestart.Tasks.UnpackFrameworks" AssemblyFile="Xamarin.iOS.Tasks.Windows.dll" />
|
||||
|
||||
<Import Project="Xamarin.iOS.HotRestart.props" />
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)Xamarin.Messaging.Build.targets" Condition="Exists('$(MSBuildThisFileDirectory)Xamarin.Messaging.Build.targets') And '$(MessagingBuildTargetsImported)' != 'true'" />
|
||||
<Import Project="$(MSBuildThisFileDirectory)Xamarin.Messaging.Apple.targets" Condition="Exists('$(MSBuildThisFileDirectory)Xamarin.Messaging.Apple.targets') And '$(MessagingAppleTargetsImported)' != 'true'" />
|
||||
|
||||
<Target Name="_DetectHotRestartSigningIdentity" AfterTargets="_DetectAppManifest"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsHotRestartBuild)' == 'true' And '$(IsHotRestartEnvironmentReady)' == 'true'" >
|
||||
|
||||
<HotRestart.Tasks.DetectSigningIdentity
|
||||
GenerateApplicationManifest="$(GenerateApplicationManifest)"
|
||||
ApplicationId="$(ApplicationId)"
|
||||
ApplicationTitle="$(ApplicationTitle)"
|
||||
AppManifest="$(_AppManifest)"
|
||||
ProvisioningProfile="$(CodesignProvision)"
|
||||
SigningKey="$(CodesignKey)">
|
||||
|
||||
<Output TaskParameter="DetectedAppId" PropertyName="_AppIdentifier" />
|
||||
<Output TaskParameter="DetectedBundleId" PropertyName="_BundleIdentifier" />
|
||||
<Output TaskParameter="DetectedAppDisplayName" PropertyName="_AppDisplayName" />
|
||||
<Output TaskParameter="DetectedCodeSigningPath" PropertyName="_CodeSigningPath" />
|
||||
<Output TaskParameter="DetectedProvisioningProfileId" PropertyName="_ProvisioningProfileId" />
|
||||
<Output TaskParameter="DetectedProvisioningProfilePath" PropertyName="_ProvisioningProfilePath" />
|
||||
</HotRestart.Tasks.DetectSigningIdentity>
|
||||
</Target>
|
||||
|
||||
<Target Name="_CollectHotRestartBundleResources" Condition="'$(IsHotRestartBuild)' == 'true'">
|
||||
<CollectBundleResources
|
||||
OptimizePropertyLists="$(OptimizePropertyLists)"
|
||||
OptimizePNGs="$(OptimizePNGs)"
|
||||
BundleResources="@(Content);@(BundleResource)"
|
||||
ProjectDir="$(MSBuildProjectDirectory)"
|
||||
ResourcePrefix="$(IPhoneResourcePrefix)">
|
||||
|
||||
<Output TaskParameter="BundleResourcesWithLogicalNames" ItemName="_HotRestartBundleResourceWithLogicalName"/>
|
||||
</CollectBundleResources>
|
||||
</Target>
|
||||
|
||||
<Target Name="_UnpackHotRestartLibraryResources" DependsOnTargets="_CollectHotRestartBundleResources"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsHotRestartBuild)' == 'true'" >
|
||||
|
||||
<UnpackLibraryResources
|
||||
Prefix="monotouch"
|
||||
NoOverwrite="@(_HotRestartBundleResourceWithLogicalName)"
|
||||
IntermediateOutputPath="$(DeviceSpecificIntermediateOutputPath)"
|
||||
TargetFrameworkDirectory="$(TargetFrameworkDirectory)"
|
||||
ReferencedLibraries="@(ReferencePath);@(ReferenceDependencyPaths);@(_ReferencesFromNuGetPackages)">
|
||||
|
||||
<Output TaskParameter="BundleResourcesWithLogicalNames" ItemName="_HotRestartBundleResourceWithLogicalName" />
|
||||
</UnpackLibraryResources>
|
||||
</Target>
|
||||
|
||||
<!-- Gets the list of assemblies that may contain frameworks -->
|
||||
<Target Name="_CollectHotRestartFrameworkAssemblies" Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsHotRestartBuild)' == 'true'">
|
||||
<ItemGroup>
|
||||
<AssembliesWithFrameworks Condition="'%(Extension)' == '.dll'" Include="@(ReferenceCopyLocalPaths)" Exclude="@(ReferenceSatellitePaths)"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_UnpackHotRestartFrameworkAssemblies"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsHotRestartBuild)' == 'true' And '$(UnpackHotRestartFrameworks)' == 'true'"
|
||||
Inputs="@(AssembliesWithFrameworks)"
|
||||
Outputs="@(AssembliesWithFrameworks -> '$(DeviceSpecificIntermediateOutputPath)UnpackedFrameworks\%(Filename)%(Extension).stamp')" >
|
||||
|
||||
<UnpackFrameworks
|
||||
ReferencedAssemblies="@(AssembliesWithFrameworks)"
|
||||
IntermediateOutputPath="$(DeviceSpecificIntermediateOutputPath)">
|
||||
|
||||
<Output TaskParameter="Frameworks" ItemName="_UnpackedFramework" />
|
||||
</UnpackFrameworks>
|
||||
|
||||
<MakeDir Directories="$(DeviceSpecificIntermediateOutputPath)UnpackedFrameworks"/>
|
||||
|
||||
<Touch AlwaysCreate="true" Files="@(AssembliesWithFrameworks -> '$(DeviceSpecificIntermediateOutputPath)UnpackedFrameworks\%(Filename)%(Extension).stamp')" >
|
||||
<Output TaskParameter="TouchedFiles" ItemName="FileWrites" />
|
||||
</Touch>
|
||||
</Target>
|
||||
|
||||
<Target Name="_CollectHotRestartFrameworks" >
|
||||
<ItemGroup>
|
||||
<_HotRestartFrameworks Include="@(None -> '%(RootDir)%(Directory)')" Condition="$([System.String]::new('%(Directory)').EndsWith('.framework\'))" KeepDuplicates="false" />
|
||||
<_HotRestartFrameworks Include="@(_UnpackedFramework);@(NativeReference)" KeepDuplicates="false" />
|
||||
<_HotRestartFrameworkExecutables Include="@(_HotRestartFrameworks -> '%(FullPath)\%(Filename)')"
|
||||
Outputs="$(DeviceSpecificIntermediateOutputPath)DynamicFrameworks\%(Filename)%(Extension).stamp" KeepDuplicates="false" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<PropertyGroup>
|
||||
<_CollectHotRestartDynamicFrameworksDependsOn>
|
||||
_CollectHotRestartFrameworkAssemblies;
|
||||
_UnpackHotRestartFrameworkAssemblies;
|
||||
_CollectHotRestartFrameworks;
|
||||
</_CollectHotRestartDynamicFrameworksDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_CollectHotRestartDynamicFrameworks" DependsOnTargets="$(_CollectHotRestartDynamicFrameworksDependsOn)"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsHotRestartBuild)' == 'true'"
|
||||
Inputs="@(_HotRestartFrameworkExecutables)"
|
||||
Outputs="@(_HotRestartFrameworkExecutables -> '%(Outputs)')" >
|
||||
|
||||
<CollectDynamicFrameworks
|
||||
Frameworks="@(_HotRestartFrameworks)" >
|
||||
|
||||
<Output TaskParameter="DynamicFrameworks" ItemName="_DynamicFrameworks" />
|
||||
</CollectDynamicFrameworks>
|
||||
|
||||
<MakeDir Directories="$(DeviceSpecificIntermediateOutputPath)DynamicFrameworks"/>
|
||||
|
||||
<Touch AlwaysCreate="true" Files="@(_HotRestartFrameworks -> '$(DeviceSpecificIntermediateOutputPath)DynamicFrameworks\%(Filename)%(Extension).stamp')" >
|
||||
<Output TaskParameter="TouchedFiles" ItemName="FileWrites" />
|
||||
</Touch>
|
||||
|
||||
<ItemGroup>
|
||||
<_HotRestartFrameworkFiles Include="%(_DynamicFrameworks.FullPath)\**\*.*" Condition="'%(_DynamicFrameworks.FullPath)' != ''" KeepDuplicates="false" >
|
||||
<FrameworkDir>%(FrameworkDir)</FrameworkDir>
|
||||
</_HotRestartFrameworkFiles>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<PropertyGroup>
|
||||
<_CreateHotRestartCachedBundleDependsOn>
|
||||
_PrepareHotRestartAppBundle;
|
||||
_CompileHotRestartAppManifest;
|
||||
_CompileHotRestartEntitlements;
|
||||
</_CreateHotRestartCachedBundleDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_CreateHotRestartCachedBundle" DependsOnTargets="$(_CreateHotRestartCachedBundleDependsOn)" />
|
||||
|
||||
<!-- Creates HotRestart app bundle and collects files to copy -->
|
||||
<Target Name="_PrepareHotRestartAppBundle" DependsOnTargets="_GenerateBuildSessionId"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsAppExtension)' == 'false' And '$(IsHotRestartBuild)' == 'true'">
|
||||
|
||||
<!--Create app bundle dir and get its path-->
|
||||
<PrepareAppBundle
|
||||
AppBundleName="$(_AppBundleName)"
|
||||
SessionId="$(BuildSessionId)"
|
||||
ShouldExtract="true">
|
||||
|
||||
<Output TaskParameter="AppBundlePath" PropertyName="HotRestartAppBundlePath" />
|
||||
</PrepareAppBundle>
|
||||
|
||||
<!-- Delete the build signature to force XMA do a full build next time -->
|
||||
<Delete Files="$(BuildSignatureFile)" Condition="Exists('$(BuildSignatureFile)')" />
|
||||
|
||||
<ItemGroup>
|
||||
<_FilesToHotRestartBundle Include="$(HotRestartAppBundlePath)\Extracted" />
|
||||
|
||||
<_FilesToHotRestartContent Include="@(MainAssembly);" >
|
||||
<DestinationSubDirectory></DestinationSubDirectory>
|
||||
</_FilesToHotRestartContent>
|
||||
|
||||
<_FilesToHotRestartContent Include="@(_FilesToHotRestartContent -> '%(RootDir)%(Directory)%(Filename).pdb')"
|
||||
Condition="Exists('%(RootDir)%(Directory)%(Filename).pdb')" />
|
||||
|
||||
<!-- TODO: We stopped filtering assemblies until we fix the net6 build -->
|
||||
<!-- <_FilesToHotRestartContent Include="@(ReferenceCopyLocalPaths -> Distinct())" Condition="Exists('$(HotRestartAppBundlePath)\%(Filename)%(Extension)') == 'false'"/> -->
|
||||
<_FilesToHotRestartContent Include="@(ReferenceCopyLocalPaths -> Distinct())"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_CompileHotRestartAppManifest"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsHotRestartBuild)' == 'true'"
|
||||
Inputs="$(_AppManifest);$(HotRestartAppBundlePath)\Extracted"
|
||||
Outputs="$(HotRestartSignedAppDir)$(_AppManifest);$(HotRestartSignedAppDir)Extracted">
|
||||
|
||||
<HotRestart.Tasks.CompileAppManifest
|
||||
AppBundlePath="$(HotRestartAppBundlePath)"
|
||||
AppManifestPath="$(_AppManifest)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CompileHotRestartEntitlements"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsHotRestartBuild)' == 'true'"
|
||||
Inputs="$(CodesignEntitlements);$(_ProvisioningProfilePath);$(HotRestartAppBundlePath)\Extracted"
|
||||
Outputs="$(HotRestartSignedAppDir)archived-expanded-entitlements.xcent;$(HotRestartSignedAppDir)Extracted">
|
||||
|
||||
<CompileEntitlements
|
||||
AppBundleDir="$(HotRestartAppBundlePath)"
|
||||
AppIdentifier="$(_AppIdentifier)"
|
||||
BundleIdentifier="$(_BundleIdentifier)"
|
||||
Entitlements="$(CodesignEntitlements)"
|
||||
CompiledEntitlements="$(DeviceSpecificIntermediateOutputPath)Entitlements.xcent"
|
||||
IsAppExtension="$(IsAppExtension)"
|
||||
ProvisioningProfile="$(_ProvisioningProfileId)"
|
||||
SdkIsSimulator="False"
|
||||
SdkPlatform="iPhoneOS"
|
||||
SdkVersion="12.2"
|
||||
SdkDevPath=" "
|
||||
TargetFrameworkMoniker="$(_ComputedTargetFrameworkMoniker)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CopyFilesToHotRestartBundle"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsAppExtension)' == 'false' And '$(IsHotRestartBuild)' == 'true'"
|
||||
DependsOnTargets="_CreateHotRestartCachedBundle;_UnpackHotRestartLibraryResources"
|
||||
Inputs="@(_HotRestartBundleResourceWithLogicalName);@(_FilesToHotRestartBundle)"
|
||||
Outputs="@(_HotRestartBundleResourceWithLogicalName -> '$(HotRestartSignedAppDir)%(LogicalName)');
|
||||
@(_FilesToHotRestartBundle -> '$(HotRestartSignedAppDir)%(Filename)%(Extension)')">
|
||||
|
||||
<!-- Copy Bundle resources -->
|
||||
<Copy SourceFiles="@(_HotRestartBundleResourceWithLogicalName)"
|
||||
DestinationFiles="@(_HotRestartBundleResourceWithLogicalName -> '$(HotRestartSignedAppDir)\%(LogicalName)')"
|
||||
SkipUnchangedFiles="true"
|
||||
Condition="'@(_HotRestartBundleResourceWithLogicalName)' != ''">
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
|
||||
<Copy SourceFiles="@(_FilesToHotRestartBundle)"
|
||||
DestinationFiles="@(_FilesToHotRestartBundle -> '$(HotRestartSignedAppDir)\%(Filename)%(Extension)')"
|
||||
SkipUnchangedFiles="true"
|
||||
Condition="'@(_FilesToHotRestartBundle)' != ''">
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
|
||||
<MakeDir Directories="$(HotRestartContentStampDir)"/>
|
||||
<Touch AlwaysCreate="true" Files="$(HotRestartContentStampDir)$(_AppBundleName).stamp" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CopyFilesToHotRestartContent"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsAppExtension)' == 'false' And '$(IsHotRestartBuild)' == 'true'"
|
||||
DependsOnTargets="_CreateHotRestartCachedBundle"
|
||||
Inputs="@(_FilesToHotRestartContent)"
|
||||
Outputs="@(_FilesToHotRestartContent -> '$(HotRestartContentDir)%(DestinationSubDirectory)%(FileName)%(Extension)');
|
||||
@(_FilesToHotRestartContent -> '$(HotRestartAppContentDir)%(DestinationSubDirectory)%(FileName)%(Extension)')">
|
||||
|
||||
<MakeDir Directories="$(HotRestartContentDir)"/>
|
||||
<MakeDir Directories="$(HotRestartAppContentDir)"/>
|
||||
|
||||
<!-- Copy assemblies and debug symbols into incremental Content folder -->
|
||||
<Copy SourceFiles="@(_FilesToHotRestartContent)"
|
||||
DestinationFiles="@(_FilesToHotRestartContent -> '$(HotRestartContentDir)%(DestinationSubDirectory)%(FileName)%(Extension)')"
|
||||
SkipUnchangedFiles="true"
|
||||
Condition="'@(_FilesToHotRestartContent)' != ''">
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
|
||||
<!-- Copy assemblies and debug symbols into app bundle's content folder -->
|
||||
<Copy SourceFiles="@(_FilesToHotRestartContent)"
|
||||
DestinationFiles="@(_FilesToHotRestartContent -> '$(HotRestartAppContentDir)%(DestinationSubDirectory)%(FileName)%(Extension)')"
|
||||
SkipUnchangedFiles="true"
|
||||
Condition="'@(_FilesToHotRestartContent)' != ''">
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
|
||||
<MakeDir Directories="$(HotRestartContentStampDir)"/>
|
||||
<MakeDir Directories="@(_FilesToHotRestartContent -> '$(HotRestartContentStampDir)%(DestinationSubDirectory)')"/>
|
||||
|
||||
<Touch AlwaysCreate="true" Files="@(_FilesToHotRestartContent -> '$(HotRestartContentStampDir)%(DestinationSubDirectory)%(FileName)%(Extension).stamp')" />
|
||||
<Touch AlwaysCreate="true" Files="@(_FilesToHotRestartContent -> '$(HotRestartContentStampDir)$(AssemblyName).hotrestartapp.stamp')" />
|
||||
<Touch AlwaysCreate="true" Files="@(_FilesToHotRestartContent -> '$(HotRestartContentDir)$(AssemblyName).hotrestartapp')" />
|
||||
<Touch AlwaysCreate="true" Files="@(_FilesToHotRestartContent -> '$(HotRestartAppContentDir)$(AssemblyName).hotrestartapp')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CopyFrameworksToHotRestartBundle"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsAppExtension)' == 'false' And '$(IsHotRestartBuild)' == 'true'"
|
||||
DependsOnTargets="_CreateHotRestartCachedBundle;_CollectHotRestartDynamicFrameworks"
|
||||
Inputs="@(_HotRestartFrameworkFiles)"
|
||||
Outputs="@(_HotRestartFrameworkFiles -> '$(HotRestartSignedAppDir)Frameworks\%(FrameworkDir)%(RecursiveDir)%(Filename)%(Extension)')">
|
||||
|
||||
<!-- Copy frameworks -->
|
||||
<Copy SourceFiles="@(_HotRestartFrameworkFiles)"
|
||||
DestinationFiles="@(_HotRestartFrameworkFiles -> '$(HotRestartAppBundlePath)\Frameworks\%(FrameworkDir)%(RecursiveDir)%(Filename)%(Extension)')"
|
||||
SkipUnchangedFiles="true"
|
||||
Condition="'@(_HotRestartFrameworkFiles)' != ''">
|
||||
|
||||
<Output TaskParameter="DestinationFiles" ItemName="FileWrites"/>
|
||||
</Copy>
|
||||
</Target>
|
||||
|
||||
<Target Name="_CollectCodeSignHotRestartInputs">
|
||||
<ItemGroup>
|
||||
<_CodeSignHotRestartInputs Include="$(_AppManifest)" Outputs="$(HotRestartSignedAppDir)$(_AppManifest)" />
|
||||
<_CodeSignHotRestartInputs Include="$(CodesignEntitlements)" Outputs="$(HotRestartSignedAppDir)$(CodesignEntitlements)" />
|
||||
<_CodeSignHotRestartInputs Include="$(_ProvisioningProfilePath)" Outputs="$(HotRestartSignedAppDir)embedded.mobileprovision" />
|
||||
<_CodeSignHotRestartInputs Include="@(_HotRestartFrameworkFiles)" Outputs="$(HotRestartAppBundlePath)\Frameworks\%(_HotRestartFrameworkFiles.FrameworkDir)%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
<_CodeSignHotRestartInputs Include="$(HotRestartAppBundlePath)\Extracted" Outputs="$(HotRestartSignedAppDir)Extracted" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<PropertyGroup>
|
||||
<_CreateHotRestartOutputBundleDependsOn>
|
||||
_CodesignHotRestartAppBundle;
|
||||
_CopyFilesToHotRestartBundle;
|
||||
_CopyFilesToHotRestartContent;
|
||||
</_CreateHotRestartOutputBundleDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_CreateHotRestartOutputBundle" Condition="'$(IsHotRestartEnvironmentReady)' == 'true'" DependsOnTargets="$(_CreateHotRestartOutputBundleDependsOn)"
|
||||
AfterTargets="_CodesignAppBundle" />
|
||||
|
||||
<Target Name="_CodesignHotRestartAppBundle"
|
||||
Condition="'$(_CanOutputAppBundle)' == 'true' And '$(IsAppExtension)' == 'false' And '$(IsHotRestartBuild)' == 'true'"
|
||||
DependsOnTargets="_CreateHotRestartCachedBundle;_CopyFrameworksToHotRestartBundle;_CollectCodeSignHotRestartInputs"
|
||||
Inputs="@(_CodeSignHotRestartInputs)"
|
||||
Outputs="@(_CodeSignHotRestartInputs -> '%(Outputs)')">
|
||||
|
||||
<HotRestart.Tasks.Codesign
|
||||
AppBundlePath="$(HotRestartAppBundlePath)"
|
||||
BundleIdentifier="$(_BundleIdentifier)"
|
||||
CodeSigningPath="$(_CodeSigningPath)"
|
||||
ProvisioningProfilePath="$(_ProvisioningProfilePath)" />
|
||||
</Target>
|
||||
|
||||
<PropertyGroup>
|
||||
<CleanDependsOn>
|
||||
$(CleanDependsOn);
|
||||
_CleanHotRestartBundle
|
||||
</CleanDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_CleanHotRestartBundle" DependsOnTargets="_GenerateBuildSessionId" >
|
||||
<!-- Gets the bundle path -->
|
||||
<PrepareAppBundle
|
||||
Condition="'$(IsHotRestartBuild)' == 'true'"
|
||||
AppBundleName="$(_AppBundleName)"
|
||||
SessionId="$(BuildSessionId)"
|
||||
ShouldExtract="false">
|
||||
|
||||
<Output TaskParameter="AppBundlePath" PropertyName="HotRestartAppBundlePath" />
|
||||
</PrepareAppBundle>
|
||||
|
||||
<RemoveDir Directories="$(HotRestartAppBundlePath)" />
|
||||
<RemoveDir Directories="$(HotRestartSignedAppOutputDir)" />
|
||||
<RemoveDir Directories="$(DeviceSpecificIntermediateOutputPath)UnpackedFrameworks" />
|
||||
<RemoveDir Directories="$(DeviceSpecificIntermediateOutputPath)DynamicFrameworks" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -4,12 +4,15 @@
|
|||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<MergeSystemAssemblies>false</MergeSystemAssemblies>
|
||||
<RuntimeIdentifier>win</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNetZip" Version="1.14.0" />
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.4" />
|
||||
<PackageReference Include="Xamarin.Messaging.Build.Client" Version="$(MessagingVersion)" IncludeAssets="contentFiles" />
|
||||
<PackageReference Include="Xamarin.Messaging.Core" Version="$(MessagingVersion)" IncludeAssets="build" />
|
||||
<PackageReference Include="Xamarin.Messaging.Server" Version="$(MessagingVersion)" IncludeAssets="contentFiles" />
|
||||
<PackageReference Include="Xamarin.iOS.HotRestart.Client" Version="$(HotRestartVersion)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Messaging\Xamarin.Messaging.Build\Xamarin.Messaging.Build.csproj">
|
||||
|
@ -17,6 +20,7 @@
|
|||
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
|
||||
<IsAgent>True</IsAgent>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\external\Xamarin.MacDev\Xamarin.MacDev\Xamarin.MacDev.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="*.props">
|
||||
|
@ -25,6 +29,10 @@
|
|||
<None Include="*.targets">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="..\..\external\macios-binaries\HotRestart\Xamarin.PreBuilt.iOS.app.zip">
|
||||
<Link>Xamarin.PreBuilt.iOS.app.zip</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Tasks\" />
|
||||
|
@ -47,18 +55,16 @@
|
|||
<Target Name="CopyRuntimeAssemblies" BeforeTargets="ILRepack">
|
||||
<ItemGroup>
|
||||
<ReferenceCopyLocalToRemove Include="@(ReferenceCopyLocalPaths)" Condition="'%(FileName)' == 'System.Text.Encoding.CodePages'" />
|
||||
|
||||
<ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalToRemove)" />
|
||||
|
||||
<ReferencePathToRemove Include="@(ReferencePath)" Condition="'%(FileName)' == 'System.Text.Encoding.CodePages'" />
|
||||
|
||||
<ReferencePath Remove="@(ReferencePathToRemove)" />
|
||||
|
||||
<ReferencePathToAdd Include="@(RuntimeTargetsCopyLocalItems)" Condition="'%(RuntimeIdentifier)' == 'win' And '%(FileName)' == 'System.Text.Encoding.CodePages'" />
|
||||
|
||||
<ReferencePath Include="@(ReferencePathToAdd)">
|
||||
<DestinationSubDirectory />
|
||||
</ReferencePath>
|
||||
<ReferenceToPreserve Include="@(ReferencePath)" Condition="'%(FileName)' == 'System.Diagnostics.Tracer'" />
|
||||
<ReferenceToPreserve Include="@(ReferencePath)" Condition="'%(FileName)' == 'System.Security.Cryptography.ProtectedData'" />
|
||||
<ReferenceToPreserve Include="@(ReferencePath)" Condition="'%(FileName)' == 'System.Security.Cryptography.Pkcs'" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
|
@ -27,5 +27,5 @@ Copyright (C) 2011-2013 Xamarin. All rights reserved.
|
|||
<RemoveDir SessionId="$(BuildSessionId)" Condition="'$(MtouchTargetsEnabled)' == 'true'" Directories="$(OutputPath);$(IntermediateOutputPath)" RemoveAppDir="$(RemoveAppDir)" ContinueOnError="true" />
|
||||
</Target>
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)Xamarin.iOS.Local.targets" Condition="Exists('$(MSBuildThisFileDirectory)Xamarin.iOS.Local.targets')" />
|
||||
<Import Project="$(MSBuildThisFileDirectory)Xamarin.iOS.HotRestart.targets" Condition="Exists('$(MSBuildThisFileDirectory)Xamarin.iOS.HotRestart.targets')" />
|
||||
</Project>
|
||||
|
|