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

[dotnet] Point app extensions to any frameworks in the root app bundle. Fixes #17876. #18913

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
51 changes: 50 additions & 1 deletion dotnet/targets/Xamarin.Shared.Sdk.targets
Expand Up @@ -10,6 +10,7 @@
<UsingTask TaskName="Xamarin.MacDev.Tasks.CompileNativeCode" AssemblyFile="$(_XamarinTaskAssembly)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.FilterStaticFrameworks" AssemblyFile="$(_XamarinTaskAssembly)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.FindAotCompiler" AssemblyFile="$(_XamarinTaskAssembly)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.GetFullPaths" AssemblyFile="$(_XamarinTaskAssembly)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.InstallNameTool" AssemblyFile="$(_XamarinTaskAssembly)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.LinkNativeCode" AssemblyFile="$(_XamarinTaskAssembly)" />
<UsingTask TaskName="Xamarin.MacDev.Tasks.MergeAppBundles" AssemblyFile="$(_XamarinTaskAssembly)" />
Expand Down Expand Up @@ -696,8 +697,49 @@
<Output TaskParameter="FrameworkToPublish" ItemName="_FilteredFrameworkToPublish" />
</FilterStaticFrameworks>

<!--

We need to use the full path to the framework for frameworks that
come from app extensions (since any relative paths from the app
extension projects won't be correct once loaded into the
containing project), so compute that. However, also do this for
app projects, so that we can properly deduplicate frameworks that
come from both extensions and the main app project.

-->
<GetFullPaths
Condition="'$(IsMacEnabled)' == 'true'"
SessionId="$(BuildSessionId)"
Items="@(_FilteredFrameworkToPublish)"
Metadata="Identity;SourceDirectory"
>
<Output TaskParameter="Output" ItemName="_FilteredFrameworkToPublishWithFullPath" />
</GetFullPaths>

<!-- If we're an app extension, store the list of all the frameworks to disk (and don't publish any of them to the appex) -->
<!-- Note that app extensions may be nested, so we first check if we have any app extensions with frameworks, read those, then store the full list to disk if we're an app extension, so the containing app project sees everything -->
<ReadItemsFromFile File="@(_ResolvedAppExtensionReferences->'%(Identity)\..\native-frameworks.items')" Condition="Exists('%(Identity)\..\native-frameworks.items')">
<Output TaskParameter="Items" ItemName="_FrameworksFromAppExtensions" />
</ReadItemsFromFile>

<WriteItemsToFile
Condition="'$(IsAppExtension)' == 'true'"
Items="@(_FilteredFrameworkToPublishWithFullPath);@(_FrameworksFromAppExtensions)"
ItemName="_FrameworksFromAppExtensions"
File="$(DeviceSpecificOutputPath)\native-frameworks.items"
IncludeMetadata="true"
Overwrite="true"
/>

<ItemGroup>
<_FrameworksFromAppExtensions Update="@(_FrameworksFromAppExtensions)">
<TargetDirectory>$(_RelativePublishDir)$(_AppBundleFrameworksDir)\%(Filename)%(Extension).framework</TargetDirectory>
</_FrameworksFromAppExtensions>
</ItemGroup>

<ItemGroup>
<_DirectoriesToPublish Include="@(_FilteredFrameworkToPublish)" />
<_DirectoriesToPublish Include="@(_FrameworksFromAppExtensions)" Condition="'$(IsAppExtension)' != 'true'" />
<_DirectoriesToPublish Include="@(_FilteredFrameworkToPublishWithFullPath)" Condition="'$(IsAppExtension)' != 'true'" />
</ItemGroup>
</Target>

Expand Down Expand Up @@ -967,6 +1009,13 @@
<_RuntimeConfigurationFile>runtimeconfig.bin</_RuntimeConfigurationFile>
</PropertyGroup>

