[mtouch][mmp] Add a `--warn-on-type-ref=X` option (#7949)

Using this option it's possible to test for the presence of a type
reference in both pre-linked and post-linked assemblies.

This makes it possible to detect if
* a 3rd party assemblies are using some specific type you would like to avoid;
* a type reference has been removed during the build (e.g. linker)

Notes:
* Custom attributes are encoded differently and not included in the assembly type references metadata.
* Assembly that define a type `X` do not have a reference (but the definition) of the type (and won't be reported).

If either the pre or post-linked warnings are not useful then it's possible
 to add `-nowarn:150x` to exclude the results.

E.g.
* `-nowarn:1502` would not report references in pre-linked assemblies;
* `-nowarn:1503` would not report references in post-linked assemblies;

Finally `-warnaserror:150x` can be used to stop a build that would not
satisfy either the pre or post-linked condition.

* `-warnaserror:1502` would not report references in pre-linked assemblies;
* `-warnaserror:1503` would not report references in post-linked assemblies;

_side note_ same as https://github.com/xamarin/xamarin-macios/pull/7925
except that this one uses the localized mtouch/mmp errors only in master (so far)
This commit is contained in:
Sebastien Pouliot 2020-02-20 22:25:23 -05:00 коммит произвёл GitHub
Родитель 1ce5eeb3dc
Коммит d83e13edf1
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
27 изменённых файлов: 415 добавлений и 7 удалений

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

@ -313,6 +313,30 @@ Change the architecture in the project's Mac Build options to 'x86_64' in order
#### MM1501: Can not resolve reference: {0}
<a name="MM1502" />
#### MM1502: One or more reference(s) to type '{0}' already exists inside '{1}' before linking
This warning might be reported when using `--warn-on-type-ref=X` if any loaded (unmodified) assembly has a type reference to the type `X`.
This can be used along with `--warnaserror:1502` to ensure a reference to a specific type (e.g. `UIKit.UIWebView`) is not being used by any assembly used the application.
Notes:
* Custom attributes are encoded differently and not included inside an assembly type references metadata.
* Assembly that define a type `X` do not have a reference (but the definition) of the type (and won't be reported).
<a name="MM1503" />
#### MM1503: One or more reference(s) to type '{0}' still exists inside '{1}' after linking
This warning might be reported when using `--warn-on-type-ref=X` if any linked (modified) assembly has a type reference to the type `X`.
This can be used along with `--warnaserror:1503` to ensure a reference to a specific type (e.g. `UIKit.UIWebView`) will not be part of (the managed side of) the application.
Notes:
* Custom attributes are encoded differently and not included inside an assembly type references metadata.
* Assembly that define a type `X` do not have a reference (but the definition) of the type (and won't be reported).
### MachO.cs
<a name="MM1600" />

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

@ -1561,6 +1561,32 @@ Things to try to solve this:
<!--- 1407 used by mmp -->
<!--- 1501 used by mmp -->
<a name="MT1502" />
#### MT1502: One or more reference(s) to type '{0}' already exists inside '{1}' before linking
This warning might be reported when using `--warn-on-type-ref=X` if any loaded (unmodified) assembly has a type reference to the type `X`.
This can be used along with `--warnaserror:1502` to ensure a reference to a specific type (e.g. `UIKit.UIWebView`) is not being used by any assembly used the application.
Notes:
* Custom attributes are encoded differently and not included inside an assembly type references metadata.
* Assembly that define a type `X` do not have a reference (but the definition) of the type (and won't be reported).
<a name="MT1503" />
#### MT1503: One or more reference(s) to type '{0}' still exists inside '{1}' after linking
This warning might be reported when using `--warn-on-type-ref=X` if any linked (modified) assembly has a type reference to the type `X`.
This can be used along with `--warnaserror:1503` to ensure a reference to a specific type (e.g. `UIKit.UIWebView`) will not be part of (the managed side of) the application.
Notes:
* Custom attributes are encoded differently and not included inside an assembly type references metadata.
* Assembly that define a type `X` do not have a reference (but the definition) of the type (and won't be reported).
### MT16xx: MachO
<!--

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

@ -339,16 +339,16 @@ class Issue4072Session : NSUrlSession {
{
using (var bundler = new BundlerTool ()) {
var code = @"
using System;
using Foundation;
using ObjCRuntime;
class T {
static void Main ()
using System;
using Foundation;
using ObjCRuntime;
class T {
static void Main ()
{
Console.WriteLine (typeof (NSObject));
}
}
";
}
";
bundler.Profile = profile;
bundler.CreateTemporaryCacheDirectory ();
bundler.CreateTemporaryApp (profile, code: code);
@ -360,5 +360,37 @@ class Issue4072Session : NSUrlSession {
bundler.AssertErrorCount (1);
}
}
[Test]
#if __MACOS__
[TestCase (Profile.macOSMobile)]
#else
[TestCase (Profile.iOS)]
#endif
public void MX1502_3 (Profile profile)
{
using (var bundler = new BundlerTool ()) {
var code = @"
using System;
using Foundation;
using ObjCRuntime;
class T {
static void Main ()
{
Console.WriteLine (typeof (NSObject));
}
}
";
bundler.Profile = profile;
bundler.CreateTemporaryCacheDirectory ();
bundler.CreateTemporaryApp (profile, code: code);
bundler.Linker = LinkerOption.LinkAll;
bundler.CustomArguments = new [] { "--warn-on-type-ref=Foundation.NSObject" };
bundler.AssertExecute ();
bundler.AssertWarning (1502, "One or more reference(s) to type 'Foundation.NSObject' already exists inside 'testApp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' before linking");
bundler.AssertWarning (1503, "One or more reference(s) to type 'Foundation.NSObject' still exists inside 'testApp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' after linking");
bundler.AssertWarningCount (2);
}
}
}
}

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

@ -66,6 +66,7 @@ namespace Xamarin.Bundler {
public List<string> LinkSkipped = new List<string> ();
public List<string> Definitions = new List<string> ();
public Mono.Linker.I18nAssemblies I18n;
public List<string> WarnOnTypeRef = new List<string> ();
public bool? EnableCoopGC;
public bool EnableSGenConc;

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

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Linker.Steps;
using Xamarin.Bundler;
#if MTOUCH
using ProductException = Xamarin.Bundler.MonoTouchException;
#else
using ProductException = Xamarin.Bundler.MonoMacException;
#endif
namespace Xamarin.Linker.Steps {
abstract public class ScanTypeReferenceStep : BaseStep {
protected readonly List<string> lookfor;
protected ScanTypeReferenceStep (List<string> list)
{
lookfor = list;
}
protected override void ProcessAssembly (AssemblyDefinition assembly)
{
foreach (var module in assembly.Modules) {
foreach (var name in lookfor) {
if (module.HasTypeReference (name))
Report (name, assembly);
}
}
}
protected abstract void Report (string typeName, AssemblyDefinition assembly);
}
public class PreLinkScanTypeReferenceStep : ScanTypeReferenceStep {
public PreLinkScanTypeReferenceStep (List<string> list) : base (list)
{
}
protected override void Report (string typeName, AssemblyDefinition assembly)
{
ErrorHelper.Show (new ProductException (1502, false, "One or more reference(s) to type '{0}' already exists inside '{1}' before linking", typeName, assembly));
}
}
public class PostLinkScanTypeReferenceStep : ScanTypeReferenceStep {
public PostLinkScanTypeReferenceStep (List<string> list) : base (list)
{
}
protected override void Report (string typeName, AssemblyDefinition assembly)
{
ErrorHelper.Show (new ProductException (1503, false, "One or more reference(s) to type '{0}' still exists inside '{1}' after linking", typeName, assembly));
}
}
}

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

@ -37,6 +37,7 @@ namespace MonoMac.Tuner {
public MonoMacLinkContext LinkContext { get; set; }
public Target Target { get; set; }
public Application Application { get { return Target.App; } }
public List<string> WarnOnTypeRef { get; set; }
public static I18nAssemblies ParseI18nAssemblies (string i18n)
{
@ -122,6 +123,9 @@ namespace MonoMac.Tuner {
if (options.LinkMode != LinkMode.None)
pipeline.AppendStep (new BlacklistStep ());
if (options.WarnOnTypeRef.Count > 0)
pipeline.AppendStep (new PreLinkScanTypeReferenceStep (options.WarnOnTypeRef));
pipeline.AppendStep (new CustomizeMacActions (options.LinkMode, options.SkippedAssemblies));
// We need to store the Field attribute in annotations, since it may end up removed.
@ -155,6 +159,10 @@ namespace MonoMac.Tuner {
pipeline.AppendStep (new OutputStep ());
// expect that changes can occur until it's all saved back to disk
if (options.WarnOnTypeRef.Count > 0)
pipeline.AppendStep (new PostLinkScanTypeReferenceStep (options.WarnOnTypeRef));
return pipeline;
}

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

@ -319,6 +319,10 @@ namespace Xamarin.Bundler {
}
},
{ "link-prohibited-frameworks", "Natively link against prohibited (rejected by AppStore) frameworks", v => { LinkProhibitedFrameworks = true; } },
{ "warn-on-type-ref=", "Warn if any of the comma-separated types is referenced by assemblies - both before and after linking", v => {
App.WarnOnTypeRef.AddRange (v.Split (new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries));
}
},
};
AddSharedOptions (App, os);
@ -1370,6 +1374,7 @@ namespace Xamarin.Bundler {
},
SkipExportedSymbolsInSdkAssemblies = !embed_mono,
Target = BuildTarget,
WarnOnTypeRef = App.WarnOnTypeRef,
};
linker_options = options;

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

@ -427,6 +427,9 @@
<Link>Errors.Designer.cs</Link>
<DependentUpon>Errors.resx</DependentUpon>
</Compile>
<Compile Include="..\linker\ScanTypeReferenceStep.cs">
<Link>Xamarin.Linker\ScanTypeReferenceStep.cs</Link>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

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

@ -582,6 +582,7 @@ namespace Xamarin.Bundler
DumpDependencies = App.LinkerDumpDependencies,
RuntimeOptions = App.RuntimeOptions,
MarshalNativeExceptionsState = MarshalNativeExceptionsState,
WarnOnTypeRef = App.WarnOnTypeRef,
Target = this,
};

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

@ -33,6 +33,7 @@ namespace MonoTouch.Tuner {
public bool DumpDependencies { get; set; }
internal PInvokeWrapperGenerator MarshalNativeExceptionsState { get; set; }
internal RuntimeOptions RuntimeOptions { get; set; }
public List<string> WarnOnTypeRef { get; set; }
public MonoTouchLinkContext LinkContext { get; set; }
public Target Target { get; set; }
@ -145,6 +146,9 @@ namespace MonoTouch.Tuner {
if (options.LinkMode != LinkMode.None)
pipeline.Append (new BlacklistStep ());
if (options.WarnOnTypeRef.Count > 0)
pipeline.Append (new PreLinkScanTypeReferenceStep (options.WarnOnTypeRef));
pipeline.Append (new CustomizeIOSActions (options.LinkMode, options.SkippedAssemblies));
// We need to store the Field attribute in annotations, since it may end up removed.
@ -192,6 +196,10 @@ namespace MonoTouch.Tuner {
pipeline.Append (new OutputStep ());
// expect that changes can occur until it's all saved back to disk
if (options.WarnOnTypeRef.Count > 0)
pipeline.Append (new PostLinkScanTypeReferenceStep (options.WarnOnTypeRef));
return pipeline;
}

12
tools/mtouch/errors.Designer.cs сгенерированный
Просмотреть файл

@ -1217,6 +1217,18 @@ namespace Xamarin.Bundler {
}
}
internal static string MX1502 {
get {
return ResourceManager.GetString("MX1502", resourceCulture);
}
}
internal static string MX1503 {
get {
return ResourceManager.GetString("MX1503", resourceCulture);
}
}
internal static string MX1600 {
get {
return ResourceManager.GetString("MX1600", resourceCulture);

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

@ -1378,6 +1378,20 @@
<comment>
</comment>
</data>
<data name="MX1502" xml:space="preserve">
<value>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</value>
<comment>
</comment>
</data>
<data name="MX1503" xml:space="preserve">
<value>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</value>
<comment>
</comment>
</data>
<data name="MX1600" xml:space="preserve">
<value>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.

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

@ -1144,6 +1144,10 @@ namespace Xamarin.Bundler
app.AddAssemblyBuildTarget (v);
}
},
{ "warn-on-type-ref=", "Warn if any of the comma-separated types is referenced by assemblies - both before and after linking", v => {
app.WarnOnTypeRef.AddRange (v.Split (new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries));
}
},
};
AddSharedOptions (app, os);

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

@ -429,6 +429,9 @@
<Compile Include="Errors.Designer.cs">
<DependentUpon>Errors.resx</DependentUpon>
</Compile>
<Compile Include="..\linker\ScanTypeReferenceStep.cs">
<Link>Xamarin.Linker\ScanTypeReferenceStep.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Core" />

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>

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

@ -2906,6 +2906,22 @@
<note>
</note>
</trans-unit>
<trans-unit id="MX1502">
<source>One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</source>
<target state="new">One or more reference(s) to type '{0}' already exists inside '{1}' before linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1503">
<source>One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</source>
<target state="new">One or more reference(s) to type '{0}' still exists inside '{1}' after linking
</target>
<note>
</note>
</trans-unit>
<trans-unit id="MX1600">
<source>Not a Mach-O dynamic library (unknown header '0x{0}'): {1}.
</source>