Merge remote-tracking branch 'origin/mono-2018-06' into mono-2018-08
This commit is contained in:
Коммит
16481d4ec1
|
@ -1340,8 +1340,8 @@ The following shows two such properties in Objective-C:
|
|||
When you apply the `DisposeAttribute` to a class, you provide a code snippet
|
||||
that will be added to the `Dispose()` method implementation of the class.
|
||||
|
||||
Since the `Dispose` method is automatically generated by the `bmac-native` and `btouch-native`
|
||||
tools, you need to use the `Dispose` attribute to inject some code in the
|
||||
Since the `Dispose` method is automatically generated by the `bgen`
|
||||
tool, you need to use the `Dispose` attribute to inject some code in the
|
||||
generated `Dispose` method implementation.
|
||||
|
||||
For example:
|
||||
|
|
|
@ -378,6 +378,20 @@ will be shown.
|
|||
|
||||
Reference: https://github.com/xamarin/xamarin-macios/issues/4072
|
||||
|
||||
### <a name="MM4176"/>MM4176: Unable to locate the delegate to block conversion type for the return value of the method {method}.
|
||||
|
||||
This is a warning indicating that the static registrar couldn't find the type
|
||||
used to convert a delegate to an Objective-C block. An attempt will be made at
|
||||
runtime to find the method, but it will likely fail as well (with an MM8009
|
||||
exception).
|
||||
|
||||
One possible reason for this warning is when manually writing bindings for API
|
||||
that uses blocks. It's recommended to use a binding project to bind
|
||||
Objective-C code, in particular when it involves blocks, since it's quite
|
||||
complicated to get it right when doing it manually.
|
||||
|
||||
If this is not the case, please file a bug at [https://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=Xamarin.Mac) with a test case.
|
||||
|
||||
# MM5xxx: GCC and toolchain
|
||||
|
||||
## MM51xx: compilation
|
||||
|
@ -508,3 +522,8 @@ There are a few reasons this may happen:
|
|||
|
||||
* It could be a bug in Xamarin.Mac. If this is the case, please file a bug at
|
||||
[https://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=Xamarin.Mac).
|
||||
|
||||
### <a name="MM8028"/>MM8028: The runtime function {function} has been linked away.
|
||||
|
||||
This usually indicates a bug in Xamarin.Mac, because runtime functions should
|
||||
not be linked away if they're needed. Please [submit an issue](https://github.com/xamarin/xamarin-macios/wiki/Submitting-Bugs-&-Suggestions).
|
||||
|
|
|
@ -1787,6 +1787,20 @@ will be shown.
|
|||
|
||||
Reference: https://github.com/xamarin/xamarin-macios/issues/4072
|
||||
|
||||
### <a name="MT4176"/>MT4176: Unable to locate the delegate to block conversion type for the return value of the method {method}.
|
||||
|
||||
This is a warning indicating that the static registrar couldn't find the type
|
||||
used to convert a delegate to an Objective-C block. An attempt will be made at
|
||||
runtime to find the method, but it will likely fail as well (with an MT8009
|
||||
exception).
|
||||
|
||||
One possible reason for this warning is when manually writing bindings for API
|
||||
that uses blocks. It's recommended to use a binding project to bind
|
||||
Objective-C code, in particular when it involves blocks, since it's quite
|
||||
complicated to get it right when doing it manually.
|
||||
|
||||
If this is not the case, please file a bug at [https://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=iOS) with a test case.
|
||||
|
||||
# MT5xxx: GCC and toolchain error messages
|
||||
|
||||
### MT51xx: Compilation
|
||||
|
@ -2527,3 +2541,8 @@ There are a few reasons this may happen:
|
|||
|
||||
* It could be a bug in Xamarin.iOS. If this is the case, please file a bug at
|
||||
[https://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=iOS).
|
||||
|
||||
### <a name="MT8028"/>MT8028: The runtime function {function} has been linked away.
|
||||
|
||||
This usually indicates a bug in Xamarin.iOS, because runtime functions should
|
||||
not be linked away if they're needed. Please [submit an issue](https://github.com/xamarin/xamarin-macios/wiki/Submitting-Bugs-&-Suggestions).
|
||||
|
|
|
@ -366,8 +366,12 @@ timestamps {
|
|||
} else {
|
||||
def outputFile = "${workspace}/xamarin-macios/wrench-launch-external.output.tmp"
|
||||
try {
|
||||
// VSTS does not allow any branch name anymore, it has to be an existing branch.
|
||||
// Since pull requests don't create branches in the xamarin org (that VSTS sees at least),
|
||||
// I've created a 'pull-request' branch which we'll use for pull requests.
|
||||
def vsts_branch = isPr ? "pull-request" : branchName;
|
||||
withCredentials ([string (credentialsId: 'macios_provisionator_pat', variable: 'PROVISIONATOR_VSTS_PAT')]) {
|
||||
sh ("make -C ${workspace}/xamarin-macios/tests wrench-launch-external MAC_PACKAGE_URL=${xmPackageUrl} IOS_PACKAGE_URL=${xiPackageUrl} WRENCH_URL=${env.RUN_DISPLAY_URL} BUILD_REVISION=${gitHash} BUILD_LANE=jenkins/${branchName} BUILD_WORK_HOST=${env.NODE_NAME} 2>&1 | tee ${outputFile}")
|
||||
sh ("make -C ${workspace}/xamarin-macios/tests wrench-launch-external MAC_PACKAGE_URL=${xmPackageUrl} IOS_PACKAGE_URL=${xiPackageUrl} WRENCH_URL=${env.RUN_DISPLAY_URL} BUILD_REVISION=${gitHash} BUILD_LANE=${vsts_branch} BUILD_WORK_HOST=${env.NODE_NAME} 2>&1 | tee ${outputFile}")
|
||||
}
|
||||
processAtMonkeyWrench (outputFile)
|
||||
} catch (error) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
ifdef ENABLE_XAMARIN
|
||||
NEEDED_MACCORE_VERSION := 07fde84362aac824c6d9596c8dae13cfa48a102e
|
||||
NEEDED_MACCORE_VERSION := fbb847be2caac894fd3d54889317d808289dd351
|
||||
NEEDED_MACCORE_BRANCH := master
|
||||
|
||||
MACCORE_DIRECTORY := maccore
|
||||
|
|
|
@ -27,8 +27,7 @@ Copyright (C) 2014 Xamarin. All rights reserved.
|
|||
<PropertyGroup>
|
||||
<BaseLibDllPath>$(MacBclPath)/Xamarin.Mac.dll</BaseLibDllPath>
|
||||
<BTouchToolPath>$(XamarinMacFrameworkRoot)/bin/</BTouchToolPath>
|
||||
<BTouchToolExe Condition="Exists('$(BTouchToolPath)/bgen')">bgen</BTouchToolExe>
|
||||
<BTouchToolExe Condition="!Exists('$(BTouchToolPath)/bgen')">bmac-mobile-mono</BTouchToolExe>
|
||||
<BTouchToolExe>bgen</BTouchToolExe>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
|
||||
<DefineConstants>__UNIFIED__;__MACOS__;$(DefineConstants)</DefineConstants>
|
||||
|
|
|
@ -106,8 +106,7 @@ namespace Xamarin.iOS.Tasks
|
|||
[Required]
|
||||
public bool EnableSGenConc { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool UseInterpreter { get; set; }
|
||||
public string Interpreter { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool LinkerDumpDependencies { get; set; }
|
||||
|
@ -405,8 +404,8 @@ namespace Xamarin.iOS.Tasks
|
|||
if (EnableSGenConc)
|
||||
args.AddLine ("--sgen-conc");
|
||||
|
||||
if (UseInterpreter)
|
||||
args.Add ("--interpreter");
|
||||
if (!string.IsNullOrEmpty (Interpreter))
|
||||
args.Add ($"--interpreter={Interpreter}");
|
||||
|
||||
switch (LinkMode.ToLowerInvariant ()) {
|
||||
case "sdkonly": args.AddLine ("--linksdkonly"); break;
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FileList Name="Xamarin.TVOS" TargetFrameworkDirectory="%TargetFrameworkDirectory%" />
|
||||
<FileList Name="Xamarin.TVOS" TargetFrameworkDirectory="%TargetFrameworkDirectory%">
|
||||
<File AssemblyName="System.Buffers" Version="4.0.99.0" />
|
||||
<File AssemblyName="System.Memory" Version="4.0.99.0" />
|
||||
</FileList>
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FileList Name="Xamarin.WatchOS" TargetFrameworkDirectory="%TargetFrameworkDirectory%" />
|
||||
<FileList Name="Xamarin.WatchOS" TargetFrameworkDirectory="%TargetFrameworkDirectory%">
|
||||
<File AssemblyName="System.Buffers" Version="4.0.99.0" />
|
||||
<File AssemblyName="System.Memory" Version="4.0.99.0" />
|
||||
</FileList>
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FileList Name="Xamarin.iOS" TargetFrameworkDirectory="%TargetFrameworkDirectory%" />
|
||||
<FileList Name="Xamarin.iOS" TargetFrameworkDirectory="%TargetFrameworkDirectory%">
|
||||
<File AssemblyName="System.Buffers" Version="4.0.99.0" />
|
||||
<File AssemblyName="System.Memory" Version="4.0.99.0" />
|
||||
</FileList>
|
||||
|
|
|
@ -51,7 +51,6 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved.
|
|||
<MtouchUseThumb Condition="'$(MtouchUseThumb)' == ''">False</MtouchUseThumb>
|
||||
<MtouchProjectDirectory>$(MSBuildProjectDirectory)</MtouchProjectDirectory>
|
||||
<MtouchEnableSGenConc Condition="'$(MtouchEnableSGenConc)' == ''">False</MtouchEnableSGenConc>
|
||||
<MtouchUseInterpreter Condition="'$(MtouchUseInterpreter)' == ''">False</MtouchUseInterpreter>
|
||||
<MtouchVerbosity Condition="$(MtouchVerbosity) == ''">2</MtouchVerbosity>
|
||||
|
||||
<IsMacEnabled>true</IsMacEnabled>
|
||||
|
|
|
@ -831,7 +831,7 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved.
|
|||
UseThumb="$(MtouchUseThumb)"
|
||||
EnableBitcode="$(MtouchEnableBitcode)"
|
||||
EnableSGenConc="$(MtouchEnableSGenConc)"
|
||||
UseInterpreter="$(MtouchUseInterpreter)"
|
||||
Interpreter="$(MtouchInterpreter)"
|
||||
AppExtensionReferences="@(_ResolvedAppExtensionReferences)"
|
||||
ArchiveSymbols="$(MonoSymbolArchive)"
|
||||
Verbosity="$(MtouchVerbosity)"
|
||||
|
|
|
@ -27,10 +27,24 @@ struct Delegates {
|
|||
|
||||
static struct Delegates delegates = { 0 };
|
||||
|
||||
static guint32
|
||||
create_linked_away_exception (const char *func)
|
||||
{
|
||||
char *msg = xamarin_strdup_printf ("The runtime function %s has been linked away.", func);
|
||||
guint32 gchandle = xamarin_create_product_exception (8028, msg);
|
||||
xamarin_free (msg);
|
||||
return gchandle;
|
||||
}
|
||||
|
||||
<# foreach (var d in delegates) { #>
|
||||
<#= d.CReturnType #>
|
||||
<#= d.EntryPoint #> (<#= d.CArgumentSignature #>)
|
||||
{
|
||||
<#if (d.ExceptionHandling && d.OnlyDynamicUsage) {#>if (delegates.<#= d.EntryPoint.Substring ("xamarin_".Length) #> == NULL) {
|
||||
*exception_gchandle = create_linked_away_exception ("<#= d.EntryPoint.Substring ("xamarin_".Length) #>");
|
||||
return<# if (d.CReturnType != "void") { #> (<#= d.CReturnType #>) 0<# } #>;
|
||||
}
|
||||
<#}#>
|
||||
<# if (d.CReturnType != "void") { #>return <# } #>delegates.<#= d.EntryPoint.Substring ("xamarin_".Length) #> (<#= d.CArgumentNames #>);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,8 @@
|
|||
new XDelegate ("id", "IntPtr", "xamarin_create_delegate_proxy",
|
||||
"MonoObject *", "IntPtr", "method",
|
||||
"MonoObject *", "IntPtr", "block",
|
||||
"const char *", "IntPtr", "signature"
|
||||
"const char *", "IntPtr", "signature",
|
||||
"unsigned int", "uint", "token_ref"
|
||||
) {
|
||||
WrappedManagedFunction = "CreateDelegateProxy",
|
||||
OnlyDynamicUsage = false,
|
||||
|
|
|
@ -2187,10 +2187,10 @@ xamarin_get_delegate_for_block_parameter (MonoMethod *method, guint32 token_ref,
|
|||
}
|
||||
|
||||
id
|
||||
xamarin_get_block_for_delegate (MonoMethod *method, MonoObject *delegate, const char *signature, guint32 *exception_gchandle)
|
||||
xamarin_get_block_for_delegate (MonoMethod *method, MonoObject *delegate, const char *signature, guint32 token_ref, guint32 *exception_gchandle)
|
||||
{
|
||||
// COOP: accesses managed memory: unsafe mode.
|
||||
return delegates.create_delegate_proxy ((MonoObject *) mono_method_get_object (mono_domain_get (), method, NULL), delegate, signature, exception_gchandle);
|
||||
return delegates.create_delegate_proxy ((MonoObject *) mono_method_get_object (mono_domain_get (), method, NULL), delegate, signature, token_ref, exception_gchandle);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2424,14 +2424,18 @@ xamarin_process_managed_exception (MonoObject *exception)
|
|||
|
||||
void
|
||||
xamarin_throw_product_exception (int code, const char *message)
|
||||
{
|
||||
xamarin_process_managed_exception_gchandle (xamarin_create_product_exception (code, message));
|
||||
}
|
||||
|
||||
guint32
|
||||
xamarin_create_product_exception (int code, const char *message)
|
||||
{
|
||||
guint32 exception_gchandle = 0;
|
||||
guint32 handle = xamarin_create_product_exception_for_error (code, message, &exception_gchandle);
|
||||
if (exception_gchandle != 0) {
|
||||
xamarin_process_managed_exception_gchandle (exception_gchandle);
|
||||
} else {
|
||||
xamarin_process_managed_exception_gchandle (handle);
|
||||
}
|
||||
if (exception_gchandle != 0)
|
||||
return exception_gchandle;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -60,7 +60,7 @@ xamarin_marshal_return_value (MonoType *mtype, const char *type, MonoObject *ret
|
|||
case _C_PTR: {
|
||||
MonoClass *klass = mono_class_from_mono_type (mtype);
|
||||
if (mono_class_is_delegate (klass)) {
|
||||
return xamarin_get_block_for_delegate (method, retval, NULL, exception_gchandle);
|
||||
return xamarin_get_block_for_delegate (method, retval, NULL, INVALID_TOKEN_REF, exception_gchandle);
|
||||
} else {
|
||||
return *(void **) mono_object_unbox (retval);
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ MonoType * xamarin_get_parameter_type (MonoMethod *managed_method, int index);
|
|||
MonoObject * xamarin_get_nsobject_with_type_for_ptr (id self, bool owns, MonoType* type, SEL selector, MonoMethod *managed_method, guint32 *exception_gchandle);
|
||||
MonoObject * xamarin_get_nsobject_with_type_for_ptr_created (id self, bool owns, MonoType *type, int32_t *created, SEL selector, MonoMethod *managed_method, guint32 *exception_gchandle);
|
||||
int * xamarin_get_delegate_for_block_parameter (MonoMethod *method, guint32 token_ref, int par, void *nativeBlock, guint32 *exception_gchandle);
|
||||
id xamarin_get_block_for_delegate (MonoMethod *method, MonoObject *delegate, const char *signature /* NULL allowed, but requires the dynamic registrar at runtime to compute */, guint32 *exception_gchandle);
|
||||
id xamarin_get_block_for_delegate (MonoMethod *method, MonoObject *delegate, const char *signature /* NULL allowed, but requires the dynamic registrar at runtime to compute */, guint32 token_ref /* INVALID_TOKEN_REF allowed, but requires the dynamic registrar at runtime */, guint32 *exception_gchandle);
|
||||
id xamarin_get_nsobject_handle (MonoObject *obj);
|
||||
void xamarin_set_nsobject_handle (MonoObject *obj, id handle);
|
||||
uint8_t xamarin_get_nsobject_flags (MonoObject *obj);
|
||||
|
@ -233,6 +233,7 @@ void xamarin_process_nsexception_using_mode (NSException *ns_exception, bool t
|
|||
void xamarin_process_managed_exception (MonoObject *exc);
|
||||
void xamarin_process_managed_exception_gchandle (guint32 gchandle);
|
||||
void xamarin_throw_product_exception (int code, const char *message);
|
||||
guint32 xamarin_create_product_exception (int code, const char *message);
|
||||
NSString * xamarin_print_all_exceptions (MonoObject *exc);
|
||||
|
||||
id xamarin_invoke_objc_method_implementation (id self, SEL sel, IMP xamarin_impl);
|
||||
|
|
|
@ -59,6 +59,7 @@ namespace Foundation {
|
|||
public string Name { get; set; }
|
||||
public string Selector { get; set; }
|
||||
public Type ReturnType { get; set; }
|
||||
public Type ReturnTypeDelegateProxy { get; set; }
|
||||
public Type[] ParameterType { get; set; }
|
||||
public bool[] ParameterByRef { get; set; }
|
||||
public Type[] ParameterBlockProxy { get; set; }
|
||||
|
|
25
src/Makefile
25
src/Makefile
|
@ -168,11 +168,7 @@ $(IOS_BUILD_DIR)/reference/System.Drawing.dll: $(IOS_SYSTEM_DRAWING_SOURCES) mon
|
|||
$(IOS_SYSTEM_DRAWING_SOURCES)
|
||||
|
||||
$(IOS_BUILD_DIR)/reference/Xamarin.iOS.dll: $(IOS_BUILD_DIR)/native-64/Xamarin.iOS.dll | $(IOS_BUILD_DIR)/reference
|
||||
@# Don't strip, btouch-native needs to execute code from Xamarin.iOS,
|
||||
@# and that'll break if we strip out the code from the reference assembly.
|
||||
@# Note that there is only btouch-native executable for both 32 and 64 bits.
|
||||
@#$(Q_GEN) mono-cil-strip $< $@
|
||||
$(Q) cp $< $@
|
||||
$(Q_GEN) mono-cil-strip $< $@
|
||||
|
||||
$(IOS_BUILD_DIR)/reference/Xamarin.iOS.pdb: $(IOS_BUILD_DIR)/native-64/Xamarin.iOS.pdb | $(IOS_BUILD_DIR)/reference
|
||||
$(Q) cp $< $@
|
||||
|
@ -753,11 +749,7 @@ $(WATCH_BUILD_DIR)/watch-32/Xamarin.WatchOS%dll $(WATCH_BUILD_DIR)/watch-32/Xama
|
|||
$(WATCHOS_SOURCES) @$(WATCH_BUILD_DIR)/watch/generated_sources
|
||||
|
||||
$(WATCH_BUILD_DIR)/reference/Xamarin.WatchOS.dll: $(WATCH_BUILD_DIR)/watch-32/Xamarin.WatchOS.dll | $(WATCH_BUILD_DIR)/reference
|
||||
@# Don't strip, bwatch needs to execute code from Xamarin.WatchOS (attributes),
|
||||
@# and that'll break if we strip out the code from the reference assembly.
|
||||
@# Note that there is only bwatch executable for both 32 and 64 bits.
|
||||
@#$(Q_GEN) mono-cil-strip $< $@
|
||||
$(Q) cp $< $@
|
||||
$(Q_GEN) mono-cil-strip $< $@
|
||||
|
||||
$(WATCH_BUILD_DIR)/reference/Xamarin.WatchOS.pdb: $(WATCH_BUILD_DIR)/watch-32/Xamarin.WatchOS.pdb | $(WATCH_BUILD_DIR)/reference
|
||||
$(Q) cp $< $@
|
||||
|
@ -966,10 +958,7 @@ $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS%dll $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVO
|
|||
$(TVOS_SOURCES) @$(TVOS_BUILD_DIR)/tvos/generated_sources
|
||||
|
||||
$(TVOS_BUILD_DIR)/reference/Xamarin.TVOS.dll: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.dll | $(TVOS_BUILD_DIR)/reference
|
||||
@# Don't strip, btv needs to execute code from Xamarin.TVOS (attributes),
|
||||
@# and that'll break if we strip out the code from the reference assembly.
|
||||
@#$(Q_GEN) mono-cil-strip $< $@
|
||||
$(Q) cp $< $@
|
||||
$(Q_GEN) mono-cil-strip $< $@
|
||||
|
||||
$(TVOS_BUILD_DIR)/reference/Xamarin.TVOS.pdb: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.pdb | $(TVOS_BUILD_DIR)/reference
|
||||
$(Q) cp $< $@
|
||||
|
@ -1060,8 +1049,8 @@ TVOS_TARGETS += \
|
|||
$(PROJECT_DIR)/MonoTouch.NUnitLite.tvos.csproj \
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/Xamarin.TVOS.dll \
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/Xamarin.TVOS.pdb \
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits/Xamarin.TVOS.dll \
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits/Xamarin.TVOS.pdb \
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits/Xamarin.TVOS.dll \
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits/Xamarin.TVOS.pdb \
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/System.Net.Http.dll \
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/System.Net.Http.pdb \
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/OpenTK-1.0.dll \
|
||||
|
@ -1088,10 +1077,10 @@ $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/mono/Xamarin.TVOS/%.config: $(TVOS_BUILD_D
|
|||
$(Q) install -m 0644 $< $@
|
||||
|
||||
# the actual architecture-specific versions
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits/Xamarin.TVOS.dll: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.dll | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits/Xamarin.TVOS.dll: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.dll | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits
|
||||
$(Q) install -m 0755 $< $@
|
||||
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits/Xamarin.TVOS.pdb: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.pdb | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/32bits
|
||||
$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits/Xamarin.TVOS.pdb: $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS.pdb | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/64bits
|
||||
$(Q) install -m 0644 $< $@
|
||||
|
||||
$(TVOS_TARGETS_DIRS):
|
||||
|
|
|
@ -247,8 +247,50 @@ namespace ObjCRuntime {
|
|||
return descriptor->copy_helper == ((BlockDescriptor *) literal->block_descriptor)->copy_helper;
|
||||
}
|
||||
|
||||
[BindingImpl (BindingImplOptions.Optimizable)]
|
||||
internal static IntPtr GetBlockForDelegate (MethodInfo minfo, object @delegate, string signature)
|
||||
static Type GetDelegateProxyType (MethodInfo minfo, uint token_ref, out MethodInfo baseMethod)
|
||||
{
|
||||
// A mirror of this method is also implemented in StaticRegistrar:GetDelegateProxyType
|
||||
// If this method is changed, that method will probably have to be updated too (tests!!!)
|
||||
baseMethod = null;
|
||||
|
||||
if (token_ref != Runtime.INVALID_TOKEN_REF)
|
||||
return (Type) Class.ResolveTokenReference (token_ref, 0x02000000 /* TypeDef */);
|
||||
|
||||
baseMethod = minfo.GetBaseDefinition ();
|
||||
var delegateProxies = baseMethod.ReturnTypeCustomAttributes.GetCustomAttributes (typeof (DelegateProxyAttribute), false);
|
||||
if (delegateProxies.Length > 0)
|
||||
return ((DelegateProxyAttribute) delegateProxies [0]).DelegateType;
|
||||
|
||||
// We might be implementing a protocol, find any DelegateProxy attributes on the corresponding interface as well.
|
||||
string selector = null;
|
||||
foreach (var iface in minfo.DeclaringType.GetInterfaces ()) {
|
||||
if (!iface.IsDefined (typeof (ProtocolAttribute), false))
|
||||
continue;
|
||||
|
||||
var map = minfo.DeclaringType.GetInterfaceMap (iface);
|
||||
for (int i = 0; i < map.TargetMethods.Length; i++) {
|
||||
if (map.TargetMethods [i] == minfo) {
|
||||
delegateProxies = map.InterfaceMethods [i].ReturnTypeCustomAttributes.GetCustomAttributes (typeof (DelegateProxyAttribute), false);
|
||||
if (delegateProxies.Length > 0)
|
||||
return ((DelegateProxyAttribute) delegateProxies [0]).DelegateType;
|
||||
}
|
||||
}
|
||||
|
||||
// It might be an optional method/property, in which case we need to check any ProtocolMember attributes
|
||||
if (selector == null)
|
||||
selector = Runtime.GetExportAttribute (minfo)?.Selector ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty (selector)) {
|
||||
var attrib = Runtime.GetProtocolMemberAttribute (iface, selector, minfo);
|
||||
if (attrib?.ReturnTypeDelegateProxy != null)
|
||||
return attrib.ReturnTypeDelegateProxy;
|
||||
}
|
||||
}
|
||||
|
||||
throw ErrorHelper.CreateError (8011, "Unable to locate the delegate to block conversion attribute ([DelegateProxy]) for the return value for the method {0}.{1}. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name);
|
||||
}
|
||||
|
||||
[BindingImpl(BindingImplOptions.Optimizable)]
|
||||
internal static IntPtr GetBlockForDelegate (MethodInfo minfo, object @delegate, uint token_ref, string signature)
|
||||
{
|
||||
if (@delegate == null)
|
||||
return IntPtr.Zero;
|
||||
|
@ -256,26 +298,22 @@ namespace ObjCRuntime {
|
|||
if (!(@delegate is Delegate))
|
||||
throw ErrorHelper.CreateError (8016, "Unable to convert delegate to block for the return value for the method {0}.{1}, because the input isn't a delegate, it's a {1}. Please file a bug at http://bugzilla.xamarin.com.", minfo.DeclaringType.FullName, minfo.Name, @delegate.GetType ().FullName);
|
||||
|
||||
var baseMethod = minfo.GetBaseDefinition ();
|
||||
|
||||
var delegateProxies = baseMethod.ReturnTypeCustomAttributes.GetCustomAttributes (typeof (DelegateProxyAttribute), false);
|
||||
if (delegateProxies.Length == 0)
|
||||
throw ErrorHelper.CreateError (8011, "Unable to locate the delegate to block conversion attribute ([DelegateProxy]) for the return value for the method {0}.{1}. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name);
|
||||
|
||||
var delegateProxy = (DelegateProxyAttribute) delegateProxies [0];
|
||||
if (delegateProxy.DelegateType == null)
|
||||
Type delegateProxyType = GetDelegateProxyType (minfo, token_ref, out var baseMethod);
|
||||
if (baseMethod == null)
|
||||
baseMethod = minfo; // 'baseMethod' is only used in error messages, and if it's null, we just use the closest alternative we have (minfo).
|
||||
if (delegateProxyType == null)
|
||||
throw ErrorHelper.CreateError (8012, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: DelegateType is null. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name);
|
||||
|
||||
var delegateProxyField = delegateProxy.DelegateType.GetField ("Handler", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
var delegateProxyField = delegateProxyType.GetField ("Handler", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
if (delegateProxyField == null)
|
||||
throw ErrorHelper.CreateError (8013, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: DelegateType ({2}) specifies a type without a 'Handler' field. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxy.DelegateType.FullName);
|
||||
throw ErrorHelper.CreateError (8013, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: DelegateType ({2}) specifies a type without a 'Handler' field. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxyType.FullName);
|
||||
|
||||
var handlerDelegate = delegateProxyField.GetValue (null);
|
||||
if (handlerDelegate == null)
|
||||
throw ErrorHelper.CreateError (8014, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: The DelegateType's ({2}) 'Handler' field is null. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxy.DelegateType.FullName);
|
||||
throw ErrorHelper.CreateError (8014, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: The DelegateType's ({2}) 'Handler' field is null. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxyType.FullName);
|
||||
|
||||
if (!(handlerDelegate is Delegate))
|
||||
throw ErrorHelper.CreateError (8015, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: The DelegateType's ({2}) 'Handler' field is not a delegate, it's a {3}. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxy.DelegateType.FullName, handlerDelegate.GetType ().FullName);
|
||||
throw ErrorHelper.CreateError (8015, "Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: The DelegateType's ({2}) 'Handler' field is not a delegate, it's a {3}. Please file a bug at http://bugzilla.xamarin.com.", baseMethod.DeclaringType.FullName, baseMethod.Name, delegateProxyType.FullName, handlerDelegate.GetType ().FullName);
|
||||
|
||||
// We now have the information we need to create the block.
|
||||
// Note that we must create a heap-allocated block, so we
|
||||
|
|
|
@ -32,6 +32,7 @@ using ProductException=MonoMac.RuntimeException;
|
|||
using ObjCRuntime;
|
||||
#endif
|
||||
#else
|
||||
using System.Linq;
|
||||
using Mono.Cecil.Cil;
|
||||
#endif
|
||||
|
||||
|
@ -297,6 +298,26 @@ namespace ObjCRuntime {
|
|||
Show (new ProductException (code, false, innerException, message, args));
|
||||
}
|
||||
|
||||
#if MMP || MTOUCH
|
||||
// Shows any warnings, and if there are any errors, throws an AggregateException.
|
||||
public static void ThrowIfErrors (IList<Exception> exceptions)
|
||||
{
|
||||
if (exceptions?.Any () != true)
|
||||
return;
|
||||
|
||||
// Separate warnings from errors
|
||||
var grouped = exceptions.GroupBy ((v) => (v as ProductException)?.Error == false);
|
||||
|
||||
var warnings = grouped.SingleOrDefault ((v) => v.Key);
|
||||
if (warnings?.Any () == true)
|
||||
Show (warnings);
|
||||
|
||||
var errors = grouped.SingleOrDefault ((v) => !v.Key);
|
||||
if (errors?.Any () == true)
|
||||
throw new AggregateException (errors);
|
||||
}
|
||||
#endif
|
||||
|
||||
public static void Show (IEnumerable<Exception> list)
|
||||
{
|
||||
List<Exception> exceptions = new List<Exception> ();
|
||||
|
|
|
@ -448,9 +448,9 @@ namespace ObjCRuntime {
|
|||
return ObjectWrapper.Convert (CreateBlockProxy ((MethodInfo) ObjectWrapper.Convert (method), block));
|
||||
}
|
||||
|
||||
static IntPtr CreateDelegateProxy (IntPtr method, IntPtr @delegate, IntPtr signature)
|
||||
static IntPtr CreateDelegateProxy (IntPtr method, IntPtr @delegate, IntPtr signature, uint token_ref)
|
||||
{
|
||||
return BlockLiteral.GetBlockForDelegate ((MethodInfo) ObjectWrapper.Convert (method), ObjectWrapper.Convert (@delegate), Marshal.PtrToStringAuto (signature));
|
||||
return BlockLiteral.GetBlockForDelegate ((MethodInfo) ObjectWrapper.Convert (method), ObjectWrapper.Convert (@delegate), token_ref, Marshal.PtrToStringAuto (signature));
|
||||
}
|
||||
|
||||
static unsafe Assembly GetEntryAssembly ()
|
||||
|
@ -777,6 +777,48 @@ namespace ObjCRuntime {
|
|||
return null;
|
||||
}
|
||||
|
||||
internal static ProtocolMemberAttribute GetProtocolMemberAttribute (Type type, string selector, MethodInfo method)
|
||||
{
|
||||
var memberAttributes = type.GetCustomAttributes<ProtocolMemberAttribute> ();
|
||||
if (memberAttributes == null)
|
||||
return null;
|
||||
|
||||
foreach (var attrib in memberAttributes) {
|
||||
if (attrib.IsStatic != method.IsStatic)
|
||||
continue;
|
||||
|
||||
if (attrib.Selector != selector)
|
||||
continue;
|
||||
|
||||
if (!attrib.IsProperty) {
|
||||
var methodParameters = method.GetParameters ();
|
||||
if ((attrib.ParameterType?.Length ?? 0) != methodParameters.Length)
|
||||
continue;
|
||||
var notApplicable = false;
|
||||
for (int i = 0; i < methodParameters.Length; i++) {
|
||||
var paramType = methodParameters [i].ParameterType;
|
||||
var isByRef = paramType.IsByRef;
|
||||
if (isByRef)
|
||||
paramType = paramType.GetElementType ();
|
||||
if (isByRef != attrib.ParameterByRef [i]) {
|
||||
notApplicable = true;
|
||||
break;
|
||||
}
|
||||
if (paramType != attrib.ParameterType [i]) {
|
||||
notApplicable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (notApplicable)
|
||||
continue;
|
||||
}
|
||||
|
||||
return attrib;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns a MethodInfo that represents the method that can be used to turn
|
||||
// a the block in the given method at the given parameter into a strongly typed
|
||||
|
@ -825,39 +867,11 @@ namespace ObjCRuntime {
|
|||
// We may run into binding assemblies built with earlier versions of the generator,
|
||||
// which means we can't rely on finding the BlockProxy attribute in the ProtocolMemberAttribute.
|
||||
if (selector == null)
|
||||
selector = method.GetCustomAttribute<ExportAttribute> ()?.Selector ?? string.Empty;
|
||||
selector = GetExportAttribute (method)?.Selector ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty (selector)) {
|
||||
var memberAttributes = iface.GetCustomAttributes<ProtocolMemberAttribute> ();
|
||||
foreach (var attrib in memberAttributes) {
|
||||
if (attrib.ParameterBlockProxy == null || attrib.ParameterBlockProxy.Length <= parameter || attrib.ParameterBlockProxy [parameter] == null)
|
||||
continue; // no need to check anything if what we want isn't there
|
||||
if (attrib.Selector != selector)
|
||||
continue;
|
||||
if (attrib.IsStatic != method.IsStatic)
|
||||
continue;
|
||||
var methodParameters = method.GetParameters ();
|
||||
if (attrib.ParameterType.Length != methodParameters.Length)
|
||||
continue;
|
||||
var notApplicable = false;
|
||||
for (int i = 0; i < methodParameters.Length; i++) {
|
||||
var paramType = methodParameters [i].ParameterType;
|
||||
var isByRef = paramType.IsByRef;
|
||||
if (isByRef)
|
||||
paramType = paramType.GetElementType ();
|
||||
if (isByRef != attrib.ParameterByRef [i]) {
|
||||
notApplicable = true;
|
||||
break;
|
||||
}
|
||||
if (paramType != attrib.ParameterType [i]) {
|
||||
notApplicable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (notApplicable)
|
||||
continue;
|
||||
|
||||
var attrib = GetProtocolMemberAttribute (iface, selector, method);
|
||||
if (attrib != null && attrib.ParameterBlockProxy.Length > parameter && attrib.ParameterBlockProxy [parameter] != null)
|
||||
return attrib.ParameterBlockProxy [parameter].GetMethod ("Create");
|
||||
}
|
||||
}
|
||||
|
||||
// Might be an implementation of an optional protocol member.
|
||||
|
@ -1011,6 +1025,31 @@ namespace ObjCRuntime {
|
|||
}
|
||||
}
|
||||
|
||||
internal static PropertyInfo FindPropertyInfo (MethodInfo accessor)
|
||||
{
|
||||
if (!accessor.IsSpecialName)
|
||||
return null;
|
||||
|
||||
foreach (var pi in accessor.DeclaringType.GetProperties ()) {
|
||||
if (pi.GetGetMethod () == accessor)
|
||||
return pi;
|
||||
if (pi.GetSetMethod () == accessor)
|
||||
return pi;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static ExportAttribute GetExportAttribute (MethodInfo method)
|
||||
{
|
||||
var attrib = method.GetCustomAttribute<ExportAttribute> ();
|
||||
if (attrib == null) {
|
||||
var pinfo = FindPropertyInfo (method);
|
||||
if (pinfo != null)
|
||||
attrib = pinfo.GetCustomAttribute<ExportAttribute> ();
|
||||
}
|
||||
return attrib;
|
||||
}
|
||||
|
||||
static NSObject IgnoreConstructionError (IntPtr ptr, IntPtr klass, Type type)
|
||||
{
|
||||
|
|
3
src/bmac
3
src/bmac
|
@ -43,7 +43,7 @@ sdk=$(echo $sdk | tr '[:upper:]' '[:lower:]')
|
|||
case $sdk in
|
||||
mobile|xamarin.mac|xammac)
|
||||
bmac="bmac-mobile.exe -no-mono-path"
|
||||
mono=$ROOT_DIR/bin/bmac-mobile-mono
|
||||
mono=/Library/Frameworks/Mono.framework/Commands/mono
|
||||
export MONO_PATH=$ROOT_DIR/lib/mono/Xamarin.Mac
|
||||
;;
|
||||
*)
|
||||
|
@ -60,7 +60,6 @@ mobile|xamarin.mac|xammac)
|
|||
refs="-baselib:$ROOT_DIR/lib/reference/mobile/Xamarin.Mac.dll --target-framework=Xamarin.Mac,Version=v2.0,Profile=Mobile"
|
||||
bmac=bmac-mobile.exe
|
||||
export MONO_PATH=$ROOT_DIR/lib/mono/Xamarin.Mac
|
||||
mono="$ROOT_DIR/bin/bmac-mobile-mono"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
|
|
@ -7519,6 +7519,9 @@ namespace Foundation
|
|||
[Static]
|
||||
[Export ("dictionaryWithSharedKeySet:")]
|
||||
NSDictionary FromSharedKeySet (NSObject sharedKeyToken);
|
||||
|
||||
[Export ("addEntriesFromDictionary:")]
|
||||
void AddEntries (NSDictionary other);
|
||||
}
|
||||
|
||||
[BaseType (typeof (NSSet))]
|
||||
|
|
|
@ -4778,6 +4778,7 @@ public partial class Generator : IMemberGatherer {
|
|||
sel = ba.Selector;
|
||||
}
|
||||
|
||||
PrintBlockProxy (pi.PropertyType);
|
||||
PrintAttributes (pi, platform:true);
|
||||
|
||||
if (not_implemented_attr == null && (!minfo.is_sealed || !minfo.is_wrapper))
|
||||
|
@ -5101,6 +5102,15 @@ public partial class Generator : IMemberGatherer {
|
|||
}
|
||||
}
|
||||
|
||||
void PrintBlockProxy (Type type)
|
||||
{
|
||||
type = GetCorrectGenericType (type);
|
||||
if (type.IsSubclassOf (TypeManager.System_Delegate)) {
|
||||
var ti = MakeTrampoline (type);
|
||||
print ("[param: BlockProxy (typeof ({0}.Trampolines.{1}))]", ns.CoreObjCRuntime, ti.NativeInvokerName);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintExport (MemberInformation minfo)
|
||||
{
|
||||
if (minfo.is_export)
|
||||
|
@ -5418,8 +5428,14 @@ public partial class Generator : IMemberGatherer {
|
|||
sb.Append (", IsStatic = ").Append (AttributeManager.HasAttribute<StaticAttribute> (mi) ? "true" : "false");
|
||||
sb.Append (", Name = \"").Append (mi.Name).Append ("\"");
|
||||
sb.Append (", Selector = \"").Append (attrib.Selector).Append ("\"");
|
||||
if (mi.ReturnType != TypeManager.System_Void)
|
||||
sb.Append (", ReturnType = typeof (").Append (RenderType (GetCorrectGenericType (mi.ReturnType))).Append(")");
|
||||
if (mi.ReturnType != TypeManager.System_Void) {
|
||||
var retType = GetCorrectGenericType (mi.ReturnType);
|
||||
sb.Append (", ReturnType = typeof (").Append (RenderType (retType)).Append (")");
|
||||
if (retType.IsSubclassOf (TypeManager.System_Delegate)) {
|
||||
var ti = MakeTrampoline (retType);
|
||||
sb.Append ($", ReturnTypeDelegateProxy = typeof ({ns.CoreObjCRuntime}.Trampolines.{ti.StaticName})");
|
||||
}
|
||||
}
|
||||
var parameters = mi.GetParameters ();
|
||||
if (parameters != null && parameters.Length > 0) {
|
||||
sb.Append (", ParameterType = new Type [] { ");
|
||||
|
@ -5489,6 +5505,15 @@ public partial class Generator : IMemberGatherer {
|
|||
sb.Append (", SetterSelector = \"").Append (ba != null ? ba.Selector : ea.Selector).Append ("\"");
|
||||
}
|
||||
sb.Append (", ArgumentSemantic = ArgumentSemantic.").Append (attrib.ArgumentSemantic);
|
||||
// Check for block/delegate proxies
|
||||
var propType = GetCorrectGenericType (pi.PropertyType);
|
||||
if (propType.IsSubclassOf (TypeManager.System_Delegate)) {
|
||||
var ti = MakeTrampoline (propType);
|
||||
if (pi.SetMethod != null)
|
||||
sb.Append ($", ParameterBlockProxy = new Type [] {{ typeof ({ns.CoreObjCRuntime}.Trampolines.{ti.NativeInvokerName}) }}");
|
||||
if (pi.GetMethod != null)
|
||||
sb.Append ($", ReturnTypeDelegateProxy = typeof ({ns.CoreObjCRuntime}.Trampolines.{ti.StaticName})");
|
||||
}
|
||||
sb.Append (")]");
|
||||
print (sb.ToString ());
|
||||
}
|
||||
|
@ -5565,6 +5590,7 @@ public partial class Generator : IMemberGatherer {
|
|||
}
|
||||
if (pi.CanWrite) {
|
||||
var setMethod = pi.GetSetMethod ();
|
||||
PrintBlockProxy (pi.PropertyType);
|
||||
PrintAttributes (setMethod, notImplemented:true);
|
||||
if (!AttributeManager.HasAttribute<NotImplementedAttribute> (setMethod))
|
||||
PrintExport (minfo, GetSetterExportAttribute (pi));
|
||||
|
|
|
@ -360,7 +360,7 @@ namespace HealthKit {
|
|||
// FIXME NS_EXTENSION_UNAVAILABLE("Not available to extensions") ;
|
||||
[Async]
|
||||
[Export ("requestAuthorizationToShareTypes:readTypes:completion:")]
|
||||
void RequestAuthorizationToShare (NSSet typesToShare, NSSet typesToRead, Action<bool, NSError> completion);
|
||||
void RequestAuthorizationToShare ([NullAllowed] NSSet typesToShare, [NullAllowed] NSSet typesToRead, Action<bool, NSError> completion);
|
||||
|
||||
// FIXME NS_EXTENSION_UNAVAILABLE("Not available to extensions") ;
|
||||
[Async]
|
||||
|
|
|
@ -289,6 +289,22 @@ namespace Bindings.Test {
|
|||
[Static]
|
||||
[Export ("optionalStaticCallback:")]
|
||||
void OptionalStaticCallback (Action<int> completionHandler);
|
||||
|
||||
[Abstract]
|
||||
[Export ("requiredReturnValue")]
|
||||
Action<int> RequiredReturnValue ();
|
||||
|
||||
[Abstract]
|
||||
[Static]
|
||||
[Export ("requiredStaticReturnValue")]
|
||||
Action<int> RequiredStaticReturnValue ();
|
||||
|
||||
[Export ("optionalReturnValue")]
|
||||
Action<int> OptionalReturnValue ();
|
||||
|
||||
[Static]
|
||||
[Export ("optionalStaticReturnValue")]
|
||||
Action<int> OptionalStaticReturnValue ();
|
||||
}
|
||||
|
||||
interface IObjCProtocolBlockTest { }
|
||||
|
@ -339,6 +355,23 @@ namespace Bindings.Test {
|
|||
[Static]
|
||||
[Export ("freedBlockCount")]
|
||||
int FreedBlockCount { get; }
|
||||
|
||||
[Static]
|
||||
[Export ("calledBlockCount")]
|
||||
int CalledBlockCount { get; }
|
||||
|
||||
[Static]
|
||||
[Export ("callProtocolWithBlockProperties:required:instance:")]
|
||||
void CallProtocolWithBlockProperties (IProtocolWithBlockProperties obj, bool required, bool instance);
|
||||
|
||||
[Static]
|
||||
[Export ("callProtocolWithBlockReturnValue:required:instance:")]
|
||||
void CallProtocolWithBlockReturnValue (IObjCProtocolBlockTest obj, bool required, bool instance);
|
||||
|
||||
[Static]
|
||||
[Export ("setProtocolWithBlockProperties:required:instance:")]
|
||||
void SetProtocolWithBlockProperties (IProtocolWithBlockProperties obj, bool required, bool instance);
|
||||
|
||||
}
|
||||
|
||||
delegate void InnerBlock (int magic_number);
|
||||
|
@ -350,6 +383,28 @@ namespace Bindings.Test {
|
|||
[Export ("evilCallback")]
|
||||
Action<int> EvilCallback { get; set; }
|
||||
}
|
||||
|
||||
delegate void SimpleCallback ();
|
||||
[BaseType (typeof (NSObject))]
|
||||
[Protocol]
|
||||
interface ProtocolWithBlockProperties {
|
||||
[Abstract]
|
||||
[Export ("myRequiredProperty")]
|
||||
SimpleCallback MyRequiredProperty { get; set; }
|
||||
|
||||
[Export ("myOptionalProperty")]
|
||||
SimpleCallback MyOptionalProperty { get; set; }
|
||||
|
||||
[Static]
|
||||
[Abstract]
|
||||
[Export ("myRequiredStaticProperty")]
|
||||
SimpleCallback MyRequiredStaticProperty { get; set; }
|
||||
|
||||
[Static]
|
||||
[Export ("myOptionalStaticProperty")]
|
||||
SimpleCallback MyOptionalStaticProperty { get; set; }
|
||||
}
|
||||
interface IProtocolWithBlockProperties { }
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ObjCRuntime {
|
||||
public static class Messaging {
|
||||
internal const string LIBOBJC_DYLIB = "/usr/lib/libobjc.dylib";
|
||||
|
||||
public struct objc_super {
|
||||
public IntPtr Handle;
|
||||
public IntPtr SuperHandle;
|
||||
}
|
||||
|
||||
[DllImport (LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
|
||||
public extern static void void_objc_msgSend_IntPtr_bool_bool (IntPtr receiver, IntPtr selector, IntPtr a, bool b, bool c);
|
||||
}
|
||||
}
|
|
@ -65,6 +65,37 @@ namespace Xamarin.BindingTests
|
|||
{
|
||||
completionHandler (42);
|
||||
}
|
||||
|
||||
public Action<int> RequiredReturnValue ()
|
||||
{
|
||||
return new Action<int> ((v) => {
|
||||
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||
});
|
||||
}
|
||||
|
||||
[Export ("optionalReturnValue")]
|
||||
public Action<int> OptionalReturnValue ()
|
||||
{
|
||||
return new Action<int> ((v) => {
|
||||
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||
});
|
||||
}
|
||||
|
||||
[Export ("requiredStaticReturnValue")]
|
||||
public static Action<int> RequiredStaticReturnValue ()
|
||||
{
|
||||
return new Action<int> ((v) => {
|
||||
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||
});
|
||||
}
|
||||
|
||||
[Export ("optionalStaticReturnValue")]
|
||||
public static Action<int> OptionalStaticReturnValue ()
|
||||
{
|
||||
return new Action<int> ((v) => {
|
||||
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class BlockCallbackClassExplicit : NSObject, IObjCProtocolBlockTest
|
||||
|
@ -92,6 +123,38 @@ namespace Xamarin.BindingTests
|
|||
{
|
||||
completionHandler (42);
|
||||
}
|
||||
|
||||
// Explicitly implemented interface member
|
||||
Action<int> IObjCProtocolBlockTest.RequiredReturnValue ()
|
||||
{
|
||||
return new Action<int> ((v) => {
|
||||
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||
});
|
||||
}
|
||||
|
||||
[Export ("optionalReturnValue")]
|
||||
public Action<int> OptionalReturnValue ()
|
||||
{
|
||||
return new Action<int> ((v) => {
|
||||
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||
});
|
||||
}
|
||||
|
||||
[Export ("requiredStaticReturnValue")]
|
||||
public static Action<int> RequiredStaticReturnValue ()
|
||||
{
|
||||
return new Action<int> ((v) => {
|
||||
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||
});
|
||||
}
|
||||
|
||||
[Export ("optionalStaticReturnValue")]
|
||||
public static Action<int> OptionalStaticReturnValue ()
|
||||
{
|
||||
return new Action<int> ((v) => {
|
||||
Assert.AreEqual (42, v, "RequiredReturnValue");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class BlockCallbackTester : ObjCBlockTester
|
||||
|
@ -101,5 +164,130 @@ namespace Xamarin.BindingTests
|
|||
completionHandler (42);
|
||||
}
|
||||
}
|
||||
|
||||
public class PropertyBlock : NSObject, IProtocolWithBlockProperties {
|
||||
[Export ("myOptionalProperty")]
|
||||
public SimpleCallback MyOptionalProperty { get; set; }
|
||||
|
||||
public SimpleCallback MyRequiredProperty { get; set; }
|
||||
|
||||
[Export ("myOptionalStaticProperty")]
|
||||
public static SimpleCallback MyOptionalStaticProperty { get; set; }
|
||||
|
||||
[Export ("myRequiredStaticProperty")]
|
||||
public static SimpleCallback MyRequiredStaticProperty { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase (true, true)]
|
||||
[TestCase (true, false)]
|
||||
[TestCase (false, true)]
|
||||
[TestCase (false, false)]
|
||||
public void ProtocolWithBlockProperties (bool required, bool instance)
|
||||
{
|
||||
using (var pb = new PropertyBlock ()) {
|
||||
var callbackCalled = false;
|
||||
SimpleCallback action = () => {
|
||||
callbackCalled = true;
|
||||
};
|
||||
if (required) {
|
||||
if (instance) {
|
||||
pb.MyRequiredProperty = action;
|
||||
} else {
|
||||
PropertyBlock.MyRequiredStaticProperty = action;
|
||||
}
|
||||
} else {
|
||||
if (instance) {
|
||||
pb.MyOptionalProperty = action;
|
||||
} else {
|
||||
PropertyBlock.MyOptionalStaticProperty = action;
|
||||
}
|
||||
}
|
||||
ObjCBlockTester.CallProtocolWithBlockProperties (pb, required, instance);
|
||||
Assert.IsTrue (callbackCalled, "Callback");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase (true, true)]
|
||||
[TestCase (true, false)]
|
||||
[TestCase (false, true)]
|
||||
[TestCase (false, false)]
|
||||
public void ProtocolWithNativeBlockProperties (bool required, bool instance)
|
||||
{
|
||||
using (var pb = new PropertyBlock ()) {
|
||||
var calledCounter = ObjCBlockTester.CalledBlockCount;
|
||||
ObjCBlockTester.SetProtocolWithBlockProperties (pb, required, instance);
|
||||
if (required) {
|
||||
if (instance) {
|
||||
pb.MyRequiredProperty ();
|
||||
} else {
|
||||
PropertyBlock.MyRequiredStaticProperty ();
|
||||
}
|
||||
} else {
|
||||
if (instance) {
|
||||
pb.MyOptionalProperty ();
|
||||
} else {
|
||||
PropertyBlock.MyOptionalStaticProperty ();
|
||||
}
|
||||
}
|
||||
Assert.AreEqual (calledCounter + 1, ObjCBlockTester.CalledBlockCount, "Blocks called");
|
||||
}
|
||||
}
|
||||
[Test]
|
||||
[TestCase (true, true)]
|
||||
[TestCase (true, false)]
|
||||
[TestCase (false, true)]
|
||||
[TestCase (false, false)]
|
||||
public void ProtocolWithReturnValues (bool required, bool instance)
|
||||
{
|
||||
using (var pb = new BlockCallbackClass ()) {
|
||||
ObjCBlockTester.CallProtocolWithBlockReturnValue (pb, required, instance);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase (true, true)]
|
||||
[TestCase (true, false)]
|
||||
[TestCase (false, true)]
|
||||
[TestCase (false, false)]
|
||||
public void LinkedAway (bool required, bool instance)
|
||||
{
|
||||
if (!(TestRuntime.IsLinkAll && TestRuntime.IsOptimizeAll))
|
||||
Assert.Ignore ("This test is only applicable if optimized & linking all assemblies.");
|
||||
|
||||
using (var pb = new FakePropertyBlock ()) {
|
||||
try {
|
||||
Messaging.void_objc_msgSend_IntPtr_bool_bool (Class.GetHandle (typeof (ObjCBlockTester)), Selector.GetHandle ("setProtocolWithBlockProperties:required:instance:"), pb.Handle, required, instance);
|
||||
Assert.Fail ("Expected an MT8028 error");
|
||||
} catch (RuntimeException re) {
|
||||
Assert.AreEqual (8028, re.Code, "Code");
|
||||
Assert.AreEqual ("The runtime function get_block_wrapper_creator has been linked away.", re.Message, "Message");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Each method here will show a warning like this:
|
||||
// MT4174: Unable to locate the block to delegate conversion method for the method ...
|
||||
// This is expected.
|
||||
// This is 'fake' because it doesn't implement the ProtocolWithBlockProperties protocol,
|
||||
// which means that XI won't be able to find the delegate<->block conversion methods
|
||||
// (either at runtime or build time).
|
||||
// The point of this test is to ensure that we don't crash when the runtime tries
|
||||
// to find those conversion methods, and instead finds that many required functions
|
||||
// have been linked away (which happen when _forcing_ the dynamic registrar to be linked away).
|
||||
public class FakePropertyBlock : NSObject {
|
||||
[Export ("myOptionalProperty")]
|
||||
public SimpleCallback MyOptionalProperty { get; set; }
|
||||
|
||||
[Export ("myRequiredProperty")]
|
||||
public SimpleCallback MyRequiredProperty { get; set; }
|
||||
|
||||
[Export ("myOptionalStaticProperty")]
|
||||
public static SimpleCallback MyOptionalStaticProperty { get; set; }
|
||||
|
||||
[Export ("myRequiredStaticProperty")]
|
||||
public static SimpleCallback MyRequiredStaticProperty { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,11 @@ namespace Xamarin.Tests
|
|||
[Test]
|
||||
public void MainThreadDeallocationTest ()
|
||||
{
|
||||
#if OPTIMIZEALL
|
||||
if (!TestRuntime.IsLinkAll)
|
||||
Assert.Ignore ("This test must be processed by the linker if all optimizations are turned on.");
|
||||
#endif
|
||||
|
||||
ObjCBlockTester.CallAssertMainThreadBlockRelease ((callback) => {
|
||||
callback (42);
|
||||
});
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
</Compile>
|
||||
<Compile Include="RuntimeTest.cs" />
|
||||
<Compile Include="CodeBehind.cs" />
|
||||
<Compile Include="Messaging.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\tests\test-libraries\libtest.m">
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
</Compile>
|
||||
<Compile Include="RuntimeTest.cs" />
|
||||
<Compile Include="CodeBehind.cs" />
|
||||
<Compile Include="Messaging.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\tests\test-libraries\libtest.m">
|
||||
|
|
|
@ -259,8 +259,11 @@ class D : NSObject {
|
|||
bundler.AssertWarning (4173, "The registrar can't compute the block signature for the delegate of type System.Delegate in the method D.D4 because System.Delegate doesn't have a specific signature.", "testApp.cs", 24);
|
||||
bundler.AssertWarning (4173, "The registrar can't compute the block signature for the delegate of type System.MulticastDelegate in the method D.D5 because System.MulticastDelegate doesn't have a specific signature.", "testApp.cs", 30);
|
||||
bundler.AssertWarning (4174, "Unable to locate the block to delegate conversion method for the method D.D3's parameter #1.", "testApp.cs", 18);
|
||||
bundler.AssertWarning (4176, "Unable to locate the delegate to block conversion type for the return value of the method D.D4.", "testApp.cs", 24);
|
||||
bundler.AssertWarning (4176, "Unable to locate the delegate to block conversion type for the return value of the method D.D5.", "testApp.cs", 30);
|
||||
bundler.AssertWarning (4176, "Unable to locate the delegate to block conversion type for the return value of the method D.D6.", "testApp.cs", 36);
|
||||
bundler.AssertErrorCount (2);
|
||||
bundler.AssertWarningCount (3);
|
||||
bundler.AssertWarningCount (6);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ namespace Xamarin.Tests
|
|||
public int Verbosity;
|
||||
public int [] WarnAsError; // null array: nothing passed to mtouch/mmp. empty array: pass --warnaserror (which means makes all warnings errors).
|
||||
public string [] XmlDefinitions;
|
||||
public string Interpreter;
|
||||
|
||||
// These are a bit smarter
|
||||
public bool NoPlatformAssemblyReference;
|
||||
|
@ -291,7 +292,12 @@ namespace Xamarin.Tests
|
|||
sb.Append (" --xml:").Append (StringUtils.Quote (xd));
|
||||
}
|
||||
|
||||
|
||||
if (Interpreter != null) {
|
||||
if (Interpreter.Length == 0)
|
||||
sb.Append (" --interpreter");
|
||||
else
|
||||
sb.Append (" --interpreter=").Append (Interpreter);
|
||||
}
|
||||
}
|
||||
|
||||
public string CreateTemporaryDirectory ()
|
||||
|
|
|
@ -655,4 +655,14 @@ partial class TestRuntime
|
|||
}
|
||||
}
|
||||
class LinkerSentinel { }
|
||||
|
||||
public static bool IsOptimizeAll {
|
||||
get {
|
||||
#if OPTIMIZEALL
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -645,6 +645,53 @@ namespace MonoTouchFixtures.Foundation {
|
|||
Assert.Throws<InvalidCastException> (() => GC.KeepAlive (dictK.Keys), "K Keys");
|
||||
Assert.Throws<InvalidCastException> (() => dictK.KeysForObject (kv), "K KeysForObject");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddEntries ()
|
||||
{
|
||||
using (var dic1 = new NSMutableDictionary<NSString, NSDate> ()) {
|
||||
var now = NSDate.Now;
|
||||
using (var dic2 = NSDictionary.FromObjectAndKey ((NSDate) now, (NSString) "key")) {
|
||||
Assert.AreEqual (0, dic1.Count, "Count 0");
|
||||
|
||||
dic1.AddEntries (dic2);
|
||||
|
||||
Assert.AreEqual (1, dic1.Count, "Count 1");
|
||||
Assert.AreEqual (now, dic1 ["key"], "Value 1");
|
||||
|
||||
dic1.AddEntries (dic2);
|
||||
|
||||
Assert.AreEqual (1, dic1.Count, "Count 2");
|
||||
Assert.AreEqual (now, dic1 ["key"], "Value 2");
|
||||
}
|
||||
|
||||
// Be nasty, and put something of the wrong type in the dictionary
|
||||
dic1.Clear ();
|
||||
using (var dic2 = NSDictionary.FromObjectAndKey ((NSString) "value", (NSString) "key")) {
|
||||
Assert.AreEqual (0, dic1.Count, "X Count 0");
|
||||
|
||||
dic1.AddEntries (dic2);
|
||||
|
||||
Assert.AreEqual (1, dic1.Count, "X Count 1");
|
||||
Assert.Throws<InvalidCastException> (() =>
|
||||
{
|
||||
var obj = dic1 [(NSString) "key"];
|
||||
}, "ICE 1");
|
||||
}
|
||||
|
||||
// Use a generic dict of the right types
|
||||
dic1.Clear ();
|
||||
using (var dic2 = new NSDictionary<NSString,NSDate> ((NSString) "key2", now.AddSeconds (3600))) {
|
||||
Assert.AreEqual (0, dic1.Count, "Y Count 0");
|
||||
|
||||
dic1.AddEntries (dic2);
|
||||
|
||||
Assert.AreEqual (1, dic1.Count, "Y Count 1");
|
||||
var obj = dic1 [(NSString) "key2"];
|
||||
Assert.AreEqual (now.AddSeconds (3600).SecondsSinceReferenceDate, obj.SecondsSinceReferenceDate, "Y Value 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,5 +93,25 @@ namespace monotouchtest
|
|||
Assert.NotNull (testDict ["Key2"], "Key2");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddEntries ()
|
||||
{
|
||||
using (var dic1 = new NSMutableDictionary ()) {
|
||||
using (var dic2 = NSDictionary.FromObjectAndKey ((NSString) "value", (NSString) "key")) {
|
||||
Assert.AreEqual (0, dic1.Count, "Count 0");
|
||||
|
||||
dic1.AddEntries (dic2);
|
||||
|
||||
Assert.AreEqual (1, dic1.Count, "Count 1");
|
||||
Assert.AreEqual ("value", dic1 ["key"].ToString (), "Value 1");
|
||||
|
||||
dic1.AddEntries (dic2);
|
||||
|
||||
Assert.AreEqual (1, dic1.Count, "Count 2");
|
||||
Assert.AreEqual ("value", dic1 ["key"].ToString (), "Value 2");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1780,6 +1780,25 @@ public class B
|
|||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MT0138 ()
|
||||
{
|
||||
using (var mtouch = new MTouchTool ()) {
|
||||
var tmpdir = mtouch.CreateTemporaryDirectory ();
|
||||
mtouch.CreateTemporaryCacheDirectory ();
|
||||
|
||||
mtouch.CreateTemporaryApp ();
|
||||
mtouch.WarnAsError = new int [] { 138 }; // This is just to make mtouch bail out early instead of spending time building the app when that's not what we're interested in.
|
||||
mtouch.Interpreter = "all,-all,foo,-bar,mscorlib.dll,mscorlib";
|
||||
mtouch.AssertExecuteFailure (MTouchAction.BuildSim, "build");
|
||||
mtouch.AssertError (138, "Cannot find the assembly 'foo', passed as an argument to --interpreter.");
|
||||
mtouch.AssertError (138, "Cannot find the assembly 'bar', passed as an argument to --interpreter.");
|
||||
mtouch.AssertError (138, "Cannot find the assembly 'mscorlib.dll', passed as an argument to --interpreter.");
|
||||
// just the name, without the extension, is the right way.
|
||||
mtouch.AssertErrorCount (3);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase ("all")]
|
||||
[TestCase ("-all")]
|
||||
|
|
|
@ -1182,6 +1182,45 @@ namespace NS {
|
|||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MT4176 ()
|
||||
{
|
||||
using (var mtouch = new MTouchTool ()) {
|
||||
var code = @"
|
||||
namespace NS {
|
||||
using System;
|
||||
using Foundation;
|
||||
using ObjCRuntime;
|
||||
|
||||
public class Consumer : NSObject
|
||||
{
|
||||
[Export (""getAction"")]
|
||||
public Action GetFunction ()
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
[Export (""getProperty"")]
|
||||
public Action GetProperty {
|
||||
get {
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
";
|
||||
mtouch.Linker = MTouchLinker.DontLink; // faster
|
||||
mtouch.Registrar = MTouchRegistrar.Static;
|
||||
mtouch.CreateTemporaryApp (extraCode: code, extraArg: "-debug");
|
||||
mtouch.WarnAsError = new int [] { 4176 };
|
||||
mtouch.AssertExecuteFailure ("build");
|
||||
mtouch.AssertError (4176, "Unable to locate the delegate to block conversion type for the return value of the method NS.Consumer.GetFunction.", "testApp.cs", 11);
|
||||
mtouch.AssertError (4176, "Unable to locate the delegate to block conversion type for the return value of the method NS.Consumer.get_GetProperty.", "testApp.cs", 17);
|
||||
mtouch.AssertErrorCount (2);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NoWarnings ()
|
||||
{
|
||||
|
|
|
@ -148,15 +148,29 @@ typedef unsigned int (^RegistrarTestBlock) (unsigned int magic);
|
|||
-(void) idAsIntPtr: (id)p1;
|
||||
@end
|
||||
|
||||
typedef void (^int_callback)(int32_t magic_number);
|
||||
@protocol ObjCProtocolBlockTest
|
||||
@required
|
||||
-(void) requiredCallback: (void (^)(int32_t magic_number))completionHandler;
|
||||
+(void) requiredStaticCallback: (void (^)(int32_t magic_number))completionHandler;
|
||||
-(void) requiredCallback: (int_callback)completionHandler;
|
||||
+(void) requiredStaticCallback: (int_callback)completionHandler;
|
||||
-(int_callback) requiredReturnValue;
|
||||
+(int_callback) requiredStaticReturnValue;
|
||||
@optional
|
||||
-(void) optionalCallback: (void (^)(int32_t magic_number))completionHandler;
|
||||
+(void) optionalStaticCallback: (void (^)(int32_t magic_number))completionHandler;
|
||||
-(void) optionalCallback: (int_callback)completionHandler;
|
||||
+(void) optionalStaticCallback: (int_callback)completionHandler;
|
||||
-(int_callback) optionalReturnValue;
|
||||
+(int_callback) optionalStaticReturnValue;
|
||||
@end
|
||||
|
||||
typedef void (^simple_callback)();
|
||||
@protocol ProtocolWithBlockProperties
|
||||
@required
|
||||
@property simple_callback myRequiredProperty;
|
||||
@property (class) simple_callback myRequiredStaticProperty;
|
||||
@optional
|
||||
@property simple_callback myOptionalProperty;
|
||||
@property (class) simple_callback myOptionalStaticProperty;
|
||||
@end
|
||||
@interface ObjCBlockTester : NSObject {
|
||||
}
|
||||
@property (retain) NSObject<ObjCProtocolBlockTest>* TestObject;
|
||||
|
@ -175,6 +189,12 @@ typedef void (^outerBlock) (innerBlock callback);
|
|||
|
||||
-(void) testFreedBlocks;
|
||||
+(int) freedBlockCount;
|
||||
|
||||
+(void) callProtocolWithBlockProperties: (id<ProtocolWithBlockProperties>) obj required: (bool) required instance: (bool) instance;
|
||||
+(void) callProtocolWithBlockReturnValue: (id<ObjCProtocolBlockTest>) obj required: (bool) required instance: (bool) instance;
|
||||
|
||||
+(void) setProtocolWithBlockProperties: (id<ProtocolWithBlockProperties>) obj required: (bool) required instance: (bool) instance;
|
||||
+(int) calledBlockCount;
|
||||
@end
|
||||
|
||||
@interface FreedNotifier : NSObject {
|
||||
|
|
|
@ -527,6 +527,7 @@ static UltimateMachine *shared;
|
|||
@end
|
||||
|
||||
static volatile int freed_blocks = 0;
|
||||
static volatile int called_blocks = 0;
|
||||
|
||||
@implementation ObjCBlockTester
|
||||
static Class _TestClass = NULL;
|
||||
|
@ -654,6 +655,73 @@ static Class _TestClass = NULL;
|
|||
{
|
||||
return freed_blocks;
|
||||
}
|
||||
+(int) calledBlockCount
|
||||
{
|
||||
return called_blocks;
|
||||
}
|
||||
|
||||
static void block_called ()
|
||||
{
|
||||
OSAtomicIncrement32 (&called_blocks);
|
||||
}
|
||||
|
||||
+(void) callProtocolWithBlockProperties: (id<ProtocolWithBlockProperties>) obj required: (bool) required instance: (bool) instance;
|
||||
{
|
||||
if (required) {
|
||||
if (instance) {
|
||||
obj.myRequiredProperty ();
|
||||
} else {
|
||||
[[(NSObject *) obj class] myRequiredStaticProperty] ();
|
||||
}
|
||||
} else {
|
||||
if (instance) {
|
||||
obj.myOptionalProperty ();
|
||||
} else {
|
||||
[[(NSObject *) obj class] myOptionalStaticProperty] ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+(void) callProtocolWithBlockReturnValue: (id<ObjCProtocolBlockTest>) obj required: (bool) required instance: (bool) instance;
|
||||
{
|
||||
if (required) {
|
||||
if (instance) {
|
||||
[obj requiredReturnValue] (42);
|
||||
} else {
|
||||
[[(NSObject *) obj class] requiredStaticReturnValue] (42);
|
||||
}
|
||||
} else {
|
||||
if (instance) {
|
||||
[obj optionalReturnValue] (42);
|
||||
} else {
|
||||
[[(NSObject *) obj class] optionalStaticReturnValue] (42);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+(void) callProtocolWithBlockPropertiesRequired: (id<ProtocolWithBlockProperties>) obj
|
||||
{
|
||||
obj.myRequiredProperty ();
|
||||
}
|
||||
|
||||
+(void) setProtocolWithBlockProperties: (id<ProtocolWithBlockProperties>) obj required: (bool) required instance: (bool) instance
|
||||
{
|
||||
simple_callback callback = ^{ block_called (); };
|
||||
if (required) {
|
||||
if (instance) {
|
||||
obj.myRequiredProperty = callback;
|
||||
} else {
|
||||
[[(NSObject *) obj class] setMyRequiredStaticProperty: callback];
|
||||
}
|
||||
} else {
|
||||
if (instance) {
|
||||
obj.myOptionalProperty = callback;
|
||||
} else {
|
||||
[[(NSObject *) obj class] setMyOptionalStaticProperty: callback];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FreedNotifier
|
||||
|
|
|
@ -182,12 +182,15 @@ namespace xharness
|
|||
yield return new TestData { Variation = "Release (all optimizations)", MTouchExtraArgs = "--registrar:static --optimize:all", Debug = false, Profiling = false, Defines = "OPTIMIZEALL" };
|
||||
yield return new TestData { Variation = "Debug (all optimizations)", MTouchExtraArgs = "--registrar:static --optimize:all", Debug = true, Profiling = false, Defines = "OPTIMIZEALL" };
|
||||
yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Ignored = true, };
|
||||
yield return new TestData { Variation = "Debug (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = true, Profiling = false, Ignored = true, };
|
||||
break;
|
||||
case "mscorlib":
|
||||
yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Ignored = true, Undefines = "FULL_AOT_RUNTIME" };
|
||||
yield return new TestData { Variation = "Debug (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = true, Profiling = false, Ignored = true, Undefines = "FULL_AOT_RUNTIME" };
|
||||
break;
|
||||
case "mini":
|
||||
yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" };
|
||||
yield return new TestData { Variation = "Debug (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" };
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -2708,7 +2711,7 @@ function toggleAll (show)
|
|||
xbuild.StartInfo.EnvironmentVariables ["MSBuildExtensionsPath"] = null;
|
||||
LogEvent (log, "Building {0} ({1})", TestName, Mode);
|
||||
if (!Harness.DryRun) {
|
||||
var timeout = TimeSpan.FromMinutes (15);
|
||||
var timeout = TimeSpan.FromMinutes (60);
|
||||
var result = await xbuild.RunAsync (log, true, timeout);
|
||||
if (result.TimedOut) {
|
||||
ExecutionResult = TestExecutingResult.TimedOut;
|
||||
|
|
|
@ -366,6 +366,15 @@ namespace xharness
|
|||
}
|
||||
}
|
||||
|
||||
public override StreamReader GetReader ()
|
||||
{
|
||||
if (File.Exists (CapturePath)) {
|
||||
return new StreamReader (new FileStream (CapturePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
|
||||
} else {
|
||||
return new StreamReader (new MemoryStream ());
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flush ()
|
||||
{
|
||||
base.Flush ();
|
||||
|
|
|
@ -380,6 +380,11 @@ namespace xharness
|
|||
return string.Empty;
|
||||
}
|
||||
|
||||
public static string GetMtouchLink (this XmlDocument csproj, string platform, string configuration)
|
||||
{
|
||||
return GetNode (csproj, "MtouchLink", platform, configuration);
|
||||
}
|
||||
|
||||
public static void SetMtouchUseLlvm (this XmlDocument csproj, bool value, string platform, string configuration)
|
||||
{
|
||||
SetNode (csproj, "MtouchUseLlvm", true ? "true" : "false", platform, configuration);
|
||||
|
@ -390,6 +395,17 @@ namespace xharness
|
|||
SetNode (csproj, "MtouchEnableBitcode", true ? "true" : "false", platform, configuration);
|
||||
}
|
||||
|
||||
public static IEnumerable<XmlNode> GetPropertyGroups (this XmlDocument csproj, string platform, string configuration)
|
||||
{
|
||||
var propertyGroups = csproj.SelectNodes ("//*[local-name() = 'PropertyGroup' and @Condition]");
|
||||
foreach (XmlNode node in propertyGroups) {
|
||||
if (!EvaluateCondition (node, platform, configuration))
|
||||
continue;
|
||||
|
||||
yield return node;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetNode (this XmlDocument csproj, string node, string value, string platform, string configuration)
|
||||
{
|
||||
var projnode = csproj.SelectElementNodes (node);
|
||||
|
@ -417,6 +433,16 @@ namespace xharness
|
|||
}
|
||||
}
|
||||
|
||||
public static string GetNode (this XmlDocument csproj, string name, string platform, string configuration)
|
||||
{
|
||||
foreach (var pg in GetPropertyGroups (csproj, platform, configuration)) {
|
||||
foreach (XmlNode node in pg.ChildNodes)
|
||||
if (node.Name == name)
|
||||
return node.InnerText;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetImport (this XmlDocument csproj)
|
||||
{
|
||||
|
|
|
@ -84,6 +84,13 @@ namespace xharness
|
|||
csproj.SetMtouchUseBitcode (true, "iPhone", "Release");
|
||||
csproj.SetMtouchUseLlvm (true, "iPhone", "Release");
|
||||
|
||||
// Not linking a watch extensions requires passing -Os to the native compiler.
|
||||
// https://github.com/mono/mono/issues/9867
|
||||
var configurations = new string [] { "Debug", "Debug32", "Release", "Release32", "Release-bitcode" };
|
||||
foreach (var c in configurations)
|
||||
if (csproj.GetMtouchLink ("iPhone", c) == "None")
|
||||
csproj.AddExtraMtouchArgs ("--gcc_flags=-Os", "iPhone", c);
|
||||
|
||||
Harness.Save (csproj, WatchOSExtensionProjectPath);
|
||||
|
||||
WatchOSExtensionGuid = csproj.GetProjectGuid ();
|
||||
|
|
|
@ -630,7 +630,6 @@
|
|||
!missing-selector! NSMutableArray::sortWithOptions:usingComparator: not bound
|
||||
!missing-selector! NSMutableData::increaseLengthBy: not bound
|
||||
!missing-selector! NSMutableData::initWithLength: not bound
|
||||
!missing-selector! NSMutableDictionary::addEntriesFromDictionary: not bound
|
||||
!missing-selector! NSMutableDictionary::initWithCapacity: not bound
|
||||
!missing-selector! NSMutableDictionary::removeObjectsForKeys: not bound
|
||||
!missing-selector! NSMutableDictionary::setDictionary: not bound
|
||||
|
|
|
@ -63,7 +63,6 @@ namespace Xamarin.Bundler {
|
|||
|
||||
public bool? EnableCoopGC;
|
||||
public bool EnableSGenConc;
|
||||
public bool UseInterpreter;
|
||||
public MarshalObjectiveCExceptionMode MarshalObjectiveCExceptions;
|
||||
public MarshalManagedExceptionMode MarshalManagedExceptions;
|
||||
|
||||
|
|
|
@ -1397,12 +1397,64 @@ namespace Registrar {
|
|||
return rv;
|
||||
}
|
||||
|
||||
public DelegateProxyAttribute GetDelegateProxyAttribute (MethodDefinition method)
|
||||
{
|
||||
if (!TryGetAttribute (method.MethodReturnType, ObjCRuntime, "DelegateProxyAttribute", out var attrib))
|
||||
return null;
|
||||
|
||||
var rv = new DelegateProxyAttribute ();
|
||||
|
||||
switch (attrib.ConstructorArguments.Count) {
|
||||
case 1:
|
||||
rv.DelegateType = ((TypeReference) attrib.ConstructorArguments [0].Value).Resolve ();
|
||||
break;
|
||||
default:
|
||||
throw ErrorHelper.CreateError (4124, "Invalid DelegateProxyAttribute found on '{0}'. Please file a bug report at https://bugzilla.xamarin.com", ((MethodReference) method)?.FullName);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
protected override string PlatformName {
|
||||
get {
|
||||
return App.PlatformName;
|
||||
}
|
||||
}
|
||||
|
||||
ProtocolMemberAttribute GetProtocolMemberAttribute (TypeReference type, string selector, ObjCMethod obj_method, MethodDefinition method)
|
||||
{
|
||||
var memberAttributes = GetProtocolMemberAttributes (type);
|
||||
foreach (var attrib in memberAttributes) {
|
||||
if (attrib.IsStatic != method.IsStatic)
|
||||
continue;
|
||||
|
||||
if (attrib.IsProperty) {
|
||||
if (method.IsSetter && attrib.SetterSelector != selector)
|
||||
continue;
|
||||
else if (method.IsGetter && attrib.GetterSelector != selector)
|
||||
continue;
|
||||
} else {
|
||||
if (attrib.Selector != selector)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!obj_method.IsPropertyAccessor) {
|
||||
var attribParameters = new TypeReference [attrib.ParameterType?.Length ?? 0];
|
||||
for (var i = 0; i < attribParameters.Length; i++) {
|
||||
attribParameters [i] = attrib.ParameterType [i];
|
||||
if (attrib.ParameterByRef [i])
|
||||
attribParameters [i] = new ByReferenceType (attribParameters [i]);
|
||||
}
|
||||
if (!ParametersMatch (method.Parameters, attribParameters))
|
||||
continue;
|
||||
}
|
||||
|
||||
return attrib;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override IEnumerable<ProtocolMemberAttribute> GetProtocolMemberAttributes (TypeReference type)
|
||||
{
|
||||
var td = type.Resolve ();
|
||||
|
@ -1434,6 +1486,9 @@ namespace Registrar {
|
|||
case "ReturnType":
|
||||
rv.ReturnType = (TypeReference)prop.Argument.Value;
|
||||
break;
|
||||
case "ReturnTypeDelegateProxy":
|
||||
rv.ReturnTypeDelegateProxy = (TypeReference) prop.Argument.Value;
|
||||
break;
|
||||
case "ParameterType":
|
||||
if (prop.Argument.Value != null) {
|
||||
var arr = (CustomAttributeArgument[])prop.Argument.Value;
|
||||
|
@ -3071,8 +3126,7 @@ namespace Registrar {
|
|||
sb.WriteLine (map.ToString ());
|
||||
sb.WriteLine (map_init.ToString ());
|
||||
|
||||
if (exceptions.Count > 0)
|
||||
throw new AggregateException (exceptions);
|
||||
ErrorHelper.ThrowIfErrors (exceptions);
|
||||
}
|
||||
|
||||
static bool HasIntPtrBoolCtor (TypeDefinition type)
|
||||
|
@ -3680,7 +3734,7 @@ namespace Registrar {
|
|||
if (creatorMethod != null) {
|
||||
token = $"0x{CreateTokenReference (creatorMethod, TokenType.Method):X} /* {creatorMethod.FullName} */ ";
|
||||
} else {
|
||||
ErrorHelper.Show (ErrorHelper.CreateWarning (App, 4174, method.Method, "Unable to locate the block to delegate conversion method for the method {0}'s parameter #{1}.",
|
||||
exceptions.Add (ErrorHelper.CreateWarning (App, 4174, method.Method, "Unable to locate the block to delegate conversion method for the method {0}'s parameter #{1}.",
|
||||
method.DescriptiveMethodName, i + 1));
|
||||
}
|
||||
}
|
||||
|
@ -3832,6 +3886,7 @@ namespace Registrar {
|
|||
setup_return.AppendLine ("res = nsstr;");
|
||||
} else if (IsDelegate (type.Resolve ())) {
|
||||
var signature = "NULL";
|
||||
var token = "INVALID_TOKEN_REF";
|
||||
if (App.Optimizations.OptimizeBlockLiteralSetupBlock == true) {
|
||||
if (type.Is ("System", "Delegate") || type.Is ("System", "MulticastDelegate")) {
|
||||
ErrorHelper.Show (ErrorHelper.CreateWarning (App, 4173, method.Method, $"The registrar can't compute the block signature for the delegate of type {type.FullName} in the method {descriptiveMethodName} because {type.FullName} doesn't have a specific signature."));
|
||||
|
@ -3843,8 +3898,14 @@ namespace Registrar {
|
|||
signature = "\"" + ComputeSignature (method.DeclaringType.Type, null, method, isBlockSignature: true) + "\"";
|
||||
}
|
||||
}
|
||||
var delegateProxyType = GetDelegateProxyType (method);
|
||||
if (delegateProxyType != null) {
|
||||
token = $"0x{CreateTokenReference (delegateProxyType, TokenType.TypeDef):X} /* {delegateProxyType.FullName} */ ";
|
||||
} else {
|
||||
exceptions.Add (ErrorHelper.CreateWarning (App, 4176, method.Method, "Unable to locate the delegate to block conversion type for the return value of the method {0}.", method.DescriptiveMethodName));
|
||||
}
|
||||
}
|
||||
setup_return.AppendLine ("res = xamarin_get_block_for_delegate (managed_method, retval, {0}, &exception_gchandle);", signature);
|
||||
setup_return.AppendLine ("res = xamarin_get_block_for_delegate (managed_method, retval, {0}, {1}, &exception_gchandle);", signature, token);
|
||||
setup_return.AppendLine ("if (exception_gchandle != 0) goto exception_handling;");
|
||||
} else {
|
||||
throw ErrorHelper.CreateError (4104,
|
||||
|
@ -4049,6 +4110,52 @@ namespace Registrar {
|
|||
}
|
||||
}
|
||||
|
||||
TypeDefinition GetDelegateProxyType (ObjCMethod obj_method)
|
||||
{
|
||||
// A mirror of this method is also implemented in BlockLiteral:GetDelegateProxyType
|
||||
// If this method is changed, that method will probably have to be updated too (tests!!!)
|
||||
MethodDefinition method = obj_method.Method;
|
||||
MethodDefinition first = method;
|
||||
MethodDefinition last = null;
|
||||
while (method != last) {
|
||||
last = method;
|
||||
var delegateProxyType = GetDelegateProxyAttribute (method);
|
||||
if (delegateProxyType?.DelegateType != null)
|
||||
return delegateProxyType.DelegateType;
|
||||
|
||||
method = GetBaseMethodInTypeHierarchy (method);
|
||||
}
|
||||
|
||||
// Might be the implementation of an interface method, so find the corresponding
|
||||
// MethodDefinition for the interface, and check for DelegateProxy attributes there as well.
|
||||
var map = PrepareMethodMapping (first.DeclaringType);
|
||||
if (map != null && map.TryGetValue (first, out var list)) {
|
||||
if (list.Count != 1)
|
||||
throw Shared.GetMT4127 (first, list);
|
||||
var delegateProxyType = GetDelegateProxyAttribute (list [0]);
|
||||
if (delegateProxyType?.DelegateType != null)
|
||||
return delegateProxyType.DelegateType;
|
||||
}
|
||||
|
||||
// Might be an implementation of an optional protocol member.
|
||||
if (obj_method.DeclaringType.Protocols != null) {
|
||||
string selector = null;
|
||||
|
||||
foreach (var proto in obj_method.DeclaringType.Protocols) {
|
||||
// We store the DelegateProxy type in the ProtocolMemberAttribute, so check those.
|
||||
if (selector == null)
|
||||
selector = obj_method.Selector ?? string.Empty;
|
||||
if (selector != null) {
|
||||
var attrib = GetProtocolMemberAttribute (proto.Type, selector, obj_method, method);
|
||||
if (attrib?.ReturnTypeDelegateProxy != null)
|
||||
return attrib.ReturnTypeDelegateProxy.Resolve ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
MethodDefinition GetBlockWrapperCreator (ObjCMethod obj_method, int parameter)
|
||||
{
|
||||
// A mirror of this method is also implemented in Runtime:GetBlockWrapperCreator
|
||||
|
@ -4087,48 +4194,35 @@ namespace Registrar {
|
|||
if (selector == null)
|
||||
selector = obj_method.Selector ?? string.Empty;
|
||||
if (selector != null) {
|
||||
var memberAttributes = GetProtocolMemberAttributes (proto.Type);
|
||||
foreach (var attrib in memberAttributes) {
|
||||
if (attrib.ParameterBlockProxy == null || attrib.ParameterBlockProxy.Length <= parameter || attrib.ParameterBlockProxy [parameter] == null)
|
||||
continue; // no need to check anything if what we want isn't there
|
||||
if (attrib.Selector != selector)
|
||||
continue;
|
||||
if (attrib.IsStatic != method.IsStatic)
|
||||
continue;
|
||||
var attribParameters = new TypeReference [attrib.ParameterType?.Length ?? 0];
|
||||
for (var i = 0; i < attribParameters.Length; i++) {
|
||||
attribParameters [i] = attrib.ParameterType [i];
|
||||
if (attrib.ParameterByRef [i])
|
||||
attribParameters [i] = new ByReferenceType (attribParameters [i]);
|
||||
}
|
||||
if (!ParametersMatch (method.Parameters, attribParameters))
|
||||
continue;
|
||||
|
||||
var attrib = GetProtocolMemberAttribute (proto.Type, selector, obj_method, method);
|
||||
if (attrib?.ParameterBlockProxy?.Length > parameter && attrib.ParameterBlockProxy [parameter] != null)
|
||||
return attrib.ParameterBlockProxy [parameter].Resolve ().Methods.First ((v) => v.Name == "Create");
|
||||
}
|
||||
|
||||
if (proto.Methods != null) {
|
||||
foreach (var pMethod in proto.Methods) {
|
||||
if (!pMethod.IsOptional)
|
||||
continue;
|
||||
if (pMethod.Name != method.Name)
|
||||
continue;
|
||||
if (!TypeMatch (pMethod.ReturnType, method.ReturnType))
|
||||
continue;
|
||||
if (ParametersMatch (method.Parameters, pMethod.Parameters))
|
||||
continue;
|
||||
|
||||
MethodDefinition extensionMethod = pMethod.Method;
|
||||
if (extensionMethod == null) {
|
||||
MapProtocolMember (obj_method.Method, out extensionMethod);
|
||||
if (extensionMethod == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
var createMethod = GetBlockProxyAttributeMethod (extensionMethod, parameter + 1);
|
||||
if (createMethod != null)
|
||||
return createMethod;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var pMethod in proto.Methods) {
|
||||
if (!pMethod.IsOptional)
|
||||
continue;
|
||||
if (pMethod.Name != method.Name)
|
||||
continue;
|
||||
if (!TypeMatch (pMethod.ReturnType, method.ReturnType))
|
||||
continue;
|
||||
if (ParametersMatch (method.Parameters, pMethod.Parameters))
|
||||
continue;
|
||||
|
||||
MethodDefinition extensionMethod = pMethod.Method;
|
||||
if (extensionMethod == null) {
|
||||
MapProtocolMember (obj_method.Method, out extensionMethod);
|
||||
if (extensionMethod == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
var createMethod = GetBlockProxyAttributeMethod (extensionMethod, parameter + 1);
|
||||
if (createMethod != null)
|
||||
return createMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4762,6 +4856,7 @@ namespace Registrar {
|
|||
header.WriteLine ("#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"");
|
||||
header.WriteLine ("#pragma clang diagnostic ignored \"-Wtypedef-redefinition\""); // temporary hack until we can stop including glib.h
|
||||
header.WriteLine ("#pragma clang diagnostic ignored \"-Wobjc-designated-initializers\"");
|
||||
header.WriteLine ("#pragma clang diagnostic ignored \"-Wunguarded-availability-new\"");
|
||||
|
||||
if (App.EnableDebug) {
|
||||
header.WriteLine ("#define DEBUG 1");
|
||||
|
@ -4843,6 +4938,11 @@ namespace Registrar {
|
|||
public TypeDefinition Type { get; set; }
|
||||
}
|
||||
|
||||
class DelegateProxyAttribute : Attribute
|
||||
{
|
||||
public TypeDefinition DelegateType { get; set; }
|
||||
}
|
||||
|
||||
class BindAsAttribute : Attribute
|
||||
{
|
||||
public BindAsAttribute (TypeReference type)
|
||||
|
@ -4863,6 +4963,7 @@ namespace Registrar {
|
|||
public string Name { get; set; }
|
||||
public string Selector { get; set; }
|
||||
public TypeReference ReturnType { get; set; }
|
||||
public TypeReference ReturnTypeDelegateProxy { get; set; }
|
||||
public TypeReference[] ParameterType { get; set; }
|
||||
public bool[] ParameterByRef { get; set; }
|
||||
public TypeReference [] ParameterBlockProxy { get; set; }
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace Xamarin.Linker {
|
|||
"Microsoft.Win32.Registry.AccessControl",
|
||||
"Microsoft.Win32.Registry",
|
||||
"System.AppContext",
|
||||
"System.Buffers",
|
||||
"System.Collections.Concurrent",
|
||||
"System.Collections.NonGeneric",
|
||||
"System.Collections.Specialized",
|
||||
|
|
|
@ -491,7 +491,7 @@ namespace Xamarin.Bundler {
|
|||
|
||||
App.InitializeCommon ();
|
||||
|
||||
Log ("Xamarin.Mac {0}{1}", Constants.Version, verbose > 0 ? "." + Constants.Revision : string.Empty);
|
||||
Log ("Xamarin.Mac {0}.{1}", Constants.Version, Constants.Revision);
|
||||
|
||||
if (verbose > 0)
|
||||
Console.WriteLine ("Selected target framework: {0}; API: {1}", targetFramework, IsClassic ? "Classic" : "Unified");
|
||||
|
|
|
@ -116,6 +116,8 @@ namespace Xamarin.Bundler {
|
|||
public string AotOtherArguments = string.Empty;
|
||||
public bool? LLVMAsmWriter;
|
||||
public Dictionary<string, string> LLVMOptimizations = new Dictionary<string, string> ();
|
||||
public bool UseInterpreter;
|
||||
public List<string> InterpretedAssemblies = new List<string> ();
|
||||
|
||||
public Dictionary<string, string> EnvironmentVariables = new Dictionary<string, string> ();
|
||||
|
||||
|
@ -129,6 +131,44 @@ namespace Xamarin.Bundler {
|
|||
|
||||
public bool? BuildDSym;
|
||||
|
||||
public bool IsInterpreted (string assembly)
|
||||
{
|
||||
// IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both.
|
||||
if (!UseInterpreter)
|
||||
return false;
|
||||
|
||||
// Go through the list of assemblies to interpret in reverse order,
|
||||
// so that the last option passed to mtouch takes precedence.
|
||||
for (int i = InterpretedAssemblies.Count - 1; i >= 0; i--) {
|
||||
var opt = InterpretedAssemblies [i];
|
||||
if (opt == "all")
|
||||
return true;
|
||||
else if (opt == "-all")
|
||||
return false;
|
||||
else if (opt == assembly)
|
||||
return true;
|
||||
else if (opt [0] == '-' && opt.Substring (1) == assembly)
|
||||
return false;
|
||||
}
|
||||
|
||||
// There's an implicit 'all' at the start of the list.
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsAOTCompiled (string assembly)
|
||||
{
|
||||
if (!UseInterpreter)
|
||||
return true;
|
||||
|
||||
// IsAOTCompiled and IsInterpreted are not opposites: mscorlib.dll can be both:
|
||||
// - mscorlib will always be processed by the AOT compiler to generate required wrapper functions for the interpreter to work
|
||||
// - mscorlib might also be fully AOT-compiled (both when the interpreter is enabled and when it's not)
|
||||
if (assembly == "mscorlib")
|
||||
return true;
|
||||
|
||||
return !IsInterpreted (assembly);
|
||||
}
|
||||
|
||||
// If we're targetting a 32 bit arch.
|
||||
bool? is32bits;
|
||||
public bool Is32Build {
|
||||
|
@ -462,7 +502,7 @@ namespace Xamarin.Bundler {
|
|||
if (EnableLLVMOnlyBitCode)
|
||||
return false;
|
||||
|
||||
if (UseInterpreter)
|
||||
if (IsInterpreted (Assembly.GetIdentity (assembly)))
|
||||
return true;
|
||||
|
||||
switch (Platform) {
|
||||
|
@ -2124,7 +2164,20 @@ namespace Xamarin.Bundler {
|
|||
|
||||
public void BundleAssemblies ()
|
||||
{
|
||||
var strip = !UseInterpreter && ManagedStrip && IsDeviceBuild && !EnableDebug && !PackageManagedDebugSymbols;
|
||||
Assembly.StripAssembly strip = ((path) =>
|
||||
{
|
||||
if (!ManagedStrip)
|
||||
return false;
|
||||
if (!IsDeviceBuild)
|
||||
return false;
|
||||
if (EnableDebug)
|
||||
return false;
|
||||
if (PackageManagedDebugSymbols)
|
||||
return false;
|
||||
if (IsInterpreted (Assembly.GetIdentity (path)))
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
var grouped = Targets.SelectMany ((Target t) => t.Assemblies).GroupBy ((Assembly asm) => asm.Identity);
|
||||
foreach (var @group in grouped) {
|
||||
|
|
|
@ -54,11 +54,7 @@ namespace Xamarin.Bundler {
|
|||
|
||||
public bool IsAOTCompiled {
|
||||
get {
|
||||
if (App.UseInterpreter)
|
||||
/* interpreter only requires a few stubs that are attached
|
||||
* to mscorlib.dll, other assemblies won't be AOT compiled */
|
||||
return FileName == "mscorlib.dll";
|
||||
return true;
|
||||
return App.IsAOTCompiled (Identity);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,15 +104,18 @@ namespace Xamarin.Bundler {
|
|||
ComputeDependencies (exceptions);
|
||||
}
|
||||
|
||||
public delegate bool StripAssembly (string path);
|
||||
|
||||
// returns false if the assembly was not copied (because it was already up-to-date).
|
||||
public bool CopyAssembly (string source, string target, bool copy_debug_symbols = true, bool strip = false)
|
||||
public bool CopyAssembly (string source, string target, bool copy_debug_symbols = true, StripAssembly strip = null)
|
||||
{
|
||||
var copied = false;
|
||||
|
||||
try {
|
||||
if (!Application.IsUptodate (source, target) && (strip || !Cache.CompareAssemblies (source, target))) {
|
||||
var strip_assembly = strip != null && strip (source);
|
||||
if (!Application.IsUptodate (source, target) && (strip_assembly || !Cache.CompareAssemblies (source, target))) {
|
||||
copied = true;
|
||||
if (strip) {
|
||||
if (strip_assembly) {
|
||||
Driver.FileDelete (target);
|
||||
Directory.CreateDirectory (Path.GetDirectoryName (target));
|
||||
MonoTouch.Tuner.Stripper.Process (source, target);
|
||||
|
@ -195,7 +194,7 @@ namespace Xamarin.Bundler {
|
|||
// Aot data is copied separately, because we might want to copy aot data
|
||||
// even if we don't want to copy the assembly (if 32/64-bit assemblies are identical,
|
||||
// only one is copied, but we still want the aotdata for both).
|
||||
public void CopyToDirectory (string directory, bool reload = true, bool check_case = false, bool only_copy = false, bool copy_debug_symbols = true, bool strip = false)
|
||||
public void CopyToDirectory (string directory, bool reload = true, bool check_case = false, bool only_copy = false, bool copy_debug_symbols = true, StripAssembly strip = null)
|
||||
{
|
||||
var target = Path.Combine (directory, FileName);
|
||||
|
||||
|
|
|
@ -486,7 +486,7 @@ namespace Xamarin.Bundler
|
|||
throw new ArgumentNullException (nameof (install_name));
|
||||
|
||||
flags.AddOtherFlag ("-shared");
|
||||
if (!App.EnableBitCode)
|
||||
if (!App.EnableBitCode && !Target.Is64Build)
|
||||
flags.AddOtherFlag ("-read_only_relocs suppress");
|
||||
if (App.EnableBitCode)
|
||||
flags.AddOtherFlag ("-lc++");
|
||||
|
|
|
@ -283,6 +283,29 @@ namespace Xamarin.Bundler
|
|||
}
|
||||
|
||||
linker_flags = new CompilerFlags (this);
|
||||
|
||||
// Verify that there are no entries in our list of intepreted assemblies that doesn't match
|
||||
// any of the assemblies we know about.
|
||||
if (App.UseInterpreter) {
|
||||
var exceptions = new List<Exception> ();
|
||||
foreach (var entry in App.InterpretedAssemblies) {
|
||||
var assembly = entry;
|
||||
if (string.IsNullOrEmpty (assembly))
|
||||
continue;
|
||||
|
||||
if (assembly [0] == '-')
|
||||
assembly = assembly.Substring (1);
|
||||
|
||||
if (assembly == "all")
|
||||
continue;
|
||||
|
||||
if (Assemblies.ContainsKey (assembly))
|
||||
continue;
|
||||
|
||||
exceptions.Add (ErrorHelper.CreateWarning (138, $"Cannot find the assembly '{assembly}', passed as an argument to --interpreter."));
|
||||
}
|
||||
ErrorHelper.ThrowIfErrors (exceptions);
|
||||
}
|
||||
}
|
||||
|
||||
// This is to load the symbols for all assemblies, so that we can give better error messages
|
||||
|
@ -1134,6 +1157,8 @@ namespace Xamarin.Bundler
|
|||
}
|
||||
|
||||
if (App.UseInterpreter)
|
||||
/* TODO: not sure? we might have to continue here, depending on
|
||||
* the set of assemblies are AOT'd? */
|
||||
return;
|
||||
|
||||
// Code in one assembly (either in a P/Invoke or a third-party library) can depend on a third-party library in another assembly.
|
||||
|
|
|
@ -455,7 +455,8 @@ namespace Xamarin.Bundler
|
|||
bool enable_debug = app.EnableDebug;
|
||||
bool enable_debug_symbols = app.PackageManagedDebugSymbols;
|
||||
bool llvm_only = app.EnableLLVMOnlyBitCode;
|
||||
bool interp = app.UseInterpreter;
|
||||
bool interp = app.IsInterpreted (Assembly.GetIdentity (filename));
|
||||
bool interp_full = !interp && app.UseInterpreter && fname == "mscorlib.dll";
|
||||
bool is32bit = (abi & Abi.Arch32Mask) > 0;
|
||||
string arch = abi.AsArchString ();
|
||||
|
||||
|
@ -474,9 +475,15 @@ namespace Xamarin.Bundler
|
|||
args.Append (app.AotArguments);
|
||||
if (llvm_only)
|
||||
args.Append ("llvmonly,");
|
||||
else if (interp)
|
||||
else if (interp) {
|
||||
if (fname != "mscorlib.dll")
|
||||
throw ErrorHelper.CreateError (99, $"Internal error: can only enable the interpreter for mscorlib.dll when AOT-compiling assemblies (tried to interpret {fname}). Please file an issue at https://github.com/xamarin/xamarin-macios/issues/new.");
|
||||
args.Append ("interp,");
|
||||
else
|
||||
} else if (interp_full) {
|
||||
if (fname != "mscorlib.dll")
|
||||
throw ErrorHelper.CreateError (99, $"Internal error: can only enable the interpreter for mscorlib.dll when AOT-compiling assemblies (tried to interpret {fname}). Please file an issue at https://github.com/xamarin/xamarin-macios/issues/new.");
|
||||
args.Append ("interp,full,");
|
||||
} else
|
||||
args.Append ("full,");
|
||||
|
||||
var aname = Path.GetFileNameWithoutExtension (fname);
|
||||
|
@ -1247,7 +1254,14 @@ namespace Xamarin.Bundler
|
|||
app.LLVMOptimizations [asm] = opt;
|
||||
}
|
||||
},
|
||||
{ "interpreter", "Enable the *experimental* interpreter.", v => { app.UseInterpreter = true; }},
|
||||
{ "interpreter:", "Enable the *experimental* interpreter. Optionally takes a comma-separated list of assemblies to interpret (if prefixed with a minus sign, the assembly will be AOT-compiled instead). 'all' can be used to specify all assemblies. This argument can be specified multiple times.", v =>
|
||||
{
|
||||
app.UseInterpreter = true;
|
||||
if (!string.IsNullOrEmpty (v)) {
|
||||
app.InterpretedAssemblies.AddRange (v.Split (new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries));
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "http-message-handler=", "Specify the default HTTP message handler for HttpClient", v => { http_message_handler = v; }},
|
||||
{ "output-format=", "Specify the output format for some commands. Possible values: Default, XML", v =>
|
||||
{
|
||||
|
@ -1341,7 +1355,7 @@ namespace Xamarin.Bundler
|
|||
throw new MonoTouchException (25, true, "No SDK version was provided. Please add --sdk=X.Y to specify which {0} SDK should be used to build your application.", app.PlatformName);
|
||||
|
||||
var framework_dir = GetFrameworkDirectory (app);
|
||||
Driver.Log ("Xamarin.iOS {0}{1} using framework: {2}", Constants.Version, verbose > 1 ? "." + Constants.Revision : string.Empty, framework_dir);
|
||||
Driver.Log ("Xamarin.iOS {0}.{1} using framework: {2}", Constants.Version, Constants.Revision, framework_dir);
|
||||
|
||||
if (action == Action.None)
|
||||
throw new MonoTouchException (52, true, "No command specified.");
|
||||
|
|
Загрузка…
Ссылка в новой задаче