Generating Third-party Native Bindings

Quantum provides a tool to generate third-party native bindings in iOS and Android using which you can generate frameworks that you can import into Quantum Visualizer to consume in your application. To download and access the NFI Generation Tool, contact Temenos Support.

NOTE: As MacOS versions 12.3 (and later) use Python 3 as the default language, ensure that you use the upgraded NFI Generation Tool that supports Python 3.

Generating iOS Third-party Native Binding Package

On the iOS platform, you can generate JavaScript bindings for an existing third-party framework by configuring the parameters in the config.plist. The generated bindings output is an archive file which you can import into Visualizer.

The frameworks are added to the config.plist using a tool that you can download from Temenos. All the steps mentioned here are to be performed on a Mac.

Pre-requisites

  • A third-party framework
  • NFI Tool from Quantum

IMPORTANT: If this is the first-time you are creating the framework, open terminal and enter the command ./install.sh to install GYP tool.

The process of generating native bindings and using them in a Visualizer project includes the following stages.

Generate the Third-party Framework for .framework

IMPORTANT: If you already have an existing third-party framework, you can go to the next step, Modifying the config.plist.

To generate the Third-party Native framework, do the following:

  1. Open your project in XCode.
    Ensure that the project is ready for the build.
  2. Open the header file of the project.
    For example, logger.h.
  3. On the extreme right-hand side, ensure that the Target Membership of the header in project is Public.
  4. In XCode, build your framework for the Generic iOS Device.
  5. If you want to verify the third-party framework on a simulator, again build your framework for the specific simulator you want to test.

    Now, you must bind the two different outputs into one file.
  6. Open the terminal
  7. Enter the following command in it.
    lipo -create
  8. In the finder, open the folder where the build files are available for the iPhone simulator.
    Release-iphonesimulator > YourProject.framework
  9. Drag and drop the executable file with the project name into the terminal.
    /Users/username/Library/Developer/XCode/DerivedData/projectname/Build/Products/Release-iphonesimulator/projectname.framework/Projectname
  10. In the finder, navigate to the folder where the build files are available. This time from the Release-iphoneos>YourProject.framework folder.
  11. Drag and drop the executable file with the project name into the terminal.
    /Users/username/Library/Developer/XCode/DerivedData/projectname/Build/Products/Release-iphoneos/projectname.framework/Projectname
  12. Enter – output after the text.
  13. In the finder, navigate to the folder where the build files are available.
    Release-iphoneos>YourProject.framework
  14. Drag and drop the executable file with the project name into the terminal.
    /Users/username/Library/Developer/XCode/DerivedData/projectname/Build/Products/Release-iphoneos/projectname.framework/Projectname
  15. The final command before it is executed looks as below.
    
    
    lipo -create /Users/username/Library/Developer/XCode/DerivedData/projectname/Build/Products/Release-iphonesimulator/projectname.framework/Projectname /Users/username/Library/Developer/XCode/DerivedData/projectname/Build/Products/Release-iphoneos/projectname.framework/Projectname -output /Users/username/Library/Developer/XCode/DerivedData/projectname/Build/Products/Release-iphoneos/projectname.framework/Projectname

    When the command is executed, the two different outputs are combined into one output containing all the required architectures to view the app on an iOS device and on iOS simulators.

  16. Copy the .framework folder of the project.
  17. Paste the folder in any location in your MAC.

Generate the Third-party Framework for .xcFramework