<!-- Not sure about how to handle nested app extensions here, but if it ever becomes a problem we can look into it (I believe only watch extensions can have embedded extensions at this point, and we don't support watchOS on .NET anyways) -->
<ItemGroup Condition="'$(IsAppExtension)' == 'true'">
<_CustomLinkFlags Include="-rpath" />
<_CustomLinkFlags Include="@executable_path/../../Frameworks" Condition="'$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS'" />
<_CustomLinkFlags Include="@executable_path/../../../../Frameworks" Condition="'$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst'" />
</ItemGroup>

<ItemGroup>
<!-- Select the native libraries from mono we need to link with and potentially copy into the app -->
<_MonoLibrary
Expand Down
69 changes: 69 additions & 0 deletions msbuild/Xamarin.MacDev.Tasks/Tasks/GetFullPaths.cs
@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

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

using Xamarin.MacDev.Tasks;
using Xamarin.Messaging.Build.Client;

#nullable enable

namespace Xamarin.MacDev.Tasks {
public class GetFullPaths : XamarinTask, ICancelableTask, ITaskCallback {
[Required]
public ITaskItem [] Items { get; set; } = Array.Empty<ITaskItem> ();

public string [] Metadata { get; set; } = Array.Empty<string> ();

[Output]
public ITaskItem [] Output { get; set; } = Array.Empty<ITaskItem> ();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd either make this a string or implement ITaskCallback.ShouldCreateOutputFile to return false, otherwise we will end up creating empty files on Windows, and I don't think this task should create any output files.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see you are keeping the metadata from the original items, so I'd just implement ITaskCallback

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@emaf fixed!


public override bool Execute ()
{
if (ShouldExecuteRemotely ())
return new TaskRunner (SessionId, BuildEngine4).RunAsync (this).Result;

return ExecuteLocally ();
}

public void Cancel ()
{
if (ShouldExecuteRemotely ())
BuildConnection.CancelAsync (BuildEngine4).Wait ();
}

bool ExecuteLocally ()
{
var rv = new List<ITaskItem> ();

foreach (var item in Items) {
var identity = item.ItemSpec;
if (Metadata.Length == 0 || Array.IndexOf (Metadata, "Identity") >= 0)
identity = Path.GetFullPath (identity);
var newItem = new TaskItem (identity);
item.CopyMetadataTo (newItem);
foreach (var md in Metadata) {
if (string.IsNullOrEmpty (md))
continue;
if (md == "Identity")
continue;
newItem.SetMetadata (md, Path.GetFullPath (newItem.GetMetadata (md)));
}
rv.Add (newItem);
}

Output = rv.ToArray ();

return !Log.HasLoggedErrors;
}

public bool ShouldCopyToBuildServer (ITaskItem item) => true;

public bool ShouldCreateOutputFile (ITaskItem item) => false;

public IEnumerable<ITaskItem> GetAdditionalItemsToBeCopied () => Enumerable.Empty<ITaskItem> ();
}
}
5 changes: 3 additions & 2 deletions msbuild/Xamarin.Shared/Xamarin.Shared.targets
Expand Up @@ -399,6 +399,7 @@ Copyright (C) 2018 Microsoft. All rights reserved.

<Delete SessionId="$(BuildSessionId)" Condition="'$(IsMacEnabled)' == 'true'" Files="$(DeviceSpecificOutputPath)codesign.items" />
<Delete SessionId="$(BuildSessionId)" Condition="'$(IsMacEnabled)' == 'true'" Files="$(DeviceSpecificOutputPath)codesign-bundle.items" />
<Delete SessionId="$(BuildSessionId)" Condition="'$(IsMacEnabled)' == 'true'" Files="$(DeviceSpecificOutputPath)native-frameworks.items" />
<Delete SessionId="$(BuildSessionId)" Condition="'$(IsMacEnabled)' == 'true'" Files="@(_IpaPackageFile)" />
</Target>

Expand Down Expand Up @@ -2095,14 +2096,14 @@ Copyright (C) 2018 Microsoft. All rights reserved.
<Output TaskParameter="Items" ItemName="_CodesignAppExtensionBundle" />
</ReadItemsFromFile>
<ItemGroup>
<_CodesignBundle Include="@(_CodesignAppExtensionBundle->'$(_AppBundleName)$(AppBundleExtension)/$(_AppPlugInsRelativePath)/%(Identity)')" />
<_CodesignBundle Include="@(_CodesignAppExtensionBundle->'$(_AppBundleName)$(AppBundleExtension)/$(_AppPlugInsRelativePath)%(Identity)')" />
</ItemGroup>
<!-- Get items to sign from app extensions -->
<ReadItemsFromFile File="@(_ResolvedAppExtensionReferences->'%(Identity)\..\codesign.items')" Condition="Exists('%(Identity)\..\codesign.items')">
<Output TaskParameter="Items" ItemName="_CodesignAppExtensionItem" />
</ReadItemsFromFile>
<ItemGroup>
<_CodesignItems Include="@(_CodesignAppExtensionItem->'$(_AppBundleName)$(AppBundleExtension)/$(_AppPlugInsRelativePath)/%(Identity)')" />
<_CodesignItems Include="@(_CodesignAppExtensionItem->'$(_AppBundleName)$(AppBundleExtension)/$(_AppPlugInsRelativePath)%(Identity)')" />
</ItemGroup>

<!-- Get app bundles to sign from watch apps -->
Expand Down
24 changes: 24 additions & 0 deletions tests/dotnet/ExtensionConsumerWithFrameworks/AppDelegate.cs
@@ -0,0 +1,24 @@
using System;
using System.Runtime.InteropServices;

using Foundation;

namespace MySimpleApp {
public class Program {
[DllImport ("__Internal")]
static extern int getUnknownE ();
[DllImport ("__Internal")]
static extern int getSomewhatUnknownD ();

static int Main (string [] args)
{
GC.KeepAlive (typeof (NSObject)); // prevent linking away the platform assembly

Console.WriteLine (getUnknownE ());
Console.WriteLine (getSomewhatUnknownD ());
Console.WriteLine (Environment.GetEnvironmentVariable ("MAGIC_WORD"));

return args.Length;
}
}
}
2 changes: 2 additions & 0 deletions tests/dotnet/ExtensionConsumerWithFrameworks/Makefile
@@ -0,0 +1,2 @@
TOP=../../..
include $(TOP)/tests/common/shared-dotnet-test.mk
@@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySimpleApp", "MySimpleApp.csproj", "{23664512-6B06-4135-9A94-C012BDA93CB1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionProject", "..\..\ExtensionProject\iOS\ExtensionProject.csproj", "{8A72DB8F-4C30-4462-9F7A-6095E41D5D46}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{23664512-6B06-4135-9A94-C012BDA93CB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23664512-6B06-4135-9A94-C012BDA93CB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23664512-6B06-4135-9A94-C012BDA93CB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23664512-6B06-4135-9A94-C012BDA93CB1}.Release|Any CPU.Build.0 = Release|Any CPU
{8A72DB8F-4C30-4462-9F7A-6095E41D5D46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A72DB8F-4C30-4462-9F7A-6095E41D5D46}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A72DB8F-4C30-4462-9F7A-6095E41D5D46}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A72DB8F-4C30-4462-9F7A-6095E41D5D46}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net$(BundledNETCoreAppTargetFrameworkVersion)-ios</TargetFramework>
</PropertyGroup>
<Import Project="..\shared.csproj" />
</Project>
@@ -0,0 +1 @@
include ../shared.mk
@@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySimpleApp", "MySimpleApp.csproj", "{B7C29D40-0079-416C-8507-FE9EE82FBD4F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionProject", "..\..\ExtensionProject\macOS\ExtensionProject.csproj", "{C32EB68F-1FF7-42DE-ABD8-C0151497595A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B7C29D40-0079-416C-8507-FE9EE82FBD4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7C29D40-0079-416C-8507-FE9EE82FBD4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7C29D40-0079-416C-8507-FE9EE82FBD4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7C29D40-0079-416C-8507-FE9EE82FBD4F}.Release|Any CPU.Build.0 = Release|Any CPU
{C32EB68F-1FF7-42DE-ABD8-C0151497595A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C32EB68F-1FF7-42DE-ABD8-C0151497595A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C32EB68F-1FF7-42DE-ABD8-C0151497595A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C32EB68F-1FF7-42DE-ABD8-C0151497595A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net$(BundledNETCoreAppTargetFrameworkVersion)-macos</TargetFramework>
</PropertyGroup>
<Import Project="..\shared.csproj" />
</Project>
@@ -0,0 +1 @@
include ../shared.mk
27 changes: 27 additions & 0 deletions tests/dotnet/ExtensionConsumerWithFrameworks/shared.csproj
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<OutputType>Exe</OutputType>

<ApplicationTitle>ExtensionConsumerWithFramework</ApplicationTitle>
<ApplicationId>com.xamarin.extensionconsumerwithframework</ApplicationId>
<RootTestsDirectory Condition="'$(RootTestsDirectory)' == ''">$(MSBuildThisFileDirectory)/../..</RootTestsDirectory>
</PropertyGroup>

<Import Project="../../common/shared-dotnet.csproj" />

<ItemGroup>
<Compile Include="../*.cs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\ExtensionProjectWithFrameworks\$(_PlatformName)\ExtensionProjectWithFrameworks.csproj">
<IsAppExtension>true</IsAppExtension>
</ProjectReference>

<!-- Both the extension and the consumer references UnknownE.framework -->
<None Include="$(RootTestsDirectory)/test-libraries/frameworks/.libs/$(RuntimeIdentifier)/UnknownE.framework" CopyToPublishDirectory="PreserveNewest" PublishFolderType="AppleFramework" />
<!-- Only the consumer references SomewhatUnknownD.framework -->
<None Include="$(RootTestsDirectory)/test-libraries/frameworks/.libs/$(RuntimeIdentifier)/SomewhatUnknownD.framework.zip" CopyToPublishDirectory="PreserveNewest" Link="Subfolder/SomewhatUnknownD.bin" PublishFolderType="CompressedAppleFramework" />
</ItemGroup>
</Project>
2 changes: 2 additions & 0 deletions tests/dotnet/ExtensionConsumerWithFrameworks/shared.mk
@@ -0,0 +1,2 @@
TOP=../../../..
include $(TOP)/tests/common/shared-dotnet.mk
@@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySimpleApp", "MySimpleApp.csproj", "{D8448FDC-1002-432B-A3A7-CCFCB833F292}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionProject", "..\..\ExtensionProject\tvOS\ExtensionProject.csproj", "{CD69BE1D-FF1B-4B6A-AB6E-5259E65B515E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D8448FDC-1002-432B-A3A7-CCFCB833F292}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8448FDC-1002-432B-A3A7-CCFCB833F292}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8448FDC-1002-432B-A3A7-CCFCB833F292}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8448FDC-1002-432B-A3A7-CCFCB833F292}.Release|Any CPU.Build.0 = Release|Any CPU
{CD69BE1D-FF1B-4B6A-AB6E-5259E65B515E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CD69BE1D-FF1B-4B6A-AB6E-5259E65B515E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CD69BE1D-FF1B-4B6A-AB6E-5259E65B515E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CD69BE1D-FF1B-4B6A-AB6E-5259E65B515E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net$(BundledNETCoreAppTargetFrameworkVersion)-tvos</TargetFramework>
</PropertyGroup>
<Import Project="..\shared.csproj" />
</Project>
@@ -0,0 +1 @@
include ../shared.mk
2 changes: 2 additions & 0 deletions tests/dotnet/ExtensionProjectWithFrameworks/Makefile
@@ -0,0 +1,2 @@
TOP=../../..
include $(TOP)/tests/common/shared-dotnet-test.mk
@@ -0,0 +1,6 @@
<?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,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionProject", "ExtensionProject.csproj", "{6938058D-AE12-4CF8-A3DD-E27BCCEF1E6E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6938058D-AE12-4CF8-A3DD-E27BCCEF1E6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6938058D-AE12-4CF8-A3DD-E27BCCEF1E6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6938058D-AE12-4CF8-A3DD-E27BCCEF1E6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6938058D-AE12-4CF8-A3DD-E27BCCEF1E6E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net$(BundledNETCoreAppTargetFrameworkVersion)-ios</TargetFramework>
</PropertyGroup>
<Import Project="..\shared.csproj" />
</Project>