conan Linux下Android NDK交叉编译Boost

Conan 是 C 和 C++ 语言的依赖项和包管理器。它是 免费和开源的 ,适用于所有平台(Windows、Linux、OSX、FreeBSD、Solaris 等),可用于开发所有目标,包括嵌入式、移动(iOS、Android)和裸机。它还与 CMake、Visual Studio (MSBuild)、Makefiles、SCons 等所有构建系统集成,包括专有系统。
它专为加速 C 和 C++ 项目的开发和持续集成而设计和优化。通过完整的二进制包管理,它可以为任意数量的不同版本的包创建和重用任意数量的不同二进制文件(用于不同的配置,如架构、编译器版本等),在所有平台上使用完全相同的过程。由于它是去中心化的,因此很容易运行自己的服务器来私下托管自己的包和二进制文件,而无需共享它们。@ 《Conan官方文档》

上一篇博客《 conan入门(十):Windows下Android NDK交叉编译Boost 》中已经说明了Windows下Android NDK交叉编译Boost的全过程。

本文在此基础上说明Linux下conan实现Android NDK交叉编译经常用到的的Boost库的过程。

相比Windows平台,Linux下遇到的问题要少很多。只要正确定义profile就可以完成交叉编译。

conan https://conan.io/

python3 https://www.python.org/

android-ndk-r19c NDK 下载

profile

因为armv7a与armv8的编译参数有挺大的不同,所以这里我们分成两个profile来定义

profile文件你可以保存在任何位置,但建议保存在Conan专门保存profile文件的文件夹下 $HOME/.conan/profiles

android_armv8_clang

include(default)
# 需要修改为你的Android NDK实际安装位置
android_ndk=/your/path/android-ndk-r19c
target_host=aarch64-linux-android
api_level=21
[settings]
arch=armv8
build_type=Release
compiler=clang
compiler.libcxx=c++_static
#compiler.libcxx=c++_shared
compiler.version=8
os=Android
os.api_level=$api_level
[tool_requires]
[options]
[env]
PATH=[$android_ndk/toolchains/llvm/prebuilt/linux-x86_64/bin]
CHOST=$target_host
AR=$target_host-ar
AS=$target_host-as
RANLIB=$target_host-ranlib
CC=$target_host$api_level-clang
CXX=$target_host$api_level-clang++
LD=$target_host-ld
STRIP=$target_host-strip
[conf]
tools.android:ndk_path=$android_ndk

android_armv7a_clang

include(default)
# 需要修改为你的Android NDK实际安装位置
android_ndk=/your/path/android-ndk-r19c
target_host=armv7a-linux-androideabi
api_level=16
[settings]
arch=armv7
build_type=Release
compiler=clang
compiler.libcxx=c++_static
#compiler.libcxx=c++_shared
compiler.version=8
os=Android
os.api_level=$api_level
[tool_requires]
[options]
[env]
PATH=[$android_ndk/toolchains/llvm/prebuilt/linux-x86_64/bin]
CHOST=$target_host
AR=arm-linux-androideabi-ar
AS=arm-linux-androideabi-as
RANLIB=arm-linux-androideabi-ranlib
CC=$target_host$api_level-clang
CXX=$target_host$api_level-clang++
LD=arm-linux-androideabi-ld
STRIP=arm-linux-androideabi-strip
[conf]
tools.android:ndk_path=$android_ndk
 

与android_armv8_clang相比针对armv7a定义的profile在定义AR,AS,RANLIB,LD,STRIP环境变量时并没有使用$target_host-XX的格式,因为对armv7的ar,as,ranlib,ld,strip程序的文件名定义规则与armv8不同,所以不存在armv7a-linux-androideabi-ar的程序,参见Android官方文档《将 NDK 与其他构建系统配合使用》中下面的说明:

注意:对于 32 位 ARM,编译器会使用前缀 armv7a-linux-androideabi,但 binutils 工具会使用前缀 arm-linux-androideabi。对于其他架构,所有工具的前缀都相同

conan install(交叉编译)

创建了profile后,编译Boost就比较简单

# 编译conan包复制到本地仓库。
$ conan install boost/1.69.0@ -pr:h android_armv7a_clang -pr:b default --build missing  -o without_stacktrace=True
 

-pr:h android_armv7a_clang 指定目标设备的profile交叉编译配置文件,如果配置文件不在Conan专门保存profile文件的文件夹$HOME/.conan/profiles下,需要准确指定路径

-pr:b default 指定使用名为default的profile文件作为当前主机的配置文件[这个参数不是必须的]

–build missing 如果依赖包中没有找到预编译的二进制包则从源码编译

conan install 命令行用法详细说明参见Conan官方文档《conan install》

-o without_stacktrace=True 指定不编译 stacktrace 库.不知道为什么conan NDK交叉编译时不会编译stacktrace,而且会导致编译结束后报错,需要分析boost的conanfile.py脚本才能找到原因.

conan install执行成功后,就会将生成的二进制包保存在本地仓库$HOME/.conan/data/boost/1.69.0/_/_package

