交叉编译

目录

  • 目录
  • 编译信息
  • 说明
  • 问题及现象
  • 解决方法

编译信息

作者:xzf

创建时间:2022/4/22

更新时间:2022/5/06

说明

工作需要用到opencv旧版本,4.5.0版本。而且需要编译为arm架构系统。并支持解码和GUI。

正常编译x86_64

编译

官方编译方法:https://docs.opencv.org/4.x/d7/d9f/tutorial_linux_install.html

# 1.下载源码,根据版需要
git clone -b 4.5.0 https://gitee.com/mirrors/opencv.git

# 2.进入源码
cd opencv

# 3.新建编译缓存区,防止源码被污染
mkdir build

# 4.生成makefile
cmake .. -DCMAKE_INSTALL_PREFIX=安装路径

#可能会遇到问题
#出现:CMake Error at cmake/OpenCVCompilerOptions.cmake:21 (else):
#解决办法 在cmake/OpenCVCompilerOptions.cmake:21 注释:else()即可。

# 5.编译make
make -j4

# 6.安装

如果需要GUI界面,需要添加相关依赖。

sudo apt-get install build-essential libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev libtiff5-dev
sudo apt-get install libgtk2.0-dev
sudo apt-get install pkg-config

但是具体缺乏什么依赖,需求再执行cmake..-D..后查看生产的说明,特别是否开启了GUI GTK+ 2.x YES,如果是 NO 需要查看缺乏了那些依赖。有些依赖不在也不会报错。

其他命令

指定安装路径(尽量使用此命令,防止被污染系统)

cmake .. -DCMAKE_INSTALL_PREFIX=<安装路径>

支持GUI需要下载GTK2.0,然后重现编译opencv

sudo apt-get install libgtk2.0-dev

直到编译opencv执行cmake命令后,出现上述支持,再编译,使用即可。

支持解码和读取视频

opencv需要打开图片需要包含支持解码ffmpeg,需要下ffmpeg

sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev

直到编译opencv执行cmake命令后,出现上述支持,再编译,使用即可。

可能遇到的报错

当需要编译FFmpeg时,在编译低版本的openc可能会报错。比如3.2.0版本

这时可以修改:

在在 opencv-3.2.0/modules/videoio/src/cap_ffmpeg_impl.hpp 里最顶端添加:

#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
#define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
#define AVFMT_RAWPICTURE 0x0020

参考https://blog.csdn.net/goodxin_ie/article/details/82856008

交叉编译方法

-----------特别注意需要下载交叉编译工具链--------------

官方编译方法:https://docs.opencv.org/4.x/d0/d76/tutorial_arm_crosscompile_with_cmake.html

基本同上,但是由于需要是格外支持的依赖库需要先编译好支持arm架构的opencv库而opencv需要先编译好ffmpeg(包含x264)库gtk2.0库

编译x264

下载x264:https://www.videolan.org/developers/x264.html

#下载
# wget https://code.videolan.org/videolan/x264/-/archive/master/x264-master.tar.bz2
git clone https://code.videolan.org/videolan/x264.git
#进入库
cd x264

编写脚本

#!/bin/bash
#
# ------------------------------------------------------------
# File name:         make_x264.sh
# Version:           1.0
# Author:            xzf
# Description:       用于交叉编译x264的脚本
# Date:              2022-04-05
# Usage:             sh make_x264.sh
# ------------------------------------------------------------

#获取绝对路径
path=$(dirname $(readlink -f "$0"))
#prefix指定路径
#cross-prefix=在交叉编译工具链的bin文件里的aarch64-linux-gnu-gcc,去掉gcc
./configure --prefix="$path/install" --enable-shared --disable-asm --host=arm-linux --cross-prefix=aarch64-linux-gnu-

执行脚本及安装

#执行脚本
sh make_x264.sh
#编译
make -j4
#安装
make install

检查生成

cd install
file libx264.so.164
#打印信息
libx264.so.164: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=eedfe78583c4b79fff99db4d2c1f3d19c74d4114, with debug_info, not stripped

编译ffmpeg

下载ffmpg:https://github.com/FFmpeg/FFmpeg.g

编写脚本

#!/bin/bash
#
# ------------------------------------------------------------
# File name:         make_ffmpeg.sh
# Version:           1.0
# Author:            xzf
# Description:       用于交叉编译x264的脚本
# Date:              2022-04-25
# Usage:             sh make_ffmpeg.sh
# ------------------------------------------------------------

