1. ホーム
  2. Android Studio

Android Studio NDK CMakeの事例とso出力パスの指定と複数sosの生成のまとめ

2022-02-26 07:39:46
<パス

##前

注:この記事の構成はすべてmacコンピュータでのものです。
Android Studioの新しい方法であるCmakeを使ってJNIコードをコンパイルしようと、以前にも試したことがあるのですが、次の2つの課題が立ちはだかりました。

  1. soライブラリは1つしか生成できない、複数のsoライブラリを一度に生成できない、以前のmkはサブモジュールを持つことができた。
  2. 生成された各soがあるディレクトリがjniLibsの下にない、パッケージ化すれば入っているのはわかるが、どうしても見えない、他の人に提供しようと思うとどこかのディレクトリに探しに行かなければならない気がする。

試してみると、この2つの問題は解決することができます。

2020年1月6日追記

Androidプロジェクトにサードパーティ製のsoライブラリがあり、以下のcmakeで出力ディレクトリをjniLibs以下に指定してjniをコンパイルした場合、soライブラリの重複エラーが発生する可能性があるため、ご注意ください。
以下の方法で、エラーを回避してください。

android {
 			..........
 		packagingOptions {
        	//resolve AS bugs. Prefer so libraries under JNILIBS
        	pickFirst 'lib/arm64-v8a/libDriver.so'
        	pickFirst 'lib/armeabi/libDriver.so'
        	pickFirst 'lib/armeabi-v7a/libDriver.so'
   		}
}


1つのsoを生成する例

デモのダウンロードはこちら: http://download.csdn.net/detail/b2259909/9766081

CMakeLists.txt ファイルを直接見てください。

# Specify the minimum version of CMAKE required
cmake_minimum_required(VERSION 3.4.1)


#C compilation option is CMAKE_C_FLAGS
# Specify compilation parameters, optional
SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

# Set the path to the last output of the generated so dynamic library
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/... /jniLibs/${ANDROID_ABI})

# Set header file search path (no need to set the header file in the same path as this txt), optional
#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common)

#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common), optional.
#LINK_DIRECTORIES(/usr/local/lib)


add_library( native-lib
             SHARED
             src/main/cpp/native-lib.cpp )

target_link_libraries( native-lib
                       log )


には、各設定が記述されています。主にこれを見てください。

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/. /jniLibs/${ANDROID_ABI})


生成されたsoライブラリは、build.gradleで指定したabiに従ってjniLibsの下に配置されます。

非常に良い、2番目の問題を最初に解決した。


複数のソケースを生成する

上記と同じデモで、モジュールを再構築します。

cppのディレクトリ構造です。


CMakeLists.txt ファイルを直接見てください。

# Specify the minimum version of CMAKE required
cmake_minimum_required(VERSION 3.4.1)


#C compilation option is CMAKE_C_FLAGS
# Specify compilation parameters, optional
SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

# Set the path to the last output of the generated so dynamic library
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/... /jniLibs/${ANDROID_ABI})

# Set header file search path (no need to set the header file in the same path as this txt), optional
#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common)

#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common), optional.
#LINK_DIRECTORIES(/usr/local/lib)


#Add subdirectory, will call CMakeLists.txt in the subdirectory
ADD_SUBDIRECTORY(one)
ADD_SUBDIRECTORY(two)


違いは、サブディレクトリを追加するのではなく

#Adding a subdirectory will call CMakeLists.txt in the subdirectory
ADD_SUBDIRECTORY(one)
ADD_SUBDIRECTORY(two)


これは、サブディレクトリにあるCmakeLists.txt for one and twoを先に実行し、正常に実行されて戻ってきます。
この時点で、サブディレクトリ1のCmakeLists.txtは。

#The variables in CMakeLists.txt that are inherited from the previous level can also be reassigned here
#C compile option is CMAKE_C_FLAGS
#Specify compilation parameters, optional
#SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#Generate so dynamic library
ADD_LIBRARY(one-lib SHARED one.cpp)

target_link_libraries(one-lib log)


サブディレクトリ2にあるCmakeLists.txt。