To generate the Third-party Native framework, do the following:

  1. Open your project in XCode.
    Ensure that the project is ready for the build.
  2. Open the header file of the project.
    For example, logger.h.
  3. On the extreme right-hand side, ensure that the Target Membership of the header in project is Public.
  4. In XCode, build your framework for the Generic iOS Device.
  5. If you want to verify the third-party framework on a simulator, build your framework again for the specific simulator you want to test.
    Now, you must generate the .xcframework output by providing the input folder path
  6. Open the terminal
  7. Enter the following command in it.
    xcodebuild -create-xcframework
  8. In the finder, open the folder where the build files are available for the iPhone simulator.
    Release-iphonesimulator > YourProject.framework
  9. Drag and drop the framework file with the project name into the terminal.
    /Users/username/Library/Developer/XCode/DerivedData/projectname/Build/Products/Release-iphonesimulator/projectname.framework
  10. In the finder, navigate to the folder where the build files are available. This time from the Release-iphoneos>YourProject.framework folder.
  11. Drag and drop the framework file with the project name into the terminal.
    /Users/username/Library/Developer/XCode/DerivedData/projectname/Build/Products/Release-iphoneos/projectname.framework
  12. The final command before it is executed looks as follows:
    
    
    xcodebuild -create-xcframework /Users/username/Library/Developer/XCode/DerivedData/projectname/Build/Products/Release-iphonesimulator/projectname.framework /Users/username/Library/Developer/XCode/DerivedData/projectname/Build/Products/Release-iphoneos/projectname.framework -output path/projectname.xcframework
    

    When the command is executed, the two folders individually holding the bindings for iOS device and iOS simulator are available under a single .xcframework folder

  13. Copy the .xcframework folder of the project.
  14. Paste the folder in any location on the MAC.

Modify the config.plist

The config.plist contains several parameters. For information on the parameters and what they do, click here.

To modify the config.plist:

  1. Navigate to the Scripts folder in the downloaded tool
    . ../nativebindings/iOS/nativebinding/scripts
  2. Open the terminal in the folder. (Options + Right-click)
  3. Enter the command open config.plist.
    The config.plist file opens.
  4. For ThirdPartyBuildFrameworks, copy an existing framework configuration, and paste it.
  5. Rename it with your framework name. For example, customlogger.
  6. For the entry ThirdPartyBuildHeaders, remove any existing entries. Create new entries for all the header files in the project. For example, if you have only one header file, for the item0, enter the value Logger.h.
  7. For the entry ThirdPartyBuildHeaderCommonPath, provide the headers path. For example, if your framework is CustomLogger.framework, then your folder structure would look as below.
    • For .framework: CustomLogger.framework (for example, Users/username/Documents/Customerlogger /CustomLogger.framework/Headers)
    • For .xcframework: CustomLogger.framework (for example, Users/username/Documents/Customerlogger /CustomLogger.xcframework/DeviceorSimulatorFolder/CustomerLogger.framework/Headers)
  8. For the entry ThirdPartyRootDir, enter the path that contains the framework. For example, if your framework is CustomLogger.framework, then your folder structure would look as below.

    • For .framework:
      CustomLogger.framework (for example, Users/username/Documents/Customerlogger /CustomLogger.framework)
    • For .xcframework: CustomLogger.framework (for example, Users/username/Documents/Customerlogger/CustomLogger.xcframework)
  9. Modify the entry Enabled to Yes. When configured to Yes, the framework is included in the build process. If configured to No, the framework is not added to the build process.
  10. Save the config.plist and close it.

Generate the Native Bindings

To generate the native bindings, do the following:

  1. Open the terminal and execute the command Python build_tp.py.
    When executed, the script starts the build process. Bindings for the framework are generated.

    If you have multiple frameworks, and don’t want all the frameworks to be generated, exclude the frameworks that you do not want to build by adding the framework to the BindingsIgnoreList under Root.
  2. The generated framework is available in iOS > nativebindings > products.

    You can use this file to import in to Visualizer. On how to import the file into Visualizer, click here.

Generate Native Bindings for Supported Architectures in System Frameworks

Support for a new key, SupportedArchs, has been added in the Config.plist file to generate native bindings for system frameworks.

The SupportedArchs key is a dictionary that contains the details of the architectures used for the device and the simulator.

The native bindings can be generated for the following types of architectures:

Root-Level Architecture

To generate the native bindings for the root-level architecture, add the SupportedArchs key at the root-level in the “Config.plist” file as follows:

Third-Party Framework-Level Architecture

To generate the native bindings for the third-party framework-level architecture, add the SupportedArchs key at the framework-level in the “Config.plist” file as follows:

The generation of native bindings for a device or simulator varies as follows based on the architectures defined:

  • If you only define the root-level architectures, the native bindings will only support root-level architectures.
  • If you define the root-level architectures and the framework-level architectures, the native bindings will support the framework-level architectures.
  • If you only define the framework-level architectures, the application will not run.

NOTE: If you define the framework-level architectures for a device and do not define the simulator architectures, the native bindings will not be generated for the simulator.

Generate Outputs for NFI Frameworks