#获取绝对路径
path=$(dirname $(readlink -f "$0"))
#prefix指定路径
#开启x264 --enable-gpl --enable-libx264
#开启交叉编译 --enable-cross-compile
#指定编译器 --cc=aarch64-linux-gnu-gcc --cxx=aarch64-linux-gnu-g++
#防止安装失败--strip=aarch64-linux-gnu-strip
./configure --prefix="$path/install" --enable-shared --disable-asm --enable-gpl --enable-libx264 --enable-cross-compile --cc=aarch64-linux-gnu-gcc --cxx=aarch64-linux-gnu-g++ --disable-ffmpeg --disable-ffprobe --strip=aarch64-linux-gnu-strip --enable-pic

增加依赖(临时)

export PKG_CONFIG_PATH=/home/xzf/work/Location/dlib/arm-lib/x264/install/lib/pkgconfig

执行脚本及安装

#执行脚本
sh make_ffmpeg.sh
#编译
make -j4
#安装
make install

编译QT源码

说明:本文选择的是5.12.3,其他版本可能会高,5.12.0编译过程会报错,貌似与GCC版本冲突,GCC-8和GCC-9的问题,具体没有深究,使用5.12.3版本没有问题。

下载地址:

#下载
wget https://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/5.12/5.12.3/single/qt-everywhere-src-5.12.3.tar.xz
#解压
tar -xvf qt-everywhere-src-5.12.3.tar.xz

找到交叉编译链,找到自己的编译器,一般都能找到,根据自己的交叉编译器来。

cd qt-everywhere-src-5.12.3.tar.xz
cd /qtbase/mkspecs

比如现在用的交叉编译器是aarch64-linux-gnu-g++mkspecs并没有这个,但是有linux-aarch64-gnu-g++,点进去就是aarch64-linux-gnu-g++查看qmake.conf,所以直接用即可或者复制修改名字为aarch64-linux-gnu-g++,如果没有就新建,复制模板改成合适的交叉编译器。

编写脚本

./configure  -prefix ./install \
        -opensource \
        -confirm-license \
        -xplatform aarch64-linux-gnu-g++ \
        -no-opengl \

执行脚本及安装

#执行脚本
sh make_ffmpeg.sh
#编译
make -j4
#安装
make install

编译opencv

编写交叉编译链接

直接复制aarch64-gnu.toolchain.cmake即可,由于目前无需修改,复制即可,若有修改,可以修改,而不改变原来的编译链接。

cp aarch64-gnu.toolchain.cmake aarch64-gnu-ivisionic.toolchain.cmake

编写脚本

cmake .. \
        -D CMAKE_BUILD_TYPE=Release \
        -D CMAKE_TOOLCHAIN_FILE=../platforms/linux/aarch64-gnu-ivisionic.toolchain.cmake \
        -D WITH_QT=ON \
        -D WITH_GTK=OFF \
        -D WITH_GTK_2_X=OFF \
        -D WITH_FFMPEG=ON \
        -D BUILD_XLIB=ON \
        -D BUILD_TESTS=OFF \
        -D BUILD_PERF_TESTS=OFF \
        -D BUILD_opencv_apps=OFF \
        -D OPENCV_GENERATE_PKGCONFIG=ON \
        -D OPENCV_FFMPEG_USE_FIND_PACKAGE=ON \
        -D OPENCV_FFMPEG_SKIP_BUILD_CHECK=ON \
        -D FFMPEG_DIR=/home/xzf/work/Location/dlib/arm-lib/ffmpeg/install \
        -D Qt5_DIR=/home/xzf/work/Location/dlib/arm-lib/qt-everywhere-src-5.12.3/install/lib/cmake/Qt5 \
        -D Qt5Core_DIR=/home/xzf/work/Location/dlib/arm-lib/qt-everywhere-src-5.12.3/install/lib/cmake/Qt5Core \
        -D Qt5Gui_DIR=/home/xzf/work/Location/dlib/arm-lib/qt-everywhere-src-5.12.3/install/lib/cmake/Qt5Gui \
        -D Qt5Widgets_DIR=/home/xzf/work/Location/dlib/arm-lib/qt-everywhere-src-5.12.3/install/lib/cmake/Qt5Widgets \
        -D Qt5Test_DIR=/home/xzf/work/Location/dlib/arm-lib/qt-everywhere-src-5.12.3/install/lib/cmake/Qt5Test \
        -D Qt5Concurrent_DIR=/home/xzf/work/Location/dlib/arm-lib/qt-everywhere-src-5.12.3/install/lib/cmake/Qt5Concurrent \

