How do I bind to a system framework with Xamarin.Mac? - macos

I'm in the proces of making an app for interacting with smartcards.
For that I'd like to use the CryptoTokenKit Framework which is standard on a Mac (located at /System/Library/Frameworks/CryptoTokenKit.framework).
This link says that it's possible to bind frameworks in a Mac project:
https://developer.xamarin.com/guides/cross-platform/macios/native-references/
I've created an ApiDefinition.cs file and a StrucsAndEnums.cs file using the following sharpie command:
sharpie bind -framework ./CryptoTokenKit.framework -sdk macosx10.13 -o ~/CryptoTokenKitBinding
I can't find any info on the internet how to implement the above mentioned files and start using the framework.

Create a Xamarin.Mac binding project within a solution.
Add a NativeReference to:
/System/Library/Frameworks/CryptoTokenKit.framework
Bind it using sharpie:
sharpie bind \
-o CryptoTokenKitFramework \
-namespace CryptoTokenKit \
-sdk macosx10.13 \
-f /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CryptoTokenKit.framework
There is a mismatch between the binding project template and the output of sharpie, so you can either delete ApiDefinition.cs and add ApiDefinitions.cs or just overwrite the template created one:
mv CryptoTokenKitFramework/ApiDefinitions.cs CryptoTokenKitFramework/ApiDefinition.cs
There will be a number of attributes like (versions will change across them):
[Watch (4,0), TV (11,0), Mac (10,12), iOS (10,0)]
As these are private frameworks on iOS, Watch, TV, so strip those platforms out. Leave the Mac attribute and the original version:
[Mac (10,11)]
Note: PlatformAttribute is obsolete but sharpie is still using it (assuming backwards version compatibility(?)), so you can use Introduced if you really want to clean up the build output:
[Introduced (PlatformName.MacOSX, 10, 11, PlatformArchitecture.Arch64)]
There will be a few [Verify] attributes that have to be reviewed/corrected. i.e. TKSmartCardUserInteraction.Cancel and TKSmartCardSlot.MakeSmartCard should both be methods not properties.
Example / Generated:
// -(TKSmartCard * _Nullable)makeSmartCard;
[NullAllowed, Export ("makeSmartCard")]
[Verify (MethodToProperty)]
TKSmartCard MakeSmartCard { get; }
Corrected:
// -(TKSmartCard * _Nullable)makeSmartCard;
[NullAllowed, Export("makeSmartCard")]
TKSmartCard MakeSmartCard();
Fix the rest of the [Verify] attributes and compiler errors, there are a bunch of bad method signatures, pointers, return types, etc.. that are generated and need corrected.
Note: TO make your life easier, make sure that you are using the latest Sharpie version:
Version: 3.4.0
SHA1: c12859dac8d43121b5a9ed866a0db8409f9df817
URL: https://dl.xamarin.com/objective-sharpie/ObjectiveSharpie-3.4.0.pkg

Related

SkiaSharp SKSvg.Load throws MissingMethodException

I use SkiaSharp libraries on my Xamarin.Core/Xamarin.iOS project.
I try to load an SVG file from the Core library like the following;
var svg = new SKSvg();
Assembly assembly = type.GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.Images.watermark_light.svg"))
{
svg.Load(stream);
}
The code throws on the "Load" step saying "System.MissingMethodException: Method not found: SkiaSharp.SKTextBlob SkiaSharp.SKTextBlob.CreatePositioned(string,SkiaSharp.SKFont,System.ReadOnlySpan`1<SkiaSharp.SKPoint>)"
My configuration:
Device: Debug|Simulator
Linker Behaviour: Don't link
Xamarin.iOS 15.4.0.0
xcode13.2: 8fc41ae82
Rider IDE: RD-221.5591.20
OS: MacOS Monterey 12.4 (21F79)
Libraries
SkiaSharp v2.88.1-preview.79
SkiaSharp.Views v2.88.1-preview.79
Svg.Skia v0.5.14
SkiaSharp.Svg v1.60.0
CoreLibrary/Images/watermark_light.svg(svg path)
I tried to add SKTextBlob reference to LinkerPleaseInclude.cs as well. But, it should not be the case when the linker behaviour is set to "Don't link". Also a added --linkskip argument for the relevant namespace. None of them worked. Any ideas about the issue?
Thanks!
Try updating to version 0.5.16 https://www.nuget.org/packages/Svg.Skia/0.5.16

How can I figure out which framework was used for build desktop application's (Zoom) UI?

