Cross-Compiling Android Shared Libraries Using CMake
Building an Android Shared Library with CMake
CMake can produce .so binaries for Android using either the NDK via dedicated variables or the provided toolchain file. Both approaches require an NDK installation. The following sections describe minimal configurations.
1. Configuring with NDK Variables
When using NDK variables, essential cross‑compilation settings must appear before the project() command. An example CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
# --- Android NDK cross-compilation (must precede project()) ---
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 21) # API level (e.g., 21 for Android 5.0)
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a) # target ABI
set(CMAKE_ANDROID_NDK /path/to/ndk/25.1.8937393)
set(CMAKE_MAKE_PROGRAM /path/to/cmake/3.22.1/bin/ninja)
set(CMAKE_ANDROID_STL_TYPE c++_shared) # STL runtime (c++_static also possible)
set(CMAKE_EXPORT_COMPILE_COMMANDS OFF)
project(my_native_lib)
# Build a shared library from source files
add_library(native_code SHARED
src/helper.cpp
src/main.cpp
)
target_include_directories(native_code PRIVATE include)
CMAKE_SYSTEM_NAMEmust beAndroid.CMAKE_SYSTEM_VERSIONselects the API level; use a value matching yourminSdkVersion.CMAKE_ANDROID_ARCH_ABIcan bearm64-v8a,armeabi-v7a,x86,x86_64etc.CMAKE_ANDROID_NDKis the root of the NDK insatllation.CMAKE_MAKE_PROGRAMpoints toninja(recommended). If it is absent, CMake picks a default generator; you may need to pass-G Ninjaexplicitly.
After configuraton and build, the resulting .so appears in the build tree (e.g., build/ or a subdirectory named after the ABI if CMAKE_LIBRARY_OUTPUT_DIRECTORY is not set).
2. Using the Official Toolchain File
A simpler alternative is to let CMake use the NDK’s built‑in android.toolchain.cmake. This file automatically sets CMAKE_SYSTEM_NAME, CMAKE_SYSTEM_VERSION, CMAKE_ANDROID_NDK, and other parameters passed through -D flags or environment variables.
Example invocation from the command line:
cmake -S . -B build \\
-DCMAKE_TOOLCHAIN_FILE=/path/to/ndk/build/cmake/android.toolchain.cmake \\
-DANDROID_ABI=arm64-v8a \\
-DANDROID_PLATFORM=android-21 \\
-G Ninja
Inside your CMakeLists.txt you can optionally set the toolchain file, again before project():
cmake_minimum_required(VERSION 3.16)
set(CMAKE_TOOLCHAIN_FILE /path/to/ndk/build/cmake/android.toolchain.cmake)
# Optionally fix the ABI and API:
set(ANDROID_ABI arm64-v8a)
set(ANDROID_PLATFORM android-21)
project(my_native_lib)
add_library(native_code SHARED src/main.cpp)
When CMAKE_TOOLCHAIN_FILE is set, the other Android‑specific variables (CMAKE_ANDROID_NDK, CMAKE_SYSTEM_NAME, etc.) are populated automatically.
Notes
- The NDK version must match the toolchain file; mixing versions can cause build errors.
- For multi‑ABI builds, invoke CMake once per ABI (e.g.,
arm64-v8aandarmeabi-v7a) or use a scripting wrapper. - If the build fails with STL errors, ensure
CMAKE_ANDROID_STL_TYPEor the equivalent-DANDROID_STL=c++_sharedmatches the required C++ runtime. - After compilation, the shared library can be integrated into a Android project’s
jniLibsfolder under the appropriate ABI directory.