编写ffmpeg-config.cmake

由于ffmpeg不支持cmake,需要自己编写ffmpeg-config.cmake,以方便opencv查找。在FFMPEG_DIR安装位置同目录下

set(ffmpeg_path "${CMAKE_CURRENT_LIST_DIR}")

message("ffmpeg_path: ${ffmpeg_path}")

set(FFMPEG_EXEC_DIR "${ffmpeg_path}/bin")
set(FFMPEG_LIBDIR "${ffmpeg_path}/lib")
set(FFMPEG_INCLUDE_DIRS "${ffmpeg_path}/include")

# library names
set(FFMPEG_LIBRARIES
    ${FFMPEG_LIBDIR}/libavformat.so
    ${FFMPEG_LIBDIR}/libavdevice.so
    ${FFMPEG_LIBDIR}/libavcodec.so
    ${FFMPEG_LIBDIR}/libavutil.so
    ${FFMPEG_LIBDIR}/libswscale.so
    ${FFMPEG_LIBDIR}/libswresample.so
    ${FFMPEG_LIBDIR}/libavfilter.so
)

# found status
set(FFMPEG_libavformat_FOUND TRUE)
set(FFMPEG_libavdevice_FOUND TRUE)
set(FFMPEG_libavcodec_FOUND TRUE)
set(FFMPEG_libavutil_FOUND TRUE)
set(FFMPEG_libswscale_FOUND TRUE)
set(FFMPEG_libswresample_FOUND TRUE)
set(FFMPEG_libavfilter_FOUND TRUE)

# library versions, 注意这几个变量,一定要设置为全局CACHE变量
set(FFMPEG_libavutil_VERSION 56.31.101 CACHE INTERNAL "FFMPEG_libavutil_VERSION") # info
set(FFMPEG_libavcodec_VERSION 58.54.100 CACHE INTERNAL "FFMPEG_libavcodec_VERSION") # info
set(FFMPEG_libavformat_VERSION 58.29.100 CACHE INTERNAL "FFMPEG_libavformat_VERSION") # info
set(FFMPEG_libavdevice_VERSION 58.8.100 CACHE INTERNAL "FFMPEG_libavdevice_VERSION") # info
set(FFMPEG_libavfilter_VERSION 7.57.100 CACHE INTERNAL "FFMPEG_libavfilter_VERSION") # info
set(FFMPEG_libswscale_VERSION 5.5.100 CACHE INTERNAL "FFMPEG_libswscale_VERSION") # info
set(FFMPEG_libavresample_VERSION 3.5.100 CACHE INTERNAL "FFMPEG_libswresample_VERSION") # info

set(FFMPEG_FOUND TRUE)
set(FFMPEG_LIBS ${FFMPEG_LIBRARIES})

status("      FFMPEG:"       FFMPEG_FOUND                 THEN "YES (find_package)"                    ELSE "NO (find_package)")
status("      avcodec:"      FFMPEG_libavcodec_VERSION    THEN "YES (${FFMPEG_libavcodec_VERSION})"    ELSE NO)
status("      avformat:"     FFMPEG_libavformat_VERSION   THEN "YES (${FFMPEG_libavformat_VERSION})"   ELSE NO)
status("      avutil:"       FFMPEG_libavutil_VERSION     THEN "YES (${FFMPEG_libavutil_VERSION})"     ELSE NO)
status("      swscale:"      FFMPEG_libswscale_VERSION    THEN "YES (${FFMPEG_libswscale_VERSION})"    ELSE NO)
status("      avresample:"   FFMPEG_libavresample_VERSION THEN "YES (${FFMPEG_libavresample_VERSION})" ELSE NO)

执行脚本及安装

#执行脚本
sh make_ffmpeg.sh
#编译
make -j4
#安装
make install

后记总结

交叉编译opencv解码加显示,并不容易,也不友好,特别某些开发板没有apt install 或者甚至没ldd的阉割版系统。比如编译 opencv 的 GUI,需要 GTK 或者QT,GTK基本非常难交叉编译,如果能直接install,会比较方便,QT编译容易,但是也不能直接显示,因为没有xcb库,需要编译xcb库才能显示器,或者其他库。本文编译opencv带ffmpeg和Qt,但是直接使用的qt库却不能使用,因为没有xcb,因此,qt链接是链接到开发板自带的qt库。才能完成显示。编译只是为了opencv能支持GUI功能。

tag(s): none
show comments · back · home
Edit with Markdown