[msbuild] Have `XcodeCompilerToolTask` use `xcrun` to start Apple tools (#9965) (#9972)

1. Use `xcrun` to run `ibtool` (and `actool`) and avoid toolchain mismatches

2. Set `DEVELOPER_DIR` so everyone (well `xcrun`) use the same toolchain

3. Workaround for `macos-arm64` issue (FB8827920)

	* Start `ibtool` as an `Apple` [Silicon] process
	* This will ensure the `ibtoold` daemon is also running as `Apple`
	* If `ibtoold` is run as `Intel` then `ibtool` asserts and build fail

```
LaunchScreen.storyboard : error : 2020-10-26 14:24:52.757 ibtoold[37142:6681382] [MT] DVTAssertions: Warning in /Library/Caches/com.apple.xbs/Sources/IDEInterfaceBuilder/IDEInterfaceBuilder-17506/InterfaceBuilderKit/Utilities/IBAbstractInterfaceBuilderPlatformToolManager.m:481
LaunchScreen.storyboard : error : Details:  Failed to attach to IBAgent-iOS with error: Error Domain=com.apple.InterfaceBuilder Code=-1 "Encountered an error communicating with IBAgent-iOS." UserInfo={NSLocalizedFailureReason=IBAgent-iOS (37146) failed to launch and exited with status 10, NSUnderlyingError=0x7fa4e58fc760 {Error Domain=com.apple.InterfaceBuilder Code=-1 "Failed to launch IBAgent-iOS via CoreSimulator spawn" UserInfo={NSLocalizedDescription=Failed to launch IBAgent-iOS via CoreSimulator spawn, NSUnderlyingError=0x7fa4e5e8a900 {Error Domain=com.apple.InterfaceBuilder Code=-1 "Failed to handshake with platform tool" UserInfo={NSLocalizedFailureReason=Failed to open connection over FIFOs with platform tool, NSLocalizedDescription=Failed to handshake with platform tool, NSUnderlyingError=0x7fa4e5e237c0 {Error Domain=com.apple.InterfaceBuilder Code=-1 "" UserInfo=0x7fa4e5e8bba0 (not displayed)}}}}}, NSLocalizedRecoverySuggestion=Please check Console.app for crash reports for "IBAgent-iOS" for further information., NSLocalizedDescription=Encountered an error communicating with IBAgent-iOS.}
LaunchScreen.storyboard : error : Object:   <IBCocoaTouchToolManager>
LaunchScreen.storyboard : error : Method:   +_THREADSAFE_launchNewToolWithLaunchContext:executionContext:toolProxyClass:proxyDelegate:failureContext:requestingMethod:error:forReason:
LaunchScreen.storyboard : error : Thread:   <NSThread: 0x7fa4e341af70>{number = 1, name = main}
LaunchScreen.storyboard : error : Please file a bug at https://feedbackassistant.apple.com with this warning message and any useful information you can provide.
LaunchScreen.storyboard : error : 2020-10-26 14:24:52.766 ibtoold[37142:6681382] [MT] IBPlatformTool: *** Failed to launch tool with description <IBCocoaTouchPlatformToolDescription: 0x7fa4e5f34160> System content for IBCocoaTouchFramework-fourteenAndLater <IBScaleFactorDeviceTypeDescription: 0x7fa4e5f2fb50> scaleFactor=2x, renderMode.identifier=(null): Encountered an error communicating with IBAgent-iOS. (Failure reason: IBAgent-iOS (37146) failed to launch and exited with status 10): Failed to launch IBAgent-iOS via CoreSimulator spawn: Failed to handshake with platform tool (Failure reason: Failed to open connection over FIFOs with platform tool): : Failed to open FIFOs for handshaking with platform tool (Failure reason: IBAgent-iOS exited before we could handshake)
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/iOS/Xamarin.iOS.Common.targets(1425,3): error : ibtool exited with code 1
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/iOS/Xamarin.iOS.Common.targets(1425,3): error :
LaunchScreen.storyboard : ibtool error : Encountered an error communicating with IBAgent-iOS.
```

Note: `main` has diverged quite a bit (net6 support) so this pull request
will need to be re-worked (it won't apply)

Fixes https://github.com/xamarin/xamarin-macios/issues/4634

Foreport of #9965 since the source code diverged from `xcode12.2`
This commit is contained in:
Sebastien Pouliot 2020-10-27 21:11:08 -04:00 коммит произвёл GitHub
Родитель a141da12b5
Коммит 7e854827d4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 33 добавлений и 13 удалений

Просмотреть файл

@ -52,7 +52,6 @@ namespace Xamarin.MacDev.Tasks
protected override void AppendCommandLineArguments (IDictionary<string, string> environment, CommandLineArgumentBuilder args, ITaskItem[] items)
{
environment.Add ("DEVELOPER_DIR", SdkDevPath);
environment.Add ("IBSC_MINIMUM_COMPATIBILITY_VERSION", MinimumOSVersion);
environment.Add ("IBC_MINIMUM_COMPATIBILITY_VERSION", MinimumOSVersion);

Просмотреть файл

@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
@ -102,14 +103,20 @@ namespace Xamarin.MacDev.Tasks
protected abstract void AppendCommandLineArguments (IDictionary<string, string> environment, CommandLineArgumentBuilder args, ITaskItem[] items);
string GetFullPathToTool ()
static bool? translated;
[DllImport ("/usr/lib/libSystem.dylib", SetLastError = true)]
static extern int sysctlbyname (/* const char */ [MarshalAs (UnmanagedType.LPStr)] string property, ref long oldp, ref long oldlenp, IntPtr newp, /* size_t */ long newlen);
// https://developer.apple.com/documentation/apple_silicon/about_the_rosetta_translation_environment
static bool IsTranslated ()
{
if (!string.IsNullOrEmpty (ToolPath))
return Path.Combine (ToolPath, ToolExe);
var path = Path.Combine (DefaultBinDir, ToolExe);
return File.Exists (path) ? path : ToolExe;
if (translated == null) {
long result = 0;
long size = sizeof (long);
translated = ((sysctlbyname ("sysctl.proc_translated", ref result, ref size, IntPtr.Zero, 0) != -1) && (result == 1));
}
return translated.Value;
}
protected int Compile (ITaskItem[] items, string output, ITaskItem manifest)
@ -123,6 +130,20 @@ namespace Xamarin.MacDev.Tasks
if (!string.IsNullOrEmpty (SdkUsrPath))
environment.Add ("XCODE_DEVELOPER_USR_PATH", SdkUsrPath);
if (!string.IsNullOrEmpty (SdkDevPath))
environment.Add ("DEVELOPER_DIR", SdkDevPath);
// workaround for ibtool[d] bug / asserts if Intel version is loaded
string tool;
if (IsTranslated ()) {
// we force the Intel (translated) msbuild process to launch ibtool as "Apple"
tool = "arch";
args.Add ("-arch", "arm64e");
args.Add ("/usr/bin/xcrun");
} else {
tool = "/usr/bin/xcrun";
}
args.Add (ToolName);
args.Add ("--errors", "--warnings", "--notices");
args.Add ("--output-format", "xml1");
@ -140,9 +161,8 @@ namespace Xamarin.MacDev.Tasks
foreach (var item in items)
args.AddQuoted (item.GetMetadata ("FullPath"));
var fileName = GetFullPathToTool ();
var arguments = args.ToList ();
var rv = ExecuteAsync (fileName, arguments, sdkDevPath, environment: environment, mergeOutput: false).Result;
var rv = ExecuteAsync (tool, arguments, sdkDevPath, environment: environment, mergeOutput: false).Result;
var exitCode = rv.ExitCode;
var messages = rv.StandardOutput.ToString ();
File.WriteAllText (manifest.ItemSpec, messages);

Просмотреть файл

@ -703,6 +703,7 @@ namespace Xamarin.MMP.Tests
[Test]
public void BuildingSameSolutionTwice_ShouldNotRunACToolTwice ()
{
const string actool = " execution started with arguments: actool --errors --warnings --notices --output-format xml1 --output-partial-info-plist ";
RunMMPTest (tmpDir => {
TI.UnifiedTestConfig test = new TI.UnifiedTestConfig (tmpDir) {
AssetIcons = true
@ -711,15 +712,15 @@ namespace Xamarin.MMP.Tests
string project = TI.GenerateUnifiedExecutableProject (test);
string buildOutput = TI.BuildProject (project);
Assert.True (buildOutput.Contains ("actool execution started with arguments"), $"Initial build should run actool");
Assert.True (buildOutput.Contains (actool), $"Initial build should run actool");
buildOutput = TI.BuildProject (project);
Assert.False (buildOutput.Contains ("actool execution started with arguments"), $"Second build should not run actool");
Assert.False (buildOutput.Contains (actool), $"Second build should not run actool");
TI.RunAndAssert ("touch", new [] { Path.Combine (tmpDir, "Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png") }, "touch icon");
buildOutput = TI.BuildProject (project);
Assert.True (buildOutput.Contains ("actool execution started with arguments"), $"Build after touching icon must run actool");
Assert.True (buildOutput.Contains (actool), $"Build after touching icon must run actool");
});
}