Support for the Mode key has been added in the Config.plist file to generate NFI outputs based on the provided input mode. The Mode key can be used at the root-level or at the third-party level in the Config.plist file. The possible input values for the Mode key are as follows:

  • FWKS: For .framework NFI Outputs
  • XCFWKS: For .xcframework NFI Outputs

NOTE: The default value for the Mode key is XCFWKS

Here is a sample implementation of the Mode key in the Config.plist file:

<key>Mode</key>
<string>XCFWKS</string>

To generate the native bindings for the System Frameworks, you can use the following commands:

  • Generate native bindings in the output for all the System Frameworks:

    python build_native
  • Generate native bindings in the output for the Foundation Framework:

    python build_native -fw Foundation
  • Generate native bindings in the output for the Foundation and UIKit Frameworks:

    python build_native -fw Foundation,UIKit

NOTE: To generate bindings for multiple frameworks, provide comma-separated values as the input.

Cache Dependent Frameworks during NFI Generation

While generating NFIs that use dependent frameworks, if you have to make multiple updates in the NFIs, the time taken for each build is high as the dependent frameworks are also packaged for each build.
To improve the build time, the NFI tool has been updated to support caching of the dependent frameworks. When you enable caching in the NFI tool, the framework dependencies are stored in the cache during the first build and used in consequent builds.

Support for the EnableCache, ClearCache, and FwksNotToCache keys has been added in the Config.plist file to implement caching during NFI generation.
Configure the EnableCache key to implement caching for the dependent frameworks in the NFI generation during the first build. Each subsequent build will then use the cached data to package the dependent frameworks in the NFI.
Use the FwksNotToCache key to specify the list of frameworks that must not be part of the cached data. If you do not specify this key in the config.plist file, all the dependent Frameworks are cached by the NFI tool.
Configure the ClearCache key to delete the data stored in the cache.
Ensure that you add the keys in the following format in the config.plist file:

NOTE:
  • If any of the build processes fail, the dependent frameworks will not be stored in the cache.
  • If you stop or interrupt a build in progress, ensure that you clear the cache or delete the specific dependent framework (that was interrupted) from the cache.
  • Ensure that you do not share the cache folder across systems as sharing the cache may cause inconsistencies in the versions of the dependent frameworks.

Config.plist Parameters

  • SDK_DIR: iPhoneOS SDK path.
    Run below command to find the SDK path

    xcrun --sdk iphoneos --show-sdk-path

  • SDK_VERSION: iOS SDK Version in Xcode using which bindings are generated.
  • TARGET_VERSION: Minimum Deployment Target
  • ThirdPartyBuildFrameworks: Set of configurations for third party frameworks for which JS bindings need to be generated.
Configuration Type Value
Mode String

FWKS or XCFWKS.

NOTE: Use FWKS for the .framework input and XCFWKS for the .xcframework input.

ThirdPartyBuildHeaders Array A set of Header files containing the interfaces for classes for which the JSBindings need to be generated
ThirdPartyBuildHeadersCommonPath String Third party framework headers folder path
ThirdPartyRootDir String The path of the folder that contains the third party framework.
enabled Boolean If If you set the value of this key as Yes, the NFI tool generates the JS bindings.
EnableCache Boolean

If you set the value of this key as YES (or 1), the frameworks are stored in the cache and retrieved when they are required. The default value of this key is YES.

ClearCache Boolean

If you set the value of this key as YES (or 1), all the cached Frameworks in the NFI tool are deleted. The default value of this key is NO.

FwksNotToCache Array

A list of Frameworks that must not be cached by the NFI Tool. If you do not specify this key in the config.plist file, all the dependent Frameworks are cached by the NFI tool.

NOTE: This key is case-sensitive. Therefore, ensure that you provide the Framework names appropriately.

 

NOTE: The lipo -create command fails when both the device and simulator use the arm64 slice architecture.
If the simulator has arm64 architecture support, you must provide XCFWKS as the input.