#Inherit variables from CMakeLists.txt from the previous level, which can also be reassigned here
#C compile option is CMAKE_C_FLAGS
#Specify compilation parameters, optional
#SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#Generate so dynamic library
ADD_LIBRARY(two-lib SHARED two.cpp)

target_link_libraries(two-lib log)


以下の2つのsoファイルが生成され、abiに従ってjniLibsの下に自動的に配置されます。

最初の質問もうまくいきました。

概要

最後に、abiFiltersの設定に加えて、build.gradleで設定する必要があります。
メインはCmakeLists.txtで、実はいろいろと指定できるんです。

  1. ということで、出力パス cmake_library_output_directory。
  2. .a 静的ライブラリの出力パス cmake_archive_output_directory。
  3. 現在コンパイルされている abi を取得します。 ANDROID_ABI
  4. コンパイルオプションです。
    CMAKE_C_FLAGS
    cmake_cxx_flags
    cmake_cxx_flags_debug/cmake_cxx_flags_release
  5. サブディレクトリのコンパイル。 add_subdirectory
  6. # .c ファイルコレクション用の変数を設定する
#All .c .cpp source files in the directory where the current cmakelists.txt is located
AUX_SOURCE_DIRECTORY(. SRC_LIST)

#Add source files from other directories to the collection variable
list(APPEND SRC_LIST
        ... /common/1.c
        ... /common/2.c
        ... /common/3.c
        ... /common/4.c
        ... /common/5.c
        ... /common/WriteLog.c
    )

# Generate the so library, using variables directly to represent those .c file collections
add_library(mylib SHARED ${SRC_LIST})


6._カスタムコマンドを実行する。

# copy header files to the same folder as the static library
add_custom_command(TARGET myjni
  PRE_BUILD
  COMMAND echo "executing a copy command"
  COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/myjni.h ${PROJECT_SOURCE_DIR}/... /... /... /build/outputs/staticLib/myjni/${ANDROID_ABI}
  COMMENT "PRE_BUILD, so This command will be executed before building target myjni"
 )



最後に、多くの場合、JNIパラメータは、Cに変換する必要があるため、我々はJAVAレイヤでネイティブメソッドを書くときに、アンドロイドIDEは自動的に赤を求める、その後、ALT + ENTERキーは自動的にJNIの下でメソッドの宣言を生成することができ、入力パラメータも我々のために変換されています。しかし、時々このプラグインが動作しないことがあります。

そこで、JNIの入力をC/C++のコードに変換するプラグインを書きました。JNI-Convert-Varは、プラグインリポジトリから直接入手できます。
最近、android studioのALT + ENTERでJNI下のメソッド宣言を自動生成する機能を実装しようとしたところ、IntelliJ IDEAのインターフェースには不慣れなものが多いことがわかりました。とりあえずあきらめるしかなかった。以下、私のロジックです。

Native宣言メソッド上でマウスをクリックした場合。

  1. ファイルの種類を確認し、javaであれば続行する
  2. ネイティブ宣言のフルメソッドを正規表現で取得し、合計3行の文字列データについて、現在の行の先頭と末尾を取得する。
  3. 現在のモジュール・ディレクトリの jni または cpp ディレクトリにある .c または .cpp ファイルをチェックします。
  4. もしファイルがなければ、ポップアップでC/C++ファイルを作成し、変換された(変換方法の特別なクラスがある)Java2Cメソッドをファイルの末尾に追加させることができます。このファイルをIDEで開いてください。
  5. JNIまたはcppディレクトリに複数のC/C++ファイルがある場合、ポップアップでC/C++ファイルを選択または作成し、ファイルを開いて変換された(変換方法の特別クラスがある)Java2Cメソッドをファイルの最後に追加することができます。. このファイルをIDEで開きます。

上のロジックで

  1. ファイルタイプで、IntelliJ IDEAのプラグイン開発APIで利用可能です。
  2. IntelliJ IDEAのプラグイン開発APIで利用可能な、現在の行の文字列データの上下3行を取得します。
  3. モジュールディレクトリのAPIはまだ提供されていません
  4. IDEでC/C++ファイルを開き、どのインターフェイスを使用するか分からない