Android NDK开发 Android.mk 转化 CMakeList.txt

编译使用jni有两种构建方式,:

  1. CMake:Android studio新的构建方式,Project Path需要选择CMakeList.txt文件路径,jni会按照这个脚本来进行编译,具体脚本的编写看下面。
  2. ndk-build:老eclipse的构建方式,也就是Android.mk的形式。
    在这里插入图片描述

在这里插入图片描述
编写CMakeList.txt,以及跟Android.mk的对比

1.设置需要设置构建jni所需的CMake的最低版本

cmake_minimum_required(VERSION 3.4.1)

2.设置生成的so动态库最后输出的路径,如果项目的so库不需要给别人使用,也可以不设置,不设置的话会生成在build里面,如果给别人使用,寻找的话还是比较麻烦,所以指定一下路径更方便。

#设置生成的so动态库最后输出的路径,set后面两个参数,
#前面一个是命令,后面是路径。
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
  1. CMAKE_LIBRARY_OUTPUT_DIRECTORY : 指定的命令,用于设置输出的路径
  2. ${PROJECT_SOURCE_DIR} :是指当前路径,也就是CMakeList.txt所在的路径,其实也可以不写,因为默认就是以CMakeList.txt所在的路径为起点。
  3. …/jniLibs: …两个点是回到上一层,一般来说我们都是建个jni文件夹用于放置c文件,CMakeList.txt是在jni文件夹下,也就是回到上一层,存放在jniLib里面。
  4. ${ANDROID_ABI} 会根据架构来生成不同的文件夹放置对应的so文件。
    在这里插入图片描述

3.设置头文件搜索路径,如果跟CMakeLists.txt同路径则不需要设置,同路径下文件夹不行。

#设置头文件搜索路径(和此txt同个路径的头文件无需设置),可选

include_directories(Cipher
                    Core
                    Core/Common
                    Core/DB
                    Core/DG)

对应于Android.mk 下的 LOCAL_C_INCLUDES

4.设置生成so库的名称,并为源文件提供一个相对路径

file(GLOB jni "*.cpp")//设置统配符
file(GLOB Cipher "Cipher/*.cpp")//设置统配符

add_library( # Sets the name of the library.  设置库的名称,也就是生成的so名称,在java代码中加载so库需要与此一致
             demo

             # Sets the library as a shared library. 将library设置为一个共享库
             SHARED

             # Provides a relative path to your source file(s).为源文件提供一个相对路径,可以使用通配符,也可以一个一个文件的引入
                demo.cpp
                ${jni}//引用上面设置到通配符
                ${Cipher}
             )

对应于Android.mk
 LOCAL_MODULE 设置so库的名称
 LOCAL_SRC_FILES  设置源文件
 FILE_LIST  设置文件列表,也就是通配符

5.使用本地系统库,在CMake默认的搜索路径就已经包含了系统库,所以直接指定名称就行,CMake会验证库是否存在。

find_library( # Sets the name of the path variable. 
                设置路径变量的名称,后面会引用到
              log-lib   //log日志,默认都需要添加

              # Specifies the name of the NDK library that 指定NDK库的名称
              # you want CMake to locate.
              log
              )

find_library( # Sets the name of the path variable. 设置路径变量的名称
               jnigraphics-lib

               # Specifies the name of the NDK library that 指定NDK库的名称
               # you want CMake to locate.
               jnigraphics
               )

对应于Android.mk 下的 LOCAL_LDLIBS

6.加载第三库,比如自己定义的库,或者用的第三方库,.a库等等

//比如添加一个第三方库libpng,这两个需要配合使用
add_library(libpng STATIC IMPORTED)
set_target_properties( libpng
                       PROPERTIES IMPORTED_LOCATION
                       ......../libpng.a )
使用的时候,只需要修改将两个libpng名称改成你需要的,可以随意取,该名称是后面用来链接使用的,再修改一下对应文件路径就ok。

对应于Android.mk 下的 LOCAL_LDLIBS

7.链接所有的库,比如上面我们添加的第三方库,添加的本地log库

target_link_libraries( # Specifies the target library.指定目标library中。 
                        //通过add_library添加的直接写设置的名字,
                        //一种是SHARED,一般来说就是我们需要生成的so文件
                        //二中是STATIC IMPORTED 添加的第三方静态库
                       demo
                       libpng

                       # Links the target library to the log library  将目标library链接到日志库
                       # included in the NDK.
                       //链接本地NDK里面的库
                       ${log-lib}
                       ${jnigraphics-lib}
                       )

8.如何通过CMakeList.txt生成多个so库?针对不同的so库,编写不同的CMakeList.txt,然后在主CMakeList.txt中加载

