1

I have an project that takes a two-step process to build an iOS app. There's the native libraries and .dext built in XCode, and then those are linked to a Xamarin project that I use to finish building the app in C# on VisualStudio build. It's simple to link the static libraries in the Xamarin project, and it's simple to embed the .dext to some other native-only app that just in XCode, but I'm not sure how to embed the .dext in the Xamarin project app.

Can you just BundleResource in the Xamarin csproj all of the files in the .dext package (embedded profile, CodeSignature, Info.plist, and the built driver) into a SystemExtension folder in the .ipa? There doesn't seem to be a way to get the signed .dext package from the Xcode build either; the Copy Files "Code Sign On Copy" checkbox is broken for specifically driver dexts.

thoms
  • 55
  • 5

2 Answers2

1

I don't know about Xamarin, but I can answer parts of your question:

There doesn't seem to be a way to get the signed .dext package from the Xcode build either; the Copy Files "Code Sign On Copy" checkbox is broken for specifically driver dexts.

This is because you really don't want to sign the dext with the same code signing setup as the app. It has its own app ID, entitlements, and corresponding provisioning profile. However, the disabled tickbox just means the dext should already be pre-signed when it comes to embedding it in the app. If you build the dext target on its own in Xcode/xcodebuild, it should already come out signed - if that's not the case, your dext target is misconfigured.

The "copy files" step is for copying items into the target bundle before it's signed, not for copying the built target elsewhere. The "code sign on copy" option individually signs the item(s) copied in, in addition to the whole bundle being signed at the end. So this isn't suitable as a mechanism for copying the built and signed dext into a specific place during your build.

All that is needed to embed the dext should be to copy it into the correct location in your app's bundle, and then sign the app normally (probably with the communicates-with-drivers entitlement).

I can't tell you how that's done with Xamarin, specifically. However, my recommendation would perhaps be an xcodebuild install step for your dext as part of your Xamarin app build. This "installs" the target after build+sign, into $DSTROOT/$INSTALL_PATH. Those variables are Xcode build settings, and can be set per project/target/configuration in the .xcodeproj/project.pbxproj or explicitly on the xcodebuild command line. If you make the DSTROOT a base directory of where Xamarin will look for items to bundle into the app, and the INSTALL_PATH the Library/SystemExtensions, that should solve your problem if I've understood correctly.

I believe on iPadOS there is also a requirement that the dext has a bundle ID that starts with the app ID's bundle ID, so something like: com.example.apps.myapp.drivername if the app's bundle identifier is com.example.apps.myapp. Xcode normally enforces this for you, but if you're assembling your bundle "by hand" there's nothing to check this.

pmdj
  • 22,018
  • 3
  • 52
  • 103
  • So, my .dext is getting signed correctly, but what's happening is that it gets signed with it's own app ID, entitlements, and profile in the DerivedData *after* the step to copy it to my project's Output directory. If I build an app and embed the dext only in Xcode, it's fine just grabbing the finished+signed product from DerivedData/USBDriverTestApp-asdfasasdasdgasda/ , but I need to move that finished product to MyXamarinProject/Output/bin so my VisualStudio Xamarin project can reference it. – thoms Jul 13 '23 at 18:29
  • @thoms This sounds like a peculiarity of whatever Xamarin uses for its build system, although I don't really see why you couldn't just invoke an `xcodebuild` command line that builds and signs your dext as part of the build process and get that to write its output to the specific path where Xamarin then goes looking for it. – pmdj Jul 13 '23 at 19:22
  • Right, I was just trying to avoid adding an extra step into the Xamarin build separate from what I already do, just run all the Xcode build in Xcode and it copies over everything in the right order (except for the .dext) and then open Visual Studio and build. Mostly just a consistency and convenience issue with the Code Sign On Copy Xcode feature not working – thoms Jul 13 '23 at 19:40
  • I've checked the entitlements and the bundle IDs, and all of them look correct, which makes me wonder if there's another part of the bundling step that's not covered by just copying over the .dext to SystemExtensions. Is there somewhere in the console logs where I could see why iOS is failing to install the .ipa? – thoms Jul 13 '23 at 19:41
  • I'm really not clear on the sequence of steps you're performing. The fact you keep talking about wanting "code sign on copy" suggests there might be some misunderstanding, either in what the feature does (sign the embedded binary or bundle with the App's code signing settings) or in how dexts *should* be signed (with their own provisioning profile). I don't know what parts of the build are covered by Xamarin, and where Xcode is responsible, but perhaps a Xamarin expert can suggest a workable approach. – pmdj Jul 14 '23 at 11:18
  • 1
    All I'm trying to do is build the .dext in Xcode and have that signed .dext copied over to an Output directory using Xcode settings. If I add a "Copy Files" step in a MyProject that only builds the dext (no app involved), that doesn't work. It copies the unsigned .dext package from DerivedData to MyProject/Output, and then signs the .dext package in DerivedData. There doesn't seem to be a way (using the normal Xcode build settings in the Xcode UI) to sign in DerivedData first and then copy from DerivedData to MyProject/Output. I'm guess I'm just assuming that's what Code Sign On Copy would do – thoms Jul 14 '23 at 13:26
  • 1
    The "copy files" step is for copying items *into* the target bundle before it's signed, not for copying the built target elsewhere. The "code sign on copy" option individually signs the item(s) copied in, in addition to the whole bundle being signed at the end. Either way, I don't think you can make it work this way. My recommendation would perhaps be an `xcodebuild install` step for your dext as part of your Xamarin app build. This "installs" the target after build+sign, into `$DSTROOT/$INSTALL_PATH` IIRC. Both variables can be set per target, project or on the `xcodebuild` command line. – pmdj Jul 15 '23 at 14:10
  • 1
    The [documentation for Xcode build settings](https://developer.apple.com/documentation/xcode/build-settings-reference) appears to agree with my memory on targets ending up in `$DSTROOT/$INSTALL_PATH`. If you make the DSTROOT a base directory of where Xamarin will look for items to bundle into the app, and the INSTALL_PATH the `Library/SystemExtensions`, that should solve your problem if I've understood correctly. – pmdj Jul 15 '23 at 14:19
  • 1
    Thanks! That should answer the second part of my question then! I had the Copy Files phase all mixed up. – thoms Jul 19 '23 at 15:35
  • I'll edit my answer to contain some of the info from my comments, as that seems like it might be useful to other users who might come across it and won't necessarily read the thread of comments. – pmdj Jul 20 '23 at 07:47
1

Yes, I can use the BundleResources to copy in the .dext into the .ipa's SystemExtensions directory.

The issue I was facing is that Xamarin also has the OptimizePropertyLists property, which will scramble the bundled .dext's Info.plist and make it unable to install. That property needs to be set false on the Xamarin app's build project.

thoms
  • 55
  • 5