cmake与交叉编译(x86 to arm)过程和问题全记录

一、背景

公司维护一批c++动态库,由于生产需要,每次更新都要在windows、linux_x86、kylin_arm等多个环境中编译一遍,操作比较麻烦,所以想通过交叉编译的方式在一台机器上边编译多个环境的动态库,减少工作量。考虑到工作难度以及本人水平,决定从官方发布的成品交叉编译工具链中选择合适的版本搭建一个交叉编译环境, 实现在linux_86平台编译linux_arm动态库。

搭建编译环境用ubuntu_x86虚拟机,动态库统一使用cmake构建编译,编译会用到一批第三方依赖库例如boost、opencv等等,既然我要生成能在kylin_arm上运行的动态库,那么这些编译过程中用到的三方库也必须是kylin_arm系统的。现在公司有一个完善的kylin_arm编译环境,所以为了节约成本,我就直接将环境中的三方库拷贝到ubuntu_x86虚拟机中,方便交叉编译的时候直接调用。

cmake中配置交叉编译工具链

, 这个比较简单,cmake可以制定gcc路径,那么我就用CROSS_COMPILE这个参数做一个区分,在编译的时候指定它为true(cmake source/fiename -DCROSS_COMPILE=true)那个cmake就会去交叉编译的路径下边查找gcc.

if(UNIX)
   if(CROSS_COMPILE)
     message(STATUS "CROSS_COMPILE:${CROSS_COMPILE}")
      SET(CMAKE_SYSTEM_NAME Linux)
      SET(CMAKE_SYSTEM_PROCESSOR arm)
      SET(TOOLCHAIN_DIR "$ENV{HOME}/x86ToArm/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu")
      set(CMAKE_C_COMPILER "${TOOLCHAIN_DIR}/bin/aarch64-linux-gnu-gcc")
      set(CMAKE_CXX_COMPILER "${TOOLCHAIN_DIR}/bin/aarch64-linux-gnu-g++")
      set(CMAKE_LINKER "${TOOLCHAIN_DIR}/bin/aarch64-linux-gnu-g++")
   elseif (EXISTS "$ENV{HOME}/local/bin/gcc")
      set(CMAKE_C_COMPILER "$ENV{HOME}/local/bin/gcc")
      set(CMAKE_CXX_COMPILER "$ENV{HOME}/local/bin/g++")
      set(CMAKE_LINKER "$ENV{HOME}/local/bin/g++")
   elseif (EXISTS "/usr/local/bin/gcc")
      set(CMAKE_C_COMPILER /usr/local/bin/gcc)
      set(CMAKE_CXX_COMPILER /usr/local/bin/g++)
      set(CMAKE_LINKER /usr/local/bin/g++)
   endif()
endif()

message(STATUS "CMAKE_C_COMPILER is : ${CMAKE_C_COMPILER}")
message(STATUS "CMAKE_CXX_COMPILER is : ${CMAKE_CXX_COMPILER}")

二、问题1 can’t find “/lib64/libharfbuzz.so”……

在编译的时候报错找不到一批这样的文件,于是我从现有的 kylin_arm里边拷贝过来放在交叉编译工具连里边。但是之后发现只有放在系统/lib64下边才能被找到,这显然还是有问题,我的交叉编译工具链我希望它是可以移植的。于是我考虑是不是我需要在cmake中设置交叉编译的

知识点:
(1)在交叉编译工具连中aarch64-linux-gnu/libc是系统根目录,libc/lib== lib, libc/usr/lib==/usr/lib
(2) 在cmake里边可以通过SET(CMAKE_SYSROOT "${TOOLCHAIN_DIR}/aarch64-linux-gnu/libc") 指定根路径, SET(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}/lib64" "$ENV{HOME}/YEECOH_LIBS_Arm") 指定搜索路径

问题分析:cmake中设置了各种路径都不起作用,它还是顽强的去/lib64下边寻找,然后忽然发现报错的库都是opencv库间接使用的,那么可以想到/lib64的路径可能是由opencv库中的cmake写死了。检查发现果然在opencv-4.5.1/lib64/cmake/opencv4/OpenCVModules.cmake中opencv将其调用的一些库路径写死了,于是将其修改为"\$<LINK_ONLY:harfbuzz>"(这是opencv中统一的写法,也可将路径直接修改成交叉编译的路径。)

三、问题2 basic_ostringstream未定义的引用

