Android跨平台编译 —— BOOST

街角的小丑 · · 63 次点击 · · 开始浏览    

前言

    android studio在2.2开始已经全面接入了cmake,用来编译jni代码。所以我们的跨平台编译同样需要与时俱进,使用cmake来完成工作。如果你不是很了解cmake,也不用担心,跟着本文探索下去,能够了解一些最基本的用法(PS:博主之前也是完全不会,摸着石头过河的,现在也还是不会……)。

    另外ndk版本使用了最新的r16b(16.1.4479499),这给之后带来了一些些问题。在最新的ndk版本中,已经将编译工具从gcc迁移到了clang,默认会使用clang进行编译。

    toolchain地址位于 ${ANDROID_SDK}/ndk-bundle/toolchains/llvm内。关于llvm和clang的关系可以参考这张图。(更详细的内容就需要自己查了,不是本文内容。)

           

    ok既然使用到了clang,那么使用的c++标准库STL自然是libc++标准库。

    我们在代码中使用的头文件,比如string.h,都会位于${ANDROID_SDK}/ndk-bundle/source文件夹内,不同的stl库会使用不同的文件路径。

    还有一部分在sysroot文件夹中,比如jni.h这个文件。

    还有一个非常重要的东西在platforms文件夹中,这个文件夹包含了不同的android版本,同时每个版本中都有不同的指令集文件夹。每一个文件夹模拟了一个真机运行环境。

    另外在开始之前,建议自己阅读下面几篇文章:

    https://developer.android.com/studio/projects/add-native-code.html

    https://developer.android.com/ndk/guides/cmake.html#variables

    https://developer.android.com/ndk/guides/cpp-support.html#hr

    当然也请打开cmake的官方文档以便查阅。

    

正文

    boost的编译实际上并不算复杂,比如我们可以直接使用

                        https://github.com/moritz-wundke/Boost-for-Android

    这个github项目已经替你实现了,这里我使用了1.65.1的版本。主要问题还是集中在如何放到自己项目中。

    我们知道cmake提供了一个方法叫做find_package,具体参数请参见官方文档。作用是使用cmake提供的脚本自动搜索并载入相关的库。比如我们需要载入boost的库:

           FIND_PACKAGE(Boost COMPONENTS filesystem REQUIRED)

    Boost是库的名字,我们只需要载入其中一个组件filesystem。REQUIRED表示必须载入,没找到就报错。

    实际上当调用find_package之后,cmake就回去寻找一个cmake的脚本,比如boost就回去寻找FindBoost.cmake的脚本。在android studio的环境下,他会到/Users/yxwang/Library/Android/sdk/cmake/3.6.4111459/share/cmake-3.6/Modules 这个文件夹下寻找。

    正常情况,我们可以使用 

set(Boost_ADDITIONAL_VERSIONS "1.65" "1.65.1")
set(Boost_NO_SYSTEM_PATHS ON)
set(BOOST_ROOT ${PROJECT_SOURCE_DIR}/src/main/cpp/boost/${ANDROID_ABI})
set(Boost_USE_STATIC_LIBS ON)
FIND_PACKAGE(Boost COMPONENTS filesystem REQUIRED)

    这几行代码来设置一些先决条件,然后findboost.cmake脚本就能正常运行,并且替我们设置好一些变量。(其中BOOST_ROOT 表示boost的地址)

    但是我发现我这边运行会出现问题,最后导致find失败,于是read the fucking source code!!

    最终发现,问题出在了其中一行find_path命令上,理论上能根据设置的路径能够最终找到需要的头文件地址,并且存放在变量Boost_INCLUDE_DIR中。

    但是我mac上发现find_path失效了。一定是缺失了某个配置,导致寻找路径出现了错误。甚至连find_path(VAL NAMES a.jpg PATH /somepath) 这种的绝对寻找都找不到…… PS在非ndk环境中似乎运行成功。如果有知道的朋友请一定留言告诉我……毕竟我是个小白  

    那么怎么办呢?既然你找不到,那就我直接来告诉你,所以代码就变成了这样

set(Boost_ADDITIONAL_VERSIONS "1.65" "1.65.1")
set(Boost_NO_SYSTEM_PATHS ON)
set(BOOST_ROOT ${PROJECT_SOURCE_DIR}/src/main/cpp/boost/${ANDROID_ABI})
set(Boost_INCLUDE_DIR ${BOOST_ROOT}/include/boost-1_65_1 )
set(Boost_LIBRARY_DIR ${BOOST_ROOT}/lib )
set(Boost_USE_STATIC_LIBS ON)

FIND_PACKAGE(Boost COMPONENTS filesystem REQUIRED)

    我手动设置了Boost_INCLUDE_DIR的位置和 Boost_LIBRARY_DIR的位置。 (请注意大小写,这个大小写多浪费了我半天时间……)

    好的,然后就可以像引入其他静态或者动态那样使用了比如,引入头文件

include_directories(${Boost_INCLUDE_DIR})

    比如引入Link库

target_link_libraries(TKAT PRIVATE ${Boost_LIBRARIES} )

    实际上调用了find_package之后还给你定义很多components的变量规则都一样,比如BOOST_FILESYSTEM_LIBRARY就表示filesystem单个库。

    

本文来自:开源中国博客

感谢作者:街角的小丑

查看原文:Android跨平台编译 —— BOOST

63 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet