Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[msbuild/tests/dotnet] Add support for xcframeworks for Hot Restart and add tests. Fixes #16571. #18103

Merged
merged 19 commits into from May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
5511849
[tests] Add support for creating temporary directories on Windows.
rolfbjarne Feb 3, 2023
d6195fe
[tests] Find the .NET executable using the DOTNET environment variabl…
rolfbjarne Feb 16, 2023
8e6104c
[tests] Add a HotRestart version of the BundleStructure test.
rolfbjarne Feb 16, 2023
f17bc64
[msbuild/dotnet] Rework Hot Restart builds.
rolfbjarne Feb 16, 2023
fcbbd29
[msbuild] Set/fix the PublishFolderType and RelativePath metadata in …
rolfbjarne Feb 16, 2023
9b2e5e8
[msbuild] Remove the CollectDynamicFrameworks task, it's no longer used.
rolfbjarne Mar 22, 2023
cb81e00
[msbuild] Remove the UnpackFrameworks task, it's no longer used.
rolfbjarne Apr 13, 2023
d9e9e2e
[msbuild] Make sure the decompression code works on Windows
rolfbjarne Mar 29, 2023
a4af76f
[msbuild] Add a bit more logging to the decompression code
rolfbjarne Mar 29, 2023
81ac597
[msbuild] Fix support for decompressing everything in a zip file
rolfbjarne Mar 29, 2023
2d1d4b1
[msbuild] Expand directories recursively into item groups.
rolfbjarne Mar 29, 2023
2431e3a
[msbuild] Make the CompileAppManifest task work on Windows.
rolfbjarne Apr 12, 2023
43b47b4
[msbuild] Use the general '[Compile|Read|Write]AppManifest' targets f…
rolfbjarne Apr 11, 2023
fd549e3
[msbuild] Rework HotRestart's DetectSigningIdentity task.
rolfbjarne Apr 13, 2023
b3478e8
[msbuild] Change the Outputs of the _CodesignHotRestartAppBundle target.
rolfbjarne Apr 19, 2023
6c4dbf8
[msbuild] Change the Outputs of the _CompileHotRestartEntitlements ta…
rolfbjarne Apr 19, 2023
2074b5e
[msbuild] Change the logic about how the prebuilt app bundle is decom…
rolfbjarne Apr 19, 2023
2899a7b
[msbuild] Use the right trailing slash for _AppContainerDir according…
rolfbjarne Apr 20, 2023
312076a
[msbuild] Check if a directory exists before trying to delete it.
rolfbjarne Apr 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 8 additions & 3 deletions dotnet/targets/Xamarin.Shared.Sdk.targets
Expand Up @@ -658,6 +658,7 @@
<_FrameworkToPublish Update="@(_FrameworkToPublish)">
<TargetDirectory>$(_RelativePublishDir)$(_AppBundleFrameworksDir)\%(Filename)%(Extension).framework</TargetDirectory>
<SourceDirectory>%(RelativeDir)</SourceDirectory>
<PublishFolderType>AppleFramework</PublishFolderType>
</_FrameworkToPublish>
</ItemGroup>

Expand Down Expand Up @@ -1495,9 +1496,10 @@
<ResolvedFileToPublish Remove="$(ProjectRuntimeConfigFilePath)" Condition="'$(GenerateRuntimeConfigurationFiles)' == 'true'" />
</ItemGroup>

<!-- This task is executed on Windows as well, for hotrestart builds -->
<ComputeBundleLocation
SessionId="$(BuildSessionId)"
Condition="'$(IsMacEnabled)' == 'true'"
Condition="'$(IsMacEnabled)' == 'true' Or '$(IsHotRestartBuild)' == 'true'"
AssemblyDirectory="$(_AppContentsRelativePath)"
BundleResource="@(BundleResource)"
BundlerDebug="$(_BundlerDebug)"
Expand Down Expand Up @@ -1572,11 +1574,13 @@
<ResolvedFileToPublish RelativePath="$(_RelativeAppBundlePath)\%(RelativePath)" />
</ItemGroup>