Limitations

  • When generating for a framework, provide all the headers for which NFI is to be generated. Providing the default framework header which contains all the public headers is not supported.
  • Support for C pointers is not available. This is a native limitation.
  • Swift libraries are not supported. Users may wrap Objective C wrappers over swift library APIs as a workaround.
  • Caching of the NFI is enabled so as to avoid rebuilding for each .KAR extraction. If the third party NFI is regenerated, execute the option
    --cleanJSLibs to ignore caching.
  • Modern objective types may not work as desired. For example, NS_ENUM.
  • When using PassKit, you will not receive the below callback of PKAddPaymentPassViewControllerDelegate protocol. This is a native issue.

    - (void) addPaymentPassViewController: (PKAddPaymentPassViewController * ) controller generateRequestWithCertificateChain: (NSArray < NSData * >*) certificates nonce: (NSData * ) nonce nonceSignature: (NSData * ) nonceSignature completionHandler: (void( ^ )(PKAddPaymentPassRequest * request)) handler;

Generating Android Third-party Native Bindings

Using this tool, you can generate an NFI bindings archive file and also generate documentation for the framework. If you want to generate documentation, you must provide the source file in the tool.

NOTE: Providing the source files location (for -sp) and list of packages (in the whitelist.txt) is mandatory to generate Intellisence and documentation.

  • Once you import the archive file into Quantum Visualizer using the Import feature, the following tasks are taken care of automatically.
  • The .jar and .aar files copy into the project. The path might be as below,
    <Kony Visualizer Workspace>/<Project Folder>/resources/customlibs/libs/android/
  • The library will be supported in Intellisense while writing the code. For Intellisense to work, you must provide the source file to the tool.
  • If you do not need the Intellisence and documentation, then you can copy the .aar or .jar libraries generated in the following path of the Kony project and start writing the NFI code without generating the bindings.
    <Kony Visualizer Workspace>/<Project Folder>/resources/customlibs/libs/android/

Before you get started, ensure that you have the following:

  • Third-party native bindings generation tool from Temenos
  • Python installed on your system
  • Ant installed on your system
  • Ensure that you configure Environment Variables for JAVA_HOME, ANT_HOME.
  • Ensure that in Environment Variables, you configure the PATH with the installation folder for Python.

Keep the jar/aar libraries ready for which you want to write NFI code. You can generate these jar/aar files using any IDE.

The .aar file will help in binding the other resources that are required in the project for the native framework to run correctly.

  1. Navigate the MKModule folder in the tool you downloaded from Temenos.
    ../nativeframeworks/android/mkmodule
  2. Open whitelist.txt file.
    This file should contain the list of packages in the library of which you want to generate documentation and Intellisence.
  3. In the file, remove all other entries and add the src file path in it. Retain the path after src till your module name.
    For example, if the src path was NFI\src\com\example\nfilibrary, where Example is the Android project name, and NFILibrary is the module name, retain the path \com\example\nfilibrary
  4. Replace the slash with .(period), for example, com.example.nfilibrary.
  5. Save the whitelist text file and close it.
  6. Open the build.xml with a text editor.
  7. For the key <target name="run-docgen">, make the following entry for <ar line =
    <arg line='/c "python mkmodule.py -mn "Test" -mv "1.1" -md "Test" -av "4.0" -wl whitelist.txt –sp “D:\TestProject\src” -tp "D:\ TestProject \build\JARlibrary.jar""' />
    The command contains eight parts. For information on the command options, click here.
  8. Make the required changes to the build.xml file and close it.
  9. Navigate the MKModule folder in the tool you downloaded from Temenos.
    For example, .../nativeframeworks/android/mkmodule
  10. In the File Explorer in the file path, type CMD.
    The Command prompt opens.
  11. Execute the command ant -f build.xml.
  12. The native bindings will be generated, and the module can be found in the path
    .../nativeframeworks/android/mkmodule/dist
    You will find both unzipped and zipped files in the folder. The generated documentation is available in the dist/documentation folder for the packages you have given in whitelist.txt file.
  13. Open Visualizer, using the Import a third-party library feature, import the .zip file into the project and use the classes as required.

Command Options

The following table explains each one of the commands that are used in this code.

Command option NameDescription
-mnModule nameName of self-sufficient module. This is the name by which the bindings are generated.
-mvModule versionVersion of self-sufficient module
-mdModule descriptionDescription of self-sufficient module
-spSource files locationAbsolute path source files
-tpThird-party sourcesThird-party library location
-tpdDirectory of the Third-party sourcesLocation of the third-party directory