Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions msbuild/Xamarin.Localization.MSBuild/MSBStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1801,4 +1801,9 @@
{0} - The number of files hashed.
{1} - The total number of input files.</comment>
</data>
<data name="E7198" xml:space="preserve">
<value>Codesign failed because '{0}' contains files with extended attributes such as 'com.apple.FinderInfo' or 'com.apple.ResourceFork' that are not allowed when signing. Run 'xattr -lr "{0}"' to locate the affected files. Remove the unwanted attributes from the original source files (for example, with 'xattr -cr "path/to/source/files"'), then clean and rebuild. See https://developer.apple.com/library/archive/qa/qa1940/_index.html for more information.</value>
Comment thread
rolfbjarne marked this conversation as resolved.
<comment>Shown when codesign fails with 'resource fork, Finder information, or similar detritus not allowed'.
{0} - The path of the file or bundle being signed. Do not translate the attribute names, shell commands, or URL.</comment>
</data>
</root>
2 changes: 2 additions & 0 deletions msbuild/Xamarin.MacDev.Tasks/Tasks/Codesign.cs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,8 @@ void Sign (SignInfo info)
Log.LogError (MSBStrings.E0005, item.ItemSpec);
if (errors.IndexOf ("errSecInternalComponent", StringComparison.Ordinal) >= 0 && System.Threading.Interlocked.CompareExchange (ref loggedInternalComponentHint, 1, 0) == 0)
Log.LogError (MSBStrings.E7184 /* Codesign failed with 'errSecInternalComponent'. This usually means the keychain is locked, which is common when building over SSH. Unlock the keychain first, for example by running 'security unlock-keychain ~/Library/Keychains/login.keychain-db'. */);
if (errors.IndexOf ("resource fork, Finder information, or similar detritus not allowed", StringComparison.Ordinal) >= 0)
Log.LogError (MSBStrings.E7198, item.ItemSpec);
} else {
var stampFile = GetCodesignStampFile (item);
if (string.IsNullOrEmpty (stampFile)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

using Microsoft.Build.Utilities;

Expand All @@ -17,6 +18,58 @@
namespace Xamarin.MacDev.Tasks {
[TestFixture]
public class CodesignTaskTests : TestBase {
[TestCase ("resource fork, Finder information, or similar detritus not allowed", 1, 1)]
[TestCase ("resource fork, Finder information, or similar detritus not allowed", 1, 2)]
[TestCase ("resource fork, Finder information, or similar detritus not allowed", 0, 1)]
[TestCase ("unrelated signing failure", 1, 1)]
[TestCase ("", 1, 1)]
public void ExtendedAttributesDiagnostic (string error, int exitCode, int resourceCount)
{
Configuration.IgnoreIfNotOnMacOS ();

var directory = Cache.CreateTemporaryDirectory ();
var tool = Path.Combine (directory, "codesign");
File.WriteAllText (tool, $"#!/bin/sh\nprintf '%s' '{error}' >&2\nexit {exitCode}\n");
Assert.That (ExecutionHelper.Execute ("/bin/chmod", new [] { "+x", tool }, out var output), Is.EqualTo (0), output.ToString ());

var resources = new TaskItem [resourceCount];
for (var i = 0; i < resourceCount; i++) {
var appBundle = Path.Combine (directory, $"App {i}.app");
Directory.CreateDirectory (appBundle);
File.WriteAllText (Path.Combine (appBundle, "App"), "executable");
resources [i] = new TaskItem (appBundle, new Dictionary<string, string> {
{ "CodesignStampFile", Path.Combine (directory, $"codesign-{i}.stamp") },
});
}

var task = CreateTask<Codesign> ();
task.CodesignAllocate = "/usr/bin/true";
task.Resources = resources;
task.SigningKey = "-";
task.TargetFrameworkMoniker = TargetFramework.DotNet_MacCatalyst_String;
task.ToolPath = directory;

var expectHint = exitCode != 0 && error.Contains ("resource fork");
var expectedErrorCount = exitCode == 0 ? 0 : resourceCount * (expectHint ? 3 : 2);
ExecuteTask (task, expectedErrorCount: expectedErrorCount);

var hints = Engine.Logger.ErrorEvents.Where (e => e.Message?.Contains ("com.apple.FinderInfo") == true).ToArray ();
Assert.That (hints.Length, Is.EqualTo (expectHint ? resourceCount : 0), "Extended attributes diagnostics");
foreach (var resource in resources) {
if (expectHint) {
var hint = hints.Single (e => e.Message?.Contains (resource.ItemSpec) == true);
Assert.That (hint.Message, Does.Contain ("com.apple.ResourceFork"), "Resource fork attribute");
Assert.That (hint.Message, Does.Contain ($"xattr -lr \"{resource.ItemSpec}\""), "Locate affected files");
Assert.That (hint.Message, Does.Contain ("xattr -cr"), "Remove attributes");
Assert.That (hint.Message, Does.Contain ("original source files"), "Fix source files");
Assert.That (hint.Message, Does.Contain ("https://developer.apple.com/library/archive/qa/qa1940/_index.html"), "Documentation");
}
Assert.That (File.Exists (resource.GetMetadata ("CodesignStampFile")), Is.EqualTo (exitCode == 0), "Stamp file");
}
if (exitCode != 0 && error.Length > 0)
Assert.That (Engine.Logger.ErrorEvents.Count (e => e.Message?.Contains (error) == true), Is.EqualTo (resourceCount * 2), "Original codesign errors");
}

[Test]
public void EntitlementsChangesInvalidateStamp ()
{
Expand Down
Loading