-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
[mono] Add iOS app builder project #34563
Merged
Merged
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
610b50a
Add iosAppBuilderTasks project
EgorBo df88839
Escape spaces in ProjectName
EgorBo f7d8299
Remove add_definitions(-DDEVICE)
EgorBo 08d6e92
Fix typoe Buillder -> Builder, also build the task as part of mono ru…
EgorBo bafe2e4
Rewrite HelloiOS sample (to use the task)
EgorBo ee568ec
Fix build
EgorBo 8449e82
Clean up
EgorBo 15a1682
Add license headers
EgorBo 19390d1
Clean up
EgorBo 183482b
dont build app if provisionig is not set
EgorBo 52a3b20
Add ExcludeFromAppDir input argument, remove stopwatch
EgorBo ee1531e
Merge branch 'master' of github.com:dotnet/runtime into ios-app-builder
EgorBo fd8e6c6
Drop DOTNET_SYSTEM_GLOBALIZATION_INVARIANT
EgorBo a80d1e9
Merge branch 'master' of github.com:dotnet/runtime into ios-app-builder
EgorBo 0afb383
Address feedback
EgorBo 22ada4a
Validate input
EgorBo 89f05c1
fix build
EgorBo be52a9d
Disable GenerateXcodeProject by default
EgorBo 5de1957
Merge branch 'master' of github.com:dotnet/runtime into ios-app-builder
EgorBo 0029a05
move to mono/msbuild
EgorBo 15c013d
Add OutputDirectory property
EgorBo fdd7f4b
Fix sample
EgorBo aa6d96a
Minor improvements
EgorBo 5c11b22
fix build issues
EgorBo bfcd8c9
Merge branch 'master' of github.com:dotnet/runtime into ios-app-builder
EgorBo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -860,6 +860,36 @@ | |
|
||
<Import Project="Directory.Build.targets" /> | ||
|
||
<Target Name="BuildAppleAppBuilder"> | ||
<MSBuild Projects="$(MonoProjectRoot)msbuild\AppleAppBuilder\AppleAppBuilder.csproj" | ||
Properties="Configuration=$(Configuration)" | ||
Targets="Restore;Build" /> | ||
</Target> | ||
|
||
<UsingTask TaskName="AppleAppBuilderTask" | ||
AssemblyFile="$(ArtifactsObjDir)mono\AppleAppBuilder\$(TargetArchitecture)\$(Configuration)\AppleAppBuilder.dll" /> | ||
|
||
<Target Name="BuildAppleApp" DependsOnTargets="BuildAppleAppBuilder"> | ||
<AppleAppBuilderTask | ||
Arch="$(TargetArchitecture)" | ||
ProjectName="$(ProjectName)" | ||
Optimized="$(Optimized)" | ||
MonoInclude="$(BinDir)include\mono-2.0" | ||
CrossCompiler="$(BinDir)cross\mono-aot-cross" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should also come from the runtime pack. |
||
MainLibraryFileName="$(MainLibraryFileName)" | ||
NativeMainSource="$(NativeMainSource)" | ||
GenerateXcodeProject="$(GenerateXcodeProject)" | ||
BuildAppBundle="$(BuildAppBundle)" | ||
DevTeamProvisioning="$(DevTeamProvisioning)" | ||
OutputDirectory="$(BinDir)\$(ProjectName)" | ||
AppDir="$(AppDir)"> | ||
<Output TaskParameter="AppBundlePath" PropertyName="AppBundlePath" /> | ||
<Output TaskParameter="XcodeProjectPath" PropertyName="XcodeProjectPath" /> | ||
</AppleAppBuilderTask> | ||
<Message Importance="High" Text="Xcode: $(XcodeProjectPath)"/> | ||
<Message Importance="High" Text="App: $(AppBundlePath)"/> | ||
</Target> | ||
|
||
<!-- Ordering matters! Overwriting the Build target. --> | ||
<!-- General targets --> | ||
<Target Name="Build" DependsOnTargets="BuildMonoRuntimeUnix;BuildMonoRuntimeWindows"> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
internal class AotCompiler | ||
{ | ||
/// <summary> | ||
/// Precompile all assemblies in parallel | ||
/// </summary> | ||
public static void PrecompileLibraries( | ||
string crossCompiler, | ||
string arch, | ||
bool parallel, | ||
string binDir, | ||
string[] libsToPrecompile, | ||
IDictionary<string, string> envVariables, | ||
bool optimize) | ||
{ | ||
Parallel.ForEach(libsToPrecompile, | ||
new ParallelOptions { MaxDegreeOfParallelism = parallel ? Environment.ProcessorCount : 1 }, | ||
lib => PrecompileLibrary(crossCompiler, binDir, lib, envVariables, optimize)); | ||
} | ||
|
||
private static void PrecompileLibrary( | ||
string crossCompiler, | ||
string arch, | ||
string binDir, | ||
string libToPrecompile, | ||
IDictionary<string, string> envVariables, | ||
bool optimize) | ||
{ | ||
Utils.LogInfo($"[AOT] {libToPrecompile}"); | ||
|
||
var crossArgs = new StringBuilder(); | ||
crossArgs | ||
.Append(" -O=gsharedvt,float32") | ||
.Append(" --nollvm") | ||
.Append(" --debug"); | ||
|
||
string libName = Path.GetFileNameWithoutExtension(libToPrecompile); | ||
var aotArgs = new StringBuilder(); | ||
aotArgs | ||
.Append("mtriple=".Append(arch).Append("-ios,") | ||
.Append("static,") | ||
.Append("asmonly,") | ||
.Append("direct-icalls,") | ||
.Append("no-direct-calls,") | ||
.Append("dwarfdebug,") | ||
.Append("outfile=").Append(Path.Combine(binDir, libName + ".dll.s,")) | ||
// TODO: | ||
//.Append("data-outfile=").Append(Path.Combine(binDir, libName + ".aotdata,")) | ||
.Append("full,"); | ||
|
||
// TODO: enable Interpreter | ||
// TODO: enable LLVM | ||
// TODO: enable System.Runtime.Intrinsics.Arm (LLVM-only for now) | ||
// e.g. .Append("mattr=+crc,") | ||
|
||
crossArgs | ||
.Append(" --aot=").Append(aotArgs).Append(" ") | ||
.Append(libToPrecompile); | ||
|
||
Utils.RunProcess(crossCompiler, crossArgs.ToString(), envVariables, binDir); | ||
|
||
var clangArgs = new StringBuilder(); | ||
if (optimize) | ||
{ | ||
clangArgs.Append(" -Os"); | ||
} | ||
clangArgs | ||
.Append(" -isysroot ").Append(Xcode.Sysroot) | ||
.Append(" -miphoneos-version-min=10.1") | ||
.Append(" -arch ").Append(arch) | ||
.Append(" -c ").Append(Path.Combine(binDir, libName)).Append(".dll.s") | ||
.Append(" -o ").Append(Path.Combine(binDir, libName)).Append(".dll.o"); | ||
|
||
Utils.RunProcess("clang", clangArgs.ToString(), workingDir: binDir); | ||
} | ||
|
||
public static void GenerateLinkAllFile(string[] objFiles, string outputFile) | ||
{ | ||
// Generates 'modules.m' in order to register all managed libraries | ||
// | ||
// | ||
// extern void *mono_aot_module_Lib1_info; | ||
// extern void *mono_aot_module_Lib2_info; | ||
// ... | ||
// | ||
// void mono_ios_register_modules (void) | ||
// { | ||
// mono_aot_register_module (mono_aot_module_Lib1_info); | ||
// mono_aot_register_module (mono_aot_module_Lib2_info); | ||
// ... | ||
// } | ||
|
||
Utils.LogInfo("Generating 'modules.m'..."); | ||
|
||
var lsDecl = new StringBuilder(); | ||
lsDecl | ||
.AppendLine("#include <mono/jit/jit.h>") | ||
.AppendLine("#include <TargetConditionals.h>") | ||
.AppendLine() | ||
.AppendLine("#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR") | ||
.AppendLine(); | ||
|
||
var lsUsage = new StringBuilder(); | ||
lsUsage | ||
.AppendLine("void mono_ios_register_modules (void)") | ||
.AppendLine("{"); | ||
foreach (string objFile in objFiles) | ||
{ | ||
string symbol = "mono_aot_module_" + | ||
Path.GetFileName(objFile) | ||
.Replace(".dll.o", "") | ||
.Replace(".", "_") | ||
.Replace("-", "_") + "_info"; | ||
|
||
lsDecl.Append("extern void *").Append(symbol).Append(';').AppendLine(); | ||
lsUsage.Append("\tmono_aot_register_module (").Append(symbol).Append(");").AppendLine(); | ||
} | ||
lsDecl | ||
.AppendLine() | ||
.Append(lsUsage) | ||
.AppendLine("}") | ||
.AppendLine() | ||
.AppendLine("#endif") | ||
.AppendLine(); | ||
|
||
File.WriteAllText(outputFile, lsDecl.ToString()); | ||
Utils.LogInfo($"Saved to {outputFile}."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Linq; | ||
using Microsoft.Build.Framework; | ||
using Microsoft.Build.Utilities; | ||
|
||
public class AppleAppBuilderTask : Task | ||
{ | ||
/// <summary> | ||
/// Path to arm64 AOT cross-compiler (mono-aot-cross) | ||
/// It's not used for x64 (Simulator) | ||
/// </summary> | ||
public string? CrossCompiler { get; set; } | ||
|
||
/// <summary> | ||
/// ProjectName is used as an app name, bundleId and xcode project name | ||
/// </summary> | ||
[Required] | ||
public string ProjectName { get; set; } = ""!; | ||
|
||
/// <summary> | ||
/// Target directory with *dll and other content to be AOT'd and/or bundled | ||
/// </summary> | ||
[Required] | ||
public string AppDir { get; set; } = ""!; | ||
|
||
/// <summary> | ||
/// Path to Mono public headers (*.h) | ||
/// </summary> | ||
[Required] | ||
public string MonoInclude { get; set; } = ""!; | ||
|
||
/// <summary> | ||
/// This library will be used as an entry-point (e.g. TestRunner.dll) | ||
/// </summary> | ||
[Required] | ||
public string MainLibraryFileName { get; set; } = ""!; | ||
|
||
/// <summary> | ||
/// Path to store build artifacts | ||
/// </summary> | ||
public string? OutputDirectory { get; set; } | ||
|
||
/// <summary> | ||
/// Produce optimized binaries (e.g. use -O2 in AOT) | ||
/// and use 'Release' config in xcode | ||
/// </summary> | ||
public bool Optimized { get; set; } | ||
|
||
/// <summary> | ||
/// Disable parallel AOT compilation | ||
/// </summary> | ||
public bool DisableParallelAot { get; set; }; | ||
|
||
/// <summary> | ||
/// Target arch, can be "arm64" (device) or "x64" (simulator) at the moment | ||
/// </summary> | ||
[Required] | ||
public string Arch { get; set; } = ""!; | ||
|
||
/// <summary> | ||
/// DEVELOPER_TEAM provisioning, needed for arm64 builds. | ||
/// </summary> | ||
public string? DevTeamProvisioning { get; set; } | ||
|
||
/// <summary> | ||
/// Build *.app bundle (using XCode for now) | ||
/// </summary> | ||
public bool BuildAppBundle { get; set; } | ||
|
||
/// <summary> | ||
/// Generate xcode project | ||
/// </summary> | ||
public bool GenerateXcodeProject { get; set; } | ||
|
||
/// <summary> | ||
/// Files to be ignored in AppDir | ||
/// </summary> | ||
public ITaskItem[]? ExcludeFromAppDir { get; set; } | ||
|
||
/// <summary> | ||
/// Path to a custom main.m with custom UI | ||
/// A default one is used if it's not set | ||
/// </summary> | ||
public string? NativeMainSource { get; set; } | ||
|
||
/// <summary> | ||
/// Use Console-style native UI template | ||
/// (use NativeMainSource to override) | ||
/// </summary> | ||
public bool UseConsoleUITemplate { get; set; } | ||
|
||
/// <summary> | ||
/// Path to *.app bundle | ||
/// </summary> | ||
[Output] | ||
public string AppBundlePath { get; set; } = ""!; | ||
|
||
/// <summary> | ||
/// Path to xcode project | ||
/// </summary> | ||
[Output] | ||
public string XcodeProjectPath { get; set; } = ""!; | ||
|
||
public override bool Execute() | ||
{ | ||
Utils.Logger = Log; | ||
bool isDevice = Arch.Equals("arm64", StringComparison.InvariantCultureIgnoreCase); | ||
if (isDevice && string.IsNullOrEmpty(CrossCompiler)) | ||
{ | ||
throw new ArgumentException("arm64 arch requires CrossCompiler"); | ||
} | ||
|
||
if (!File.Exists(Path.Combine(AppDir, MainLibraryFileName))) | ||
{ | ||
throw new ArgumentException($"MainLibraryFileName='{MainLibraryFileName}' was not found in AppDir='{AppDir}'"); | ||
} | ||
|
||
// escape spaces | ||
ProjectName = ProjectName.Replace(" ", "-"); | ||
|
||
string[] excludes = new string[0]; | ||
if (ExcludeFromAppDir != null) | ||
{ | ||
excludes = ExcludeFromAppDir | ||
.Where(i => !string.IsNullOrEmpty(i.ItemSpec)) | ||
.Select(i => i.ItemSpec) | ||
.ToArray(); | ||
} | ||
string[] libsToAot = Directory.GetFiles(AppDir, "*.dll") | ||
.Where(f => !excludes.Contains(Path.GetFileName(f))) | ||
.ToArray(); | ||
|
||
string binDir = Path.Combine(AppDir, $"bin-{ProjectName}-{Arch}"); | ||
if (!string.IsNullOrEmpty(OutputDirectory)) | ||
{ | ||
binDir = OutputDirectory; | ||
} | ||
Directory.CreateDirectory(binDir); | ||
|
||
// run AOT compilation only for devices | ||
if (isDevice) | ||
{ | ||
if (string.IsNullOrEmpty(CrossCompiler)) | ||
throw new InvalidOperationException("cross-compiler is not set"); | ||
|
||
AotCompiler.PrecompileLibraries(CrossCompiler, Arch, !DisableParallelAot, binDir, libsToAot, | ||
new Dictionary<string, string> { {"MONO_PATH", AppDir} }, | ||
Optimized); | ||
} | ||
|
||
// generate modules.m | ||
AotCompiler.GenerateLinkAllFile( | ||
Directory.GetFiles(binDir, "*.dll.o"), | ||
Path.Combine(binDir, "modules.m")); | ||
|
||
if (GenerateXcodeProject) | ||
{ | ||
XcodeProjectPath = Xcode.GenerateXCode(ProjectName, MainLibraryFileName, | ||
AppDir, binDir, MonoInclude, UseConsoleUITemplate, NativeMainSource); | ||
|
||
if (BuildAppBundle) | ||
{ | ||
if (isDevice && string.IsNullOrEmpty(DevTeamProvisioning)) | ||
{ | ||
// DevTeamProvisioning shouldn't be empty for arm64 builds | ||
Utils.LogInfo("DevTeamProvisioning is not set, BuildAppBundle step is skipped."); | ||
} | ||
else | ||
{ | ||
AppBundlePath = Xcode.BuildAppBundle( | ||
Path.Combine(binDir, ProjectName, ProjectName + ".xcodeproj"), | ||
Arch, Optimized, DevTeamProvisioning); | ||
} | ||
} | ||
Utils.LogInfo($"Xcode: {XcodeProjectPath}\n App: {AppBundlePath}"); | ||
} | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<OutputType>Library</OutputType> | ||
<OutputPath>bin</OutputPath> | ||
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<EmbeddedResource Include="Templates\*.*" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Build" Version="$(RefOnlyMicrosoftBuildVersion)" /> | ||
<PackageReference Include="Microsoft.Build.Framework" Version="$(RefOnlyMicrosoftBuildFrameworkVersion)" /> | ||
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="$(RefOnlyMicrosoftBuildTasksCoreVersion)" /> | ||
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(RefOnlyMicrosoftBuildUtilitiesCoreVersion)" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<Compile Include="AotCompiler.cs" /> | ||
<Compile Include="AppleAppBuilder.cs" /> | ||
<Compile Include="Utils.cs" /> | ||
<Compile Include="Xcode.cs" /> | ||
</ItemGroup> | ||
</Project> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should better come from runtime pack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @steveisok @akoeplinger
how do I build the "runtime pack", I've just built my repo with
build.sh -c Release -os iOS -arch arm64 -subset Mono+Libs+Libs.Tests
and don't see any runtime packs. The only location where I can findmono-2.0
headers andmono-aot-cross
is this$(BinDir)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's in a PR. You'll have to update
src/mono/netcore/sample/iOS/Program.csproj
when it's ready.