<!-- This task is executed on Windows as well, for hotrestart builds -->
<!-- resolve any .xcframeworks and binding resource packages -->
<ResolveNativeReferences
SessionId="$(BuildSessionId)"
Condition="'$(IsMacEnabled)' == 'true'"
Condition="'$(IsMacEnabled)' == 'true' Or '$(IsHotRestartBuild)' == 'true'"
Architectures="$(TargetArchitectures)"
FrameworksDirectory="$(_AppFrameworksRelativePath)"
IntermediateOutputPath="$(DeviceSpecificIntermediateOutputPath)"
NativeReferences="@(_UnresolvedXCFrameworks);@(_AppleBindingResourcePackage);@(_CompressedAppleFrameworks);@(_CompressedAppleBindingResourcePackage)"
SdkIsSimulator="$(_SdkIsSimulator)"
Expand Down Expand Up @@ -1636,9 +1640,10 @@
</_CompressedPlugIns>
</ItemGroup>

<!-- This task is executed from Windows as well when using HotRestart -->
<Unzip
SessionId="$(BuildSessionId)"
Condition="'$(IsMacEnabled)' == 'true'"
Condition="'$(IsMacEnabled)' == 'true' Or '$(IsHotRestartBuild)' == 'true'"
ZipFilePath="%(_CompressedPlugIns.Identity)"
ExtractionPath="%(_CompressedPlugIns.ExtractionPath)"
>
Expand Down
5 changes: 5 additions & 0 deletions msbuild/Xamarin.Localization.MSBuild/MSBStrings.resx
Expand Up @@ -1492,4 +1492,9 @@
<data name="E7113" xml:space="preserve">
<value>Can't process the zip file '{0}' on this platform: the file '{1}' is a symlink.</value>
</data>

<data name="E7114" xml:space="preserve">
<value>The "{0}" task was not given a value for the parameter "{1}", which is required when building on this platform.</value>
</data>

</root>
13 changes: 10 additions & 3 deletions msbuild/Xamarin.MacDev.Tasks/Decompress.cs
Expand Up @@ -5,6 +5,7 @@
using System.IO.Compression;
using System.Reflection;

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

