2

I'm pretty new to integrating Android NDK. I'm trying to return different text while calling a native function to my main app. I have two build types - release and debug. How do I send different strings to my main app for different build types?

Below is the code :

native-lib.cpp

extern "C"
JNIEXPORT jstring JNICALL
Java_test_main_MainActivity_getStringFromJNI(JNIEnv *env, jobject thiz) {
    std::string stringToBeReturned = "Hello";
    return env->NewStringUTF(stringToBeReturned.c_str());
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )
find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )
target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib})

I'd like to get the build type in the native-lib.cpp so that I can change the value of stringToBeReturned depending upon the build type. Kindly help.

Kavach Chandra
  • 770
  • 1
  • 10
  • 25
  • 2
    See https://stackoverflow.com/questions/44084950/set-android-mk-flag-through-gradle-depending-on-build-type/44108432#44108432 Same principle, except you'd use `cmake` instead of `ndkBuild`, and you might have to use `cppFlags` instead of `cFlags`. – Michael Apr 26 '21 at 06:00
  • how do I get the value of flags in the cpp file? – Kavach Chandra Apr 26 '21 at 13:15
  • 1
    Either use `#ifdef` to initialize the string to different values based on whether a flag is set, or use something like https://stackoverflow.com/questions/46771588/read-build-arguments-from-ndk-code/46774983#46774983 – Michael Apr 26 '21 at 13:23

2 Answers2

2

add to CMakeLists.txt:

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions("-DMY_DEBUG")
else(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions("-DMY_RELEASE")
endif(CMAKE_BUILD_TYPE STREQUAL "Debug")

after that you can use #ifdef in your code

another option is to pass arguments to build from gradle script

debug {
   externalNativeBuild {
       cmake {
           arguments "-DMY_DEBUG
        }
    }
}
Boris
  • 196
  • 3
0

So I was able to achieve what I wanted with the help of the suggestions in the comment section as below:

I started by adding my build.gradle while at module level.

{
defaultConfig
   ...
   ...
   ...
   //other properties
  externalNativeBuild{
            cmake{
                cppFlags "-DBUILD_TYPE=debug"
            }
        }
}

buildTypes {
        release {
           ...
           ...
           //other properties
            externalNativeBuild{
                cmake{
                    cppFlags "-DBUILD_TYPE=release"
                }
            }
        }
}

Here, BUILD_TYPE is the name of the variable being passed and debug and release are it value for different build types.

Then in my native-lib.cpp, I applied the following code:

#define xstr(s) str(s) //important header
#define str(s) #s //important header
extern "C"
JNIEXPORT jstring JNICALL
Java_test_main_MainActivity_getStringFromJNI(JNIEnv *env, jobject thiz) {
    std::string stringToBeReturned;
    std::string build_type = xstr(BUILD_TYPE); //get the value of the variable from grade.build
    if(build_type=="debug"){
      stringToBeReturned = "Yay!! String returned from debug variant!"
    }else if(build_type=="release"){
      stringToBeReturned = "Yay!! String returned from release variant!"
    }
    return env->NewStringUTF(stringToBeReturned.c_str());
}
Kavach Chandra
  • 770
  • 1
  • 10
  • 25