-
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 18 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 |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// 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 binDir, | ||
string[] libsToPrecompile, | ||
IDictionary<string, string> envVariables, | ||
bool optimize) | ||
{ | ||
Parallel.ForEach(libsToPrecompile, | ||
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, | ||
lib => PrecompileLibrary(crossCompiler, binDir, lib, envVariables, optimize)); | ||
} | ||
|
||
private static void PrecompileLibrary( | ||
string crossCompiler, | ||
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=arm64-ios,") | ||
.Append("static,") | ||
.Append("asmonly,") | ||
.Append("direct-icalls,") | ||
.Append("no-direct-calls,") | ||
.Append("dwarfdebug,") | ||
.Append("outfile=").Append(Path.Combine(binDir, libName + ".dll.s,")) | ||
.Append("full,"); | ||
|
||
// TODO: save *.aotdata | ||
// 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 arm64") | ||
.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,164 @@ | ||
// 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 a custom main.m with custom UI | ||
/// A default one is used if it's not set | ||
/// </summary> | ||
public string? NativeMainSource { get; set; } | ||
|
||
/// <summary> | ||
/// Produce optimized binaries (e.g. use -O2 in AOT) | ||
/// </summary> | ||
public bool Optimized { 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 *.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}"); | ||
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, 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, 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> |
39 changes: 39 additions & 0 deletions
39
src/mono/AppleAppBuilder/Templates/CMakeLists.txt.template
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,39 @@ | ||
cmake_minimum_required(VERSION 3.14.5) | ||
|
||
project(%ProjectName%) | ||
|
||
set(APP_RESOURCES | ||
%AppResources% | ||
) | ||
|
||
add_executable( | ||
%ProjectName% | ||
%MainSource% | ||
runtime.h | ||
runtime.m | ||
modules.m | ||
${APP_RESOURCES} | ||
) | ||
|
||
include_directories("%MonoInclude%") | ||
|
||
set_target_properties(%ProjectName% PROPERTIES | ||
MACOSX_BUNDLE TRUE | ||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in | ||
XCODE_ATTRIBUTE_ENABLE_BITCODE "NO" | ||
XCODE_ATTRIBUTE_DEAD_CODE_STRIPPING "NO" | ||
RESOURCE "${APP_RESOURCES}" | ||
) | ||
|
||
# FIXME: `XCODE_ATTRIBUTE_DEAD_CODE_STRIPPING` should not be NO | ||
|
||
target_link_libraries( | ||
%ProjectName% | ||
"-framework Foundation" | ||
"-framework Security" | ||
"-framework UIKit" | ||
"-framework GSS" | ||
"-lz" | ||
"-liconv" | ||
%NativeLibrariesToLink% | ||
) |
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
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.
I still think this should come as input to the task (e.g. from publish)
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.
the
AppDir
is basically thedotnet publish
location - we need everything in the directory anyway.Collection of files as an input makes it harder to use via command line 🙁