Android JNI介绍(八)- CMakeLists的使用

3,178 阅读3分钟

本系列文章列表:

Android JNI介绍(一)- 第一个Android JNI工程

Android JNI介绍(二)- 第一个JNI工程的详细分析

Android JNI介绍(三)- Java和Native的互相调用

Android JNI介绍(四)- 异常的处理

Android JNI介绍(五)- 函数的注册

Android JNI介绍(六)- 依赖其他库

Android JNI介绍(七)- 引用的管理

Android JNI介绍(八)- CMakeLists的使用


在我们编写Android Native工程时,现在主流的方式是使用CMakelists.txt进行工程配置 (ndk-build + android.mk + application.mk的方式也可以编译,但是用的已经不多了),工欲善其事,必先利其器,如果熟悉了CMakeLists的编写,对于JNI开发会有不小的帮助。本文将介绍一些常见的CMakeLists的脚本编写方法。

一、什么是CMakeLists

  • 首先介绍下CMake
    简单来说,CMake就是一个跨平台构建工具,支持包括C/C++/Java等多种语言的工程构建,官网详细介绍如下。。

    CMake is an open-source, cross-platform family of tools designed to build, test and package software. CMake is used to control the software compilation process using simple platform and compiler independent configuration files, and generate native makefiles and workspaces that can be used in the compiler environment of your choice. The suite of CMake tools were created by Kitware in response to the need for a powerful, cross-platform build environment for open-source projects such as ITK and VTK.

    CMake是一个开放源代码,跨平台的工具系列,旨在构建,测试和打包软件。CMake用于使用简单平台和与编译器无关的配置文件来控制软件编译过程,并生成可在您选择的编译器环境中使用的本机makefile和工作区。CMake工具套件是由Kitware创建的,旨在满足ITK和VTK等开源项目对强大,跨平台构建环境的需求。

  • 文档首页
    cmake.org/cmake/help/…

  • CMake内建变量
    cmake.org/cmake/help/…

  • CMake指令
    cmake.org/cmake/help/…

  • 什么是CMakeLists.txt
    CMakeLists.txt是CMake构建脚本。

二、CMakeLists能做什么

CMakeLists.txt是CMake构建脚本。结合CMake的命令和内部变量,我们可以做很多事情,比如:

  • 为C/C++代码添加宏定义
      add_definitions(-DFOO -DBAR ...)
      add_definitions(-DCOUNT=1 -DNAME="jack" ...)
    
  • 判断编译环境
      # CMAKE_SYSTEM_NAME表示编译目标系统名,比如在Windows上交叉编译Android的库,那么CMAKE_SYSTEM_NAME就是Android
      # CMAKE_HOST_SYSTEM_NAME表示编译环境设备系统名,比如在Windows上编译Android的库,那么CMAKE_HOST_SYSTEM_NAME就是Windows
      message(STATUS "CMAKE_SYSTEM_NAME is :${CMAKE_SYSTEM_NAME}")
      message(STATUS "CMAKE_HOST_SYSTEM_NAME is :${CMAKE_HOST_SYSTEM_NAME}")
      message(STATUS "CMAKE_HOST_SYSTEM is :${CMAKE_HOST_SYSTEM}")
      message(STATUS "CMAKE_HOST_WIN32 is :${CMAKE_HOST_WIN32}")
      message(STATUS "CMAKE_HOST_UNIX is :${CMAKE_HOST_UNIX}")
      message(STATUS "CMAKE_HOST_APPLE is :${CMAKE_HOST_APPLE}")
      message(STATUS "CMAKE_HOST_SOLARIS is :${CMAKE_HOST_SOLARIS}")
    
  • 判断当前编译的是Debug版本还是Release版本
     # 根据当前编译的是Debug版本还是Release版本添加不同的宏
     if (${CMAKE_BUILD_TYPE} MATCHES "Debug")
         add_definitions(-DDebug)
     else ()
         add_definitions(-DRelease)
     endif ()
    
  • 文件操作
    # 文件操作
      # 获取文件路径、名称,保存到变量中
      get_filename_component(parent_dir ${CMAKE_SOURCE_DIR} DIRECTORY)
      get_filename_component(current_dir ${CMAKE_SOURCE_DIR} ABSOLUTE)
      get_filename_component(current_dir_name ${CMAKE_SOURCE_DIR} NAME)
      # 读取文件内容
      file(READ ${CMAKE_SOURCE_DIR}/config file_content)
      # 递归遍历目录下的所有.cpp文件保存到变量中
      file(GLOB_RECURSE allSources ${CMAKE_SOURCE_DIR}/ *.cpp)
      message(STATUS "GLOB_RECURSE allSources ${CMAKE_SOURCE_DIR}/ *.cpp")
      # 循环打印
      foreach (source1 ${allSources})
          message(STATUS "source1 is ${source1}")
      endforeach ()
      # 遍历目录下直属的所有.cpp文件保存到变量中
      file(GLOB directSources ${CMAKE_SOURCE_DIR}/ *.cpp)
      # 循环打印
      message(STATUS "GLOB directSources ${CMAKE_SOURCE_DIR}/ *.cpp")
      foreach (source2 ${directSources})
          message(STATUS "source2 is ${source2}")
      endforeach ()
      
      message(STATUS "file_content is: ${file_content}")
      message(STATUS "parent_dir is: ${parent_dir}")
      message(STATUS "current_dir is: ${current_dir}")
      message(STATUS "current_dir_name is: ${current_dir_name}")
    
  • 变量操作
      # 变量操作
      set(varList a)
      message(STATUS "varList is: ${varList}")
      set(varList ${varList} b)
      message(STATUS "varList is: ${varList}")
      set(varList ${varList} c)
      message(STATUS "varList is: ${varList}")
      message(STATUS "print all variable in varList:")
      foreach (var ${varList})
          message(STATUS "var is ${var}")
      endforeach ()
    
  • 设置编译的内容
    • 编译可执行文件
      add_executable(exe sources)
    
    • 编译动态库
      add_library(lib SHARED sources)
    
    • 编译动态库
      add_library(lib STATIC sources)
    
  • 寻找动态库
     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)
    
  • 链接动态库
    target_link_libraries(
          lib
          ${log-lib})
    
  • 隐藏符号并导出符号表
      # Debug版本添加日志库,Release版本不添加日志库,并隐藏符号,并导出符号表
      if (${CMAKE_BUILD_TYPE} MATCHES "Debug")
          list(APPEND libraries ${log-lib})
          add_definitions("-DLOG_OPEN")
      else ()
          set(CMAKE_CXX_VISIBILITY_PRESET hidden)
          set(CMAKE_C_VISIBILITY_PRESET hidden)
          set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
          set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
          set(CMAKE_SHARED_LINKER_FLAGS  "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-Map=output.map" CACHE INTERNAL "")
      endif ()
    

以上是一些常用的命令和内部变量的基本使用,由于CMakeLists的功能太多无法一一列举,可尝试练习,熟悉CMake语法。

三、Demo下载