执行conan search boost/1.69.0@会显示二进制包的信息

$ conan search boost/1.69.0@
Existing packages for recipe boost/1.69.0:
    Package_ID: d5a659f866f2a1b5b329c11fa125a3f69ba4574c
        [options]
            addr2line_location: /usr/bin/addr2line
            asio_no_deprecated: False
            buildid: None
            bzip2: True
            diagnostic_definitions: False
            error_code_header_only: False
            extra_b2_flags: None
            fPIC: True
            filesystem_no_deprecated: False
            header_only: False
            i18n_backend_iconv: libiconv
            i18n_backend_icu: False
            layout: system
            lzma: False
            magic_autolink: False
            multithreading: True
            namespace: boost
            namespace_alias: False
            numa: True
            segmented_stacks: False
            shared: False
            system_no_deprecated: False
            visibility: hidden
            with_stacktrace_backtrace: False
            without_atomic: False
            without_chrono: False
            without_container: False
            without_context: False
            without_contract: False
            without_coroutine: False
            without_date_time: False
            without_exception: False
            without_fiber: False
            without_filesystem: False
            without_graph: False
            without_graph_parallel: True
            without_iostreams: False
            without_locale: False
            without_log: False
            without_math: False
            without_mpi: True
            without_program_options: False
            without_python: True
            without_random: False
            without_regex: False
            without_serialization: False
            without_stacktrace: False
            without_system: False
            without_test: False
            without_thread: False
            without_timer: False
            without_type_erasure: False
            without_wave: False
            zlib: True
            zstd: False
        [settings]
            arch: armv7
            build_type: Release
            compiler: clang
            compiler.libcxx: c++_static
            compiler.version: 8
            os: Android
            os.api_level: 16
        [requires]
            bzip2/1.0.8:deac87feb545b6b90ea1825dffccbb58b211ca1b
            libiconv/1.16:e8e0f6eaaa4f4f91532bc7c429b1be1edd37301a
            zlib/1.2.11:e8e0f6eaaa4f4f91532bc7c429b1be1edd37301a
        Outdated from recipe: False

conan upload(上传到私有制品库)

项目编译成功就可以上执行conan upload传到私有制品库了:

conan upload boost/1.69.0  -r ${repo} --all
# ${repo}为私有制品库的名字
 

–all 指定上传所有内容(配置文件conanfile.py,源码和二进制包),如果不指定些选项,只上传除二进制包之外的所有文件

关于 conan upload命令的详细说明参见Conan官方文档:《conan upload》

《conan install》

《conan upload》

《将 NDK 与其他构建系统配合使用》

conan系列文章

《conan入门(一):conan 及 JFrog Artifactory 安装》
《conan入门(二):conan 服务配置-密码管理及策略》
《conan入门(三):上传预编译的库(artifact)》
《conan入门(四):conan 引用第三方库示例》
《conan入门(五):conan 交叉编译引用第三方库示例》
《conan入门(六):conanfile.txt conanfile.py的区别》
《conan入门(七):将自己的项目生成conan包》
《conan入门(八):交叉编译自己的conan包项目》
《conan入门(九):NDK交叉编译自己的conan包项目塈profile的定义》
《conan入门(十):Windows下Android NDK交叉编译Boost》
《conan入门(十一):Linux下Android NDK交叉编译Boost》
《conan入门(十二):Windows NDK 编译 boost报错:CMake was unable to find a build program … MinGW Makefile》
《conan入门(十三):conan info 命令的基本用法》
《conan入门(十四):conan new 命令的新特性–模板功能(–template)》
《conan入门(十五):AttributeError: ‘CMake‘ object has no attribute ‘definitions‘》
《conan入门(十六):profile template功能实现不同平台下profile的统一》
《conan入门(十七):支持android NDK (armv7,armv8,x86,x86_64)交叉编译的统一profile jinja2模板》
《conan入门(十八):Cannot recognize the Windows subsystem, install MSYS2/cygwin or specify a build_require》
《conan入门(十九):封装第三方开源库cpp_redis示例》
《conan入门(二十):封装只包含头文件(header_only)的库示例》
《conan入门(二十一):解决MinGW编译Openssl的编译错误:crypto/dso/dso_win32.c》
《conan入门(二十二):编译 openssl要求python 3.7以上版本》
《conan入门(二十三):Windows下MinGW编译libcurl》
《conan入门(二十四):通过CONAN_DISABLE_CHECK_COMPILER禁用编译器检查》
《conan入门(二十五):imports将包安装到本地项目或其他指定位置》
《conan入门(二十六):使用make编译makefile》
《conan入门(二十七):因profile [env]字段废弃导致的boost/1.81.0 在aarch64-linux-gnu下交叉编译失败》
《conan入门(二十八):解决conan 1.60.0下 arch64-linux-gnu交叉编译openssl/3.1.2报错问题》
《conan入门(二十九):对阿里mnn进行Conan封装塈conans.CMake和conan.tools.cmake.CMake的区别》
《conan入门(三十):对腾讯ncnn进行Conan封装》
《conan入门(三十一):在命令行(shell)中从profile中读取配置参数》
《conan 入门(三十二):package_info中配置禁用CMakeDeps生成使用项目自己生成的config.cmake》
《conan 入门(三十三):requirements()指定header的可见性(transitive_headers)》
《conan 入门(三十四):conan 2.x实现对只有Makefile的项目(erpcgen)的封装示例》
《conan 入门(三十五):在conanfile.py中获取C++编译器完整路径的方法》
《conan入门(三十六):在set_version方法中从pom.xml中读取版本号实现动态版本定义》
《conan 入门(三十七):conan 2.x通过定义环境变量(environment)执行make编译只有Makefile的项目(erpcgen)》
《conan 入门(三十八):conan二进制包的兼容性及自定义package_id的方式》
《conan入门(三十九):conan 2.x 引用第三方库示例》

