-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
@(XcodeProjectReference)
Introduces a new `@(XcodeProjectReference)` item to help simplify the content that needs to be added to the binding .csproj file. This item will translate relevant metadata to the `@(NativeReference)` item that is automatically added to the project after the xcode project is built. Build task wrappers for `xcodebuild` and `sharpie` have been added to improve msbuild output and error logging when a tool invocation fails.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -403,6 +403,7 @@ FodyWeavers.xsd | |
|
||
xcuserdata/ | ||
|
||
build/ | ||
.build/ | ||
*.xcframework | ||
Pods/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,94 +1,118 @@ | ||
<Project> | ||
|
||
<PropertyGroup> | ||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration> | ||
|
||
<XcodeDefaultBuildDir>.build</XcodeDefaultBuildDir> | ||
<XcodeBuildDirName Condition=" '$(XcodeBuildDirName)' == '' ">$(XcodeDefaultBuildDir)</XcodeBuildDirName> | ||
|
||
<_XcodeProjectFullPath>$([System.IO.Path]::GetFullPath($(XcodeProject)))</_XcodeProjectFullPath> | ||
|
||
<XcodeScheme Condition=" '$(XcodeScheme)' == '' ">$([System.IO.Path]::GetFilenameWithoutExtension($(XcodeProject)))</XcodeScheme> | ||
|
||
<XcodeProjectDir Condition=" '$(XcodeProjectDir)' == '' ">$([System.IO.Path]::GetDirectoryName($(_XcodeProjectFullPath)))</XcodeProjectDir> | ||
<XcodeBuildDir Condition=" '$(XcodeBuildDir)' == '' ">$([System.IO.Path]::Combine($(XcodeProjectDir), $(XcodeBuildDirName)))</XcodeBuildDir> | ||
|
||
<XcodeBuildXCFramework Condition=" '$(XcodeBuildXCFramework)' == '' ">True</XcodeBuildXCFramework> | ||
|
||
<XcodeBuildiOS Condition=" '$(XcodeBuildiOS)' == '' ">True</XcodeBuildiOS> | ||
<XcodeBuildiOSSimulator Condition=" '$(XcodeBuildiOSSimulator)' == '' ">True</XcodeBuildiOSSimulator> | ||
<XcodeBuildMacCatalyst Condition=" '$(XcodeBuildMacCatalyst)' == '' ">True</XcodeBuildMacCatalyst> | ||
|
||
<_XcodeBuildDirFullPath>$([System.IO.Path]::GetFullPath($(XcodeBuildDir)))</_XcodeBuildDirFullPath> | ||
<_XcodeProjectDirFullPath>$([System.IO.Path]::GetFullPath($(XcodeProjectDir)))</_XcodeProjectDirFullPath> | ||
|
||
<_XcArchiveiOSFullPath>$([System.IO.Path]::Combine($(_XcodeBuildDirFullPath), $(XcodeScheme)-ios.xcarchive))</_XcArchiveiOSFullPath> | ||
<_XcArchiveiOSSimulatorFullPath>$([System.IO.Path]::Combine($(_XcodeBuildDirFullPath), $(XcodeScheme)-iossimulator.xcarchive))</_XcArchiveiOSSimulatorFullPath> | ||
<_XcArchiveMacCatalystFullPath>$([System.IO.Path]::Combine($(_XcodeBuildDirFullPath), $(XcodeScheme)-maccatalyst.xcarchive))</_XcArchiveMacCatalystFullPath> | ||
<_XcArchiveExtraArgs>ENABLE_BITCODE=NO SKIP_INSTALL=NO SWIFT_INSTALL_OBJC_HEADER=YES BUILD_LIBRARY_FOR_DISTRIBUTION=YES OTHER_LDFLAGS='-ObjC' OTHER_SWIFT_FLAGS='-no-verify-emitted-module-interface' OBJC_CFLAGS='-fno-objc-msgsend-selector-stubs -ObjC'</_XcArchiveExtraArgs> | ||
|
||
<_XcFrameworkFullPath>$([System.IO.Path]::Combine($(_XcodeBuildDirFullPath), $(XcodeScheme).xcframework))</_XcFrameworkFullPath> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<_XcodeProjectInputs Include="$(_XcodeProjectDirFullPath)/**/*.swift" Exclude="$(_XcodeBuildDirFullPath)/**" /> | ||
<_XcodeProjectInputs Include="$(_XcodeProjectDirFullPath)/**/*.h" Exclude="$(_XcodeBuildDirFullPath)/**" /> | ||
<_XcodeProjectInputs Include="$(_XcodeProjectFullPath)/*.pbxproj" /> | ||
<_XcodeProjectInputs Include="$(_XcodeProjectFullPath)/*.xcworkspace" /> | ||
</ItemGroup> | ||
|
||
<PropertyGroup Condition="$(TargetFramework.Contains('ios')) Or $(TargetFramework.Contains('maccatalyst'))"> | ||
<_GenerateBindingsDependsOn> | ||
BuildXCFramework; | ||
ObjSharpieBind; | ||
$(_GenerateBindingsDependsOn); | ||
</_GenerateBindingsDependsOn> | ||
</PropertyGroup> | ||
|
||
<Target Name="BuildXCFramework" | ||
Condition=" '$(XcodeBuildXCFramework)' == 'true' " | ||
DependsOnTargets="$(BuildXCFrameworkDependsOnTargets)" | ||
Inputs="@(_XcodeProjectInputs)" | ||
Outputs="$(_XcFrameworkFullPath)/Info.plist"> | ||
<Error Condition=" !Exists('$(_XcodeProjectFullPath)') " Text="Xcode project '$(_XcodeProjectFullPath)' not found." /> | ||
|
||
<Exec Condition=" '$(XcodeBuildiOS)' == 'True' " Command="xcodebuild -project $(_XcodeProjectFullPath) archive -scheme $(XcodeScheme) -configuration $(Configuration) -archivePath $(_XcArchiveiOSFullPath) -destination 'generic/platform=iOS' $(_XcArchiveExtraArgs)" /> | ||
<Exec Condition=" '$(XcodeBuildiOSSimulator)' == 'True' " Command="xcodebuild -project $(_XcodeProjectFullPath) archive -scheme $(XcodeScheme) -configuration $(Configuration) -archivePath $(_XcArchiveiOSSimulatorFullPath) -destination 'generic/platform=iOS Simulator' $(_XcArchiveExtraArgs)" /> | ||
<Exec Condition=" '$(XcodeBuildMacCatalyst)' == 'True' " Command="xcodebuild -project $(_XcodeProjectFullPath) archive -scheme $(XcodeScheme) -configuration $(Configuration) -archivePath $(_XcArchiveMacCatalystFullPath) -destination 'generic/platform=macOS,variant=Mac Catalyst' $(_XcArchiveExtraArgs)" /> | ||
|
||
<ItemGroup> | ||
<_CreateXcFxArgs Include="-create-xcframework" /> | ||
<_CreateXcFxArgs Condition=" '$(XcodeBuildiOS)' == 'True' " Include="-archive $(_XcArchiveiOSFullPath) -framework $(XcodeScheme).framework" /> | ||
<_CreateXcFxArgs Condition=" '$(XcodeBuildiOSSimulator)' == 'True' " Include="-archive $(_XcArchiveiOSSimulatorFullPath) -framework $(XcodeScheme).framework" /> | ||
<_CreateXcFxArgs Condition=" '$(XcodeBuildMacCatalyst)' == 'True' " Include="-archive $(_XcArchiveMacCatalystFullPath) -framework $(XcodeScheme).framework" /> | ||
<_CreateXcFxArgs Include="-output $(_XcFrameworkFullPath)" /> | ||
</ItemGroup> | ||
|
||
<RemoveDir Directories="$(_XcFrameworkFullPath)" /> | ||
<Exec Command="xcodebuild @(_CreateXcFxArgs, ' ')" /> | ||
</Target> | ||
|
||
<PropertyGroup> | ||
<ObjSharpieBind Condition=" '$(ObjSharpieBind)' == '' ">True</ObjSharpieBind> | ||
<ObjSharpieBindOutputDir Condition=" '$(ObjSharpieBindOutputDir)' == '' ">$(_XcodeBuildDirFullPath)/Binding</ObjSharpieBindOutputDir> | ||
<ObjSharpieSourceHeader>$(_XcArchiveiOSFullPath)/Products/Library/Frameworks/$(XcodeScheme).framework/Headers/$(XcodeScheme)-Swift.h</ObjSharpieSourceHeader> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ObjcBindingApiDefinitionFiles Include="$(ObjSharpieBindOutputDir)/ApiDefinitions.cs" /> | ||
<_ObjSharpieInputs Include="$(ObjSharpieSourceHeader)" /> | ||
</ItemGroup> | ||
|
||
<Target Name="ObjSharpieBind" | ||
Condition="'$(ObjSharpieBind)' == 'true'" | ||
Inputs="@(_ObjSharpieInputs)" | ||
Outputs="@(ObjcBindingApiDefinitionFiles)"> | ||
<ItemGroup> | ||
<_ObjSharpieArgs Include="--output=$(ObjSharpieBindOutputDir)" /> | ||
<_ObjSharpieArgs Include="--namespace=$(ObjSharpieBindNamespace)" /> | ||
<_ObjSharpieArgs Include="--framework $(_XcArchiveiOSFullPath)/Products/Library/Frameworks/$(XcodeScheme).framework" /> | ||
</ItemGroup> | ||
<Exec Command="sharpie bind @(_ObjSharpieArgs, ' ')" /> | ||
</Target> | ||
<Import Project="$(MSBuildThisFileDirectory)Common.targets" Condition=" '$(CommonTargetsImported)' != 'true' " /> | ||
|
||
<UsingTask TaskName="Sharpie" AssemblyFile="$(BindingExtBuildTasksAssembly)"/> | ||
<UsingTask TaskName="XcodeBuild" AssemblyFile="$(BindingExtBuildTasksAssembly)"/> | ||
|
||
<PropertyGroup> | ||
<XcodeProjectConfiguration Condition=" '$(XcodeProjectConfiguration)' == '' ">Release</XcodeProjectConfiguration> | ||
<XcodeBuildiOS Condition=" '$(XcodeBuildiOS)' == '' ">true</XcodeBuildiOS> | ||
<XcodeBuildiOSSimulator Condition=" '$(XcodeBuildiOSSimulator)' == '' ">true</XcodeBuildiOSSimulator> | ||
<XcodeBuildMacCatalyst Condition=" '$(XcodeBuildMacCatalyst)' == '' ">true</XcodeBuildMacCatalyst> | ||
<EnableDefaultSharpieiOSItems Condition=" '$(EnableDefaultSharpieiOSItems)' == '' ">false</EnableDefaultSharpieiOSItems> | ||
|
||
<_XcArchiveExtraArgs>$(_XcArchiveExtraArgs) ENABLE_BITCODE=NO SKIP_INSTALL=NO SWIFT_INSTALL_OBJC_HEADER=YES BUILD_LIBRARY_FOR_DISTRIBUTION=YES</_XcArchiveExtraArgs> | ||
<_XcArchiveExtraArgs>$(_XcArchiveExtraArgs) OTHER_LDFLAGS="-ObjC" OTHER_SWIFT_FLAGS="-no-verify-emitted-module-interface" OBJC_CFLAGS="-fno-objc-msgsend-selector-stubs -ObjC"</_XcArchiveExtraArgs> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup Condition="$(TargetFramework.Contains('ios')) Or $(TargetFramework.Contains('maccatalyst'))"> | ||
<_GenerateBindingsDependsOn> | ||
_BuildXcodeProjects; | ||
_SharpieBindXcodeProjects; | ||
$(_GenerateBindingsDependsOn); | ||
</_GenerateBindingsDependsOn> | ||
</PropertyGroup> | ||
|
||
<ItemDefinitionGroup> | ||
<XcodeProjectReference> | ||
<Kind>Framework</Kind> | ||
<SmartLink>true</SmartLink> | ||
</XcodeProjectReference> | ||
</ItemDefinitionGroup> | ||
|
||
<!-- TODO Fix incremental builds --> | ||
<Target Name="_GetBuildXcodeProjectsInputs"> | ||
<ItemGroup> | ||
<_XcbInputs Include="@(XcodeProjectReference->'%(RootDir)%(Directory)**/*.swift')" /> | ||
<_XcbInputs Include="@(XcodeProjectReference->'%(RootDir)%(Directory)**/*.h')" /> | ||
<_XcbInputs Include="@(XcodeProjectReference->'%(RootDir)%(Directory)**/*.pbxproj')" /> | ||
<_XcbInputs Include="@(XcodeProjectReference->'%(RootDir)%(Directory)**/*.xcworkspace')"/> | ||
<_XcbInputs Remove="@(XcodeProjectReference->'%(RootDir)%(Directory)%(SchemeName)/build/**/*')" /> | ||
</ItemGroup> | ||
</Target> | ||
|
||
<Target Name="_BuildXcodeProjects" | ||
Condition=" '@(XcodeProjectReference->Count())' != '0' " | ||
DependsOnTargets="_EnsureBuildTasksAssembly;_GetBuildXcodeProjectsInputs;$(BuildXcodeProjectsDependsOnTargets)" | ||
Inputs="@(_XcbInputs)" | ||
Outputs="@(XcodeProjectReference->'%(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName).xcframework/Info.plist')" > | ||
|
||
<!-- Create xcarchive files for configured platforms --> | ||
<XcodeBuild Condition=" '$(XcodeBuildiOS)' == 'true' " | ||
Check failure on line 52 in eng/Common.macios.targets GitHub Actions / build
Check failure on line 52 in eng/Common.macios.targets GitHub Actions / build
Check failure on line 52 in eng/Common.macios.targets GitHub Actions / build
Check failure on line 52 in eng/Common.macios.targets GitHub Actions / build
Check failure on line 52 in eng/Common.macios.targets GitHub Actions / build
Check failure on line 52 in eng/Common.macios.targets GitHub Actions / build
Check failure on line 52 in eng/Common.macios.targets GitHub Actions / build
Check failure on line 52 in eng/Common.macios.targets GitHub Actions / build
Check failure on line 52 in eng/Common.macios.targets GitHub Actions / build
|
||
Arguments="-project "%(XcodeProjectReference.FullPath)" archive -scheme %(SchemeName) -configuration $(XcodeProjectConfiguration) -archivePath "@(XcodeProjectReference->'%(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName)-ios.xcarchive')" -destination "generic/platform=iOS" $(_XcArchiveExtraArgs)" | ||
WorkingDirectory="%(XcodeProjectReference.RootDir)%(XcodeProjectReference.Directory)" > | ||
</XcodeBuild> | ||
|
||
<XcodeBuild Condition=" '$(XcodeBuildiOSSimulator)' == 'true' " | ||
Arguments="-project "%(XcodeProjectReference.FullPath)" archive -scheme %(SchemeName) -configuration $(XcodeProjectConfiguration) -archivePath "@(XcodeProjectReference->'%(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName)-iossimulator.xcarchive')" -destination "generic/platform=iOS Simulator" $(_XcArchiveExtraArgs)" | ||
WorkingDirectory="%(XcodeProjectReference.RootDir)%(XcodeProjectReference.Directory)" > | ||
</XcodeBuild> | ||
|
||
<XcodeBuild Condition=" '$(XcodeBuildMacCatalyst)' == 'true' " | ||
Arguments="-project "%(XcodeProjectReference.FullPath)" archive -scheme %(SchemeName) -configuration $(XcodeProjectConfiguration) -archivePath "@(XcodeProjectReference->'%(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName)-maccatalyst.xcarchive')" -destination "generic/platform=macOS,variant=Mac Catalyst" $(_XcArchiveExtraArgs)" | ||
WorkingDirectory="%(XcodeProjectReference.RootDir)%(XcodeProjectReference.Directory)" > | ||
</XcodeBuild> | ||
|
||
<!-- Create xcframework file from xcarchive files --> | ||
<ItemGroup> | ||
<_CreateXcFxArgs Include="-create-xcframework" /> | ||
<_CreateXcFxArgs Condition=" '$(XcodeBuildiOS)' == 'true' " Include="@(XcodeProjectReference->'-archive %(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName)-ios.xcarchive')" /> | ||
<_CreateXcFxArgs Condition=" '$(XcodeBuildiOS)' == 'true' " Include="-framework %(XcodeProjectReference.SchemeName).framework" /> | ||
<_CreateXcFxArgs Condition=" '$(XcodeBuildiOSSimulator)' == 'true' " Include="@(XcodeProjectReference->'-archive %(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName)-iossimulator.xcarchive')" /> | ||
<_CreateXcFxArgs Condition=" '$(XcodeBuildiOSSimulator)' == 'true' " Include="-framework %(XcodeProjectReference.SchemeName).framework" /> | ||
<_CreateXcFxArgs Condition=" '$(XcodeBuildMacCatalyst)' == 'true' " Include="@(XcodeProjectReference->'-archive %(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName)-maccatalyst.xcarchive')" /> | ||
<_CreateXcFxArgs Condition=" '$(XcodeBuildMacCatalyst)' == 'true' " Include="-framework %(XcodeProjectReference.SchemeName).framework" /> | ||
<_CreateXcFxArgs Include="@(XcodeProjectReference->'-output %(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName).xcframework')" /> | ||
</ItemGroup> | ||
|
||
<RemoveDir Directories="@(XcodeProjectReference->'%(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName).xcframework')" /> | ||
|
||
<XcodeBuild Arguments="@(_CreateXcFxArgs, ' ')" | ||
WorkingDirectory="%(XcodeProjectReference.RootDir)%(XcodeProjectReference.Directory)" > | ||
</XcodeBuild> | ||
|
||
<ItemGroup> | ||
<NativeReference Include="@(XcodeProjectReference->'%(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName).xcframework')"> | ||
<Kind>%(XcodeProjectReference.Kind)</Kind> | ||
<SmartLink>%(XcodeProjectReference.SmartLink)</SmartLink> | ||
</NativeReference> | ||
</ItemGroup> | ||
|
||
<Error Condition=" !Exists('@(NativeReference)') " Text="Xcode project built successfully but did not produce expected output file: '@(NativeReference)'" /> | ||
<Message Text="Adding reference to Xcode project output: @(NativeReference)" /> | ||
</Target> | ||
|
||
|
||
<Target Name="_GetSharpieBindInputs"> | ||
<ItemGroup> | ||
<_SharpieInputs Include="@(XcodeProjectReference->'%(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName)-ios.xcarchive/Products/Library/Frameworks/%(SchemeName).framework')" /> | ||
</ItemGroup> | ||
</Target> | ||
|
||
<Target Name="_SharpieBindXcodeProjects" | ||
Condition=" '@(XcodeProjectReference->Count())' != '0' and '@(XcodeProjectReference->'%(SharpieBind)')' == 'true' " | ||
DependsOnTargets="_GetSharpieBindInputs" | ||
Inputs="@(_SharpieInputs)" | ||
Outputs="@(XcodeProjectReference->'%(RootDir)%(Directory)%(SchemeName)/build/sharpie/ApiDefinitions.cs')"> | ||
|
||
<ItemGroup> | ||
<_ObjSharpieArgs Include="@(XcodeProjectReference->'--output=%(RootDir)%(Directory)%(SchemeName)/build/sharpie')" /> | ||
<_ObjSharpieArgs Include="--namespace=%(XcodeProjectReference.SharpieNamespace)" /> | ||
<_ObjSharpieArgs Include="@(XcodeProjectReference->'--framework %(RootDir)%(Directory)%(SchemeName)/build/%(SchemeName)-ios.xcarchive/Products/Library/Frameworks/%(SchemeName).framework')" /> | ||
</ItemGroup> | ||
|
||
<Sharpie Arguments="bind @(_ObjSharpieArgs, ' ')" /> | ||
</Target> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
using Microsoft.Build.Framework; | ||
|
||
namespace Microsoft.Maui.BindingExtensions.Build.Tasks | ||
{ | ||
public class Sharpie : BindingToolTask | ||
{ | ||
public override string TaskPrefix => "SHRP"; | ||
|
||
protected override string ToolName => "sharpie"; | ||
|
||
|
||
public string Arguments { get; set; } = string.Empty; | ||
|
||
|
||
public Sharpie() | ||
{ | ||
} | ||
|
||
protected override string GenerateFullPathToTool() | ||
{ | ||
return Path.Combine("/usr", "local", "bin", ToolExe); | ||
} | ||
|
||
protected override string GenerateCommandLineCommands() => Arguments; | ||
|
||
public override bool RunTask() | ||
{ | ||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) | ||
{ | ||
if (!File.Exists (GenerateFullPathToTool ())) { | ||
Log.LogCodedWarning($"{TaskPrefix}1000", "Unable to locate `sharpie`, please install https://aka.ms/objective-sharpie."); | ||
return false; | ||
} | ||
|
||
return base.RunTask(); | ||
} | ||
else | ||
{ | ||
Log.LogCodedWarning($"{TaskPrefix}1000", "sharpie is not currently supported on this platform. Please build this project on a macOS machine."); | ||
return false; | ||
} | ||
} | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
using Microsoft.Build.Framework; | ||
|
||
namespace Microsoft.Maui.BindingExtensions.Build.Tasks | ||
{ | ||
public class XcodeBuild : BindingToolTask | ||
{ | ||
public override string TaskPrefix => "XCBD"; | ||
|
||
protected override string ToolName => "xcodebuild"; | ||
|
||
|
||
public string Arguments { get; set; } = string.Empty; | ||
|
||
|
||
public XcodeBuild() | ||
{ | ||
} | ||
|
||
protected override string GenerateFullPathToTool() | ||
{ | ||
return Path.Combine("/usr", "bin", ToolExe); | ||
} | ||
|
||
protected override string GenerateCommandLineCommands() => Arguments; | ||
|
||
public override bool RunTask() | ||
{ | ||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) | ||
{ | ||
return base.RunTask(); | ||
} | ||
else | ||
{ | ||
Log.LogCodedWarning($"{TaskPrefix}1000", "xcodebuild is not currently supported on this platform. Please build this project on a macOS machine."); | ||
return false; | ||
} | ||
} | ||
|
||
} | ||
} |