[release/7.0.2xx-xcode14.3] [dotnet] Add targets to compute mlaunch arguments for installing and launching mobile apps. Fixes #18359. (#18451)
Add public targets to compute the mlaunch command lines for installing and launching mobile apps. These new targets are: * ComputeMlaunchInstallArguments * ComputeMlaunchRunArguments As part of this change, also create a few new public properties: * MlaunchPath * MlaunchRunArguments * MlaunchInstallArguments * MlaunchRunScript * MlaunchInstallScript If the *Script variables are set, the corresponding target will create a script file with the path to mlaunch + the corresponding arguments. Otherwise, it's also possible to get the arguments directly from the build log. Fixes https://github.com/xamarin/xamarin-macios/issues/18359. Backport of #18446. --------- Co-authored-by: GitHub Actions Autoformatter <github-actions-autoformatter@xamarin.com>
This commit is contained in:
Родитель
8606b32d07
Коммит
c0f492f938
|
@ -8,6 +8,7 @@
|
|||
<_DotNetRootRemoteDirectory Condition="$(_DotNetRootRemoteDirectory) == ''">/usr/local/share/dotnet/</_DotNetRootRemoteDirectory>
|
||||
<_XamarinSdkRootDirectoryOnMac Condition="'$(_XamarinSdkRootDirectory)' != ''">$(_XamarinSdkRootDirectory.Replace('$(NetCoreRoot)', '$(_DotNetRootRemoteDirectory)'))</_XamarinSdkRootDirectoryOnMac>
|
||||
<_MlaunchPath Condition="'$(_MlaunchPath)' == ''">$(_XamarinSdkRootDirectoryOnMac)tools/bin/mlaunch</_MlaunchPath>
|
||||
<MlaunchPath Condition="'$(MlaunchPath)' == ''">$(_XamarinSdkRootDirectoryOnMac)tools/bin/mlaunch</MlaunchPath>
|
||||
<AfterMicrosoftNETSdkTargets>$(AfterMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)..\targets\Microsoft.iOS.Windows.Sdk.targets</AfterMicrosoftNETSdkTargets>
|
||||
|
||||
<_XamarinSdkRootOnMac Condition="'$(_XamarinSdkRoot)' != ''">$(_XamarinSdkRoot.Replace('$(NetCoreRoot)', '$(_DotNetRootRemoteDirectory)'))</_XamarinSdkRootOnMac>
|
||||
|
|
|
@ -1817,34 +1817,51 @@
|
|||
<!-- Install & Run -->
|
||||
|
||||
<PropertyGroup>
|
||||
<_MlaunchPath Condition="'$(_MlaunchPath)' == ''">$(_XamarinSdkRootDirectory)tools\bin\mlaunch</_MlaunchPath>
|
||||
<!-- We used to use '_MlaunchPath' as the property name, but we've made it public, so it's MlaunchPath now, but keep setting/supporting the underscored version for a while -->
|
||||
<MlaunchPath Condition="'$(MlaunchPath)' == '' And '$(_MlaunchPath)' != ''">$(_MlaunchPath)</MlaunchPath>
|
||||
<MlaunchPath Condition="'$(MlaunchPath)' == ''">$(_XamarinSdkRootDirectory)tools\bin\mlaunch</MlaunchPath>
|
||||
<_MlaunchPath Condition="'$(_MlaunchPath)' == ''">$(MlaunchPath)</_MlaunchPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_InstallMobile" DependsOnTargets="_DetectSdkLocations;_GenerateBundleName" Condition="'$(_SdkIsSimulator)' == 'false'">
|
||||
<Target Name="ComputeMlaunchInstallArguments" DependsOnTargets="_DetectSdkLocations;_GenerateBundleName;_DetectAppManifest;_ComputeMlaunchInstallArguments" />
|
||||
<Target Name="_ComputeMlaunchInstallArguments" Condition="'$(_SdkIsSimulator)' == 'false'">
|
||||
<!-- Launching from the command line on windows hasn't been implemented: https://github.com/xamarin/xamarin-macios/issues/16609 -->
|
||||
<Error Condition="$([MSBuild]::IsOSPlatform('windows'))" Text="It's currently not supported to launch an app from the command line on Windows." />
|
||||
<Error Condition="!Exists('$(_AppBundleManifestPath)')" Text="The app must be built before the arguments to launch the app using mlaunch can be computed." />
|
||||
|
||||
<GetMlaunchArguments
|
||||
SessionId="$(BuildSessionId)"
|
||||
AppBundlePath="$(_AppBundlePath)"
|
||||
AppManifestPath="$(_AppBundleManifestPath)"
|
||||
DeviceName="$(_DeviceName)"
|
||||
InstallApp="$(_AppBundlePath)"
|
||||
MlaunchPath="$(_MlaunchPath)"
|
||||
MlaunchPath="$(MlaunchPath)"
|
||||
SdkDevPath="$(_SdkDevPath)"
|
||||
SdkIsSimulator="$(_SdkIsSimulator)"
|
||||
SdkVersion="$(_SdkVersion)"
|
||||
TargetFrameworkMoniker="$(_ComputedTargetFrameworkMoniker)"
|
||||
>
|
||||
<Output TaskParameter="MlaunchArguments" PropertyName="_MlaunchInstallArguments" />
|
||||
<Output TaskParameter="MlaunchArguments" PropertyName="MlaunchInstallArguments" />
|
||||
</GetMlaunchArguments>
|
||||
|
||||
<Exec SessionId="$(BuildSessionId)" Command="$(_MlaunchPath) $(_MlaunchInstallArguments)" />
|
||||
<WriteLinesToFile
|
||||
File="$(MlaunchInstallScript)"
|
||||
Lines="$(MlaunchPath) $(MlaunchInstallArguments)"
|
||||
Overwrite="true"
|
||||
WriteOnlyWhenDifferent="true"
|
||||
Condition="'$(MlaunchInstallScript)' != ''"
|
||||
/>
|
||||
</Target>
|
||||
|
||||
<!-- This is only needed for mobile platforms, RunCommand and RunArguments are defined for macOS in Microsoft.macOS.Sdk.targets. -->
|
||||
<Target Name="_PrepareRunMobile" DependsOnTargets="_InstallMobile" Condition="'$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'">
|
||||
<Target Name="_InstallMobile" DependsOnTargets="_DetectSdkLocations;_GenerateBundleName;ComputeMlaunchInstallArguments" Condition="'$(_SdkIsSimulator)' == 'false'">
|
||||
<Exec SessionId="$(BuildSessionId)" Command="$(MlaunchPath) $(MlaunchInstallArguments)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="ComputeMlaunchRunArguments" DependsOnTargets="_DetectSdkLocations;_GenerateBundleName;_DetectAppManifest" Condition="'$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'">
|
||||
<!-- Launching from the command line on windows hasn't been implemented: https://github.com/xamarin/xamarin-macios/issues/16609 -->
|
||||
<Error Condition="$([MSBuild]::IsOSPlatform('windows'))" Text="It's currently not supported to launch an app from the command line on Windows." />
|
||||
<Error Condition="!Exists('$(_AppBundleManifestPath)')" Text="The app must be built before the arguments to launch the app using mlaunch can be computed." />
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- capture output by default -->
|
||||
<_MlaunchCaptureOutput Condition="'$(_MlaunchCaptureOutput)' == ''">true</_MlaunchCaptureOutput>
|
||||
|
@ -1869,7 +1886,7 @@
|
|||
DeviceName="$(_DeviceName)"
|
||||
EnvironmentVariables="@(MlaunchEnvironmentVariables)"
|
||||
LaunchApp="$(_AppBundlePath)"
|
||||
MlaunchPath="$(_MlaunchPath)"
|
||||
MlaunchPath="$(MlaunchPath)"
|
||||
SdkIsSimulator="$(_SdkIsSimulator)"
|
||||
SdkDevPath="$(_SdkDevPath)"
|
||||
SdkVersion="$(_SdkVersion)"
|
||||
|
@ -1878,12 +1895,23 @@
|
|||
TargetFrameworkMoniker="$(_ComputedTargetFrameworkMoniker)"
|
||||
WaitForExit="$(_MlaunchWaitForExit)"
|
||||
>
|
||||
<Output TaskParameter="MlaunchArguments" PropertyName="_MlaunchRunArguments" />
|
||||
<Output TaskParameter="MlaunchArguments" PropertyName="MlaunchRunArguments" />
|
||||
</GetMlaunchArguments>
|
||||
|
||||
<WriteLinesToFile
|
||||
File="$(MlaunchRunScript)"
|
||||
Lines="$(MlaunchPath) $(MlaunchRunArguments)"
|
||||
Overwrite="true"
|
||||
WriteOnlyWhenDifferent="true"
|
||||
Condition="'$(MlaunchRunScript)' != ''"
|
||||
/>
|
||||
</Target>
|
||||
|
||||
<!-- This is only needed for mobile platforms, RunCommand and RunArguments are defined for macOS in Microsoft.macOS.Sdk.targets. -->
|
||||
<Target Name="_PrepareRunMobile" DependsOnTargets="_InstallMobile;ComputeMlaunchRunArguments" Condition="'$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'">
|
||||
<PropertyGroup>
|
||||
<RunCommand>$(_MlaunchPath)</RunCommand>
|
||||
<RunArguments>$(_MlaunchRunArguments)</RunArguments>
|
||||
<RunCommand>$(MlaunchPath)</RunCommand>
|
||||
<RunArguments>$(MlaunchRunArguments)</RunArguments>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
|
@ -239,6 +240,46 @@ namespace Xamarin.Tests {
|
|||
}
|
||||
}
|
||||
|
||||
#if NET
|
||||
public static bool TryFindPropertyValue (string binlog, string property, [NotNullWhen (true)] out string? value)
|
||||
#else
|
||||
public static bool TryFindPropertyValue (string binlog, string property, out string? value)
|
||||
#endif
|
||||
{
|
||||
value = null;
|
||||
|
||||
var reader = new BinLogReader ();
|
||||
foreach (var record in reader.ReadRecords (binlog)) {
|
||||
var args = record?.Args;
|
||||
if (args is null)
|
||||
continue;
|
||||
if (args is PropertyInitialValueSetEventArgs pivsea) {
|
||||
if (string.Equals (property, pivsea.PropertyName, StringComparison.OrdinalIgnoreCase))
|
||||
value = pivsea.PropertyValue;
|
||||
} else if (args is PropertyReassignmentEventArgs prea) {
|
||||
if (string.Equals (property, prea.PropertyName, StringComparison.OrdinalIgnoreCase))
|
||||
value = prea.NewValue;
|
||||
} else if (args is ProjectEvaluationFinishedEventArgs pefea) {
|
||||
var dict = pefea.Properties as IDictionary<string, string>;
|
||||
if (dict is not null && dict.TryGetValue (property, out var pvalue))
|
||||
value = pvalue;
|
||||
} else if (args is BuildMessageEventArgs bmea) {
|
||||
if (bmea.Message.StartsWith ("Output Property: ", StringComparison.Ordinal)) {
|
||||
var kvp = bmea.Message.Substring ("Output Property: ".Length);
|
||||
var eq = kvp.IndexOf ('=');
|
||||
if (eq > 0) {
|
||||
var propname = kvp.Substring (0, eq);
|
||||
var propvalue = kvp.Substring (eq + 1);
|
||||
if (propname == property)
|
||||
value = propvalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value is not null;
|
||||
}
|
||||
|
||||
// Returns a diagnostic build log as a string
|
||||
public static string PrintToString (string path)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using Mono.Cecil;
|
||||
|
||||
using Xamarin.Tests;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Xamarin.Tests {
|
||||
[TestFixture]
|
||||
public class MlaunchTest : TestBaseClass {
|
||||
[Test]
|
||||
[TestCase (ApplePlatform.iOS, "ios-arm64")]
|
||||
[TestCase (ApplePlatform.TVOS, "tvos-arm64")]
|
||||
public void GetMlaunchInstallArguments (ApplePlatform platform, string runtimeIdentifiers)
|
||||
{
|
||||
var project = "MySimpleApp";
|
||||
Configuration.IgnoreIfIgnoredPlatform (platform);
|
||||
Configuration.AssertRuntimeIdentifiersAvailable (platform, runtimeIdentifiers);
|
||||
|
||||
var outputPath = Path.Combine (Cache.CreateTemporaryDirectory (), "install.sh");
|
||||
var project_path = GetProjectPath (project, runtimeIdentifiers: runtimeIdentifiers, platform: platform, out var appPath);
|
||||
var properties = GetDefaultProperties (runtimeIdentifiers);
|
||||
properties ["EnableCodeSigning"] = "false"; // Skip code signing, since that would require making sure we have code signing configured on bots.
|
||||
|
||||
// Create the app manifest first, since it's required to compute the mlaunch install arguments
|
||||
DotNet.Execute ("build", project_path, properties, target: "_DetectSdkLocations;_DetectAppManifest;_CompileAppManifest;_WriteAppManifest");
|
||||
|
||||
properties ["MlaunchInstallScript"] = outputPath;
|
||||
var rv = DotNet.Execute ("build", project_path, properties, target: "ComputeMlaunchInstallArguments");
|
||||
|
||||
if (!BinLog.TryFindPropertyValue (rv.BinLogPath, "MlaunchInstallArguments", out var mlaunchInstallArguments))
|
||||
Assert.Fail ("Could not find the property 'MlaunchInstallArguments' in the binlog.");
|
||||
|
||||
if (!BinLog.TryFindPropertyValue (rv.BinLogPath, "MlaunchPath", out var mlaunchPath))
|
||||
Assert.Fail ("Could not find the property 'MlaunchPath' in the binlog.");
|
||||
Assert.That (mlaunchPath, Does.Exist, "mlaunch existence");
|
||||
|
||||
var expectedArguments = new StringBuilder ();
|
||||
expectedArguments.Append ("--installdev ");
|
||||
expectedArguments.Append (appPath.Substring (Path.GetDirectoryName (project_path)!.Length + 1)).Append ('/');
|
||||
expectedArguments.Append ($" --wait-for-exit:false");
|
||||
Assert.AreEqual (expectedArguments.ToString (), mlaunchInstallArguments);
|
||||
|
||||
var scriptContents = File.ReadAllText (outputPath).Trim ('\n'); ;
|
||||
var expectedScriptContents = mlaunchPath + " " + expectedArguments.ToString ();
|
||||
Assert.AreEqual (expectedScriptContents, scriptContents, "Script contents");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase (ApplePlatform.iOS, "iossimulator-x64;iossimulator-arm64", ":v2:runtime=com.apple.CoreSimulator.SimRuntime.iOS-16-4,devicetype=com.apple.CoreSimulator.SimDeviceType.iPhone-14-Pro")]
|
||||
[TestCase (ApplePlatform.iOS, "ios-arm64", "")]
|
||||
[TestCase (ApplePlatform.TVOS, "tvossimulator-arm64", ":v2:runtime=com.apple.CoreSimulator.SimRuntime.tvOS-16-4,devicetype=com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-3rd-generation-1080p")]
|
||||
public void GetMlaunchRunArguments (ApplePlatform platform, string runtimeIdentifiers, string device)
|
||||
{
|
||||
var project = "MySimpleApp";
|
||||
Configuration.IgnoreIfIgnoredPlatform (platform);
|
||||
Configuration.AssertRuntimeIdentifiersAvailable (platform, runtimeIdentifiers);
|
||||
|
||||
var outputPath = Path.Combine (Cache.CreateTemporaryDirectory (), "launch.sh");
|
||||
var project_path = GetProjectPath (project, runtimeIdentifiers: runtimeIdentifiers, platform: platform, out var appPath);
|
||||
var properties = GetDefaultProperties (runtimeIdentifiers);
|
||||
properties ["EnableCodeSigning"] = "false"; // Skip code signing, since that would require making sure we have code signing configured on bots.
|
||||
|
||||
// Create the app manifest first, since it's required to compute the mlaunch run arguments
|
||||
DotNet.Execute ("build", project_path, properties, target: "_DetectSdkLocations;_DetectAppManifest;_CompileAppManifest;_WriteAppManifest");
|
||||
|
||||
properties ["MlaunchRunScript"] = outputPath;
|
||||
var rv = DotNet.Execute ("build", project_path, properties, target: "ComputeMlaunchRunArguments");
|
||||
|
||||
if (!BinLog.TryFindPropertyValue (rv.BinLogPath, "MlaunchRunArguments", out var mlaunchRunArguments))
|
||||
Assert.Fail ("Could not find the property 'MlaunchRunArguments' in the binlog.");
|
||||
|
||||
if (!BinLog.TryFindPropertyValue (rv.BinLogPath, "MlaunchPath", out var mlaunchPath))
|
||||
Assert.Fail ("Could not find the property 'MlaunchPath' in the binlog.");
|
||||
Assert.That (mlaunchPath, Does.Exist, "mlaunch existence");
|
||||
|
||||
var expectedArguments = new StringBuilder ();
|
||||
var isSim = runtimeIdentifiers.Contains ("simulator");
|
||||
expectedArguments.Append (isSim ? "--launchsim " : "--launchdev ");
|
||||
expectedArguments.Append (appPath.Substring (Path.GetDirectoryName (project_path)!.Length + 1)).Append ('/');
|
||||
if (isSim) {
|
||||
expectedArguments.Append (" --device \"");
|
||||
expectedArguments.Append (device);
|
||||
expectedArguments.Append ('"');
|
||||
}
|
||||
expectedArguments.Append ($" --wait-for-exit:true");
|
||||
Assert.AreEqual (expectedArguments.ToString (), mlaunchRunArguments);
|
||||
|
||||
var scriptContents = File.ReadAllText (outputPath).Trim ('\n'); ;
|
||||
var expectedScriptContents = mlaunchPath + " " + expectedArguments.ToString ();
|
||||
Assert.AreEqual (expectedScriptContents, scriptContents, "Script contents");
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче