arm-linux-cc 4.4.3 交叉编译gstreamer1.18

最近在折腾ARM开发板,想把gstreamer移植到开发板上,记录以下折腾过程。

1 配置交叉编译文件

之前有一篇文章记录了ubuntu下编译gstreamer,Ubuntu18.04编译gstreamer 1.18源码,记录了代码拉取地址。代码拉取后在gst-build目录下创建交叉编译配置文件cross_file.txt,文件中内容如下:

[binaries]
c = 'arm-none-linux-gnueabi-gcc'
cpp = 'arm-none-linux-gnueabi-g++'
ar = 'arm-none-linux-gnueabi-ar'
strip = 'arm-none-linux-gnueabi-strip'
pkgconfig = '/usr/share/doc/pkg-config'

[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'ARM9'
endian = 'little'

[build_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

在gst-build目录执行编译,includedir指定头文件路径,libdir指定依赖的so路径,两个目录必须是gst-build的子目录:

meson --cross-file cross_file.txt \
--prefix=$(pwd)/install/ \
--includedir $(pwd)/prebuild_lib/install/include \
--libdir $(pwd)/prebuild_lib/install/lib \
build/ 

2 配置meson的过程中遇到的问题

配置meson的过程中遇到了以下问题,逐一记录了解决方案。

1 下载glib失败

gstreamer 依赖glib,所以编译的时候检测到toolchain中没有安装glib的话会自动从git仓库拉取代码,但是国内访问github或者gitlib比较慢,会出现time out的问题。

fatal: unable to access 'https://gitlab.gnome.org/GNOME/glib.git/': Failed to connect to gitlab.gnome.org port 443: Connection timed out
subprojects/gstreamer/meson.build:482:0: ERROR: Git command failed: ['/usr/bin/git', 'clone', 'https://gitlab.gnome.org/GNOME/glib.git', 'glib']

遇到这种问题可以选择使用国内“Gitee 极速下载”拉取代码,“Gitee 极速下载” 是为了提升国内下载速度的镜像仓库,每日同步一次。 gitee极速下载网址https://gitee.com/organizations/mirrors/projects,在搜索框输入glid,找到对应的项目。
将sgt-build/subprojects/glib.wrap中的git clone地址更改gitee极速下载查到的地址,wrap文件记录的每个lib 的clone地址,其他lib下载慢也可以使用同样的方法解决。

[wrap-git]
directory=glib
url=https://gitee.com/mirrors/glib.git
push-url=[email protected]:mirrors/glib.git
revision=glib-2-62

更改后clone glib速度1M以上,快的飞起。

2 glib缺少libmount

meson 在build之前会检查每个项目的依赖,依赖检查完毕后才会开始编译。检查glib依赖的时候出现了libmount找不到错误,错误信息如下。

glib| Run-time dependency mount found: NO
subprojects/glib/meson.build:1868:2: ERROR: Pkg-config binary for machine MachineChoice.HOST not found. Giving up.

找到对应的meson 文件,发现确实在检测libmount时失败。

libmount_dep = []
if host_system == 'linux' and get_option('libmount')
  libmount_dep = [dependency('mount', version : '>=2.23', required : true)]
  glib_conf.set('HAVE_LIBMOUNT', 1)
endif

目前我接触到的meson添加依赖项的方式有两种(应该还有其他方式,暂时未接触到)。第一种就是通过 dependency关键字添加依赖,这类依赖一般是编译安装好的lib,和我们用cmake添加lib没什么区别。第二种方法也是meson比较强大的地方,它可以把依赖项目的源码下载在项目,编译的时候直接作为一个子项目编译,这就是为什么我们使用meson编译的时候会自动下载依赖项目;这种方式添加依赖时使用subproject关键字,并且项目种要有对应的wrap文件指明项目clone的地址。
上面的libmount是通过dependency添加的依赖,所以需要手动交叉编译安装到toolchain路径下。libmount不是单独lib,包含在util-linux中,所需要下载编译util-linux。

1 下载代码
并切换到v2.32分支是因为master 分支使用了meson编译,会有编译错误,所以还是使用makefile的方式。

git clone https://github.com/karelzak/util-linux.git
git checkout -b stable/v2.32

2 第一次编译
util-linux子项目之间有依赖关系,所以需要逐个编译安装,不编译某个lib时可以使用–disable配置,如–disable-libuuid,第一次编译的时候需要把大部分lib都关闭掉才能编译通过。

./autogen.sh

然后配置makefile

./configure CC=arm-none-linux-gnueabi-gcc \
CXX=arm-none-linux-gnueabi-g++ \
--prefix=/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi \
--host=arm-none-linux-gnueabi \
--target=arm-none-linux-gnueabi  \
--without-python --without-tinfo --without-ncursesw \
--without-ncurses --without-systemd --without-libblkid  \
--disable-libblkid --disable-login-utils \
--disable-libuuid --disable-libfdisk

配置完后执行编译安装命令。

make
make install

执行make install的时候遇到了如下错误:

./libtool: line 1719: arm-none-linux-gnueabi-ranlib: command not found
Makefile:5118: recipe for target 'install-usrlib_execLTLIBRARIES' failed

出现错误的原因可以参考这篇文章make install时"arm-linux-ranlib command not found",参照里面的方案切换成root用户执行install:

sudo su
make install

install完成后记得不要忘了切换回原来的用户。

su usename

3 重新配置makefile,编译出libuuid。

./configure CC=arm-none-linux-gnueabi-gcc CXX=arm-none-linux-gnueabi-g++ \
--prefix=/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi \
--host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi  \
--without-python --without-tinfo --without-ncursesw \
--without-ncurses --without-systemd \
-disable-libmount --disable-libblkid --disable-libfdisk

然后执行make install ,install 之前同样要使用su命令。之所以先编译libuuid是因为libfdisk和libblkid的编译依赖libuuid,否则会出现如下错误:

./.libs/libblkid.so: undefined reference to `uuid_unparse@UUID_1.0'
collect2: ld returned 1 exit status
Makefile:5977: recipe for target 'blkid' failed

4 编译libblkid,因为libfdisk的编译依赖libblkid。

./configure CC=arm-none-linux-gnueabi-gcc CXX=arm-none-linux-gnueabi-g++ \
--prefix=/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi \
--host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi  \
--without-python --without-tinfo --without-ncursesw --without-ncurses \
--without-systemd -disable-libmount --disable-libfdisk

5 编译libfdisk,libmount的编译依赖libfdisk。

./configure CC=arm-none-linux-gnueabi-gcc CXX=arm-none-linux-gnueabi-g++ \
--prefix=/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi \
--host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi  \
--without-python --without-tinfo --without-ncursesw --without-ncurses \
--without-systemd -disable-libmount 

6 编译libmount

./configure CC=arm-none-linux-gnueabi-gcc CXX=arm-none-linux-gnueabi-g++ \
--prefix=/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi \
--host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi  \
--without-python --without-tinfo --without-ncursesw --without-ncurses \
--without-systemd

终于编译除了libmount,像俄罗斯套娃一样。note:如果编译的时候某个项目缺少依赖的lib,可以先disable该项目,先编译出依赖再开启。
libmount install完成后重新配置meson,但是仍然会出现找不到该lib的错误。

glib| Run-time dependency mount found: NO
subprojects/glib/meson.build:1868:2: ERROR: Pkg-config binary for machine MachineChoice.HOST not found. Giving up.

install 仍然找不到lib是因为pkgconfig文件路径不正确,pkgconfig文件的后缀名是.pc,里面指明了该lib的头文件以及so地址,如mount.pc。

prefix=/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi
exec_prefix=/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi
libdir=/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib
includedir=/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/include

Name: mount
Description: mount library
Version: 2.32.1
Requires.private: blkid
Cflags: -I${includedir}/libmount
Libs: -L${libdir} -lmount

之前编译的libmount install 在了toolchain目录,所以在cross_file.txt中更新pkgconfig路径。

[properties]
pkg_config_libdir = ['/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib/pkgconfig']

[binaries]
c = 'arm-none-linux-gnueabi-gcc'
cpp = 'arm-none-linux-gnueabi-g++'
ar = 'arm-none-linux-gnueabi-ar'
strip = 'arm-none-linux-gnueabi-strip'
pkgconfig = 'pkg-config'

[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'ARM9'
endian = 'little'

[build_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'i686'
endian = 'little'

更新pkgconfig就可以meson配置时就可以检测到该lib了,会出现以下log。

Run-time dependency mount found: YES 2.32.1

3 gst-omx配置错误

meson 配置gst-omx时会出现以下错误:

subprojects/gst-omx/meson.build:220:2: ERROR: Problem encountered: Unsupported omx target specified. Use the -Dtarget option

原因option 中target参数没有指定的原因,所以通过-D参数修改subprojects/gst-omx目录下meson_option.txt中target选项。

meson build --cross-file cross_file.txt -D gst-omx:target=rpi 

不出意外的话这次会配置成功,会出现以下log:

All GStreamer modules 1.18.5.1

  Subprojects
    FFmpeg                    : YES 12 warnings
    avtp                      : YES
    dssim                     : NO Dependency "libpng" not found, tried pkgconfig
    gl-headers                : YES
    glib                      : YES 4 warnings
    glib-networking           : NO Problem encountered: No TLS backends enabled. Please enable at least one TLS backend
    gst-devtools              : YES
    gst-editing-services      : NO Feature 'ges' disabled
    gst-examples              : YES
    gst-integration-testsuites: YES
    gst-libav                 : YES
    gst-omx                   : NO Feature 'omx' disabled
    gst-plugins-bad           : YES 1 warnings
    gst-plugins-base          : YES 2 warnings
    gst-plugins-good          : YES 2 warnings
    gst-plugins-rs            : NO Feature 'rs' disabled
    gst-plugins-ugly          : NO Requested variable "plugins_cache_generator" not found.
    gst-python                : NO Subproject "subprojects/pygobject" required but not found.
    gst-rtsp-server           : YES
    gstreamer                 : YES 3 warnings
    gstreamer-sharp           : NO Feature 'sharp' disabled
    gstreamer-vaapi           : NO Feature 'vaapi' disabled
    json-glib                 : YES
    libdrm                    : YES
    libffi                    : YES
    libmicrodns               : YES
    libnice                   : NO Problem encountered: Either GnuTLS or OpenSSL is required as crypto library, but neither was found
    libopenjp2                : NO Dependency "wxWidgets" not found, tried config-tool
    libpsl                    : YES
    libsoup                   : YES 4 warnings
    libxml2                   : YES
    openh264                  : NO Program 'nasm nasm.exe' not found
    openssl                   : NO Neither a subproject directory nor a openssl.wrap file was found.
    orc                       : YES 3 warnings
    pygobject                 : NO Python dependency not found
    sqlite                    : YES
    tinyalsa                  : NO Neither a subproject directory nor a tinyalsa.wrap file was found.
    x264                      : YES

Found ninja-1.10.2.git.kitware.jobserver-1 at /usr/local/bin/ninja

3 编译过程中遇到的问题

配置成功后可以执行编译命令:

ninja -C build

编译的过程中遇到了不少问题,逐一记录解决方案。

1 编译glib失败

编译glib中遇到了以下错误:

../subprojects/glib/glib/gnulib/xsize.h:65: error: no previous prototype for 'xsum'
../subprojects/glib/glib/gnulib/xsize.h:76: error: no previous prototype for 'xsum3'
../subprojects/glib/glib/gnulib/xsize.h:86: error: no previous prototype for 'xsum4'
../subprojects/glib/glib/gnulib/xsize.h:96: error: no previous prototype for 'xmax'

解决方案可以参考arm-linux-cc 4.4.3 交叉编译glib 2.70.1。
直接subprojects/glib目录meson.build文件中加一句use_system_printf = true,强制使用系统print,不编译vasnprintf。

# Our printf is 'good' only if vsnpintf()/snprintf()/printf() supports C99 well enough
use_system_printf = have_good_vsnprintf and have_good_snprintf and have_good_printf
use_system_printf = true
glib_conf.set('USE_SYSTEM_PRINTF', use_system_printf)
glibconfig_conf.set('GLIB_USING_SYSTEM_PRINTF', use_system_printf)

2 编译gst-plugins-base遇到“declarations are only allowed in C99 mode”错误

错误信息如下:

../subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c:2772: error: 'for' loop initial declarations are only allowed in C99 mode
../subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c:2772: note: use option -std=c99 or -std=gnu99 to compile your code

出现错误的原因是gcc是基于c89标准的,而C89标准不支持循环语句如下这样定义:

for(int i=0; i<len; i++) {}

必须要写成下面这样:

int i;
for(i=0;i<len;i++){}

卧底个乖乖,难道要逐一改用到for循环的源码吗,那岂不是要人命!当然不是,编译的时候可以通过添加参数换成gnu99标准就可以了,编译单个文件可以这样写:

gcc src.c -std=gnu99 -o src

meson 编译在cross_file.txt中添加参数就可以了,更改后文件如下:

[properties]
pkg_config_libdir = ['/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib/pkgconfig', '/home/zhy/code/toolchain_lib/lib/pkgconfig']
c_args = ['-std=gnu99']

[binaries]
c = 'arm-none-linux-gnueabi-gcc'
cpp = 'arm-none-linux-gnueabi-g++'
ar = 'arm-none-linux-gnueabi-ar'
strip = 'arm-none-linux-gnueabi-strip'
pkgconfig = 'pkg-config'

[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'ARM9'
endian = 'little'

[build_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

3 编译gst-plugins-good遇到“‘O_CLOEXEC’ undeclared”错误

错误信息入下:

../subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c:3032: error: 'O_CLOEXEC' undeclared (first use in this function)
../subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c:3032: error: (Each undeclared identifier is reported only once
../subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c:3032: error: for each function it appears in.)

原因是O_CLOEXEC宏未定义,同样在cross_file.txt添加宏定义,添加后的cross_file.txt:

[properties]
pkg_config_libdir = ['/usr/local/arm/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib/pkgconfig', '/home/zhy/code/toolchain_lib/lib/pkgconfig']
c_args = ['-std=gnu99', '-D_GNU_SOURCE']

[binaries]
c = 'arm-none-linux-gnueabi-gcc'
cpp = 'arm-none-linux-gnueabi-g++'
ar = 'arm-none-linux-gnueabi-ar'
strip = 'arm-none-linux-gnueabi-strip'
pkgconfig = 'pkg-config'

[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'ARM9'
endian = 'little'

[build_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

cross_file.txt来来回回改了三次,因为是记录过程,所以没有一次性写清楚。

4 编译libdrm遇到“undefined reference to ‘clock_gettime’”错误

错误信息如下:

subprojects/libdrm-2.4.100/amdgpu/libdrm_amdgpu.so.1.0.0.p/amdgpu_cs.c.o: In function `amdgpu_cs_calculate_timeout':
/home/zhy/code/gstreamer/source_code/gst-build/build/../subprojects/libdrm-2.4.100/amdgpu/amdgpu_cs.c:407: undefined reference to `clock_gettime'
collect2: ld returned 1 exit status

查看错误信息是在编译libdrm_amdgpu时出错,因为不需要amdgpu模块,所以选择不编译,将gst-build/subprojects/libdrm-2.4.100/meson_option.txt中amdgpu设置为false。

option(
  'amdgpu',
  type : 'combo',
  value : 'false',
  choices : ['true', 'false', 'auto'],
  description : '''Enable support for amdgpu's KMS API.''',
)

5 编译ges遇到“redefinition of typedef ‘GESMarkerList’”错误

错误信息如下:

../subprojects/gst-editing-services/ges/ges-marker-list.h:49: error: redefinition of typedef 'GESMarkerList'

ges模块不知道是干啥的,所以暂时选择不编译,修改gst-build/meson_option.txt,将ges设置为disabled。

option('devtools', type : 'feature', value : 'auto')
option('ges', type : 'feature', value : 'disabled')
option('rtsp_server', type : 'feature', value : 'auto')

经过这一系列的操作,终于可以编译通过了,但是会有很多编译警告,主要是glib的,目前使用的版本是2.62,这些warning在2.71中已经修复了,暂时不理会,编译成功截图如下:
arm-linux-cc 4.4.3 交叉编译gstreamer1.18_第1张图片贴上来的原因主要是证明没有瞎写,没有乱抄误导别人。

3 总结

编译过程跌跌撞撞,花费了两个周末,总的原则是能编译过的就开启编译,编译不过的就不编译。目前还没有在开发板上测试运行,也不知道能不能跑的起来,后续试验了会更新结果。

4 参考文章

https://www.cnblogs.com/dakewei/p/11133189.html
Cross-compiling with gst-build and GStreamer
https://blog.csdn.net/weixin_42489042/article/details/84445288

你可能感兴趣的:(GStreamer,arm开发板,ubuntu,arm开发,交叉编译)