Cmake 学習記録 (9) -- Cmake を使用して Android .so ライブラリをクロスコンパイルする

I.はじめに

現時点では、Android Studio を使用して Android 用の .so をコンパイルするのは比較的簡単ですが、場合によっては Android Studio 用の Android プロジェクトを作成する必要があります。ここでは、Android Studio なしで Cmake および C++ 開発ツール Clion を使用できることが記録されています (または他の開発ツール。これらの開発ツールは Android Studio と同じではなく、どのツールでも使用できます)。
実際、.so をコンパイルするもっと簡単な方法があります。たとえば、cmake を使用して C++ プロジェクトを Linux 環境で直接コンパイルすることができ、この時点で .so ライブラリが表示されます。ただし、開発環境が Mac または Windows の場合、目的のファイルではない dylib または exe ファイルが生成されるため、クロスコンパイル技術を使用する必要があります。
Cmake は、Android .so ファイルをコンパイルする 2 つの方法、NDKまたはクロス ツールチェーンを提供します。私は Android 開発に携わっているため、既製の NDK 依存関係があり、クロスコンパイル チェーンをダウンロードする必要があります。なのでコンパイルにはNDKを使っていますが、おそらくこれに従って修正することも可能です。後日、時間があるときにクロスツールチェーンを使ったコンパイル方法を記録していきます。
プロジェクトがごちゃごちゃしているので後で整理しますが、 NDK
を使うクロスツールチェーンを使うかに関わらずNDKとの関連付けが必要で、NDKなしで.soをコンパイルしても問題ありません。

2. NDK を使用してコンパイルされた関連コード

開発ツールは CLion です。Android Studio と CLion の両方が ninja ビルド システムを使用していることに注意してください。他のビルド システムを使用している場合は、それを変更する必要がありますが、記事内のコードには既にこのコードが含まれており、そのまま使用できます。プロジェクト全体の構造は次のとおりです
:
ここに画像の説明を挿入
コア コードは次のとおりです:
コードの設定部分はproject(untitled VERSION 1.0)関数呼び出しの前に記述する必要があることに注意してください

# control where the static and shared libraries are built so that on windows
# we don't need to tinker with the path to run the executable
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 21) # API level
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a)
set(CMAKE_ANDROID_NDK /Users/c/Documents/sdk/android/ndk/25.1.8937393)
#set(CMAKE_TOOLCHAIN_FILE /Users/c/Documents/sdk/android/ndk/25.1.8937393/build/cmake/android.toolchain.cmake)
set(CMAKE_MAKE_PROGRAM /Users/c/Documents/sdk/android/cmake/3.22.1/bin/ninja)
#set(CMAKE_ANDROID_STL_TYPE gnustl_static) # 需要注意的是NDK不支持这个属性,可能是NDK版本原因,所以使用c++_shared,
set(CMAKE_ANDROID_STL_TYPE c++_shared)
set(CMAKE_EXPORT_COMPILE_COMMANDS NO)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")

aux_source_directory(. SRC_LIST) #把当前目录(.)下所有源代码文件和头文件加入变量SRC_LIST
#ADD_EXECUTABLE(hello ${SRC_LIST}) #生成应用程序 hello (在windows下会自动生成hello.exe)

# 将相关文件添加到SqrtLibrary库 ,最终编译成共享库 .so
add_library(SqrtLibrary SHARED
        ${SRC_LIST}
        )

CMakeLists.txt

cmake_minimum_required(VERSION 3.23) # 这是Cmake版本

#======这一段来自Android开发者平台:https://developer.android.google.cn/ndk/guides/cmake?hl=zh-cn#using_prebuilt_libraries 
#-DCMAKE_FIND_ROOT_PATH=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/.cxx/cmake/universalDebug/prefab/armeabi-v7a/prefab
#-DCMAKE_BUILD_TYPE=Debug
#-DCMAKE_TOOLCHAIN_FILE=${HOME}/Android/Sdk/ndk/22.1.7171670/build/cmake/android.toolchain.cmake
#-DANDROID_ABI=armeabi-v7a
#-DANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670
#-DANDROID_PLATFORM=android-23
#-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a
#-DCMAKE_ANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670
#-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
#-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a
#-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a
#-DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.10.2.4988404/bin/ninja
#-DCMAKE_SYSTEM_NAME=Android
#-DCMAKE_SYSTEM_VERSION=23

#====== end ======


