Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
BlackBerry Development Advisor
russellandrade
Posts: 19
Registered: ‎03-18-2012
My Device: Blackberry Z10
My Carrier: Rogers

Using the new NDK versioning macros to detect API versions

[ Edited ]

HI folks

There have been a few questions from our community about how to handle different API versions in your application and I thought this is an important enough topic to address in the forums as well. For example let us say you are building an app that is intended to run on both 10.0 and 10.1 targets, but you do have some version specific logic embedded in it.  For example you want to use an 10.1 API but still have the same codebase compile successfully on 10.0.  One way to do this is to have separate copies of your app for each stream.  However this can start to get unwieldy and add additional complexity to your workflow.  There is another way to do this with the versioning macros we are adding in 10.1.  This post is to walk you through how you can use this platform versioning support for handling code branches within your app.

I should first preface this post by saying that for many developers this will be a non-issue.  Many 10.0 apps will not require changes in their code or logic to work on 10.1 so you can ignore this post.  However if you need to make 10.1 specific changes continue reading.

The versioning defines and macros are added in a new header we have defined called 'bbndk.h'.  This header provides defines for the major and minor version numbers and will be kept up to date accordingly as we introduce new NDK versions.  Here are some of the useful defines you can leverage in these headers to determine API version.

 

/**

 * @brief Check whether the BlackBerry Native SDK is the given version or

 * higher.

 *

 * The @c BBNDK_VERSION_AT_LEAST() macro checks whether the BlackBerry Native

 * SDK is the given version or higher.  For example, to conditionally compile

 * some code only if building with BlackBerry Native SDK 10.1.0 or higher, use:

 *

 * @param major The major number of the version to check.

 * @param minor The minor number of the version to check.

 * @param patch The patch number of the version to check.

 *

 * @return true if the current version of the BlackBerry Native SDK is the same

 * or greater than the given version, else false.

 *

 * @since BlackBerry 10.1.0

 */

#define BBNDK_VERSION_AT_LEAST(major, minor, patch) \

    (BBNDK_VERSION_CURRENT >= BBNDK_VERSION_ENCODE(major, minor, patch)) 

 

For example for 10.1 which is our latest NDK release, the check BBNDK_VERSION_AT_LEAST(10,1,0)  should return TRUE.

We only added bbndk.h in 10.1 however so you would still experience some challenges if you needed to detect betwene 10.0 and 10.1 in your app.  You can’t just include bbndk.h in your app as the app would not compile on 10.0 and you are still back to square one.  To remedy this issue, we will be adding bbndk.h into bps.h in a soon to appear 10.1 target update.  By doing this, it means you don’t have to include bbndk directly in your source code as it is likely already included indirectly.  If you are writing a game, you likely already include bps.h directly in your code which means you get access to the macros in bbndk as well.  If you are developing a Cascades UI framework app, bps.h is included indirectly since all Cascades UI framework apps derive from bb::cascades::Application which in turn derives from bb::Application which in turn includes bps.h.  Adding this in bps.h should therefore cover a majority of the existing BlackBerry 10 based native applications.  

Once we make this change you can check for the presence of the versioning macros to determine if the code is being compiled on a 10.0 target, a 10.1 target or any target after 10.1.  As an example the following logic can help you select between 10.0 and 10.1 :

 

#ifdef BBNDK_VERSION_AT_LEAST

#if BBNDK_VERSION_AT_LEAST(10,_X_,0) 

  //add your logic for release 10.X here where _X_ is the number

   //of a new release 

  

#elif BBNDK_VERSION_AT_LEAST(10,1,0)

   //add your 10.1 logic here 

#endif

#else

// add your 10.0 logic here

#endif

 

Since BBNDK_ BBNDK_VERSION_AT_LEAST is not defined in 10.0, the #else clause handles the 10.0 case.  Moving forward though since BBNDK_VERSION_AT_LEAST will be defined on 10.1 and newer releases, you can check for the explicit value of the major and minor release numbers to handle logic for releases 10.1 and above as seen in the code snippet. 

 

While bbndk.h is currently available in our 10.1 gold release, we haven’t made the change yet to add bbndk.h to bps.h.  We plan to add that in a subsequent 10.1 target  update.  I will send out an update to this thread once that change has been made.  If you do intend on using these defines to distinguish between 10.0 and 10.1 releases, you should make sure to rebase your app off that new 10.1 target that introduces this change.  This is to ensure that the #ifdef BBNDK_VERSION_AT_LEAST check returns TRUE on the 10.1 target.

 

Hope this helps.

Russell Andrade
Senior Product Manager, Native SDK
Twitter : @russell_andrade
Please use plain text.
Developer
step_jac
Posts: 89
Registered: ‎05-31-2012
My Device: BlackBerry Playbook
My Carrier: Bell

Re: Using the new NDK versioning macros to detect API versions

Thanks for the post Russell!

 

Wish this had been available during the PBOS 2.0 release.

Can you confirm weak linking of system libs at runtime?

 

For example:

    if( RuntimeOSVersion() == BB_10_1 )

    {

         OS101API();

    }

    else if( RuntimeOSVersion() == BB_10_0 )

    {

         OS100FallbackAPI();

    }

    else // PBOS

    {

         PBOSFallbackAPI();        

    }

 

where the function calls presumably lie in system SOs.

 

