Execute Native executable on Android

Budhdi Sharma
Android Champ
Published in
4 min readApr 8, 2024

The Android platform has evolved tremendously over the years, offering developers an increasingly robust and versatile ecosystem for building innovative applications. While the Android framework primarily focuses on Java and Kotlin as the primary programming languages, the platform also provides the ability to leverage native code written in languages such as C and C++.

Incorporating native C/C++ code into Android applications can bring significant benefits, including:

  1. Performance Optimisation: Native code can offer superior performance compared to Java/Kotlin, especially for computationally intensive tasks or low-level hardware interactions.
  2. Hardware Integration: Native code allows direct access to the device’s underlying hardware, enabling you to leverage features and capabilities that may not be easily accessible through the standard Android APIs.
  3. Legacy Library Integration: Many established C/C++ libraries and frameworks can be integrated into Android apps, allowing you to leverage existing codebases and expertise.
  4. Platform-Specific Optimizations: Native code can be tailored and optimized for specific Android hardware architectures, such as ARM or x86, to achieve maximum efficiency.

Despite these advantages, compiling and executing C/C++ executable programs on the Android platform requires a specific set of steps and considerations. In this article, we’ll guide you through the basic process, ensuring you have the necessary knowledge to harness the power of native code and seamlessly integrate it into your Android applications.

Writing the C/C++ Code

First the you can now start writing your native C/C++ code. Here’s a simple “Hello Print” example(main.cpp) in C++:

#include <iostream>
int main() {
for (int i = 0; i < 10; ++i)
std::cout << "Hello................ " << std::endl;
return 0;
}

Compiling C/C++ Code on Android: CMake and the NDK Toolchain

The Android platform typically relies on the CMake build system to call the Android NDK (Native Development Kit) toolchain and compile native C/C++ code. Google provides two main approaches to support this integration:

  1. Built-in Support of CMake:
  • This method requires CMake version 3.21 or newer, as well as an Android NDK version greater than r23.
  • This approach is considered the mainstream direction for the future, as it provides built-in support for compiling native code on Android.

2. Tool-chain File Support:

  • This is the current mainstream approach and is the method used by the Android Gradle plugin.
  • It involves leveraging a specific toolchain file provided by the Android NDK to configure the build process.

The Android Gradle plugin uses the NDK toolchain file approach, making it the more widely-used and well-documented option for most Android developers working with native C/C++ code.

In the following sections, we’ll explore the steps for writing the CMakeLists.txt file and setting up the build environment using the Toolchain File Support approach.

Configuring the CMake Build

The first step in the compilation process is to create a CMakeLists.txt file that defines the build configuration for your native C/C++ code. Here's an example:

cmake_minimum_required(VERSION 3.0)
project(main)
add_executable(${PROJECT_NAME} main.cpp)

This CMake configuration file sets the minimum required CMake version to 3.0, defines the project name as “main,” and adds an executable target using the main.cpp source file.

Building the Native Code with the Toolchain File Support

With the CMakeLists.txt file in place, you can now create a compilation script, such as build.sh, to automate the build process. Here's an example:

export ANDROID_NDK=/path/to/your/android/ndk

rm -r build
mkdir build && cd build

# Toolchain File Support
cmake \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=x86_64 \
-DANDROID_PLATFORM=android-29 \
-DANDROID_STL=c++_shared \
..

cmake --build .

This script first sets the ANDROID_NDK environment variable to the path of your Android NDK installation. It then removes any existing build directory, creates a new one, and changes to the build directory.

The key part of this script is the CMake command that uses the Toolchain File Support approach. It specifies the following parameters:

  • DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake: Tells CMake to use the Android NDK's toolchain file for the build configuration.
  • -DANDROID_ABI=x86_64: Sets the target Android ABI (Application Binary Interface) to x86_64.
  • -DANDROID_PLATFORM=android-29: Specifies the target Android platform version as API level 29.
  • -DANDROID_STL=c++_shared: Selects the C++ standard library to use (in this case, the shared version of the C++ standard library).

Finally, the cmake --build . command executes the build process, generating the native executable.

Executing the Program on the Simulator

To run the compiled C/C++ executable on the Android simulator, you’ll need to perform the following steps:

# Compile the program
chmod +x build.sh
./build.sh
# Open the emulator, steps omitted
# Upload the executable file
adb push build/test /data/local/tmp
# Upload the STL dynamic library
adb push /path/to/your/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so /data/local/tmp
# Enter the emulator shell
adb shell
# Execute the program
cd /data/local/tmp
export LD_LIBRARY_PATH=/data/local/tmp && ./test
  1. Make the build.sh script executable: chmod +x build.sh
  2. Run the build.sh script to compile the program.
  3. Push the compiled executable (test) to the /data/local/tmp directory on the Android emulator or device using adb push.
  4. Push the C++ standard library dynamic library (libc++_shared.so) to the same directory using adb push.
  5. Open an ADB (Android Debug Bridge) shell on the emulator or device.
  6. Navigate to the /data/local/tmp directory and run the executable, setting the LD_LIBRARY_PATH environment variable to include the directory where the C++ standard library is located.

By following these steps, you can successfully compile and execute your C/C++ executable program on the Android platform, leveraging the power of native code within your Android applications.

--

--

Budhdi Sharma
Android Champ

As an AOSP developer, I specialize in creating robust framework and system applications that seamlessly integrate with embedded systems on various SOCs