using Xamarin.Bundler;
Expand Down Expand Up @@ -86,7 +87,7 @@ public static bool TryDecompress (TaskLoggingHelper log, string zip, string reso
{
decompressedResource = Path.Combine (decompressionDir, resource);

var stampFile = decompressedResource + ".stamp";
var stampFile = decompressedResource.TrimEnd ('\\', '/') + ".stamp";

if (FileCopier.IsUptodate (zip, stampFile, XamarinTask.GetFileCopierReportErrorCallback (log), XamarinTask.GetFileCopierLogCallback (log), check_stamp: false))
return true;
Expand Down Expand Up @@ -117,6 +118,8 @@ public static bool TryDecompress (TaskLoggingHelper log, string zip, string reso
createdFiles.Add (decompressedResource);
} else if (Directory.Exists (decompressedResource)) {
createdFiles.AddRange (Directory.GetFiles (decompressedResource, "*", SearchOption.AllDirectories));
} else {
log.LogWarning ("The extracted file or directory '{0}' could not be found." /* The extracted file or directory '{0}' could not be found. */, decompressedResource);
}

return rv;
Expand Down Expand Up @@ -168,11 +171,14 @@ static bool TryDecompressUsingSystemIOCompression (TaskLoggingHelper log, string
if (entryPath.Length == 0)
continue;

if (entryPath.StartsWith (resourceAsDir, StringComparison.Ordinal)) {
if (string.IsNullOrEmpty (resource)) {
// an empty resource means extract everything, so we want this
} else if (entryPath.StartsWith (resourceAsDir, StringComparison.Ordinal)) {
// yep, we want this entry
} else if (entryPath == resource) {
// we want this one too
} else {
log.LogMessage (MessageImportance.Low, "Did not extract {0} because it didn't match the resource {1}", entryPath, resource);
// but otherwise nope
continue;
}
Expand All @@ -189,14 +195,15 @@ static bool TryDecompressUsingSystemIOCompression (TaskLoggingHelper log, string
}

var isDir = entryPath [entryPath.Length - 1] == zipDirectorySeparator;
var targetPath = Path.Combine (decompressionDir, entryPath);
var targetPath = Path.Combine (decompressionDir, entryPath.Replace (zipDirectorySeparator, Path.DirectorySeparatorChar));
if (isDir) {
Directory.CreateDirectory (targetPath);
} else {
Directory.CreateDirectory (Path.GetDirectoryName (targetPath));
using var streamWrite = File.OpenWrite (targetPath);
using var streamRead = entry.Open ();
streamRead.CopyTo (streamWrite);
log.LogMessage (MessageImportance.Low, "Extracted {0} into {1}", entryPath, targetPath);
}
}

Expand Down
Expand Up @@ -45,7 +45,6 @@ public abstract class CompileAppManifestTaskBase : XamarinTask {

public string DebugIPAddresses { get; set; } = String.Empty;

[Required]
public string DefaultSdkVersion { get; set; } = String.Empty;

public ITaskItem [] FontFilesToRegister { get; set; } = Array.Empty<ITaskItem> ();
Expand Down Expand Up @@ -75,7 +74,6 @@ public abstract class CompileAppManifestTaskBase : XamarinTask {
[Required]
public bool SdkIsSimulator { get; set; }

[Required]
public string SdkVersion { get; set; } = String.Empty;

public string SupportedOSPlatformVersion { get; set; } = String.Empty;
Expand All @@ -95,6 +93,10 @@ public abstract class CompileAppManifestTaskBase : XamarinTask {
}
}

bool OnWindows {
get => Environment.OSVersion.Platform == PlatformID.Win32NT;
}

public override bool Execute ()
{
PDictionary plist;
Expand Down Expand Up @@ -276,6 +278,9 @@ bool SetMinimumOSVersion (PDictionary plist)
// Nothing is specified in the Info.plist - use SupportedOSPlatformVersion, and if that's not set, then use the sdkVersion
if (!string.IsNullOrEmpty (convertedSupportedOSPlatformVersion)) {
minimumOSVersion = convertedSupportedOSPlatformVersion;
} else if (OnWindows && string.IsNullOrEmpty (SdkVersion)) {
// When building on Windows (Hot Restart), we're not using any Xcode version, so there's no SdkVersion either, so use the min OS version we support if the project doesn't specify anything.
minimumOSVersion = Xamarin.SdkVersions.GetMinVersion (Platform).ToString ();
} else {
minimumOSVersion = SdkVersion;
}
Expand Down Expand Up @@ -305,14 +310,21 @@ bool SetMinimumOSVersion (PDictionary plist)

bool Compile (PDictionary plist)
{
var currentSDK = Sdks.GetAppleSdk (Platform);
if (!OnWindows) {
if (string.IsNullOrEmpty (DefaultSdkVersion)) {
Log.LogError (MSBStrings.E7114 /* The "{0}" task was not given a value for the parameter "{1}", which is required when building on this platform. */, GetType ().Name, "DefaultSdkVersion");
return false;
}

sdkVersion = AppleSdkVersion.Parse (DefaultSdkVersion);
if (!currentSDK.SdkIsInstalled (sdkVersion, SdkIsSimulator)) {
Log.LogError (null, null, null, null, 0, 0, 0, 0, MSBStrings.E0013, Platform, sdkVersion);
return false;
var currentSDK = Sdks.GetAppleSdk (Platform);

sdkVersion = AppleSdkVersion.Parse (DefaultSdkVersion);
if (!currentSDK.SdkIsInstalled (sdkVersion, SdkIsSimulator)) {
Log.LogError (null, null, null, null, 0, 0, 0, 0, MSBStrings.E0013, Platform, sdkVersion);
return false;
}
SetXcodeValues (plist, currentSDK);
}
SetXcodeValues (plist, currentSDK);

switch (Platform) {
case ApplePlatform.iOS:
Expand Down Expand Up @@ -408,7 +420,7 @@ void Validation (PDictionary plist)

var supportedDevices = plist.GetUIDeviceFamily ();
var macCatalystOptimizedForMac = (supportedDevices & IPhoneDeviceType.MacCatalystOptimizedForMac) == IPhoneDeviceType.MacCatalystOptimizedForMac;
if (macCatalystOptimizedForMac) {
if (macCatalystOptimizedForMac && !OnWindows) {
if (Platform != ApplePlatform.MacCatalyst) {
LogAppManifestError (MSBStrings.E7098 /* The UIDeviceFamily value '6' is not valid for this platform. It's only valid for Mac Catalyst. */);
return; // no need to look for more errors, they will probably not make much sense.
Expand Down
Expand Up @@ -99,6 +99,7 @@ public override bool Execute ()

// Figure out the relative directory inside the app bundle where the item is supposed to be placed.
var relativePath = string.Empty;
var virtualProjectPath = GetVirtualAppBundlePath (item);
switch (publishFolderType) {
case PublishFolderType.Assembly:
relativePath = AssemblyDirectory;
Expand All @@ -119,16 +120,23 @@ public override bool Execute ()
continue;
case PublishFolderType.CompressedAppleFramework:
relativePath = FrameworksDirectory;
virtualProjectPath = Path.GetFileNameWithoutExtension (item.ItemSpec);
if (virtualProjectPath.EndsWith (".xcframework", StringComparison.OrdinalIgnoreCase))
virtualProjectPath = Path.ChangeExtension (virtualProjectPath, ".framework");
break;
case PublishFolderType.AppleBindingResourcePackage:
// Nothing to do here, this is handled fully in the targets file
break;
case PublishFolderType.CompressedAppleBindingResourcePackage:
// Nothing to do here, this is handled fully in the targets file
virtualProjectPath = RemoveExtension (virtualProjectPath, ".zip");
break;
case PublishFolderType.PlugIns:
relativePath = PlugInsDirectory;
break;
case PublishFolderType.CompressedPlugIns:
relativePath = PlugInsDirectory;
virtualProjectPath = string.Empty;
break;
case PublishFolderType.RootDirectory:
break;
Expand All @@ -151,7 +159,6 @@ public override bool Execute ()
}

// Compute the relative path of the item relative to the root of the app bundle
var virtualProjectPath = GetVirtualAppBundlePath (item);
relativePath = Path.Combine (relativePath, virtualProjectPath);
item.SetMetadata ("RelativePath", relativePath);
}
Expand All @@ -163,7 +170,7 @@ public override bool Execute ()
var items = entry.Value;
var item = new TaskItem (entry.Key);
item.SetMetadata ("PublishFolderType", "AppleFramework");
item.SetMetadata ("RelativePath", Path.Combine (FrameworksDirectory, Path.GetFileName (entry.Key)));
item.SetMetadata ("RelativePath", Path.Combine (FrameworksDirectory, Path.ChangeExtension (Path.GetFileName (entry.Key), "framework")));
list.Add (item);
}

Expand All @@ -172,6 +179,13 @@ public override bool Execute ()
return !Log.HasLoggedErrors;
}

static string RemoveExtension (string path, string extension)
{
if (path.EndsWith (extension, StringComparison.OrdinalIgnoreCase))
return path.Substring (0, path.Length - extension.Length);
return path;
}

// Check if the input, or any of it's parent directories is either an *.xcframework, or a *.framework
static bool TryGetFrameworkDirectory (string path, out string? frameworkDirectory)
{
Expand Down
Expand Up @@ -44,6 +44,9 @@ public abstract class ResolveNativeReferencesBase : XamarinTask {
[Required]
public string? Architectures { get; set; }

[Required]
public string FrameworksDirectory { get; set; } = string.Empty;

[Required]
public string IntermediateOutputPath { get; set; } = string.Empty;

Expand Down Expand Up @@ -142,12 +145,16 @@ void ProcessNativeReference (ITaskItem item, string name, List<ITaskItem> native
var nr = new TaskItem (item);
nr.ItemSpec = GetActualLibrary (name);
nr.SetMetadata ("Kind", "Framework");
nr.SetMetadata ("PublishFolderType", "AppleFramework");
nr.SetMetadata ("RelativePath", Path.Combine (FrameworksDirectory, Path.GetFileName (Path.GetDirectoryName (nr.ItemSpec))));
native_frameworks.Add (nr);
return;
} else if (parentDirectory.EndsWith (".framework", StringComparison.OrdinalIgnoreCase) && Path.GetFileName (name) == Path.GetFileNameWithoutExtension (parentDirectory)) {
var nr = new TaskItem (item);
nr.ItemSpec = GetActualLibrary (name);
nr.SetMetadata ("Kind", "Framework");
nr.SetMetadata ("PublishFolderType", "AppleFramework");
nr.SetMetadata ("RelativePath", Path.Combine (FrameworksDirectory, Path.GetFileName (Path.GetDirectoryName (nr.ItemSpec))));
native_frameworks.Add (nr);
return;
}
Expand All @@ -157,6 +164,7 @@ void ProcessNativeReference (ITaskItem item, string name, List<ITaskItem> native
var nr = new TaskItem (item);
nr.ItemSpec = name;
nr.SetMetadata ("Kind", "Dynamic");
nr.SetMetadata ("PublishFolderType", "DynamicLibrary");
native_frameworks.Add (nr);
return;
}
Expand All @@ -166,6 +174,7 @@ void ProcessNativeReference (ITaskItem item, string name, List<ITaskItem> native
var nr = new TaskItem (item);
nr.ItemSpec = name;
nr.SetMetadata ("Kind", "Static");
nr.SetMetadata ("PublishFolderType", "StaticLibrary");
native_frameworks.Add (nr);
return;
}
Expand All @@ -177,6 +186,8 @@ void ProcessNativeReference (ITaskItem item, string name, List<ITaskItem> native
var nr = new TaskItem (item);
nr.ItemSpec = GetActualLibrary (frameworkPath);
nr.SetMetadata ("Kind", "Framework");
nr.SetMetadata ("PublishFolderType", "AppleFramework");
nr.SetMetadata ("RelativePath", Path.Combine (FrameworksDirectory, Path.GetFileName (Path.GetDirectoryName (nr.ItemSpec))));
native_frameworks.Add (nr);
return;
}
Expand All @@ -188,6 +199,8 @@ void ProcessNativeReference (ITaskItem item, string name, List<ITaskItem> native
var nr = new TaskItem (item);
nr.ItemSpec = GetActualLibrary (frameworkPath);
nr.SetMetadata ("Kind", "Framework");
nr.SetMetadata ("PublishFolderType", "AppleFramework");
nr.SetMetadata ("RelativePath", Path.Combine (FrameworksDirectory, Path.GetFileName (Path.GetDirectoryName (nr.ItemSpec))));
native_frameworks.Add (nr);
return;
}
Expand Down Expand Up @@ -272,6 +285,8 @@ void ProcessSidecar (ITaskItem r, string resources, List<ITaskItem> native_frame
continue;
t.ItemSpec = GetActualLibrary (frameworkPath);
t.SetMetadata ("Kind", "Framework");
t.SetMetadata ("PublishFolderType", "AppleFramework");
t.SetMetadata ("RelativePath", Path.Combine (FrameworksDirectory, Path.GetFileName (Path.GetDirectoryName (t.ItemSpec))));
break;
}
case ".framework": {
Expand All @@ -283,6 +298,8 @@ void ProcessSidecar (ITaskItem r, string resources, List<ITaskItem> native_frame
}
t.ItemSpec = GetActualLibrary (frameworkPath);
t.SetMetadata ("Kind", "Framework");
t.SetMetadata ("PublishFolderType", "AppleFramework");
t.SetMetadata ("RelativePath", Path.Combine (FrameworksDirectory, Path.GetFileName (Path.GetDirectoryName (t.ItemSpec))));
break;
}
case ".dylib": // macOS
Expand All @@ -294,6 +311,7 @@ void ProcessSidecar (ITaskItem r, string resources, List<ITaskItem> native_frame
}
t.ItemSpec = dylibPath;
t.SetMetadata ("Kind", "Dynamic");
t.SetMetadata ("PublishFolderType", "DynamicLibrary");
break;
case ".a": // static library
string? aPath;
Expand All @@ -304,6 +322,7 @@ void ProcessSidecar (ITaskItem r, string resources, List<ITaskItem> native_frame
}
t.ItemSpec = aPath;
t.SetMetadata ("Kind", "Static");
t.SetMetadata ("PublishFolderType", "StaticLibrary");
break;
default:
Log.LogWarning (MSBStrings.W7105 /* Unexpected extension '{0}' for native reference '{1}' in binding resource package '{2}'. */, Path.GetExtension (name), name, r.ItemSpec);
Expand Down
3 changes: 3 additions & 0 deletions msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj
Expand Up @@ -69,6 +69,9 @@
<Link>Versions.dotnet.g.cs</Link>
</Compile>
<Compile Remove="Errors.designer.cs" /> <!-- The 'CoreResGen' target will add it again from the EmbeddedResource item, this avoids a warning about the file being compiled twice -->
<Compile Include="..\..\tools\common\SdkVersions.cs">
<Link>external\SdkVersions.cs</Link>
</Compile>
</ItemGroup>

<ItemGroup>
Expand Down