# control where the static and shared libraries are built so that on windows
# we don't need to tinker with the path to run the executable
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 21) # API level
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a)
set(CMAKE_ANDROID_NDK /Users/c/Documents/sdk/android/ndk/25.1.8937393)
set(CMAKE_MAKE_PROGRAM /Users/c/Documents/sdk/android/cmake/3.22.1/bin/ninja)
#set(CMAKE_ANDROID_STL_TYPE gnustl_static) # 需要注意的是NDK不支持这个属性,可能是NDK版本原因,所以使用c++_shared,
set(CMAKE_ANDROID_STL_TYPE c++_shared)
set(CMAKE_EXPORT_COMPILE_COMMANDS NO)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")

project(untitled VERSION 1.0)

add_subdirectory(libscanner)
configure_file(square.h.in square.h)

# specify the C++ standard
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)


# 通过BUILD_SHARED_LIBS 创建共享库,后面值需要设置为ON,
# 这个属性写到这里,如果libscanner使用这个值的话有时候会报找不到的错误,如果经过反复Build后无法解决,将该属性写到相关的libscanner的CMakeLists.txt。但是这样的话最终rebuld后只会生成libscanner的.so。不过这也是预想的情况本身顶层目录也没有要求生成.so文件
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)

add_executable(untitled square_main.cpp)

target_link_libraries(untitled PUBLIC scanner tutorial_compiler_flags)
target_include_directories(untitled PUBLIC
        "${PROJECT_BINARY_DIR}"
        "${PROJECT_SOURCE_DIR}/libscanner"
        )

# 打印日志
message("---PROJECT_BINARY_DIR--${PROJECT_BINARY_DIR}")
message("---PROJECT_SOURCE_DIR--${PROJECT_SOURCE_DIR}")
message("---libscanner头文件--${PROJECT_SOURCE_DIR}/libscanner")

libscanner/CMakeLists.txt

add_library(scanner scanner.cpp) # 默认编译成静态库
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(scanner
        INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
        )

#add_executable(MakeTable scanner.cpp)
#target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags)
aux_source_directory(. SRC_LIST) #把当前目录(.)下所有源代码文件和头文件加入变量SRC_LIST
#ADD_EXECUTABLE(hello ${SRC_LIST}) #生成应用程序 hello (在windows下会自动生成hello.exe)


# 将相关文件添加到SqrtLibrary库
add_library(SqrtLibrary SHARED
       ${SRC_LIST}
        )


# 文件应该去哪个路径下面查找
target_include_directories(SqrtLibrary PRIVATE
        ${CMAKE_CURRENT_BINARY_DIR}
        )

# 将tutorial_compiler_flags库链接到SqrtLibrary
target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)

# 将SqrtLibrary库链接到libscanner
target_link_libraries(scanner PRIVATE SqrtLibrary)

# 将tutorial_compiler_flags库链接到libscanner
target_link_libraries(scanner PUBLIC tutorial_compiler_flags)


message("YM--->${BUILD_SHARED_LIBS}")

# state that SqrtLibrary need PIC when the default is shared libraries
set_target_properties(SqrtLibrary PROPERTIES
        POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
        )

書き込み後に再ビルドすると、ビルドフォルダー内に生成された.soライブラリが見つかります。

4 番目に、クロス ツール チェーンを使用してコンパイルします。

クロスツールチェーンを使用すると、上記の方法に比べてコンパイル時のコード変更は1行だけとなり、NDK r-19の新バージョン以降の変更により、より使いやすくなりました。CMAKE_TOOLCHAIN_FILE プロパティを指定するだけです

#set(CMAKE_ANDROID_NDK /Users/c/Documents/sdk/android/ndk/25.1.8937393)
set(CMAKE_TOOLCHAIN_FILE /Users/c/Documents/sdk/android/ndk/25.1.8937393/build/cmake/android.toolchain.cmake)

4. 参考リンク

  1. Android 公式 Web サイトの CMake の概要
  2. CMake を使用した NDK プログラムのコンパイルについての深い理解
  3. cmake ツールチェーン(7)
  4. アンドロイド/ndk-サンプル
  5. CMAKE は Linux 上で Android のコンパイル、パッケージ化、リリース環境を構築します
  6. Android クロスコンパイル用の共通ライブラリ (cmake)
  7. 10. NDKクロスコンパイル時の注意事項
  8. cmake:add_libraryの詳細な説明

おすすめ

転載: blog.csdn.net/Mr_Tony/article/details/130956210