This would allow us to have single binaries across all devices, which would be great for our workflow.

 

Thanks!

 

Stephane

Please use plain text.
BlackBerry Development Advisor
smcveigh
Posts: 666
Registered: ‎11-29-2011
My Device: developer
My Carrier: other

Re: Using the new NDK versioning macros to detect API versions

unfortunately, in C/C++, code like this (assuming you've got a RuntimeOSVersion() function):

 

if (RuntimeOSVersion() == BB_10_1) {
    OS101API();
} else {
    OtherAPI();
}

Will simply fail to load, as the symbols for OS101API() will not be found.

 

One possible approach would be to separate out your code which depends on OS101API() and OtherAPI() into 2 .so files.  eg.  myFunctions101.so  and myFunctionsOther.so

 

Then your code would do something like:

if (RuntimeOSVersion() == BB_10_1) {
    handle = dlopen("myFunctions101.so", RTLD_NOW);
} else {
    handle = dlopen("myFunctionsOther.so", RTLD_NOW);
}
doSomethingFptr = dlsym(handle, "doSomething");
doSomethingElseFptr = dlsym(handle, "doSomethingElse"); ...

Where doSomething() and doSomethingElse() are 2 functions your app needs to do which may have differing implementations based on the compile-time NDK version.

 

Cheers,

Sean

Please use plain text.
Developer
step_jac
Posts: 89
Registered: ‎05-31-2012
My Device: BlackBerry Playbook
My Carrier: Bell

Re: Using the new NDK versioning macros to detect API versions

Thanks Sean,

 

That should work beautifully. Completely escaped me to use user SOs. Just package these up as BAR assets I assume? is /app/native added to the dlopen search path and proper permissions set on the SO when the app is installed from AppWorld?

 

However, I guess we'll still need to deal with the fact that SDK 10 built BARs can't be deployed to Playbook.

 

Best,

 

Stephane

Please use plain text.
BlackBerry Development Advisor
smcveigh
Posts: 666
Registered: ‎11-29-2011
My Device: developer
My Carrier: other

Re: Using the new NDK versioning macros to detect API versions

See the docs for dlopen()...

https://developer.blackberry.com/native/reference/bb10/com.qnx.doc.neutrino.lib_ref/topic/d/dlopen.h...

They call out that you will need to explicitly use procmgr_ability() to grant your app the "PROCMGR_AID_PROT_EXEC" ability.  There are plenty of example usages in the docs.

 

As for paths, LD_LIBRARY_PATH will be searched.. it may include appropriate local paths in your app's directory.  Worst case - you can assemble a path to your lib.

 

Cheers,

Sean

Please use plain text.
BlackBerry Development Advisor
jhoffmann
Posts: 38
Registered: ‎10-26-2011
My Device: BlackBerry Bold 9900
My Carrier: Rogers

Re: Using the new NDK versioning macros to detect API versions

There should be a line in the bar-descriptor.xml that sets the LD_LIBRARY_PATH to app/native/lib, e.g.:

 

<env var="LD_LIBRARY_PATH" value="app/native/lib"/>

So you install your libraries as assets like:

 

<asset path="local/path/to/libMyLib.so" type="Qnx/Elf">lib/libMyLib.so</asset>

Please use plain text.
Developer
dkonigs
Posts: 243
Registered: ‎07-25-2008
My Device: Bold 9900

Re: Using the new NDK versioning macros to detect API versions

So there's one other version-detection case that this solution doesn't cover.  Build configuration.  Specifically, I want to be able to detect the NDK version from within my qmake (.pro, .pri) files.  This is so I can include/exclude libraries and source files depending on the NDK version.

 

I've noticed that the full version is embedded in both the QNX_TARGET_VERSION and QNX_TARGET environment variables, but only the latter is defined when in Momentics.  Regardless, using some hacky qmake foo, I've been able to parse/split the data out of these.

 

However, a simple and official solution would by far be preferable.

Please use plain text.
Developer
blackqtcoder
Posts: 145
Registered: ‎05-18-2012
My Device: PlayBook & STL100-1 LE Z10 & Dev Alpha C
My Carrier: Telefonica Spain

Re: Using the new NDK versioning macros to detect API versions

Will be possible to filter NDK versions through QML code?
Thanks
---------------------------------------------------------------
Leandro Cerdan - Duantox Apps
BlackBerry Elite dev
TapyHold, Built for Blackberry multimedia scrapbook
Please use plain text.
Developer
dkonigs
Posts: 243
Registered: ‎07-25-2008
My Device: Bold 9900

Re: Using the new NDK versioning macros to detect API versions

I'd like an answer to this as well.

 

For now, we can kludge around it by using the static asset selector.  Any QML files that are in static asset selector subdirectories will be seen on 10.1, and ignored on 10.0.  Of course this doesn't solve the future 10.1 -> 10.2 problem we're going to face.

Please use plain text.
BlackBerry Development Advisor
russellandrade
Posts: 19
Registered: ‎03-18-2012
My Device: Blackberry Z10
My Carrier: Rogers

Re: Using the new NDK versioning macros to detect API versions

We are looking into the issues of supporting versioning in QML as well as makefiles.  We likely won't be able to add that support to the 10.1 release but it is definitely under consideration for the next release.

Russell Andrade
Senior Product Manager, Native SDK
Twitter : @russell_andrade
Please use plain text.