I would like to know which framework was used to build Zoom(windows & mac)'s UI.
Is that possible somehow? Would decompiling help?
Zoom's desktop application
You can download Zoom's Linux client and choose Other Linux OS from the drop down menu. Then run the following command in a Linux terminal:
$ tar -xf zoom_x86_64.tar.xz
The execution of the command results in a directory called zoom being created and when you list it's contents using this command:
$ ls zoom
You get the following output:
audio libQt5DBus.so.5 libQt5QuickTemplates2.so.5.12.9 libturbojpeg.so
dingdong1.pcm libQt5DBus.so.5.12 libQt5QuickWidgets.so meeting_chat_chime.pcm
dingdong.pcm libQt5DBus.so.5.12.9 libQt5QuickWidgets.so.5 meeting_raisehand_chime.pcm
double_beep.pcm libQt5Gui.so libQt5QuickWidgets.so.5.12 platforminputcontexts
Droplet.pcm libQt5Gui.so.5 libQt5QuickWidgets.so.5.12.9 platforms
egldeviceintegrations libQt5Gui.so.5.12 libQt5Script.so platformthemes
Embedded.properties libQt5Gui.so.5.12.9 libQt5Script.so.5 Qt
generic libQt5Network.so libQt5Script.so.5.12 qt.conf
getbssid.sh libQt5Network.so.5 libQt5Script.so.5.12.9 QtGraphicalEffects
getmem.sh libQt5Network.so.5.12 libQt5Svg.so QtQml
iconengines libQt5Network.so.5.12.9 libQt5Svg.so.5 QtQuick
imageformats libQt5OpenGL.so libQt5Svg.so.5.12 QtQuick.2
json libQt5OpenGL.so.5 libQt5Svg.so.5.12.9 QtWayland
leave.pcm libQt5OpenGL.so.5.12 libQt5WaylandClient.so record_start.pcm
libfdkaac2.so libQt5OpenGL.so.5.12.9 libQt5WaylandClient.so.5 record_stop.pcm
libicudata.so libQt5Qml.so libQt5WaylandClient.so.5.12 ring.pcm
libicudata.so.56 libQt5Qml.so.5 libQt5WaylandClient.so.5.12.9 ringtone
libicudata.so.56.1 libQt5Qml.so.5.12 libQt5Widgets.so sip
libicui18n.so libQt5Qml.so.5.12.9 libQt5Widgets.so.5 timezones
libicui18n.so.56 libQt5QuickControls2.so libQt5Widgets.so.5.12 translations
libicui18n.so.56.1 libQt5QuickControls2.so.5 libQt5Widgets.so.5.12.9 version.txt
libicuuc.so libQt5QuickControls2.so.5.12 libQt5X11Extras.so wayland-decoration-client
libicuuc.so.56 libQt5QuickControls2.so.5.12.9 libQt5X11Extras.so.5 wayland-graphics-integration-client
libicuuc.so.56.1 libQt5Quick.so libQt5X11Extras.so.5.12 wayland-graphics-integration-server
libmpg123.so libQt5Quick.so.5 libQt5X11Extras.so.5.12.9 wayland-shell-integration
libQt5Core.so libQt5Quick.so.5.12 libQt5XcbQpa.so wr_ding.pcm
libQt5Core.so.5 libQt5Quick.so.5.12.9 libQt5XcbQpa.so.5 xcbglintegrations
libQt5Core.so.5.12 libQt5QuickTemplates2.so libQt5XcbQpa.so.5.12 zoom
libQt5Core.so.5.12.9 libQt5QuickTemplates2.so.5 libQt5XcbQpa.so.5.12.9 ZoomLauncher
libQt5DBus.so libQt5QuickTemplates2.so.5.12 libquazip.so zopen
As you can see, a lot of the filenames start with libQt5 or Qt, so I would assume, that the framework used to develop the Linux desktop client is the Qt Framework. And because the Linux client and the Windows client share the same user interface, they are probably both using Qt.

V8 : Isolate is incompatible with the embedded blob

I am trying to create custom snapshot from some Javascript file. I was able to create a snapshot using the command
mksnapshot.exe snapshot11.js --startup_blob snap.bin
but when I was trying to create an Isolate with this snap.bin file I got this message
The Isolate is incompatible with the embedded blob. This is usually caused by incorrect usage of mksnapshot. When generating custom snapshots, embedders must ensure they pass the same flags as during the V8 build process (e.g.: --turbo-instruction-scheduling).
I am guessing that I need recreate the snapshot with the proper flags but I couldn't find which flags I need to use.
My args.gn
is_component_build=true
v8_static_library=false
is_official_build=false
is_debug=true
use_custom_libcxx=false
use_custom_libcxx_for_host=false
target_cpu="x64"
use_goma=false
v8_use_external_startup_data=false
v8_enable_i18n_support = false
symbol_level=2
v8_enable_fast_mksnapshot=true
Any lead will be helpful.
10x
You can invoke ninja with -v to have it print all the commands it executes; e.g. if you compile V8 with:
ninja -v -C out/... v8_monolith
then you'll find a line for the mksnapshot invocation in the output, and can copy the flags from there. (If you have already compiled V8, ninja will say "nothing to do"; in that case you can either clean out everything, or just delete snapshot_blob.bin and libv8_monolith.so.)

Converting static framework to dynamic