# 再主CMakeList.txt中加载其他的子CMakeList.txt文件
# 指定子CMakeList.txt文件路径(指定到CMakeList.txt所在文件夹即可)
ADD_SUBDIRECTORY(FrameWork/ThirdParty/a)
ADD_SUBDIRECTORY(b)

9.如果不进行配置,那么默认会生成四种架构的so库文件,如何生成指定的so库文件

完整的CMakeList.txt文件脚本

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# 设置生成的so动态库最后输出的路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

#设置头文件搜索路径(和此txt同个路径的头文件无需设置),可选
include_directories(Cipher
                    Core
                    Core/Common
                    Core/DB
                    Core/DG
                   )

file(GLOB jni "*.cpp")
file(GLOB Cipher "Cipher/*.cpp")


# Creates and names a library, sets it as either STATIC  
# or SHARED, and provides the relative paths to its source code. 
# You can define multiple libraries, and CMake builds them for you. 
# Gradle automatically packages shared libraries with your APK. Gradle

add_library( # Sets the name of the library.  设置库的名称。
             demo

             # Sets the library as a shared library. 将library设置为一个共享库
             SHARED

             # Provides a relative path to your source file(s).为源文件提供一个相对路径
                demo.cpp
                ${jni}
                ${Cipher}
             )


# Searches for a specified prebuilt library and stores the path as a   
# variable. Because CMake includes system libraries in the search path by  
# default, you only need to specify the name of the public NDK library  
# you want to add. CMake verifies that the library exists before 
# completing its build.  

find_library( # Sets the name of the path variable. 设置路径变量的名称
              log-lib

              # Specifies the name of the NDK library that 指定NDK库的名称
              # you want CMake to locate.
              log
              )

find_library( # Sets the name of the path variable. 设置路径变量的名称
               jnigraphics-lib

               # Specifies the name of the NDK library that 指定NDK库的名称
               # you want CMake to locate.
               jnigraphics
               )

# Specifies libraries CMake should link to your target library. You  
# can link multiple libraries, such as libraries you define in this  
# build script, prebuilt third-party libraries, or system libraries. 


add_library(libpng STATIC IMPORTED)
set_target_properties( libpng
                       PROPERTIES IMPORTED_LOCATION
                       ..../libpng.a )

target_link_libraries( # Specifies the target library.
                       demo
                       libpng

                       # Links the target library to the log library 
                       # included in the NDK.
                       ${log-lib}
                       ${jnigraphics-lib}
                       )
//加载子CMakeList.txt文件
ADD_SUBDIRECTORY(FrameWork/ThirdParty/a)
ADD_SUBDIRECTORY(b)
externalNativeBuild {
            cmake {
                cppFlags ""
                abiFilters "armeabi-v7a"//需要什么构架的so,就在这边添加即可
            }
        }

所遇到的问题

1.从eclipse转化过来的工程,使用CMakeList.txt,部分头文件的导入路径会发生改变,需要进行修改。可能跟CMakeList.txt里面的头文件配置有关系。

2.More than one file was found with OS independent path ‘lib/arm64-v8a/xxx.so’ 如果运行的时候遇到这个问题。在gradle里面配置一下。原因不详,按理说通过CMakeList.txt设置生成目录到jniLibs后,so存放在jniLibs里面,而在gradle里面配置只有so库存放在lib下才需要,但是看这个错误好像是lib下冲突,但我lib下并没有存放so文件,编译可以通过,运行就会报错,然后我看了一下bulid下面也有一份so库文件,难道运行后,会自动将bulid下的so文件复制到lib里面吗?如果有知道的原因,麻烦告诉一声,感激不尽!

sourceSets{
    main{
         jniLibs.srcDirs = ['libs']
    }
}

更多参考https://blog.csdn.net/u012528526/article/details/80647537

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.
# 设置构建本机库所需的CMake的最小版本。
cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

# 创建并命名库,将其设置为静态或共享,并提供到其源代码的相对路径。
#您可以定义多个库,CMake为您构建它们。
# Gradle自动将共享库打包到APK中。
add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

# 搜索指定的预构建库并将路径存储为变量。
# 因为CMake在搜索路径by中包含了系统库默认情况下,
# 您只需要指定公共NDK库的名称 CMake验证库之前是否存在完成构建。
find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

#指定库CMake应该链接到目标库。你可以链接多个库,
#比如您在本文中定义的库构建脚本、预构建的第三方库或系统库
target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )
发布了134 篇原创文章 · 获赞 197 · 访问量 41万+

猜你喜欢

转载自blog.csdn.net/u011733020/article/details/101286069