From 97ab14801f21046cc078b55edd8678cd6415507d Mon Sep 17 00:00:00 2001 From: Andoni Morales Alastruey Date: Fri, 3 Feb 2023 09:16:40 +0100 Subject: [PATCH] [dotnet] Add support for .so files (#16887) Autotools-based project using libtool's -module flag generate plugins with the .so extension that needs to be treated like DynamicLibraries in terms of deployment location and relocation, except they are not linked to the app. This PR adds support for such .so files: they're treated as .dylib files, except that they're not linked to the app. --- dotnet/BundleContents.md | 15 +++++++++++++++ dotnet/targets/Xamarin.Shared.Sdk.targets | 18 ++++++++++++++---- .../Tasks/ComputeBundleLocationTaskBase.cs | 8 +++++++- .../BundleStructure/MacCatalyst/NoneQ.so | 1 + tests/dotnet/BundleStructure/iOS/NoneQ.so | 1 + tests/dotnet/BundleStructure/macOS/NoneQ.so | 1 + tests/dotnet/BundleStructure/shared.csproj | 8 ++++++++ tests/dotnet/BundleStructure/tvOS/NoneQ.so | 1 + tests/dotnet/UnitTests/BundleStructureTest.cs | 3 +++ tests/dotnet/UnitTests/ProjectTest.cs | 1 + tests/test-libraries/libraries/Makefile | 4 ++++ ...cLibrariesInRuntimesNativeDirectory.targets | 7 +++++++ 12 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 tests/dotnet/BundleStructure/MacCatalyst/NoneQ.so create mode 100644 tests/dotnet/BundleStructure/iOS/NoneQ.so create mode 100644 tests/dotnet/BundleStructure/macOS/NoneQ.so create mode 100644 tests/dotnet/BundleStructure/tvOS/NoneQ.so diff --git a/dotnet/BundleContents.md b/dotnet/BundleContents.md index 9cbcf799cb..cb8e45a866 100644 --- a/dotnet/BundleContents.md +++ b/dotnet/BundleContents.md @@ -63,6 +63,7 @@ wrong, then developers can override the target location by: * \*.framework.zip and \*.xcframework.zip: `PublishFolderType=CompressedAppleFramework` * \*.dylib: `PublishFolderType=DynamicLibrary` +* \*.so: `PublishFolderType=PluginLibrary` * \*.a: `PublishFolderType=StaticLibrary` * No other files are copied. We show a warning if we find any such files. @@ -174,6 +175,20 @@ The target directory is the same as for `Assembly`: *Warning*: The App Store will reject any apps with \*.dylib files (for iOS and tvOS, not for macOS or Mac Catalyst). +### PluginLibrary + +These are plugins provided as un-versioned dynamic library (\*.so or \*.dylib) files. + +An example are GStreamer plugins: `libgstogg.dylib` + +We will _not_ link with these libraries when linking the native executable since +this type of plugins are loaded on demand at runtime. + +The target directory is the same as for `DynamicLibrary` + +*Warning*: The App Store will reject any apps with dynamic library files, for iOS and +tvOS plugins must be provided as static libraries. + ### StaticLibrary These are static libraries (\*.a) files. diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets index cf45e7f9c2..0e48ed478b 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.targets +++ b/dotnet/targets/Xamarin.Shared.Sdk.targets @@ -1212,7 +1212,7 @@ - <_DynamicLibraryToReidentify Include="@(_FileNativeReference)" Condition="'%(Extension)' == '.dylib'"> + <_DynamicLibraryToReidentify Include="@(_FileNativeReference)" Condition="'%(Kind)' == 'Dynamic'"> _FileNativeReference %(_FileNativeReference.RelativePath) @@ -1257,6 +1257,12 @@ Outputs="$(_IntermediateNativeLibraryDir)$(_NativeExecutableName);$(_MtouchSymbolsList)" > + + <_NativeReferences Include="@(_FrameworkNativeReference)" /> + + <_NativeReferences Include="@(_FileNativeReference)" Condition="'%(_FileNativeReference.LinkToExecutable)' != 'false'" /> + + - + + Condition="('$(_SdkIsSimulator)' != 'false' Or '$(_PlatformName)' == 'macOS' Or '$(_PlatformName)' == 'MacCatalyst') And ('%(Extension)' == '.dylib' Or '%(Extension)' == '.so') " /> <_ResolvedFileToPublish_DynamicLibrary Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.PublishFolderType)' == 'DynamicLibrary'" /> <_FileNativeReference Include="@(_ResolvedFileToPublish_DynamicLibrary)" Kind="Dynamic" /> + + <_ResolvedFileToPublish_PluginLibrary Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.PublishFolderType)' == 'PluginLibrary'" /> + <_FileNativeReference Include="@(_ResolvedFileToPublish_PluginLibrary)" Kind="Dynamic" LinkToExecutable="false" /> + <_AppleBindingResourcePackage Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.PublishFolderType)' == 'AppleBindingResourcePackage'" /> diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeBundleLocationTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeBundleLocationTaskBase.cs index 21da64e4d3..d1fdb32c92 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeBundleLocationTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeBundleLocationTaskBase.cs @@ -135,6 +135,9 @@ namespace Xamarin.MacDev.Tasks { case PublishFolderType.DynamicLibrary: relativePath = AssemblyDirectory; break; + case PublishFolderType.PluginLibrary: + relativePath = AssemblyDirectory; + break; case PublishFolderType.StaticLibrary: // Nothing to do here. continue; @@ -320,11 +323,13 @@ namespace Xamarin.MacDev.Tasks { return PublishFolderType.CompressedAppleFramework; } - // *.a and *.dylib + // *.a, *.dylib and *.so if (filename.EndsWith (".a", StringComparison.OrdinalIgnoreCase)) { return PublishFolderType.StaticLibrary; } else if (filename.EndsWith (".dylib", StringComparison.OrdinalIgnoreCase)) { return PublishFolderType.DynamicLibrary; + } else if (filename.EndsWith (".so", StringComparison.OrdinalIgnoreCase)) { + return PublishFolderType.PluginLibrary; } // no other files are copied @@ -363,6 +368,7 @@ namespace Xamarin.MacDev.Tasks { PlugIns, CompressedPlugIns, DynamicLibrary, // link with + copy to app bundle + PluginLibrary, // copy to app bundle (but not link with main executable) StaticLibrary, // link with (but not copy to app bundle) Unknown, } diff --git a/tests/dotnet/BundleStructure/MacCatalyst/NoneQ.so b/tests/dotnet/BundleStructure/MacCatalyst/NoneQ.so new file mode 100644 index 0000000000..ed4b4730b5 --- /dev/null +++ b/tests/dotnet/BundleStructure/MacCatalyst/NoneQ.so @@ -0,0 +1 @@ +NoneQ diff --git a/tests/dotnet/BundleStructure/iOS/NoneQ.so b/tests/dotnet/BundleStructure/iOS/NoneQ.so new file mode 100644 index 0000000000..ed4b4730b5 --- /dev/null +++ b/tests/dotnet/BundleStructure/iOS/NoneQ.so @@ -0,0 +1 @@ +NoneQ diff --git a/tests/dotnet/BundleStructure/macOS/NoneQ.so b/tests/dotnet/BundleStructure/macOS/NoneQ.so new file mode 100644 index 0000000000..ed4b4730b5 --- /dev/null +++ b/tests/dotnet/BundleStructure/macOS/NoneQ.so @@ -0,0 +1 @@ +NoneQ diff --git a/tests/dotnet/BundleStructure/shared.csproj b/tests/dotnet/BundleStructure/shared.csproj index 3bd836e1a0..e80f1ff016 100644 --- a/tests/dotnet/BundleStructure/shared.csproj +++ b/tests/dotnet/BundleStructure/shared.csproj @@ -54,6 +54,10 @@ PreserveNewest + + + PreserveNewest + PreserveNewest @@ -103,6 +107,10 @@ PreserveNewest + + + PreserveNewest + diff --git a/tests/dotnet/BundleStructure/tvOS/NoneQ.so b/tests/dotnet/BundleStructure/tvOS/NoneQ.so new file mode 100644 index 0000000000..ed4b4730b5 --- /dev/null +++ b/tests/dotnet/BundleStructure/tvOS/NoneQ.so @@ -0,0 +1 @@ +NoneQ diff --git a/tests/dotnet/UnitTests/BundleStructureTest.cs b/tests/dotnet/UnitTests/BundleStructureTest.cs index 47841719b2..054edf6f66 100644 --- a/tests/dotnet/UnitTests/BundleStructureTest.cs +++ b/tests/dotnet/UnitTests/BundleStructureTest.cs @@ -120,6 +120,7 @@ namespace Xamarin.Tests { expectedFiles.Add ($"{assemblyDirectory}NoneC.pdb"); expectedFiles.Add ($"{assemblyDirectory}NoneD.exe"); expectedFiles.Add ($"{assemblyDirectory}libNoneE.dylib"); + expectedFiles.Add ($"{assemblyDirectory}libNoneE.so"); // NoneF.a is not bundled // Sub/NoneG.txt is not bundled // Sub/NoneH.txt is not bundled @@ -129,6 +130,7 @@ namespace Xamarin.Tests { expectedFiles.Add ($"{assemblyDirectory}NoneL.config"); // NoneM.unknown is not bundled expectedFiles.Add ($"{assemblyDirectory}libSkipInstallNameTool.dylib"); + expectedFiles.Add ($"{assemblyDirectory}libSkipInstallNameTool.so"); expectedFiles.Add ($"{resourcesDirectory}basn3p08.png"); expectedFiles.Add ($"{resourcesDirectory}basn3p08_with_loc.png"); @@ -335,6 +337,7 @@ namespace Xamarin.Tests { Assert.That (missingFiles, Is.Empty, "No missing files"); AssertDynamicLibraryId (platform, appPath, assemblyDirectory, "libSkipInstallNameTool.dylib"); + AssertDynamicLibraryId (platform, appPath, assemblyDirectory, "libSkipInstallNameTool.so"); AssertLibraryArchitectures (appPath, runtimeIdentifiers); } diff --git a/tests/dotnet/UnitTests/ProjectTest.cs b/tests/dotnet/UnitTests/ProjectTest.cs index 5ed055c601..39e2beaecc 100644 --- a/tests/dotnet/UnitTests/ProjectTest.cs +++ b/tests/dotnet/UnitTests/ProjectTest.cs @@ -1218,6 +1218,7 @@ namespace Xamarin.Tests { AssertThatDylibExistsAndIsReidentified (appPath, "libtest.dylib"); AssertThatDylibExistsAndIsReidentified (appPath, "/subdir/libtest.dylib"); + AssertThatDylibExistsAndIsReidentified (appPath, "/subdir/libtest.so"); ExecuteWithMagicWordAndAssert (appExecutable); } diff --git a/tests/test-libraries/libraries/Makefile b/tests/test-libraries/libraries/Makefile index 13c34b1ee0..a27609a8fc 100644 --- a/tests/test-libraries/libraries/Makefile +++ b/tests/test-libraries/libraries/Makefile @@ -35,6 +35,7 @@ $(1)_$(3)_TARGETS += \ .libs/$(3)/lib$(1).a \ .libs/$(3)/lib$(1).o \ .libs/$(3)/lib$(1).dylib \ + .libs/$(3)/lib$(1).so \ $(3)_TARGETS += \ $$($(1)_$(3)_TARGETS) \ @@ -56,6 +57,9 @@ endif .libs/$(3)/lib$(1).a: .libs/$(3)/lib$(1).o $$(call Q_2,AR [$(1)]) $(XCODE_DEVELOPER_ROOT)/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar cru $$@ $$< +.libs/$(3)/lib$(1).so: .libs/$(3)/lib$(1).dylib + $$(Q) $(CP) .libs/$(3)/lib$(1).dylib .libs/$(3)/lib$(1).so + $$($(3)_$(1)_DIRECTORIES): $$(Q) mkdir -p $$@ diff --git a/tests/test-libraries/nugets/DynamicLibrariesInRuntimesNativeDirectory/Xamarin.Tests.DynamicLibrariesInRuntimesNativeDirectory.targets b/tests/test-libraries/nugets/DynamicLibrariesInRuntimesNativeDirectory/Xamarin.Tests.DynamicLibrariesInRuntimesNativeDirectory.targets index ddb2d06307..837d26bd97 100644 --- a/tests/test-libraries/nugets/DynamicLibrariesInRuntimesNativeDirectory/Xamarin.Tests.DynamicLibrariesInRuntimesNativeDirectory.targets +++ b/tests/test-libraries/nugets/DynamicLibrariesInRuntimesNativeDirectory/Xamarin.Tests.DynamicLibrariesInRuntimesNativeDirectory.targets @@ -7,5 +7,12 @@ PreserveNewest Included + + false + $(OutputDirectory)\subdir\%(FileName).so + PreserveNewest + PreserveNewest + Included + \ No newline at end of file