Xamarin and binding to a Swift Framework



  • So, I'm not expecting much help from this crowd since I'm sure most of you don't work with either Xamarin or Xcode, but I am trying to bind a Framework built in Swift for use in a Xamarin.iOS project.

    I've attempted to follow the official walkthrough from Microsoft to no avail, but the framework I have is both already built and exposing what we need via Objective-C header shenanigans, so a good chunk of the walkthrough (which covers building a proxy library in case the framework doesn't have said Objective-C stuff) should be able to be skipped.

    So, what I have is:

    • I create the binding library project.
    • On the Mac, I use the terminal to do the sharpie commands to generate C# code from the framework's headers.
    • I lift those C# files into my binding library project.
    • I add a Native Framework Reference of the Library.framework folder in question (we actually have two, one that is native only, the other for native and the simulator).
    • On Windows, I build the binding library project, it gives "0 warnings, 0 errors".
    • Visual Studio then shows 1 warning for that binding library project: The referenced component 'Native References\Library.framework' could not be found.
    • Adding the binding library as a reference to a Xamarin.iOS project works, but the namespace and classes that the sharpie command output into the C# file aren't accessible.
    • Switching to the Mac, I build the binding library, again, "0 warnings, 0 errors".
    • Visual Studio for Mac then does not show any warning like it did on Windows.
    • Adding the binding library as a reference to a Xamarin.iOS project works and is accessible, but I can't build the Xamarin.iOS project.
      • If I linked the native only framework, I can't build for the Simulator (obviously) but even building for our dev phone doesn't work (codesign errors, despite being debug builds).
      • If I linked the native and simulator framework, it fails to build for the Simulator as it acts like it can only find the arm64 binaries (plus some other header shenanigans that I assume the vendor would have to fix, but they already fixed the headers once and nothing stands out as being wrong with the mixed headers).

    The real problem is, the point of us using Xamarin is to be able to build from Windows, so I don't have to use the Mac for everything, but the binding library piece just doesn't seem to work, but I have to think it's either specific to my setup as I can't find anything about the issues I'm running into, and I run into identical issues when attempting to do similar examples with other frameworks (at least, the one or two I managed to find that expose swift headers with Objective-C bindings included).

    What is even weirder is that one time, when attempting to build the binding library on Windows, it "just worked" and everything seemed OK, it could be seen in the Xamarin.iOS project, but as it was the end of the day, I closed down and went home. Next day, suddenly it can't be seen again and rebuilding gave the same warning about not finding the reference.

    I've also attempted to build something using the new potential Xamarin Binding Tools for Swift but, after the fun of having to downgrade the tooling, that didn't work either because I guess the framework we have from the vendor is missing a file that these binding tools need.



  • Well, an update, I guess.

    I found this on the Visual Studio Developer Community forums, which is exactly the problem I am having on Windows... except it was reported for VS2017 while I'm on VS2019, and Microsoft says it was fixed.

    So, screw it, we can build the binding library on the Mac, copy the DLL to a share, and reference it and build on the Windows side. That all worked fine.

    Now, the problem of the native framework is cropping up. Specifically, that they gave us a version that is native only that we have working, and one that is for native and the simulator which doesn't. Well, if we have to make a new app (or update an app with screenshots), we do not have the two iPhones that match the dimensions Apple requires to natively run the apps for this library, so I need to use the version with the simulator.

    Back on the Mac, just to make sure I can get something that works. Switch over the frameworks to the "native and simulator" version and I get the following errors when linking:

    log clang : error : linker command failed with exit code 1 (use -v to see invocation)

    error MT5209 : Native linking error : warning: ignoring file "/.../obj/iPhoneSimulator/Debug/device-builds/iphone 11 pro max-14.5/mtouch-cache/Library1.framework/Library1", building for iOS Simulator-x86_64 but attempting to link with file built for iOS-arm64

    error MT5209 : Native linking error : warning: ignoring file "/.../obj/iPhoneSimulator/Debug/device-builds/iphone 11 pro max-14.5/mtouch-cache/Library2.framework/Library2", building for iOS Simulator-x86_64 but attempting to link with file built for iOS-arm64

    MTOUCH : error MT5211: Native linking failed, undefined Objective-C class: LibraryApi. The symbol '_OBJC_CLASS_$_LibraryApi' could not be found in any of the libraries or frameworks linked with your application.

    Now, I assume the last error is tied to the middle two errors, specifically since it skips linking the library, it can't find a symbol that one of the two would contain.

    Problem is, I can't find anything about the error message for the middle two relating to Xamarin. I have only ever been able to find information for those errors (and potential resolutions for them) specifically about Xcode.



  • @ChaosTheEternal Yeah, that does sound like the library which supposedly covers the simulator actually doesn't.

    Are you sure you referenced the proper file when switching things around? I remember Xcode doing non-obvious file linking when I had to mess around with that.



  • @Rhywden Problem is, I have to assume they actually do as the vendor has other clients that have implemented the library without problem (though they did so natively, while we are apparently the first vendor knowingly attempting implementation with Xamarin).



  • @ChaosTheEternal Then I'd go with "XCode picks up the wrong version", i.e. it still tries to build with the "ARM only" library.



  • @Rhywden Yes, that is exactly what I expect those errors are. But the linking process is 100% handled by Visual Studio, so the question is "does anyone know how to make it so it will attempt to use the right architecture?" or "does anyone know how to specify in the project properties in Visual Studio to inject things into the xcodeproj file that is generated during compile to try to override this?" or "does anyone know any linker flags that could be set to specify to use a specific architecture from Xcode's clang?"

    The only setting I can find is the "Supported Architectures" one in Visual Studio, and for a simulator build, it is set to the only option available: x86_64



  • @ChaosTheEternal Have you tried wiping the "ARM only" library files from the face of the earth all folders? That should then result in file not found errors.



  • @Rhywden The folder structure of what we got is like this:

    • Library.xcframework
      • ios-arm64
        • Library.framework
          • <all the files>
      • ios-arm64_x86_64
        • Library.framework
          • <all the files>

    What we reference are the .framework folders, which are after the folder specifying what architectures are inside. No, I don't really know why we got one that is arm64 only and one that is arm64 + x86_64.

    When I built originally, I referenced the arm64-only framework in the project. Then, deleted the reference from the project and referenced the arm64+x86_64 framework. So, as of right now, there shouldn't be any "remembering the arm64-only" in the project.

    The only thing I can think of to do right now is to dig into the actual mixed framework folder and see about removing all of the files specifically labelled arm64 and see if that either breaks things worse or makes it work (though if it does the latter, that won't help since I need the arm64 files for release builds).



  • @ChaosTheEternal Maybe also try this stuff on the XCode side:



  • @Rhywden Didn't help.


    @ChaosTheEternal said in Xamarin and binding to a Swift Framework:

    The only thing I can think of to do right now is to dig into the actual mixed framework folder and see about removing all of the files specifically labelled arm64 and see if that either breaks things worse or makes it work (though if it does the latter, that won't help since I need the arm64 files for release builds).

    Haha, fuck me. This actually worked.

    And with a bit of C# Project hacking, I can have the iPhoneSimulator build use the x86_64 framework versions, and the iPhone build use the arm64 framework versions. The only problem I have left then is that apparently having the doubled up references in the binding library makes Visual Studio confused and not know of the interface in the iOS project (despite only doubling up the framework references and not the actual C# code explaining the references), but it is only broken for the IDE.

    It'll actually compile and run and seemingly work fine.



  • Well, shit.

    So, my plan to just "compile DLLs on the Mac and set up Windows to consume them as a reference per configuration" did work in the IDE, but at build time, it calls codesign to replace existing signatures in the DLL and fails with a permission denied error.

    Looking online, the only suggestions I can find don't help. "Use automatic provisioning" didn't work. Most are talking about some framework called Flutter (which isn't what we're using).

    So, fall back to the Mac, and try it again, this time using the direct project reference, and it somehow also fails due to the same error but on the other framework file.

    I'm not sure how my testing app has it working for building on a device and now in the simulator without codesign issues but my actual production app project just don't work, even when effectively lifting the working project's csproj file over the production project's csproj file.


Log in to reply