Merge remote-tracking branch 'origin/main' into darc-main-fc6e47e2-7b69-4464-b65f-8f67ca26b4e8
This commit is contained in:
Коммит
31e9352a52
|
@ -80,7 +80,7 @@ endif
|
||||||
|
|
||||||
# For release branches, modify the following variables to hardcode a version name
|
# For release branches, modify the following variables to hardcode a version name
|
||||||
# Set the NUGET_HARDCODED_PRERELEASE_IDENTIFIER variable to the prerelease identifer you want (say "rc.1")
|
# Set the NUGET_HARDCODED_PRERELEASE_IDENTIFIER variable to the prerelease identifer you want (say "rc.1")
|
||||||
NUGET_HARDCODED_PRERELEASE_IDENTIFIER=rc.1
|
NUGET_HARDCODED_PRERELEASE_IDENTIFIER=rc.2
|
||||||
# Set the NUGET_HARDCODED_PRERELEASE_BRANCH variable to the exact name for the branch the above variable should apply to (so that any other branches won't pick it up by accident).
|
# Set the NUGET_HARDCODED_PRERELEASE_BRANCH variable to the exact name for the branch the above variable should apply to (so that any other branches won't pick it up by accident).
|
||||||
# For the previous example, this would be "release/6.0.2xx-rc1"
|
# For the previous example, this would be "release/6.0.2xx-rc1"
|
||||||
# When creating a release branch from main, this must be changed from "main" to the new release branch.
|
# When creating a release branch from main, this must be changed from "main" to the new release branch.
|
||||||
|
@ -529,12 +529,12 @@ $(TOP)/dotnet.config: $(TOP)/eng/Versions.props
|
||||||
$(Q) mv $@.tmp $@
|
$(Q) mv $@.tmp $@
|
||||||
|
|
||||||
ifneq ("$(wildcard /usr/local/share/dotnet/dotnet)","")
|
ifneq ("$(wildcard /usr/local/share/dotnet/dotnet)","")
|
||||||
DOTNET=/usr/local/share/dotnet/dotnet
|
SYSTEM_DOTNET=/usr/local/share/dotnet/dotnet
|
||||||
else
|
else
|
||||||
ifneq ("$(wildcard /usr/local/share/dotnet/x64/dotnet)","")
|
ifneq ("$(wildcard /usr/local/share/dotnet/x64/dotnet)","")
|
||||||
DOTNET=/usr/local/share/dotnet/x64/dotnet
|
SYSTEM_DOTNET=/usr/local/share/dotnet/x64/dotnet
|
||||||
else
|
else
|
||||||
DOTNET=/must/install/dotnet
|
SYSTEM_DOTNET=/must/install/dotnet
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -66,11 +66,11 @@ MAC_PACKAGE_VERSION=8.9.0.$(MAC_COMMIT_DISTANCE)
|
||||||
# WARNING: Do **not** use versions higher than the available Xcode SDK or else we will have issues with mtouch (See https://github.com/xamarin/xamarin-macios/issues/7705)
|
# WARNING: Do **not** use versions higher than the available Xcode SDK or else we will have issues with mtouch (See https://github.com/xamarin/xamarin-macios/issues/7705)
|
||||||
# When bumping the major macOS version in MACOS_NUGET_VERSION also update the macOS version where we execute on bots in jenkins/Jenkinsfile (in the 'node' element)
|
# When bumping the major macOS version in MACOS_NUGET_VERSION also update the macOS version where we execute on bots in jenkins/Jenkinsfile (in the 'node' element)
|
||||||
|
|
||||||
IOS_NUGET_VERSION=15.4.100
|
IOS_NUGET_VERSION=15.4.200
|
||||||
TVOS_NUGET_VERSION=15.4.100
|
TVOS_NUGET_VERSION=15.4.200
|
||||||
WATCHOS_NUGET_VERSION=8.5.100
|
WATCHOS_NUGET_VERSION=8.5.200
|
||||||
MACOS_NUGET_VERSION=12.3.100
|
MACOS_NUGET_VERSION=12.3.200
|
||||||
MACCATALYST_NUGET_VERSION=15.4.100
|
MACCATALYST_NUGET_VERSION=15.4.200
|
||||||
|
|
||||||
|
|
||||||
# Defines the default platform version if it's not specified in the TFM. The default should not change for a given .NET version:
|
# Defines the default platform version if it's not specified in the TFM. The default should not change for a given .NET version:
|
||||||
|
|
|
@ -2636,5 +2636,32 @@ namespace Xamarin.Localization.MSBuild {
|
||||||
return ResourceManager.GetString("W7093", resourceCulture);
|
return ResourceManager.GetString("W7093", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Code signing has been requested multiple times for '{0}', with different metadata. The metadata for one are: '{1}', while the metadata for the other are: '{2}'.
|
||||||
|
/// </summary>
|
||||||
|
public static string W7095 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("W7095", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Code signing has been requested multiple times for '{0}', with different metadata. The metadata '{1}={2}' has been set for one item, but not the other..
|
||||||
|
/// </summary>
|
||||||
|
public static string W7096 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("W7096", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Code signing has been requested multiple times for '{0}', with different metadata. The metadata '{1}' has been values for each item (once it's '{2}', another time it's '{3}')..
|
||||||
|
/// </summary>
|
||||||
|
public static string W7097 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("W7097", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1395,4 +1395,16 @@
|
||||||
<data name="E7094" xml:space="preserve">
|
<data name="E7094" xml:space="preserve">
|
||||||
<value>The file or directory '{0}' is not a framework nor a file within a framework.</value>
|
<value>The file or directory '{0}' is not a framework nor a file within a framework.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
|
<data name="W7095" xml:space="preserve">
|
||||||
|
<value>Code signing has been requested multiple times for '{0}', with different metadata. The metadata for one are: '{1}', while the metadata for the other are: '{2}'</value>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<data name="W7096" xml:space="preserve">
|
||||||
|
<value>Code signing has been requested multiple times for '{0}', with different metadata. The metadata '{1}={2}' has been set for one item, but not the other.</value>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<data name="W7097" xml:space="preserve">
|
||||||
|
<value>Code signing has been requested multiple times for '{0}', with different metadata. The metadata '{1}' has been values for each item (once it's '{2}', another time it's '{3}').</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -135,6 +135,36 @@ namespace Xamarin.MacDev.Tasks {
|
||||||
output.Add (item);
|
output.Add (item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We may be asked to sign the same item multiple times (in particular for universal .NET builds)
|
||||||
|
// Here we de-duplicate (based on itemspec). We also verify that the metadata is the same between
|
||||||
|
// all deduplicated items, and if not, we show a warning.
|
||||||
|
var grouped = output.GroupBy (v => v.ItemSpec);
|
||||||
|
foreach (var group in grouped) {
|
||||||
|
if (group.Count () < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var all = group.ToArray ();
|
||||||
|
var firstMetadata = all [0].CloneCustomMetadataToDictionary ();
|
||||||
|
for (var i = 1; i < all.Length; i++) {
|
||||||
|
var nextMetadata = all [i].CloneCustomMetadataToDictionary ();
|
||||||
|
if (nextMetadata.Count != firstMetadata.Count) {
|
||||||
|
Log.LogWarning (MSBStrings.W7095, /* Code signing has been requested multiple times for '{0}', with different metadata. The metadata for one are: '{1}', while the metadata for the other are: '{2}' */ group.Key, string.Join (", ", firstMetadata.Keys), string.Join (", ", nextMetadata.Keys));
|
||||||
|
} else {
|
||||||
|
foreach (var kvp in firstMetadata) {
|
||||||
|
if (!nextMetadata.TryGetValue (kvp.Key, out var nextValue)) {
|
||||||
|
Log.LogWarning (MSBStrings.W7096, /* Code signing has been requested multiple times for '{0}', with different metadata. The metadata '{1}={2}' has been set for one item, but not the other. */ group.Key, kvp.Key, kvp.Value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nextValue != kvp.Value) {
|
||||||
|
Log.LogWarning (MSBStrings.W7097, /* Code signing has been requested multiple times for '{0}', with different metadata. The metadata '{1}' has been values for each item (once it's '{2}', another time it's '{3}'). */ group.Key, kvp.Key, kvp.Value, nextValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output.Remove (all [i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OutputCodesignItems = output.ToArray ();
|
OutputCodesignItems = output.ToArray ();
|
||||||
|
|
||||||
return !Log.HasLoggedErrors;
|
return !Log.HasLoggedErrors;
|
||||||
|
|
|
@ -37,7 +37,11 @@ namespace MonoTouchFixtures.HealthKit {
|
||||||
Assert.That (details.ValidationError.Length, Is.EqualTo ((nint) 0), "Length");
|
Assert.That (details.ValidationError.Length, Is.EqualTo ((nint) 0), "Length");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#if __MACCATALYST__
|
||||||
|
var throwsException = TestRuntime.CheckXcodeVersion (12, 0);
|
||||||
|
#else
|
||||||
var throwsException = TestRuntime.CheckXcodeVersion (11, 0);
|
var throwsException = TestRuntime.CheckXcodeVersion (11, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (throwsException) {
|
if (throwsException) {
|
||||||
#if NET
|
#if NET
|
||||||
|
|
|
@ -95,11 +95,7 @@ namespace MonoTouchFixtures.MediaAccessibility {
|
||||||
Assert.Null (e, "ro / set / no error"); // weird, it can't be saved back to the file metadata
|
Assert.Null (e, "ro / set / no error"); // weird, it can't be saved back to the file metadata
|
||||||
|
|
||||||
var s = MAImageCaptioning.GetCaption (url, out e);
|
var s = MAImageCaptioning.GetCaption (url, out e);
|
||||||
#if __MACCATALYST__
|
|
||||||
if (true) {
|
|
||||||
#else
|
|
||||||
if (TestRuntime.CheckXcodeVersion (12, TestRuntime.MinorXcode12APIMismatch)) {
|
if (TestRuntime.CheckXcodeVersion (12, TestRuntime.MinorXcode12APIMismatch)) {
|
||||||
#endif
|
|
||||||
Assert.AreEqual ("xamarin", s, "ro / roundtrip 2");
|
Assert.AreEqual ("xamarin", s, "ro / roundtrip 2");
|
||||||
} else {
|
} else {
|
||||||
Assert.Null (s, "ro / roundtrip 3"); // not very surprising since Set can't save it
|
Assert.Null (s, "ro / roundtrip 3"); // not very surprising since Set can't save it
|
||||||
|
@ -108,11 +104,7 @@ namespace MonoTouchFixtures.MediaAccessibility {
|
||||||
|
|
||||||
Assert.True (MAImageCaptioning.SetCaption (url, "xamarin", out e), "Set 2");
|
Assert.True (MAImageCaptioning.SetCaption (url, "xamarin", out e), "Set 2");
|
||||||
s = MAImageCaptioning.GetCaption (url, out e);
|
s = MAImageCaptioning.GetCaption (url, out e);
|
||||||
#if __MACCATALYST__
|
|
||||||
if (true) {
|
|
||||||
#else
|
|
||||||
if (TestRuntime.CheckXcodeVersion (12, TestRuntime.MinorXcode12APIMismatch)) {
|
if (TestRuntime.CheckXcodeVersion (12, TestRuntime.MinorXcode12APIMismatch)) {
|
||||||
#endif
|
|
||||||
Assert.AreEqual ("xamarin", s, "ro / back to original");
|
Assert.AreEqual ("xamarin", s, "ro / back to original");
|
||||||
} else {
|
} else {
|
||||||
Assert.Null (s, "ro / back to original");
|
Assert.Null (s, "ro / back to original");
|
||||||
|
@ -135,11 +127,7 @@ namespace MonoTouchFixtures.MediaAccessibility {
|
||||||
Assert.Null (e, "rw / set / no error"); // weird, it can't be saved back to the file metadata
|
Assert.Null (e, "rw / set / no error"); // weird, it can't be saved back to the file metadata
|
||||||
|
|
||||||
var s = MAImageCaptioning.GetCaption (rw_url, out e);
|
var s = MAImageCaptioning.GetCaption (rw_url, out e);
|
||||||
#if __MACCATALYST__
|
if (TestRuntime.CheckXcodeVersion (12, TestRuntime.MinorXcode12APIMismatch)) {
|
||||||
if (true) {
|
|
||||||
#else
|
|
||||||
if (TestRuntime.CheckXcodeVersion (12, TestRuntime.MinorXcode12APIMismatch)) {
|
|
||||||
#endif
|
|
||||||
Assert.AreEqual ("xamarin", s, "rw / roundtrip"); // :)
|
Assert.AreEqual ("xamarin", s, "rw / roundtrip"); // :)
|
||||||
} else {
|
} else {
|
||||||
Assert.Null (s, "rw / roundtrip"); // :(
|
Assert.Null (s, "rw / roundtrip"); // :(
|
||||||
|
@ -148,11 +136,7 @@ namespace MonoTouchFixtures.MediaAccessibility {
|
||||||
|
|
||||||
Assert.True (MAImageCaptioning.SetCaption (rw_url, "xamarin", out e), "Set 2");
|
Assert.True (MAImageCaptioning.SetCaption (rw_url, "xamarin", out e), "Set 2");
|
||||||
s = MAImageCaptioning.GetCaption (rw_url, out e);
|
s = MAImageCaptioning.GetCaption (rw_url, out e);
|
||||||
#if __MACCATALYST__
|
if (TestRuntime.CheckXcodeVersion (12, TestRuntime.MinorXcode12APIMismatch)) {
|
||||||
if (true) {
|
|
||||||
#else
|
|
||||||
if (TestRuntime.CheckXcodeVersion (12, TestRuntime.MinorXcode12APIMismatch)) {
|
|
||||||
#endif
|
|
||||||
Assert.AreEqual ("xamarin", s, "rw / back to original");
|
Assert.AreEqual ("xamarin", s, "rw / back to original");
|
||||||
} else {
|
} else {
|
||||||
Assert.Null (s, "rw / back to original");
|
Assert.Null (s, "rw / back to original");
|
||||||
|
|
|
@ -355,68 +355,220 @@ namespace Xamarin.MacDev.Tasks {
|
||||||
task.NativeStripItems = nativeStripItems.ToArray ();
|
task.NativeStripItems = nativeStripItems.ToArray ();
|
||||||
task.TargetFrameworkMoniker = TargetFramework.GetTargetFramework (platform, isDotNet).ToString ();
|
task.TargetFrameworkMoniker = TargetFramework.GetTargetFramework (platform, isDotNet).ToString ();
|
||||||
Assert.IsTrue (task.Execute (), "Execute");
|
Assert.IsTrue (task.Execute (), "Execute");
|
||||||
|
Assert.AreEqual (0, Engine.Logger.WarningsEvents.Count, "Warning Count");
|
||||||
|
|
||||||
var outputCodesignItems = task.OutputCodesignItems;
|
VerifyCodesigningResults (infos, task.OutputCodesignItems, platform);
|
||||||
Assert.That (outputCodesignItems.Select (v => v.ItemSpec), Is.Unique, "Uniqueness");
|
|
||||||
|
|
||||||
var failures = new List<string> ();
|
|
||||||
var itemsFound = new List<ITaskItem> ();
|
|
||||||
foreach (var info in infos) {
|
|
||||||
var item = outputCodesignItems.SingleOrDefault (v => string.Equals (v.ItemSpec, info.ItemSpec, StringComparison.OrdinalIgnoreCase));
|
|
||||||
info.CodesignItem = item;
|
|
||||||
if (IsPlatform (info.SignedOn, platform)) {
|
|
||||||
if (item is null) {
|
|
||||||
failures.Add ($"Expected '{info.ItemSpec}' to be signed.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (item is not null) {
|
|
||||||
failures.Add ($"Did not expect '{info.ItemSpec}' to be signed.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item is null)
|
|
||||||
continue;
|
|
||||||
itemsFound.Add (item);
|
|
||||||
|
|
||||||
foreach (var kvp in info.Metadata) {
|
|
||||||
var metadata = item.GetMetadata (kvp.Key);
|
|
||||||
if (metadata == string.Empty && kvp.Value != string.Empty) {
|
|
||||||
failures.Add ($"Item '{info.ItemSpec}': Expected metadata '{kvp.Key}' not found (with value '{kvp.Value}').");
|
|
||||||
} else if (!string.Equals (metadata, kvp.Value)) {
|
|
||||||
failures.Add ($"Item '{info.ItemSpec}': Expected value '{kvp.Value}' for metadata '{kvp.Key}', but got '{metadata}' instead.\nExpected: {kvp.Value}\nActual: {metadata}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var customMetadata = item.CopyCustomMetadata ();
|
|
||||||
var unexpectedMetadata = customMetadata.Keys.ToHashSet ();
|
|
||||||
unexpectedMetadata.ExceptWith (info.Metadata.Keys);
|
|
||||||
unexpectedMetadata.Remove ("OriginalItemSpec");
|
|
||||||
foreach (var unexpected in unexpectedMetadata) {
|
|
||||||
if (string.IsNullOrEmpty (customMetadata [unexpected]))
|
|
||||||
continue;
|
|
||||||
failures.Add ($"Item '{info.ItemSpec}': Unexpected metadata '{unexpected}' with value '{customMetadata [unexpected]}'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var itemsNotFound = outputCodesignItems.Where (v => !itemsFound.Contains (v)).ToArray ();
|
|
||||||
foreach (var itemNotFound in itemsNotFound) {
|
|
||||||
failures.Add ($"Did not expect '{itemNotFound.ItemSpec}' to be signed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failures.Count > 0) {
|
|
||||||
Console.WriteLine ($"{failures.Count} failures");
|
|
||||||
foreach (var f in failures)
|
|
||||||
Console.WriteLine (f);
|
|
||||||
Console.WriteLine ($"{failures.Count} failures");
|
|
||||||
}
|
|
||||||
Assert.That (failures, Is.Empty, "Failures");
|
|
||||||
} finally {
|
} finally {
|
||||||
Environment.CurrentDirectory = currentDir;
|
Environment.CurrentDirectory = currentDir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[TestCase (ApplePlatform.iOS, true)]
|
||||||
|
[TestCase (ApplePlatform.iOS, false)]
|
||||||
|
[TestCase (ApplePlatform.TVOS, true)]
|
||||||
|
[TestCase (ApplePlatform.TVOS, false)]
|
||||||
|
[TestCase (ApplePlatform.WatchOS, false)]
|
||||||
|
[TestCase (ApplePlatform.MacOSX, true)]
|
||||||
|
[TestCase (ApplePlatform.MacOSX, false)]
|
||||||
|
[TestCase (ApplePlatform.MacCatalyst, true)]
|
||||||
|
public void Duplicated (ApplePlatform platform, bool isDotNet)
|
||||||
|
{
|
||||||
|
var tmpdir = Cache.CreateTemporaryDirectory ();
|
||||||
|
|
||||||
|
var currentDir = Environment.CurrentDirectory;
|
||||||
|
try {
|
||||||
|
Environment.CurrentDirectory = tmpdir;
|
||||||
|
var codesignItems = new List<ITaskItem> ();
|
||||||
|
var codesignBundle = new List<ITaskItem> ();
|
||||||
|
|
||||||
|
string codeSignatureSubdirectory = string.Empty;
|
||||||
|
switch (platform) {
|
||||||
|
case ApplePlatform.MacCatalyst:
|
||||||
|
case ApplePlatform.MacOSX:
|
||||||
|
codeSignatureSubdirectory = "Contents/";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bundleAppMetadata = new Dictionary<string, string> {
|
||||||
|
{ "RequireCodeSigning", "true" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var createDumpMetadata = new Dictionary<string, string> {
|
||||||
|
{ "RequireCodeSigning", "true" },
|
||||||
|
};
|
||||||
|
|
||||||
|
codesignItems = new List<ITaskItem> {
|
||||||
|
new TaskItem ("Bundle.app/Contents/MonoBundle/createdump", createDumpMetadata),
|
||||||
|
new TaskItem ("Bundle.app/Contents/MonoBundle/createdump", createDumpMetadata),
|
||||||
|
};
|
||||||
|
|
||||||
|
codesignBundle = new List<ITaskItem> {
|
||||||
|
new TaskItem ("Bundle.app", bundleAppMetadata),
|
||||||
|
};
|
||||||
|
|
||||||
|
var infos = new CodesignInfo [] {
|
||||||
|
new CodesignInfo ("Bundle.app", Platforms.All, bundleAppMetadata.Set ("CodesignStampFile", $"Bundle.app/{codeSignatureSubdirectory}_CodeSignature/CodeResources")),
|
||||||
|
new CodesignInfo ("Bundle.app/Contents/MonoBundle/createdump", Platforms.All, createDumpMetadata.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Contents/MonoBundle/createdump")),
|
||||||
|
};
|
||||||
|
|
||||||
|
var allFiles = infos.Select (v => v.ItemSpec).ToArray ();
|
||||||
|
Touch (tmpdir, allFiles);
|
||||||
|
|
||||||
|
var task = CreateTask<ComputeCodesignItems> ();
|
||||||
|
task.AppBundleDir = "Bundle.app";
|
||||||
|
task.CodesignBundle = codesignBundle.ToArray ();
|
||||||
|
task.CodesignItems = codesignItems.ToArray ();
|
||||||
|
task.CodesignStampPath = "codesign-stamp-path/";
|
||||||
|
task.TargetFrameworkMoniker = TargetFramework.GetTargetFramework (platform, isDotNet).ToString ();
|
||||||
|
Assert.IsTrue (task.Execute (), "Execute");
|
||||||
|
Assert.AreEqual (0, Engine.Logger.WarningsEvents.Count, "Warning Count");
|
||||||
|
|
||||||
|
VerifyCodesigningResults (infos, task.OutputCodesignItems, platform);
|
||||||
|
} finally {
|
||||||
|
Environment.CurrentDirectory = currentDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[TestCase (ApplePlatform.iOS, true)]
|
||||||
|
[TestCase (ApplePlatform.iOS, false)]
|
||||||
|
[TestCase (ApplePlatform.TVOS, true)]
|
||||||
|
[TestCase (ApplePlatform.TVOS, false)]
|
||||||
|
[TestCase (ApplePlatform.WatchOS, false)]
|
||||||
|
[TestCase (ApplePlatform.MacOSX, true)]
|
||||||
|
[TestCase (ApplePlatform.MacOSX, false)]
|
||||||
|
[TestCase (ApplePlatform.MacCatalyst, true)]
|
||||||
|
public void DuplicatedWithDifferentMetadata (ApplePlatform platform, bool isDotNet)
|
||||||
|
{
|
||||||
|
var tmpdir = Cache.CreateTemporaryDirectory ();
|
||||||
|
|
||||||
|
var currentDir = Environment.CurrentDirectory;
|
||||||
|
try {
|
||||||
|
Environment.CurrentDirectory = tmpdir;
|
||||||
|
var codesignItems = new List<ITaskItem> ();
|
||||||
|
var codesignBundle = new List<ITaskItem> ();
|
||||||
|
|
||||||
|
string codeSignatureSubdirectory = string.Empty;
|
||||||
|
switch (platform) {
|
||||||
|
case ApplePlatform.MacCatalyst:
|
||||||
|
case ApplePlatform.MacOSX:
|
||||||
|
codeSignatureSubdirectory = "Contents/";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bundleAppMetadata = new Dictionary<string, string> {
|
||||||
|
{ "RequireCodeSigning", "true" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var createDumpMetadata1 = new Dictionary<string, string> {
|
||||||
|
{ "RequireCodeSigning", "true" },
|
||||||
|
{ "OnlyIn1", "true" },
|
||||||
|
{ "InOneAndTwoWithDifferentValues", "1" },
|
||||||
|
};
|
||||||
|
var createDumpMetadata2 = new Dictionary<string, string> {
|
||||||
|
{ "RequireCodeSigning", "true" },
|
||||||
|
{ "OnlyIn2", "true" },
|
||||||
|
{ "InOneAndTwoWithDifferentValues", "2" },
|
||||||
|
};
|
||||||
|
var createDumpMetadata3 = new Dictionary<string, string> {
|
||||||
|
{ "RequireCodeSigning", "true" },
|
||||||
|
};
|
||||||
|
|
||||||
|
codesignItems = new List<ITaskItem> {
|
||||||
|
new TaskItem ("Bundle.app/Contents/MonoBundle/createdump", createDumpMetadata1),
|
||||||
|
new TaskItem ("Bundle.app/Contents/MonoBundle/createdump", createDumpMetadata2),
|
||||||
|
new TaskItem ("Bundle.app/Contents/MonoBundle/createdump", createDumpMetadata3),
|
||||||
|
};
|
||||||
|
|
||||||
|
codesignBundle = new List<ITaskItem> {
|
||||||
|
new TaskItem ("Bundle.app", bundleAppMetadata),
|
||||||
|
};
|
||||||
|
|
||||||
|
var infos = new CodesignInfo [] {
|
||||||
|
new CodesignInfo ("Bundle.app", Platforms.All, bundleAppMetadata.Set ("CodesignStampFile", $"Bundle.app/{codeSignatureSubdirectory}_CodeSignature/CodeResources")),
|
||||||
|
new CodesignInfo ("Bundle.app/Contents/MonoBundle/createdump", Platforms.All, createDumpMetadata1.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Contents/MonoBundle/createdump")),
|
||||||
|
};
|
||||||
|
|
||||||
|
var allFiles = infos.Select (v => v.ItemSpec).ToArray ();
|
||||||
|
Touch (tmpdir, allFiles);
|
||||||
|
|
||||||
|
var task = CreateTask<ComputeCodesignItems> ();
|
||||||
|
task.AppBundleDir = "Bundle.app";
|
||||||
|
task.CodesignBundle = codesignBundle.ToArray ();
|
||||||
|
task.CodesignItems = codesignItems.ToArray ();
|
||||||
|
task.CodesignStampPath = "codesign-stamp-path/";
|
||||||
|
task.TargetFrameworkMoniker = TargetFramework.GetTargetFramework (platform, isDotNet).ToString ();
|
||||||
|
Assert.IsTrue (task.Execute (), "Execute");
|
||||||
|
Assert.AreEqual (3, Engine.Logger.WarningsEvents.Count, "Warning Count");
|
||||||
|
Assert.AreEqual ("Code signing has been requested multiple times for 'Bundle.app/Contents/MonoBundle/createdump', with different metadata. The metadata 'OnlyIn1=true' has been set for one item, but not the other.", Engine.Logger.WarningsEvents [0].Message, "Message #0");
|
||||||
|
Assert.AreEqual ("Code signing has been requested multiple times for 'Bundle.app/Contents/MonoBundle/createdump', with different metadata. The metadata 'InOneAndTwoWithDifferentValues' has been values for each item (once it's '1', another time it's '2').", Engine.Logger.WarningsEvents [1].Message, "Message #1");
|
||||||
|
Assert.AreEqual ("Code signing has been requested multiple times for 'Bundle.app/Contents/MonoBundle/createdump', with different metadata. The metadata for one are: 'RequireCodeSigning, OnlyIn1, InOneAndTwoWithDifferentValues, CodesignStampFile', while the metadata for the other are: 'RequireCodeSigning, CodesignStampFile'", Engine.Logger.WarningsEvents [2].Message, "Message #2");
|
||||||
|
|
||||||
|
VerifyCodesigningResults (infos, task.OutputCodesignItems, platform);
|
||||||
|
} finally {
|
||||||
|
Environment.CurrentDirectory = currentDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void VerifyCodesigningResults (CodesignInfo [] infos, ITaskItem[] outputCodesignItems, ApplePlatform platform)
|
||||||
|
{
|
||||||
|
Assert.That (outputCodesignItems.Select (v => v.ItemSpec), Is.Unique, "Uniqueness");
|
||||||
|
|
||||||
|
var failures = new List<string> ();
|
||||||
|
var itemsFound = new List<ITaskItem> ();
|
||||||
|
foreach (var info in infos) {
|
||||||
|
var item = outputCodesignItems.SingleOrDefault (v => string.Equals (v.ItemSpec, info.ItemSpec, StringComparison.OrdinalIgnoreCase));
|
||||||
|
info.CodesignItem = item;
|
||||||
|
if (IsPlatform (info.SignedOn, platform)) {
|
||||||
|
if (item is null) {
|
||||||
|
failures.Add ($"Expected '{info.ItemSpec}' to be signed.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (item is not null) {
|
||||||
|
failures.Add ($"Did not expect '{info.ItemSpec}' to be signed.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is null)
|
||||||
|
continue;
|
||||||
|
itemsFound.Add (item);
|
||||||
|
|
||||||
|
foreach (var kvp in info.Metadata) {
|
||||||
|
var metadata = item.GetMetadata (kvp.Key);
|
||||||
|
if (metadata == string.Empty && kvp.Value != string.Empty) {
|
||||||
|
failures.Add ($"Item '{info.ItemSpec}': Expected metadata '{kvp.Key}' not found (with value '{kvp.Value}').");
|
||||||
|
} else if (!string.Equals (metadata, kvp.Value)) {
|
||||||
|
failures.Add ($"Item '{info.ItemSpec}': Expected value '{kvp.Value}' for metadata '{kvp.Key}', but got '{metadata}' instead.\nExpected: {kvp.Value}\nActual: {metadata}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var customMetadata = item.CopyCustomMetadata ();
|
||||||
|
var unexpectedMetadata = customMetadata.Keys.ToHashSet ();
|
||||||
|
unexpectedMetadata.ExceptWith (info.Metadata.Keys);
|
||||||
|
unexpectedMetadata.Remove ("OriginalItemSpec");
|
||||||
|
foreach (var unexpected in unexpectedMetadata) {
|
||||||
|
if (string.IsNullOrEmpty (customMetadata [unexpected]))
|
||||||
|
continue;
|
||||||
|
failures.Add ($"Item '{info.ItemSpec}': Unexpected metadata '{unexpected}' with value '{customMetadata [unexpected]}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemsNotFound = outputCodesignItems.Where (v => !itemsFound.Contains (v)).ToArray ();
|
||||||
|
foreach (var itemNotFound in itemsNotFound) {
|
||||||
|
failures.Add ($"Did not expect '{itemNotFound.ItemSpec}' to be signed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failures.Count > 0) {
|
||||||
|
Console.WriteLine ($"{failures.Count} failures");
|
||||||
|
foreach (var f in failures)
|
||||||
|
Console.WriteLine (f);
|
||||||
|
Console.WriteLine ($"{failures.Count} failures");
|
||||||
|
}
|
||||||
|
Assert.That (failures, Is.Empty, "Failures");
|
||||||
|
}
|
||||||
|
|
||||||
bool IsPlatform (Platforms platforms, ApplePlatform platform)
|
bool IsPlatform (Platforms platforms, ApplePlatform platform)
|
||||||
{
|
{
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash -ex
|
#!/bin/bash -ex
|
||||||
|
|
||||||
cd $(dirname $0)
|
cd "$(dirname "$0")"
|
||||||
./system-dependencies.sh --provision-mono --ignore-autotools --ignore-xamarin-studio --ignore-xcode --ignore-osx --ignore-cmake
|
./system-dependencies.sh --provision-mono --ignore-autotools --ignore-xamarin-studio --ignore-xcode --ignore-osx --ignore-cmake --ignore-dotnet
|
||||||
|
|
|
@ -6,7 +6,7 @@ ifdef INCLUDE_MAC
|
||||||
SUBDIRS+=mmp
|
SUBDIRS+=mmp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SUBDIRS+=mtouch xibuild mlaunch siminstaller
|
SUBDIRS+=mtouch xibuild mlaunch siminstaller nnyeah
|
||||||
|
|
||||||
ifdef ENABLE_INSTALL_SOURCE
|
ifdef ENABLE_INSTALL_SOURCE
|
||||||
SUBDIRS += install-source
|
SUBDIRS += install-source
|
||||||
|
|
|
@ -36,6 +36,11 @@ parameters:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: true
|
default: true
|
||||||
|
|
||||||
|
- name: runWindowsIntegration
|
||||||
|
displayName: Run Windows integration tests
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
- name: runGovernanceTests
|
- name: runGovernanceTests
|
||||||
displayName: Run Governance Checks
|
displayName: Run Governance Checks
|
||||||
type: boolean
|
type: boolean
|
||||||
|
@ -370,6 +375,7 @@ stages:
|
||||||
keyringPass: $(pass--lab--mac--builder--keychain)
|
keyringPass: $(pass--lab--mac--builder--keychain)
|
||||||
demands: ${{ config.demands }}
|
demands: ${{ config.demands }}
|
||||||
|
|
||||||
|
- ${{ if eq(parameters.runWindowsIntegration, true) }}:
|
||||||
- template: templates/windows/stage.yml
|
- template: templates/windows/stage.yml
|
||||||
parameters:
|
parameters:
|
||||||
stageName: windows_integration
|
stageName: windows_integration
|
||||||
|
|
|
@ -80,5 +80,5 @@ steps:
|
||||||
targetPath: ${{ parameters.outputPath }}
|
targetPath: ${{ parameters.outputPath }}
|
||||||
${{ else }}:
|
${{ else }}:
|
||||||
targetPath: ${{ parameters.workingDirectory }}/${{ parameters.outputPath }}
|
targetPath: ${{ parameters.workingDirectory }}/${{ parameters.outputPath }}
|
||||||
artifactName: $(Agent.Name)-${{ parameters.outputPath }}
|
artifactName: $(Agent.Name)-$(System.JobName)-$(System.JobId)-${{ parameters.outputPath }}
|
||||||
continueOnError: true
|
continueOnError: true
|
||||||
|
|
|
@ -36,7 +36,6 @@ steps:
|
||||||
- bash: cd $(System.DefaultWorkingDirectory)/xamarin-macios/ && git clean -xdf
|
- bash: cd $(System.DefaultWorkingDirectory)/xamarin-macios/ && git clean -xdf
|
||||||
displayName: 'Clean workspace'
|
displayName: 'Clean workspace'
|
||||||
|
|
||||||
|
|
||||||
# download the packages that have been created, install them, later download the zip files that contain the already built
|
# download the packages that have been created, install them, later download the zip files that contain the already built
|
||||||
# tests and execute them.
|
# tests and execute them.
|
||||||
|
|
||||||
|
@ -182,8 +181,6 @@ steps:
|
||||||
$(Build.SourcesDirectory)/artifacts/mac-test-package/test-dependencies.sh
|
$(Build.SourcesDirectory)/artifacts/mac-test-package/test-dependencies.sh
|
||||||
displayName: Install dependencies.
|
displayName: Install dependencies.
|
||||||
timeoutInMinutes: 60
|
timeoutInMinutes: 60
|
||||||
env:
|
|
||||||
IGNORE_DOTNET: 1 # Not needed for the tests.
|
|
||||||
|
|
||||||
- pwsh: |
|
- pwsh: |
|
||||||
Import-Module $Env:SYSTEM_DEFAULTWORKINGDIRECTORY\xamarin-macios\tools\devops\automation\scripts\GitHub.psm1
|
Import-Module $Env:SYSTEM_DEFAULTWORKINGDIRECTORY\xamarin-macios\tools\devops\automation\scripts\GitHub.psm1
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
TOP=../..
|
||||||
|
include $(TOP)/Make.config
|
||||||
|
|
||||||
|
all-local:: bin/Debug/net5.0/nnyeah.dll
|
||||||
|
|
||||||
|
install-local:: all-local
|
||||||
|
|
||||||
|
bin/Debug/net5.0/nnyeah.dll: $(wildcard **/*.cs) $(wildcard **/*.csproj) $(wildcard *.sln) Makefile
|
||||||
|
$(Q_BUILD) $(SYSTEM_MSBUILD) "/bl:$@.binlog" /restore $(MSBUILD_VERBOSITY) $(wildcard *.sln)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(Q_BUILD) $(SYSTEM_MSBUILD) "/bl:$@.binlog" /restore $(MSBUILD_VERBOSITY) /t:Clean $(wildcard *.sln)
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace nnyeah {
|
||||||
|
public abstract class BaseTransformEventArgs : EventArgs {
|
||||||
|
public BaseTransformEventArgs (string containerName, string methodName, string targetOperand)
|
||||||
|
{
|
||||||
|
ContainerName = containerName;
|
||||||
|
MethodName = methodName;
|
||||||
|
TargetOperand = targetOperand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ContainerName { get; init; }
|
||||||
|
public string MethodName { get; init; }
|
||||||
|
public string TargetOperand { get; init; }
|
||||||
|
|
||||||
|
public abstract string HelpfulMessage ();
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,5 +5,6 @@ namespace nnyeah {
|
||||||
Replace,
|
Replace,
|
||||||
Insert,
|
Insert,
|
||||||
Append,
|
Append,
|
||||||
|
Warn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace nnyeah {
|
||||||
static void Main (string [] args)
|
static void Main (string [] args)
|
||||||
{
|
{
|
||||||
if (args.Length != 2) {
|
if (args.Length != 2) {
|
||||||
Console.Error.WriteLine ("Usage: mono nnyeah.exe /path/to/input/file.dll /path/to/output/file.dll");
|
Console.Error.WriteLine ("Usage: dotnet nnyeah.dll /path/to/input/file.dll /path/to/output/file.dll");
|
||||||
Environment.Exit (1);
|
Environment.Exit (1);
|
||||||
}
|
}
|
||||||
using var stm = new FileStream (args [0], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
using var stm = new FileStream (args [0], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||||
|
|
|
@ -24,6 +24,9 @@ namespace nnyeah {
|
||||||
Dictionary<string, Transformation> methodSubs = new Dictionary<string, Transformation> ();
|
Dictionary<string, Transformation> methodSubs = new Dictionary<string, Transformation> ();
|
||||||
Dictionary<string, Transformation> fieldSubs = new Dictionary<string, Transformation> ();
|
Dictionary<string, Transformation> fieldSubs = new Dictionary<string, Transformation> ();
|
||||||
|
|
||||||
|
public event EventHandler<WarningEventArgs>? WarningIssued;
|
||||||
|
public event EventHandler<TransformEventArgs>? Transformed;
|
||||||
|
|
||||||
public Reworker (Stream stm)
|
public Reworker (Stream stm)
|
||||||
{
|
{
|
||||||
this.stm = stm;
|
this.stm = stm;
|
||||||
|
@ -255,7 +258,13 @@ namespace nnyeah {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (instr, trans) in changes) {
|
foreach (var (instr, trans) in changes) {
|
||||||
trans.PerformTransform (instr, body);
|
if (!trans.TryPerformTransform (instr, body)) {
|
||||||
|
WarningIssued?.Invoke (this, new WarningEventArgs (body.Method.DeclaringType.FullName, body.Method.Name, trans.Operand, trans.Message!));
|
||||||
|
} else {
|
||||||
|
var added = (uint)trans.Instructions.Count;
|
||||||
|
var removed = trans.Action == TransformationAction.Remove || trans.Action == TransformationAction.Replace ? (uint)1 : 0;
|
||||||
|
Transformed?.Invoke (this, new TransformEventArgs (body.Method.DeclaringType.FullName, body.Method.Name, trans.Operand, added, removed));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace nnyeah {
|
||||||
|
public class TransformEventArgs : BaseTransformEventArgs {
|
||||||
|
public TransformEventArgs (string containerName, string methodName, string targetOperand, uint addedCount, uint removedCount)
|
||||||
|
: base (containerName, methodName, targetOperand)
|
||||||
|
{
|
||||||
|
AddedCount = addedCount;
|
||||||
|
RemovedCount = removedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint AddedCount { get; init; }
|
||||||
|
public uint RemovedCount { get; init; }
|
||||||
|
|
||||||
|
public override string HelpfulMessage ()
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder ();
|
||||||
|
sb.Append ($"In {ContainerName}.{MethodName}, found reference to {TargetOperand}. Added {AddedCount} IL instructions");
|
||||||
|
if (RemovedCount > 0)
|
||||||
|
sb.Append ($" and removed {RemovedCount} IL instructions");
|
||||||
|
sb.Append ('.');
|
||||||
|
return sb.ToString ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,11 +26,20 @@ namespace nnyeah {
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Transformation (string operand, string warningMessage)
|
||||||
|
{
|
||||||
|
Operand = operand;
|
||||||
|
Action = TransformationAction.Warn;
|
||||||
|
Instructions = new List<Instruction> ();
|
||||||
|
Message = warningMessage;
|
||||||
|
}
|
||||||
|
|
||||||
public string Operand { get; private set; }
|
public string Operand { get; private set; }
|
||||||
public TransformationAction Action { get; private set; }
|
public TransformationAction Action { get; private set; }
|
||||||
public List<Instruction> Instructions { get; private set; }
|
public List<Instruction> Instructions { get; private set; }
|
||||||
|
public string? Message { get; private set; }
|
||||||
|
|
||||||
public void PerformTransform (Instruction old, MethodBody body)
|
public bool TryPerformTransform (Instruction old, MethodBody body)
|
||||||
{
|
{
|
||||||
var il = body.GetILProcessor ();
|
var il = body.GetILProcessor ();
|
||||||
switch (Action) {
|
switch (Action) {
|
||||||
|
@ -53,7 +62,10 @@ namespace nnyeah {
|
||||||
}
|
}
|
||||||
il.Remove (old);
|
il.Remove (old);
|
||||||
break;
|
break;
|
||||||
|
case TransformationAction.Warn:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction AddVariableIfNeeded (MethodBody body, Instruction instr)
|
static Instruction AddVariableIfNeeded (MethodBody body, Instruction instr)
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace nnyeah {
|
||||||
|
public class WarningEventArgs : BaseTransformEventArgs {
|
||||||
|
public WarningEventArgs (string containerName, string methodName, string targetOperand, string message)
|
||||||
|
: base (containerName, methodName, targetOperand)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Message { get; init; }
|
||||||
|
|
||||||
|
public override string HelpfulMessage ()
|
||||||
|
{
|
||||||
|
return $"In {ContainerName}.{MethodName}, found reference to {TargetOperand} - this is not transformable and will likely not work if invoked.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче