交叉編譯c++給android呼叫

汗牛充栋發表於2024-10-10

NDK及其作用

NDK(Native Development Kit)是一個由 Google 提供的工具集,用於在 Android 平臺上開發 C++ 或其他本機程式碼。NDK 的主要作用是允許開發人員使用 C、C++ 和其他本機語言編寫程式碼,並將其編譯為能夠在 Android 裝置上執行的本機程式碼(通常是共享庫 .so 檔案)。

NDK 的主要作用:

  1. 本機程式碼開發:NDK 允許開發人員使用 C、C++ 或其他本機語言編寫 Android 應用的部分或全部程式碼。這對於需要高效能運算、直接訪問硬體功能或跨平臺相容性的應用程式非常有用。

  2. 效能最佳化:透過使用本機程式碼,開發人員可以更好地最佳化應用程式的效能,特別是對於需要執行計算密集型任務或需要更高控制權的應用程式。

  3. 複用現有程式碼:NDK 允許開發人員將現有的 C、C++ 程式碼或庫整合到 Android 應用中,這樣可以更好地複用現有的程式碼資產。

  4. 訪問底層硬體:透過本機程式碼,開發人員可以更容易地訪問裝置的底層硬體功能,如相機、感測器等,以及執行更高階別的硬體控制。

  5. 跨平臺相容性:使用 NDK,開發人員可以更輕鬆地將現有的跨平臺 C、C++ 程式碼移植到 Android 平臺,從而實現跨平臺相容性。

  6. 加密和安全性:透過將關鍵部分的程式碼編譯為本機程式碼,可以提高應用程式的安全性,因為本機程式碼更難被逆向工程或篡改。

NDK下載

NDK下載方式有兩種:

  1. 透過官網連結下載對應作業系統的NDK
  2. 筆者另一篇博文(AndroidSDK下載(不透過AndroidStudio))提到的透過命令列工具進行下載

下載後目錄結構大致如下:

├─build
│  ├─cmake
│  │  └─hooks
│  │      ├─post
│  │      └─pre
│  ├─core
│  │  └─toolchains
│  │      ├─aarch64-linux-android-clang
│  │      ├─arm-linux-androideabi-clang
│  │      ├─riscv64-linux-android-clang
│  │      ├─x86-clang
│  │      └─x86_64-clang
│  ├─gmsl
│  └─tools
├─meta
├─prebuilt
│  └─windows-x86_64
├─python-packages
├─shader-tools
│  └─windows-x86_64
├─simpleperf
├─sources
├─toolchains
│  └─llvm
│      └─prebuilt
│          └─windows-x86_64
└─wrap.sh

交叉編譯示例

示例一

opencv編譯

  1. 下載opencv原始碼
  2. 在包含CMakeLists.txt的根目錄中新建編譯目錄build
  3. 開啟build目錄
  4. 執行cmake命令如下:

    cmake -G"Ninja"
    -DCMAKE_ANDROID_NDK="xxx/android-ndk"
    -DCMAKE_MAKE_PROGRAM="xxx/ninja.exe"
    -DCMAKE_TOOLCHAIN_FILE="xxx/android-ndk/build/cmake/android.toolchain.cmake" -DCMAKE_INSTALL_PREFIX="../install"
    -DCMAKE_SYSTEM_NAME="Android"
    -DANDROID_NATIVE_API_LEVEL="25"
    -DANDROID_PLATFORM="android-25"
    -DCMAKE_ANDROID_ARCH_ABI="arm64-v8a"
    -DCMAKE_ANDROID_STL_TYPE="c++_shared"
    -DBUILD_ANDROID_PROJECTS=OFF ..

  5. 其中關鍵的配置CMAKE_ANDROID_NDK用於配置ndk所在目錄,CMAKE_TOOLCHAIN_FILE用於配置工具鏈檔案,此檔案包含了編譯過程中所需的工具、庫、及平臺選項。CMAKE_SYSTEM_NAME告訴cmake編譯的作業系統為android, ANDROID_PLATFORM用於指定與Android SDK匹配的版本,ANDROID_NATIVE_API_LEVEL指定 NDK版本的API級別,CMAKE_ANDROID_ARCH_ABI用於指定cpu架構, 最後-G用於指定構建系統, 由於筆者是在Windows 上編譯, 所以指定了Ninja, Linux一般指定為Unix Makefiles
  6. 由於筆者選擇的構建系統為Ninja, 所以呼叫Ninja開始編譯, 最後透過呼叫Ninja install進行安裝。 與make類似

重要的編譯選項為ANDROID_PLATFORMCMAKE_ANDROID_ARCH_ABICMAKE_TOOLCHAIN_FILE

可根據不同的作業系統選擇不同的構建系統, 如Linux一般為Unix Makefiles, Windows一般為NinjaVisual Studio

示例二

結合vscode編譯一個自己寫的so庫

程式碼的部分就省略了, 主要看關鍵配置CMakePresets.json檔案:

{
    "version": 8,
    "configurePresets": [
        {
            "name": "android compile",
            "displayName": "android compile",
            "description": "Sets Ninja generator, build and install directory",
            "generator": "Ninja",
            "binaryDir": "${sourceDir}/out/build/${presetName}",
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Debug",
                "CMAKE_ANDROID_NDK": "xxx/android-ndk",
                "CMAKE_MAKE_PROGRAM": "xxx/ninja.exe",
                "ANDROID_ABI": "arm64-v8a",
                "ANDROID_PLATFORM": "android-21",
                "CMAKE_ANDROID_STL_TYPE":"c++_shared",
                "CMAKE_TOOLCHAIN_FILE": "xxx/build/cmake/android.toolchain.cmake",
                "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
            }
        }
    ]
}

然後編輯自己的CMakeLists.txt檔案, 與本機編譯(對應交叉編譯)沒什麼不同。

透過CMakePresets.json達到了示例一相同的效果, 只是方式不一樣。 編譯選項都是一樣的。

相關文章