xamarin-macios icon indicating copy to clipboard operation
xamarin-macios copied to clipboard

XIB files are not copied from the referenced executable project

Open snechaev opened this issue 6 months ago • 2 comments

Apple platform

macOS

Framework version

net8.0-, net9.0-

Affected platform version

.net 9.0.203

Description

Note: I'm not sure if this should be fixed. However, it may be reasonable to add a compile-time error or warning.

During quick prototyping, I accidentally referenced the executable project instead of the class library. I was able to successfully reuse the code from this project, but I was not able to use the xib-s interface definitions because xib files was not copied to the final app bundle.

The expected behavior may be one of the following

  • copy the xib files from all referenced projects;
  • do not allow references to executable projects. Add the corresponding compiler warning or error.

Additional notes

I believe that is pretty strange to reference the executable project, but there are a few nuances:

  • tooling (xcsync, Rider) can't handle the UI in the class libraries. The corresponding classes are simply not visible in XCode when the "Edit with XCode" action. So, some people may try to reference executable projects to workaround the tooling issues.
  • IDE hotfixes.I encountered this issue after the Rider told me something like "Foo is undefined. Let's reference the AnotherApp.csproj and add the missing using directives to fix this".

Steps to Reproduce

  • Open test project UiFromExecutable.zip

  • run the AppToReference project and make sure it run and works - you can see the NSCollectionView with a buttons (one button for each collection item)

  • run the UiFromClassLib and find the exception telling "could not dequeue an item of kind: NSCollectionElementKindItem with identifier MyItem - must register a nib or a class for the identifier, or name a nib or class to match the identifier"

    Full exception text

      ObjCRuntime.ObjCException: Objective-C exception thrown.  Name: NSInternalInconsistencyException Reason: could not dequeue an item of kind: NSCollectionElementKindItem with identifier MyItem - must register a nib or a class for the identifier, or name a nib or class to match the identifier
      Native stack trace:
      	0   CoreFoundation                      0x000000018a14727c __exceptionPreprocess + 176
      	1   libobjc.A.dylib                     0x0000000189c2a158 objc_exception_throw + 60
      	2   Foundation                          0x000000018b2bb1cc -[NSCalendarDate initWithCoder:] + 0
      	3   AppKit                              0x000000018e3bb2e4 -[_NSCollectionViewCore _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:] + 1244
      	4   AppKit                              0x000000018e3bbd84 -[_NSCollectionViewCore dequeueReusableItemWithReuseIdentifier:forIndexPath:] + 84
      	5   AppKit                              0x000000018dacf678 -[NSCollectionView makeItemWithIdentifier:forIndexPath:] + 88
      	6   UiFromClassLib                      0x000000010416b2d0 xamarin_dyn_objc_msgSend + 160
      	7   ???                                 0x00000003012701e8 0x0 + 12904235496
      	8   ???                                 0x000000030126fbb0 0x0 + 12904233904
      	9   ???                                 0x000000030126f974 0x0 + 12904233332
      	10  ???                                 0x0000000301853874 0x0 + 12910409844
      	11  ???                                 0x0000000300492e18 0x0 + 12889697816
      	12  ???                                 0x00000003004ad234 0x0 + 12889805364
      	13  ???                                 0x0000000301257918 0x0 + 12904134936
      	14  ???                                 0x0000000301256e64 0x0 + 12904132196
      	15  ???                                 0x0000000301256ccc 0x0 + 12904131788
      	16  UiFromClassLib                      0x0000000104154b54 xamarin_bridge_runtime_invoke_method + 132
      	17  UiFromClassLib                      0x00000001041665f4 mono_runtime_invoke + 72
      	18  UiFromClassLib                      0x0000000104163fa8 xamarin_invoke_trampoline + 6072
      	19  UiFromClassLib                      0x000000010416a3c0 xamarin_arch_trampoline + 148
      	20  UiFromClassLib                      0x000000010416b1a4 xamarin_arm64_common_trampoline + 64
      	21  AppKit                              0x000000018dacf508 -[_NSCollectionViewDataSourceAdapter collectionView:itemForRepresentedObjectAtIndexPath:] + 220
      	22  AppKit                              0x000000018e3afaf8 -[_NSCollectionViewCore _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:] + 100
      	23  AppKit                              0x000000018e3b24c8 -[_NSCollectionViewCore _updateVisibleCellsNow:] + 3156
      	24  AppKit                              0x000000018e3b6204 -[_NSCollectionViewCore _layoutItems] + 212
      	25  AppKit                              0x000000018dac3138 -[NSCollectionView layout] + 304
      	26  AppKit                              0x000000018e3dfe30 ___NSViewLayout_block_invoke + 592
      	27  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	28  AppKit                              0x000000018d97903c _NSViewLayout + 96
      	29  AppKit                              0x000000018e3d64dc __36-[NSView _layoutSubtreeWithOldSize:]_block_invoke + 364
      	30  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	31  AppKit                              0x000000018d978fd0 -[NSView _layoutSubtreeWithOldSize:] + 100
      	32  AppKit                              0x000000018e3d6620 __36-[NSView _layoutSubtreeWithOldSize:]_block_invoke + 688
      	33  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	34  AppKit                              0x000000018d978fd0 -[NSView _layoutSubtreeWithOldSize:] + 100
      	35  AppKit                              0x000000018e3d6620 __36-[NSView _layoutSubtreeWithOldSize:]_block_invoke + 688
      	36  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	37  AppKit                              0x000000018d978fd0 -[NSView _layoutSubtreeWithOldSize:] + 100
      	38  AppKit                              0x000000018e3d6620 __36-[NSView _layoutSubtreeWithOldSize:]_block_invoke + 688
      	39  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	40  AppKit                              0x000000018d978fd0 -[NSView _layoutSubtreeWithOldSize:] + 100
      	41  AppKit                              0x000000018e3d6620 __36-[NSView _layoutSubtreeWithOldSize:]_block_invoke + 688
      	42  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	43  AppKit                              0x000000018d978fd0 -[NSView _layoutSubtreeWithOldSize:] + 100
      	44  AppKit                              0x000000018e3d6fc4 __56-[NSView _layoutSubtreeIfNeededAndAllowTemporaryEngine:]_block_invoke + 796
      	45  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	46  AppKit                              0x000000018d978b90 -[NSView _layoutSubtreeIfNeededAndAllowTemporaryEngine:] + 100
      	47  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	48  AppKit                              0x000000018d978b20 -[NSView layoutSubtreeIfNeeded] + 96
      	49  AppKit                              0x000000018e681850 -[NSWindow(NSConstraintBasedLayoutInternal) _layoutViewTree] + 104
      	50  AppKit                              0x000000018e6819d8 -[NSWindow(NSConstraintBasedLayoutInternal) layoutIfNeeded] + 240
      	51  AppKit                              0x000000018d9d7754 __NSWindowGetDisplayCycleObserverForLayout_block_invoke + 364
      	52  AppKit                              0x000000018d9d6cec NSDisplayCycleObserverInvoke + 168
      	53  AppKit                              0x000000018d9d6948 NSDisplayCycleFlush + 644
      	54  QuartzCore                          0x00000001922ca76c _ZN2CA11Transaction19run_commit_handlersE18CATransactionPhase + 120
      	55  QuartzCore                          0x00000001922c950c _ZN2CA11Transaction6commitEv + 320
      	56  AppKit                              0x000000018da5aac8 __62+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayLink]_block_invoke + 272
      	57  AppKit                              0x000000018e41b4e4 ___NSRunLoopObserverCreateWithHandler_block_invoke + 64
      	58  CoreFoundation                      0x000000018a0d180c __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 36
      	59  CoreFoundation                      0x000000018a0d16f8 __CFRunLoopDoObservers + 536
      	60  CoreFoundation                      0x000000018a0d0d24 __CFRunLoopRun + 776
      	61  CoreFoundation                      0x000000018a0d03c4 CFRunLoopRunSpecific + 608
      	62  HIToolbox                           0x000000019487d19c RunCurrentEventLoopInMode + 292
      	63  HIToolbox                           0x000000019487ce2c ReceiveNextEventCommon + 220
      	64  HIToolbox                           0x000000019487cd30 _BlockUntilNextEventMatchingListInModeWithFilter + 76
      	65  AppKit                              0x000000018d931cc8 _DPSNextEvent + 660
      	66  AppKit                              0x000000018e1284d0 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 700
      	67  AppKit                              0x000000018d924ffc -[NSApplication run] + 476
      	68  AppKit                              0x000000018d8fc240 NSApplicationMain + 880
      	69  ???                                 0x000000030125319c 0x0 + 12904116636
      	70  ???                                 0x0000000301252e90 0x0 + 12904115856
      	71  ???                                 0x000000030124aa20 0x0 + 12904081952
      	72  libcoreclr.dylib                    0x0000000105dabab8 CallDescrWorkerInternal + 132
      	73  libcoreclr.dylib                    0x0000000105c2f794 _ZN18MethodDescCallSite16CallTargetWorkerEPKyPyi + 832
      	74  libcoreclr.dylib                    0x0000000105b33a9c _Z7RunMainP10MethodDescsPiPP8PtrArray + 624
      	75  libcoreclr.dylib                    0x0000000105b33df8 _ZN8Assembly17ExecuteMainMethodEPP8PtrArrayi + 268
      	76  libcoreclr.dylib                    0x0000000105b5843c _ZN8CorHost215ExecuteAssemblyEjPKDsiPS1_Pj + 640
      	77  libcoreclr.dylib                    0x0000000105b234b4 coreclr_execute_assembly + 232
      	78  UiFromClassLib                      0x0000000104166318 mono_jit_exec + 204
      	79  UiFromClassLib                      0x000000010416a274 xamarin_main + 884
      	80  UiFromClassLib                      0x000000010420aac8 main + 64
      	81  dyld                                0x0000000189c67154 start + 2476
    
         at ObjCRuntime.Messaging.NativeHandle_objc_msgSend_NativeHandle_NativeHandle(IntPtr receiver, IntPtr selector, NativeHandle arg1, NativeHandle arg2)
         at AppKit.NSCollectionView.MakeItem(String identifier, NSIndexPath indexPath) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/dotnet/macos/generated-sources/AppKit/NSCollectionView.g.cs:line 865
         at AppToReference.TestCollectionViewDataSource.GetItem(NSCollectionView collectionView, NSIndexPath indexPath) in /Users/sergey/Downloads/UiFromClassLib/Shared/TestCollectionViewDataSource.cs:line 51
         at InvokeStub_TestCollectionViewDataSource.GetItem(Object, Span`1)
         at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
      Native stack trace:
      	0   CoreFoundation                      0x000000018a14727c __exceptionPreprocess + 176
      	1   libobjc.A.dylib                     0x0000000189c2a158 objc_exception_throw + 60
      	2   Foundation                          0x000000018b2bb1cc -[NSCalendarDate initWithCoder:] + 0
      	3   AppKit                              0x000000018e3bb2e4 -[_NSCollectionViewCore _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:] + 1244
      	4   AppKit                              0x000000018e3bbd84 -[_NSCollectionViewCore dequeueReusableItemWithReuseIdentifier:forIndexPath:] + 84
      	5   AppKit                              0x000000018dacf678 -[NSCollectionView makeItemWithIdentifier:forIndexPath:] + 88
      	6   UiFromClassLib                      0x000000010416b2d0 xamarin_dyn_objc_msgSend + 160
      	7   ???                                 0x00000003012701e8 0x0 + 12904235496
      	8   ???                                 0x000000030126fbb0 0x0 + 12904233904
      	9   ???                                 0x000000030126f974 0x0 + 12904233332
      	10  ???                                 0x0000000301853874 0x0 + 12910409844
      	11  ???                                 0x0000000300492e18 0x0 + 12889697816
      	12  ???                                 0x00000003004ad234 0x0 + 12889805364
      	13  ???                                 0x0000000301257918 0x0 + 12904134936
      	14  ???                                 0x0000000301256e64 0x0 + 12904132196
      	15  ???                                 0x0000000301256ccc 0x0 + 12904131788
      	16  UiFromClassLib                      0x0000000104154b54 xamarin_bridge_runtime_invoke_method + 132
      	17  UiFromClassLib                      0x00000001041665f4 mono_runtime_invoke + 72
      	18  UiFromClassLib                      0x0000000104163fa8 xamarin_invoke_trampoline + 6072
      	19  UiFromClassLib                      0x000000010416a3c0 xamarin_arch_trampoline + 148
      	20  UiFromClassLib                      0x000000010416b1a4 xamarin_arm64_common_trampoline + 64
      	21  AppKit                              0x000000018dacf508 -[_NSCollectionViewDataSourceAdapter collectionView:itemForRepresentedObjectAtIndexPath:] + 220
      	22  AppKit                              0x000000018e3afaf8 -[_NSCollectionViewCore _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:] + 100
      	23  AppKit                              0x000000018e3b24c8 -[_NSCollectionViewCore _updateVisibleCellsNow:] + 3156
      	24  AppKit                              0x000000018e3b6204 -[_NSCollectionViewCore _layoutItems] + 212
      	25  AppKit                              0x000000018dac3138 -[NSCollectionView layout] + 304
      	26  AppKit                              0x000000018e3dfe30 ___NSViewLayout_block_invoke + 592
      	27  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	28  AppKit                              0x000000018d97903c _NSViewLayout + 96
      	29  AppKit                              0x000000018e3d64dc __36-[NSView _layoutSubtreeWithOldSize:]_block_invoke + 364
      	30  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	31  AppKit                              0x000000018d978fd0 -[NSView _layoutSubtreeWithOldSize:] + 100
      	32  AppKit                              0x000000018e3d6620 __36-[NSView _layoutSubtreeWithOldSize:]_block_invoke + 688
      	33  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	34  AppKit                              0x000000018d978fd0 -[NSView _layoutSubtreeWithOldSize:] + 100
      	35  AppKit                              0x000000018e3d6620 __36-[NSView _layoutSubtreeWithOldSize:]_block_invoke + 688
      	36  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	37  AppKit                              0x000000018d978fd0 -[NSView _layoutSubtreeWithOldSize:] + 100
      	38  AppKit                              0x000000018e3d6620 __36-[NSView _layoutSubtreeWithOldSize:]_block_invoke + 688
      	39  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	40  AppKit                              0x000000018d978fd0 -[NSView _layoutSubtreeWithOldSize:] + 100
      	41  AppKit                              0x000000018e3d6620 __36-[NSView _layoutSubtreeWithOldSize:]_block_invoke + 688
      	42  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	43  AppKit                              0x000000018d978fd0 -[NSView _layoutSubtreeWithOldSize:] + 100
      	44  AppKit                              0x000000018e3d6fc4 __56-[NSView _layoutSubtreeIfNeededAndAllowTemporaryEngine:]_block_invoke + 796
      	45  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	46  AppKit                              0x000000018d978b90 -[NSView _layoutSubtreeIfNeededAndAllowTemporaryEngine:] + 100
      	47  AppKit                              0x000000018d9748fc NSPerformVisuallyAtomicChange + 108
      	48  AppKit                              0x000000018d978b20 -[NSView layoutSubtreeIfNeeded] + 96
      	49  AppKit                              0x000000018e681850 -[NSWindow(NSConstraintBasedLayoutInternal) _layoutViewTree] + 104
      	50  AppKit                              0x000000018e6819d8 -[NSWindow(NSConstraintBasedLayoutInternal) layoutIfNeeded] + 240
      	51  AppKit                              0x000000018d9d7754 __NSWindowGetDisplayCycleObserverForLayout_block_invoke + 364
      	52  AppKit                              0x000000018d9d6cec NSDisplayCycleObserverInvoke + 168
      	53  AppKit                              0x000000018d9d6948 NSDisplayCycleFlush + 644
      	54  QuartzCore                          0x00000001922ca76c _ZN2CA11Transaction19run_commit_handlersE18CATransactionPhase + 120
      	55  QuartzCore                          0x00000001922c950c _ZN2CA11Transaction6commitEv + 320
      	56  AppKit                              0x000000018da5aac8 __62+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayLink]_block_invoke + 272
      	57  AppKit                              0x000000018e41b4e4 ___NSRunLoopObserverCreateWithHandler_block_invoke + 64
      	58  CoreFoundation                      0x000000018a0d180c __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 36
      	59  CoreFoundation                      0x000000018a0d16f8 __CFRunLoopDoObservers + 536
      	60  CoreFoundation                      0x000000018a0d0d24 __CFRunLoopRun + 776
      	61  CoreFoundation                      0x000000018a0d03c4 CFRunLoopRunSpecific + 608
      	62  HIToolbox                           0x000000019487d19c RunCurrentEventLoopInMode + 292
      	63  HIToolbox                           0x000000019487ce2c ReceiveNextEventCommon + 220
      	64  HIToolbox                           0x000000019487cd30 _BlockUntilNextEventMatchingListInModeWithFilter + 76
      	65  AppKit                              0x000000018d931cc8 _DPSNextEvent + 660
      	66  AppKit                              0x000000018e1284d0 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 700
      	67  AppKit                              0x000000018d924ffc -[NSApplication run] + 476
      	68  AppKit                              0x000000018d8fc240 NSApplicationMain + 880
      	69  ???                                 0x000000030125319c 0x0 + 12904116636
      	70  ???                                 0x0000000301252e90 0x0 + 12904115856
      	71  ???                                 0x000000030124aa20 0x0 + 12904081952
      	72  libcoreclr.dylib                    0x0000000105dabab8 CallDescrWorkerInternal + 132
      	73  libcoreclr.dylib                    0x0000000105c2f794 _ZN18MethodDescCallSite16CallTargetWorkerEPKyPyi + 832
      	74  libcoreclr.dylib                    0x0000000105b33a9c _Z7RunMainP10MethodDescsPiPP8PtrArray + 624
      	75  libcoreclr.dylib                    0x0000000105b33df8 _ZN8Assembly17ExecuteMainMethodEPP8PtrArrayi + 268
      	76  libcoreclr.dylib                    0x0000000105b5843c _ZN8CorHost215ExecuteAssemblyEjPKDsiPS1_Pj + 640
      	77  libcoreclr.dylib                    0x0000000105b234b4 coreclr_execute_assembly + 232
      	78  UiFromClassLib                      0x0000000104166318 mono_jit_exec + 204
      	79  UiFromClassLib                      0x000000010416a274 xamarin_main + 884
      	80  UiFromClassLib                      0x000000010420aac8 main + 64
      	81  dyld                                0x0000000189c67154 start + 2476
    
  • inspect app bundle content ./UiFromClassLib/UiFromClassLib/bin/Debug/net9.0-macos/osx-arm64/UiFromClassLib.app/Contents/Resources and find that MyItem.xib does not exists here (but exists in the app bundle for the AppToReference

  • Note that in the UiFromClassLib.ViewController we explicitly referencing/instantiating the TestCollectionViewDataSource type from the AppToReference, so compiler should not optimize out the whole assembly.

Did you find any workaround?

All works fine if all the UI will be in the current executable project or in the class library. Just do not try to reuse UI from the other executable project.

Build logs

msbuild.binlog.zip

snechaev avatar Jun 03 '25 19:06 snechaev

Additionally, even if I copy MyItem.xib to the destination project (UiFromClassLib), the app still won't run because the MyItem obj-c class (not xib) cannot be found. It looks like registrar does not register types from the referenced executable project. I'm not sure if this is a separate issue or just another case of the general rule "do not reference executables".

snechaev avatar Jun 04 '25 13:06 snechaev

I can reproduce this.

The reason the resources aren't collected from the executable project reference, is that we only collect resources from projects that aren't apps or app extensions:

https://github.com/dotnet/macios/blob/26b2e27a7f587b8907b69034c455419631d38e97/msbuild/Xamarin.Shared/Xamarin.Shared.targets#L2072

This is by design, and I don't think it should change (it would either involve increasing the app size for all apps with resources, because the resources would be included there, or it would require us to build executable projects differently depending on whether they're referenced elsewhere or not, which sounds like a bad idea).

It looks doable to create a warning/error though, it would probably involve something like this:

  1. Add OutputType to the AdditionalPropertiesFromProject item group.
  2. Add a target that checks _MSBuildProjectReferenceExistent for references to executable projects / app projects (note that we have to allow references to app extensions, because that's how we attach app extensions to apps). An escape hatch would be nice.
  3. Add a test!

This doesn't sound like it's affecting a lot of people though, so unless that changes it won't have a high priority to get it fixed.

Thanks for the excellent bug report!

rolfbjarne avatar Jun 05 '25 09:06 rolfbjarne