diff --git a/eng/testing/AppleRunnerTemplate.sh b/eng/testing/AppleRunnerTemplate.sh index 47352018d1ac4..42f787af20d88 100644 --- a/eng/testing/AppleRunnerTemplate.sh +++ b/eng/testing/AppleRunnerTemplate.sh @@ -35,6 +35,8 @@ if [[ "$TARGET" == "ios-device" ]]; then SCHEME_SDK=Release-iphoneos; fi if [[ "$TARGET" == "tvos-device" ]]; then SCHEME_SDK=Release-appletvos; fi if [[ "$TARGET" == "maccatalyst" ]]; then SCHEME_SDK=Release-maccatalyst; fi +if [[ "$TARGET" == "ios-device" || "$TARGET" == "tvos-device" ]]; then SIGNAL_APP_END="--signal-app-end"; fi + cd $EXECUTION_DIR # it doesn't support parallel execution yet, so, here is a hand-made semaphore: @@ -62,6 +64,7 @@ $HARNESS_RUNNER apple $XHARNESS_CMD \ --targets="$TARGET" \ --xcode="$XCODE_PATH" \ --output-directory="$XHARNESS_OUT" \ + $SIGNAL_APP_END \ $ADDITIONAL_ARGS _exitCode=$? diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 698e5884ccf05..c62916ed2d15a 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -2,6 +2,9 @@ $([MSBuild]::NormalizeDirectory('$(OutDir)', 'AppBundle')) + $(AppBundleRoot)tests\$(AssemblyName) + $(AppBundleRoot)runonly\$(AssemblyName) + $([MSBuild]::NormalizeDirectory('$(PublishDir)', 'AppBundle')) $([MSBuild]::NormalizePath('$(BundleDir)', '$(RunScriptOutputName)')) true @@ -159,6 +162,10 @@ true AppleTestRunner.dll <_MobileIntermediateOutputPath Condition="'$(RunAOTCompilation)' == 'true'">$(IntermediateOutputPath)mobile + true + false + false + true Full @@ -217,8 +224,9 @@ ForceInterpreter="$(MonoForceInterpreter)" InvariantGlobalization="$(InvariantGlobalization)" UseConsoleUITemplate="True" - GenerateXcodeProject="True" - BuildAppBundle="True" + GenerateXcodeProject="$(GenerateXcodeProject)" + GenerateCMakeProject="$(GenerateCMakeProject)" + BuildAppBundle="$(GenerateXcodeProject)" Optimized="$(Optimized)" DevTeamProvisioning="$(DevTeamProvisioning)" OutputDirectory="$(BundleDir)" @@ -226,17 +234,17 @@ - - + + - + <_appFiles Include="$(AppBundlePath)/../**/*" /> + Condition="'$(ArchiveTests)' == 'true' and '$(IgnoreForCI)' != 'true' and '$(GenerateXcodeProject)' == 'true'" /> diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props index e7d17e8005c17..635f2bfc037ce 100644 --- a/src/libraries/Directory.Build.props +++ b/src/libraries/Directory.Build.props @@ -116,6 +116,9 @@ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(TestArchiveRoot)runtime/ + true + $(ArtifactsDir)bundles\ + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'ref', '$(NetCoreAppCurrent)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'runtime', '$(NetCoreAppCurrent)-$(TargetOS)-$(Configuration)-$(TargetArchitecture)')) diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 5c3c8dcf0c9b0..95e71caccc534 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -332,6 +332,85 @@ Condition="'$(TestAssemblies)' == 'true' and '$(Coverage)' == 'true'" /> + + + + + + + + + + $(TestArchiveRoot)tests/ + $(TestArchiveRoot)runonly/ + + $(TestArchiveNormalTestsRoot)$(OSPlatformConfig)/ + $(TestArchiveFunctionalTestsRoot)$(OSPlatformConfig)/ + + $(AppBundleRoot)/tests/ + $(AppBundleRoot)/runonly/ + + $(AppBundleRoot)/tests.all/ + $(AppBundleRoot)/runonly.all/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - /// The Apple OS we are targeting (iOS or tvOS) + /// The Apple OS we are targeting (ios, tvos, iossimulator, tvossimulator) /// [Required] public string TargetOS @@ -64,7 +64,7 @@ public string TargetOS public ITaskItem[] Assemblies { get; set; } = Array.Empty(); /// - /// Target arch, can be "arm64" (device) or "x64" (simulator) at the moment + /// Target arch, can be "arm64", "arm" or "x64" at the moment /// [Required] public string Arch { get; set; } = ""!; @@ -106,6 +106,11 @@ public string TargetOS /// public bool GenerateXcodeProject { get; set; } + /// + /// Generate CMake project + /// + public bool GenerateCMakeProject { get; set; } + /// /// Files to be ignored in AppDir /// @@ -224,14 +229,12 @@ public override bool Execute() throw new ArgumentException("Using DiagnosticPorts require diagnostics_tracing runtime component."); } + var generator = new Xcode(Log, TargetOS, Arch); + if (GenerateXcodeProject) { - Xcode generator = new Xcode(Log, TargetOS, Arch); - generator.EnableRuntimeLogging = EnableRuntimeLogging; - generator.DiagnosticPorts = DiagnosticPorts; - XcodeProjectPath = generator.GenerateXCode(ProjectName, MainLibraryFileName, assemblerFiles, assemblerFilesToLink, - AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, RuntimeComponents, NativeMainSource); + AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, EnableRuntimeLogging, DiagnosticPorts, RuntimeComponents, NativeMainSource); if (BuildAppBundle) { @@ -242,10 +245,15 @@ public override bool Execute() } else { - AppBundlePath = generator.BuildAppBundle(XcodeProjectPath, Arch, Optimized, DevTeamProvisioning); + AppBundlePath = generator.BuildAppBundle(XcodeProjectPath, Optimized, DevTeamProvisioning); } } } + else if (GenerateCMakeProject) + { + generator.GenerateCMake(ProjectName, MainLibraryFileName, assemblerFiles, assemblerFilesToLink, + AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, EnableRuntimeLogging, DiagnosticPorts, RuntimeComponents, NativeMainSource); + } return true; } diff --git a/src/tasks/AppleAppBuilder/Xcode.cs b/src/tasks/AppleAppBuilder/Xcode.cs index 2e938d8ea0e36..05a643c304727 100644 --- a/src/tasks/AppleAppBuilder/Xcode.cs +++ b/src/tasks/AppleAppBuilder/Xcode.cs @@ -9,10 +9,111 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; +public class XcodeCreateProject : Task +{ + private string targetOS = TargetNames.iOS; + + /// + /// The Apple OS we are targeting (ios, tvos, iossimulator, tvossimulator) + /// + [Required] + public string TargetOS + { + get + { + return targetOS; + } + + set + { + targetOS = value.ToLower(); + } + } + + /// + /// Target arch, can be "arm64", "arm" or "x64" at the moment + /// + [Required] + public string Arch { get; set; } = ""!; + + /// + /// Path to the directory with the CMakeLists.txt to create a project for. + /// + [Required] + public string CMakeListsDirectory { get; set; } = ""!; + + /// + /// Name of the generated project. + /// + [Required] + public string ProjectName { get; set; } = ""!; + + public override bool Execute() + { + new Xcode(Log, TargetOS, Arch).CreateXcodeProject(ProjectName, CMakeListsDirectory); + + return true; + } +} + +public class XcodeBuildApp : Task +{ + private string targetOS = TargetNames.iOS; + + /// + /// The Apple OS we are targeting (ios, tvos, iossimulator, tvossimulator) + /// + [Required] + public string TargetOS + { + get + { + return targetOS; + } + + set + { + targetOS = value.ToLower(); + } + } + + /// + /// Target arch, can be "arm64", "arm" or "x64" at the moment + /// + [Required] + public string Arch { get; set; } = ""!; + + /// + /// Path to the .xcodeproj file + /// + [Required] + public string XcodeProjectPath { get; set; } = ""!; + + /// + /// DEVELOPER_TEAM provisioning, needed for arm64 builds. + /// + public string? DevTeamProvisioning { get; set; } + + /// + /// Produce optimized binaries and use 'Release' config in xcode + /// + public bool Optimized { get; set; } + + /// Path to the directory where the .app should be created + /// + public string? DestinationFolder { get; set; } + + public override bool Execute() + { + new Xcode(Log, TargetOS, Arch).BuildAppBundle(XcodeProjectPath, Optimized, DevTeamProvisioning, DestinationFolder); + + return true; + } +} + internal class Xcode { private string RuntimeIdentifier { get; set; } - private string SysRoot { get; set; } private string Target { get; set; } private string XcodeArch { get; set; } private TaskLoggingHelper Logger { get; set; } @@ -21,33 +122,71 @@ public Xcode(TaskLoggingHelper logger, string target, string arch) { Logger = logger; Target = target; - XcodeArch = (arch == "x64") ? "x86_64" : arch; + RuntimeIdentifier = $"{Target}-{arch}"; + XcodeArch = arch switch { + "x64" => "x86_64", + "arm" => "armv7", + _ => arch + }; + } + + public string GenerateXCode( + string projectName, + string entryPointLib, + IEnumerable asmFiles, + IEnumerable asmLinkFiles, + string workspace, + string binDir, + string monoInclude, + bool preferDylibs, + bool useConsoleUiTemplate, + bool forceAOT, + bool forceInterpreter, + bool invariantGlobalization, + bool optimized, + bool enableRuntimeLogging, + string? diagnosticPorts, + string? runtimeComponents=null, + string? nativeMainSource = null) + { + var cmakeDirectoryPath = GenerateCMake(projectName, entryPointLib, asmFiles, asmLinkFiles, workspace, binDir, monoInclude, preferDylibs, useConsoleUiTemplate, forceAOT, forceInterpreter, invariantGlobalization, optimized, enableRuntimeLogging, diagnosticPorts, runtimeComponents, nativeMainSource); + CreateXcodeProject(projectName, cmakeDirectoryPath); + return Path.Combine(binDir, projectName, projectName + ".xcodeproj"); + } + + public void CreateXcodeProject(string projectName, string cmakeDirectoryPath) + { + string targetName; switch (Target) { - case TargetNames.iOS: - SysRoot = Utils.RunProcess(Logger, "xcrun", "--sdk iphoneos --show-sdk-path"); + case TargetNames.MacCatalyst: + targetName = "Darwin"; break; + case TargetNames.iOS: case TargetNames.iOSsim: - SysRoot = Utils.RunProcess(Logger, "xcrun", "--sdk iphonesimulator --show-sdk-path"); + targetName = "iOS"; break; case TargetNames.tvOS: - SysRoot = Utils.RunProcess(Logger, "xcrun", "--sdk appletvos --show-sdk-path"); - break; case TargetNames.tvOSsim: - SysRoot = Utils.RunProcess(Logger, "xcrun", "--sdk appletvsimulator --show-sdk-path"); + targetName = "tvOS"; break; default: - SysRoot = Utils.RunProcess(Logger, "xcrun", "--sdk macosx --show-sdk-path"); + targetName = Target.ToString(); break; } + var deployTarget = (Target == TargetNames.MacCatalyst) ? " -DCMAKE_OSX_ARCHITECTURES=" + XcodeArch : " -DCMAKE_OSX_DEPLOYMENT_TARGET=10.1"; + var cmakeArgs = new StringBuilder(); + cmakeArgs + .Append("-S.") + .Append(" -B").Append(projectName) + .Append(" -GXcode") + .Append(" -DCMAKE_SYSTEM_NAME=").Append(targetName) + .Append(deployTarget); - RuntimeIdentifier = $"{Target}-{arch}"; + Utils.RunProcess(Logger, "cmake", cmakeArgs.ToString(), workingDir: cmakeDirectoryPath); } - public bool EnableRuntimeLogging { get; set; } - public string? DiagnosticPorts { get; set; } = ""!; - - public string GenerateXCode( + public string GenerateCMake( string projectName, string entryPointLib, IEnumerable asmFiles, @@ -60,13 +199,15 @@ public string GenerateXCode( bool forceAOT, bool forceInterpreter, bool invariantGlobalization, - bool stripDebugSymbols, + bool optimized, + bool enableRuntimeLogging, + string? diagnosticPorts, string? runtimeComponents=null, string? nativeMainSource = null) { // bundle everything as resources excluding native files var excludes = new List { ".dll.o", ".dll.s", ".dwarf", ".m", ".h", ".a", ".bc", "libmonosgen-2.0.dylib", "libcoreclr.dylib" }; - if (stripDebugSymbols) + if (optimized) { excludes.Add(".pdb"); } @@ -181,9 +322,9 @@ public string GenerateXCode( { // these libraries are linked via modules.m var name = Path.GetFileNameWithoutExtension(asm); - aotSources += $"add_library({name} OBJECT {asm}){Environment.NewLine}"; - toLink += $" {name}{Environment.NewLine}"; - aotList += $" {name}"; + aotSources += $"add_library({projectName}_{name} OBJECT {asm}){Environment.NewLine}"; + toLink += $" {projectName}_{name}{Environment.NewLine}"; + aotList += $" {projectName}_{name}"; } foreach (string asmLinkFile in asmLinkFiles) @@ -219,14 +360,14 @@ public string GenerateXCode( defines.AppendLine("add_definitions(-DINVARIANT_GLOBALIZATION=1)"); } - if (EnableRuntimeLogging) + if (enableRuntimeLogging) { defines.AppendLine("add_definitions(-DENABLE_RUNTIME_LOGGING=1)"); } - if (!string.IsNullOrEmpty(DiagnosticPorts)) + if (!string.IsNullOrEmpty(diagnosticPorts)) { - defines.AppendLine($"\nadd_definitions(-DDIAGNOSTIC_PORTS=\"{DiagnosticPorts}\")"); + defines.AppendLine($"\nadd_definitions(-DDIAGNOSTIC_PORTS=\"{diagnosticPorts}\")"); } cmakeLists = cmakeLists.Replace("%Defines%", defines.ToString()); @@ -252,33 +393,6 @@ public string GenerateXCode( File.WriteAllText(Path.Combine(binDir, "app.entitlements"), entitlementsTemplate.Replace("%Entitlements%", ent.ToString())); } - string targetName; - switch (Target) - { - case TargetNames.MacCatalyst: - targetName = "Darwin"; - break; - case TargetNames.iOS: - case TargetNames.iOSsim: - targetName = "iOS"; - break; - case TargetNames.tvOS: - case TargetNames.tvOSsim: - targetName = "tvOS"; - break; - default: - targetName = Target.ToString(); - break; - } - var deployTarget = (Target == TargetNames.MacCatalyst) ? " -DCMAKE_OSX_ARCHITECTURES=" + XcodeArch : " -DCMAKE_OSX_DEPLOYMENT_TARGET=10.1"; - var cmakeArgs = new StringBuilder(); - cmakeArgs - .Append("-S.") - .Append(" -B").Append(projectName) - .Append(" -GXcode") - .Append(" -DCMAKE_SYSTEM_NAME=").Append(targetName) - .Append(deployTarget); - File.WriteAllText(Path.Combine(binDir, "runtime.h"), Utils.GetEmbeddedResource("runtime.h")); @@ -302,13 +416,11 @@ public string GenerateXCode( .Replace("//%APPLE_RUNTIME_IDENTIFIER%", RuntimeIdentifier) .Replace("%EntryPointLibName%", Path.GetFileName(entryPointLib))); - Utils.RunProcess(Logger, "cmake", cmakeArgs.ToString(), workingDir: binDir); - - return Path.Combine(binDir, projectName, projectName + ".xcodeproj"); + return binDir; } public string BuildAppBundle( - string xcodePrjPath, string architecture, bool optimized, string? devTeamProvisioning = null) + string xcodePrjPath, bool optimized, string? devTeamProvisioning = null, string? destination = null) { string sdk = ""; var args = new StringBuilder(); @@ -330,29 +442,28 @@ public string BuildAppBundle( .Append(" DEVELOPMENT_TEAM=").Append(devTeamProvisioning); } - - if (architecture == "arm64") + if (XcodeArch == "arm64" || XcodeArch == "armv7") { switch (Target) { case TargetNames.iOS: sdk = "iphoneos"; - args.Append(" -arch arm64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; case TargetNames.iOSsim: sdk = "iphonesimulator"; - args.Append(" -arch arm64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; case TargetNames.tvOS: sdk = "appletvos"; - args.Append(" -arch arm64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; case TargetNames.tvOSsim: sdk = "appletvsimulator"; - args.Append(" -arch arm64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; default: @@ -372,12 +483,12 @@ public string BuildAppBundle( { case TargetNames.iOSsim: sdk = "iphonesimulator"; - args.Append(" -arch x86_64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; case TargetNames.tvOSsim: sdk = "appletvsimulator"; - args.Append(" -arch x86_64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; default: @@ -400,6 +511,13 @@ public string BuildAppBundle( string appPath = Path.Combine(Path.GetDirectoryName(xcodePrjPath)!, config + "-" + sdk, Path.GetFileNameWithoutExtension(xcodePrjPath) + ".app"); + if (destination != null) + { + var newAppPath = Path.Combine(destination, Path.GetFileNameWithoutExtension(xcodePrjPath) + ".app"); + Directory.Move(appPath, newAppPath); + appPath = newAppPath; + } + long appSize = new DirectoryInfo(appPath) .EnumerateFiles("*", SearchOption.AllDirectories) .Sum(file => file.Length);