在这里插入图片描述分析:
(1) 交叉编译中自带的glibc版本是libstdc++.so.6.0.24, 麒麟编译使用的版本是0.28.
(2) 使用命令:nm -D /home/x86ToArm/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/aarch64-linux-gnu/libc/lib/libstdc++.so | c++filt | grep basic_ostringstream 查看报错的那个basic_ostringstream发现0.28版本中有定义,而0.24中没有定义。那么基本可以确定是版本不对的问题。 【参考链接:https://blog.csdn.net/Three_dog/article/details/104701644
在这里插入图片描述(3)检查发现/home/x86ToArm/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/aarch64-linux-gnu/lib64这个路径下边是交叉编译自带的libstdc++.so.6.0.24,交叉编译使用的应该是他, 从现有的kylin_arm环境中将0.28的版本拷贝过来替换掉交叉编译中的libstdc++.so.6.0.24(一套库),这个报错就没有了

四、问题3 libc.so 未定义的引用

在这里插入图片描述
知识点:
(1)libc.so: glibc, 是底层c库; listdc++.so: 底层c++库。
(2) listdc++.so可以直接通过替换动态库文件来升级版本;但是libc.so不能简单替换,由交叉编译工具的制作过程可知,gcc与glibc是强关联的。

分析:
我在编译动态库的过程中是从现有的麒麟arm环境中拷贝了所需的一些底层库, 该麒麟环境有两套gcc: gcc9.3 + libc0.28 + libstdc++ 0.28 、gcc7.3+libc0.24+libstdc++0.24。 其中有两个库是用libc0.28编译的。而我使用的交叉编译工具链是:gcc7.3+ glibc0.24+libstdc++0.24。由于libc不能直接拷贝替换,那就只能考虑使用更高版本的交叉编译工具链。从官网下载了一个比较合适的版本:gcc8.3+libc0.28+libstdc++0.25。将其中的stdc++动态可直接替换成0.28版本的,就可以了。最终生成的动态库可以在现有的麒麟arm环境中运行。

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux中使用CMake进行交叉编译的步骤如下: 1. 首先,需要编写一个适用于目标平台的工具链文件。这个文件可以指定交叉编译工具的路径、系统名称等信息。例如,可以在工具链文件中设置CMAKE_SYSTEM_NAME为Linux,指定交叉编译工具的路径为TOOLCHAIN_PATH。 2. 在执行CMake命令开始构建时,可以使用参数--toolchain或者-DCMAKE_TOOLCHAIN_FILE=指定工具链文件的路径。这样,CMake就会使用指定的工具链文件进行交叉编译。 举个例子,假设工具链文件的路径为/path/to/toolchain-file.cmake,可以使用以下命令进行交叉编译cmake ... --toolchain=/path/to/toolchain-file.cmake 或者 cmake ... -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain-file.cmake 这样,CMake就会根据工具链文件中的设置进行交叉编译,生成适用于目标平台的库文件或可执行文件。 引用内容: [1] 交叉编译笔者在工作中经常会遇到。笔者开发使用的宿主机一般都是Linux(Ubuntu),交叉编译的目的基本都是为了将程序代码编译成目标嵌入式平台的库文件,然后再在目标系统上调用集成,一般都是ARM系列的CPU。而对于不同操作系统(Windows、Linux、MacOS)之间的交叉编译,则主要是为了编译示例程序,方便在不同操作系统上进行展示或者调试。 [2] toolchain.cmake set(CMAKE_SYSTEM_NAME Linux) #这里以Linux为例 set(TOOLCHAIN_PATH /home/test/src/func/build) 这里指定toolchain的目录 set(TOOLCHAIN_PATH ${tools}/usr/local/arm/gcc-linaro-6.5.0-2018.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc) 这里指定交叉编译工具的路径 set(TOOLCHAIN_PATH ${tools}/usr/local/arm/gcc-linaro-6.5.0-2018.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g ) 这里指定交叉编译工具的路径 [3] 在需要进行交叉编译的时候,先编写一个适用于目标平台的工具链文件,然后在执行cmake命令开始构建时,可以使用参数--toolchain或者-DCMAKE_TOOLCHAIN_FILE=指定工具链文件的路径即可: cmake...--toolchain<path/to/toolchain-file> #or cmake...-DCMAKE_TOOLCHAIN_FILE=<path/to/toolchain-file>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值