I want to convert static iOS framework (https://github.com/comScore/ComScore-iOS-watchOS-tvOS/tree/master/ComScore/iOS) into dynamic.
> clang -arch x86_64 -dynamiclib -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator10.3.sdk -lc++ -F . -framework ComScore -ObjC -o ComScoreDynamic
This command is successful, however, there is a problem with symbol visibility.
When I check symbols in the original framework it is around 4k of public symbols:
> nm -gU ComScore.framework/ComScore | wc -l
4387
In dynamic version only very few of them:
nm -gU ComScoreDynamic
0000000000114af8 S _OBJC_CLASS_$_SCORCommonUtils
0000000000114940 S _OBJC_CLASS_$_SCORCrossPublisherIdSourceValue
0000000000114a08 S _OBJC_CLASS_$_SCORHTTP
0000000000114990 S _OBJC_CLASS_$_SCORHelper
0000000000114aa8 S _OBJC_CLASS_$_SCORObfuscation
0000000000114a80 S _OBJC_CLASS_$_SCORReachability
0000000000114918 S _OBJC_CLASS_$_SCORUniqueId
0000000000114b20 S _OBJC_METACLASS_$_SCORCommonUtils
00000000001149e0 S _OBJC_METACLASS_$_SCORCrossPublisherIdSourceValue
0000000000114a30 S _OBJC_METACLASS_$_SCORHTTP
0000000000114968 S _OBJC_METACLASS_$_SCORHelper
0000000000114ad0 S _OBJC_METACLASS_$_SCORObfuscation
0000000000114a58 S _OBJC_METACLASS_$_SCORReachability
00000000001149b8 S _OBJC_METACLASS_$_SCORUniqueId
00000000001166b0 D __ZTINSt3__117bad_function_callE
00000000000d5d60 S __ZTSNSt3__117bad_function_callE
All other symbols marked as internal (t and s markings).
How can I keep symbols external?
UPDATE:
Looks like this can be similar problem: Export an `OBJC_CLASS` from one static lib as part of another
Problem is that symbols in static lib are exported as private_extern and there is no way to preserve them in dynamic library.
The public symbols in the comScore framework are marked private external. This can be seen with the nm utility and looking for the SCORAnalytics class:
nm -m ComScore/iOS/ComScore.framework/Versions/A/ComScore |grep _OBJC_CLASS_\$_SCORAnalytics
Shows:
---------------- (LTO,DATA) private external _OBJC_CLASS_$_SCORAnalytics
This means the symbol can only be linked against once. When Cocoapods performs a pre-link for secondary ('transitive') dependencies, these symbols lose their extern attribute. The idea here is to prevent public symbols from a dependency from leaking into those of another library. The problem is that, for Swift projects, they aren't fully resolved until the final app link; by that point they're no longer available.
The real issue is that the comScore library is a static framework. The best solution would be for comScore to release it as a dynamic framework, but these are only supported by iOS 8 and above; comScore insists on support all the way back to iOS 6. I know.
For now, my solution is to include the comScore framework directly in our Cocoapod and vend it within the Podspec, allowing it to work with both Obj-C and Swift projects. The downside is I have to manually update our Cocoapod every time comScore releases a new version. There would also be symbol conflicts if another pod included comScore, but since our pod is a metrics aggregator that logs to several backends, it's likely to be the only metrics component in use. YMMV.

How can I run com.apple.tools.info-plist-utility?

I am using XCode to build an iPhone application, where I would like to externally process the info plist file in the same manner as the XCode build step shown below does
Processing /Users/kte/Projects/build/Debug-iphonesimulator/TestAppGen.app/Info.plist TestAppGen-Info.plist
mkdir /Users/kte/Projects/build/Debug-iphonesimulator/TestAppGen.app
cd /Users/kte/Projects/TestAppGen
setenv PATH "/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
<com.apple.tools.info-plist-utility> TestAppGen-Info.plist -genpkginfo /Users/kte/Projects/build/Debug-iphonesimulator/TestAppGen.app/PkgInfo -expandbuildsettings -format xml -o /Users/kte/Projects/build/Debug-iphonesimulator/TestAppGen.app/Info.plist
This excerpt from the build log refers to a com.apple.tools.info-plist-utility, which I gather from various sources around the net, is an internal XCode utility.
Is it possible to run the com.apple.tools.info-plist-utility from a command line?
You can use a tool called PlistBuddy, /usr/libexec/PlistBuddy, have a look at its man page.
But you will also need to convert the plist back to a binary plist file. This can be done like this in a build script
plutil -convert binary1 "$TARGET_BUILD_DIR/$INFOPLIST_PATH"
The "plutil" answer is a great start. Unfortunately the Xcode build process does more to the Info.plist file than converting it to binary, for example on my system it adds in the fields:
-MinimumOSVersion
-PlatformName
-CFBundleExecutable
-SDKName
-CFBundleResourceSpecification
-CFBundleSupportedPlatforms
According to the Apple documentation you aren't supposed to set up some of these values yourself:
MinimumOSVersion
MinimumOSVersion (String). When you
build an iPhone application, Xcode
notes the target OS (as determined by
the Base SDK selection) as the
MinimimOSVersion property. Do not
specify this property yourself in the
Info.plist file; it is a
system-written property. When you
publish your application to the App
Store, the store indicates the iPhone
OS release on which your application
can run based on this property. It is
equivalent to the
LSMinimumSystemVersion property on Mac
OS X.
I'm running into all sorts of problems trying to re-sign my application as part of my custom build process.

Resources