上一篇博客《conan入门(十):Windows下Android NDK交叉编译Boost》中已经说明了Windows下Android NDK交叉编译Boost的全过程。本文在此基础上说明Linux下conan实现Android NDK交叉编译经常用到的的Boost库的过程。相比Windows平台,Linux下遇到的问题要少很多。只要正确定义profile就可以完成交叉编译。
1. 简介   最近,项目的需求——将原本运行在Linux的上C/C++移植到Android上运行。折腾了3天,终于可以编译出使用了boost库的可执行程序。这边主要是记录下,并分享出来,供需要的人员参考,希望对大家有所帮助。如果有什么问题可以在下面评论或发私信。 2.android-ndkLinux上的安装   博主的ndk版本是从底层的驱动人员那边获取的。这边使用的ndk版本是:android-ndk32-r10b-linux-x86。如果你使用的版本不一致也没什么关系,一般差异不会太大,只需要稍作.
Android平台使用boost库,没有linux平台上那么方便。 尤其在新版本ndk,高通的车机项目,网上的boost_for_android不一定适用。 本人在移植安卓vsomeip版本时,采用以下方法 (部分boost库析构需要添加virtual) 步骤1: 克隆出boost 不同于直接拉取整个boost仓库,这里采用拉取小仓库 $ mkdir boost-1.70.0 $ cd boost-1.70.0/ $ vi get_boost.sh 为了能够在Android平台上使用一些Linux中的C/C++库,我们需要使用AndroidNDK来编译那些Linux库的源代码,使用NDK开发时,通常使用Android.mk或者Cmake来构建C/C++代码 但是一般Linux库是通过一个configure脚本来生成MakeFile的方式来构建的,在Linux上构建一个Linux库的一般流程如下: ./configure make install 这样的话就和我们通常使用NDK时构建C/C++代码的方式不一样 一种常见的解决
由于以往我写过不少使用boost库开发的项目,而最近准备移植一些代码到android上(上层界面以及jni层我不管,也没研究过,现在只完成代码的移植编译,具体如何调用,由其它人负责),所以先要解决的就是boost库本身的移植问题。 在google上找了一些相关的资料,然后在http://stackoverflow.com上找到一个给力的帖子: http://stackoverflow.com/
其中,`<path-to-conanfile>`是指定的Conanfile路径,可以是本地路径或者远程路径,`[OPTIONS]`是可选的命令行选项,用于指定安装选项,如`--build`指定是否在本地构建依赖项。 例如,安装一个名为`boost/1.75.0`的依赖项,可以执行以下命令: conan install boost/1.75.0 执行该命令后,Conan将下载并安装`boost/1.75.0`依赖项,并将其添加到项目的依赖项列表中。 10km: 我,我明白了,这个1是只匹配第一行,这是sed 指定编辑匹配范围的地址类型的一种:这是原文说明 Addresses Sed commands can be given with no addresses, in which case the command will be executed for all input lines; with one address, in which case the command will only be executed for input lines which match that address; or with two addresses, in which case the command will be executed for all input lines which match the inclusive range of lines starting from the first address and continuing to the second address. Three things to note about address ranges: the syntax is addr1,addr2 (i.e., the addresses are separated by a comma); the line which addr1 matched will always be accepted, even if addr2 selects an earlier line; and if addr2 is a regexp, it will not be tested against the line that addr1 matched. After the address (or address-range), and before the command, a ! may be inserted, which specifies that the command shall only be executed if the address (or address-range) does n[code=csharp] https://linux.die.net/man/1/sed [/code] linux:sed修改xml中的值示例 表情包我还是没表达清楚,其实我想问的不是\1,想问的是67行感叹号后面一位的这个1,就是!1"中间这个1的含义表情包 linux:sed修改xml中的值示例 10km: 所以这个\1是正则表达式的一部分,可以百度搜索关键字“ 正则表达式 反向引用“,获取关于它的用法说明,你所说的g,可以理解为正则表达式配置参数,在bash shell中一般跟在正则表达式结尾,并不是必须的 linux:sed修改xml中的值示例 10km: \1 正则表达式前向引用,即匹配前面的捕获组1,参见 https://blog.csdn.net/Arrogant_95/article/details/82864717