VLC - Android 学习笔记(二)

狗年的初一大概是我过的最纠结的一次新年了。一个看起来毫不讲理的BUG,陪着我度过了青岛的三天三夜。明天就要回家了,今天写篇,描述下这个编译错误,记录下这几天做过的尝试。

1 初读

前一篇学习笔记已经记录了VLC-Android初步安装配置的一些内容。大概扫了一眼发现竟然找不到任何vlc的实现或者库文件!有的只是一些外部的框架或者接口……难道我要重新从头边学边改一遍吗T^T

万幸,VLC并没有这么残忍。

在compile.sh里有这么一段:

####################
# Fetch VLC source #
####################

TESTED_HASH=f7fc778
if [ ! -d "vlc" ]; then
    diagnostic "VLC source not found, cloning"
    git clone https://git.videolan.org/git/vlc/vlc-3.0.git vlc
    checkfail "vlc source: git clone failed"
fi
diagnostic "VLC source found"
cd vlc
if ! git cat-file -e ${TESTED_HASH}; then
    cat 1>&2 << EOF
***
*** Error: Your vlc checkout does not contain the latest tested commit: ${TESTED_HASH}
***
EOF
    exit 1
fi
if [ "$RELEASE" = 1 ]; then
    git reset --hard ${TESTED_HASH}
fi
cd ..

这里的主要目的就是clone指定版本的VLC源码,之后作为源码的一部分整体进行编译。

这里有必要提一下另一个文件:compile-libvlc.sh,这个文件的主要任务是管理刚刚下载的VLC源码,把VLC作为lib文件加入项目,通过参数设置并执行我们之前vlc正常编译的过程,最终生成 libvlc.solibvlcjni.so两个核心的依赖。

看到了 .so文件的生成依然使用的是vlc的源码长舒了一口气,这样按理说我们只要屏蔽了vlc源码的下载校验,然后把之前更改好的vlc项目放进去执行编译,就可以把我们的补丁带进移动端。

那么,动手吧。

2 磕绊

理想总是很美好,BUG总会在你最兴高采烈的时候和你谈谈人生。

编译的过程中像往常一样报了一个很不起眼的错:

checking for iconv... no, consider installing GNU libiconv
configure: error: iconv() not found
make: *** [.zvbi] Error 1
contribs: make failed

第一反应是有库没有安装,iconv是交叉编译时在 ./bootstrap 中新打开的参数:--enable-iconv . 那会不会是提到的libiconv库没有安装?

用 apt-cache search 查了一下有关的包:

libiconv-hook-dev - header files of libiconv-hook
libiconv-hook1 - extension of iconv for libapache-mod-encoding

好像只有这两个像一点,但又不是我们需要的包。上网找了一下发现是有libiconv源码可以自己编译安装,安装完后使用 ln 命令链接到我们需要的地方就好。

最开始我也是这么做的,但后来在查找PATH的时候偶然看到了:

PKG_CONFIG_LIBDIR=$VLC_SRC_DIR/contrib/$TARGET_TUPLE/lib/pkgconfig \
PKG_CONFIG_PATH=$VLC_SRC_DIR/contrib/$TARGET_TUPLE/lib/pkgconfig \
PATH=../contrib/bin:$PATH \

PKG_CONFIG是依赖查询的路径,而这里把/vlc/contrib加入了查询,进入contrib目录,发现在对应的ABI目录下多了很多原本没有安装过的依赖,突然想起来第一次compile的时候下载了很多东西,路径的话是在/vlc/contrib/tarballs里:


VLC - Android 学习笔记(二)_第1张图片
心疼我的流量

里面明显是有libiconv的!找了一下iconv,.h .a .la 一应俱全...Excuse me??

3 崩坏

这是编译的时候报错的log(vlc):

.../vlc/conftest.c:46: undefined reference to `libiconv_open'
.../vlc/conftest.c:47: undefined reference to `libiconv'
.../vlc/conftest.c:48: undefined reference to `libiconv_close'
collect2: error: ld returned 1 exit status

log很符合编译过程中缺失iconv()函数的现象,但上面提到的三个函数在iconv.h中都有明确定义,为什么会找不到呢???

hwren@hwren-PC:~/Documents/vlc-android$ which iconv
/usr/local/bin/iconv
hwren@hwren-PC:~/Documents/vlc-android$ iconv --version
iconv (GNU libiconv 1.15)
Copyright (C) 2000-2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
作者 Bruno Haible。

这是我自己安装的iconv,也能正常使用,到处都有还说找不到这就很不友好了哇T^T

3.1 尝试升级

官方给的Android编译说明中有这么一条说明:

VLC - Android 学习笔记(二)_第2张图片
在下很面

大概意思就是,出现了返回1的Error的时候,你可以升级一下依赖试试。

虽然我出错的不是dvdnav,但依然觉得,嗯...你说的有道理。
于是傻傻的 sudo apt upgrade 了一下:


VLC - Android 学习笔记(二)_第3张图片
心疼流量x10

结果并没有起到什么作用,重新运行了一下 vlc/extra/tools/bootstrap ,发现还是不行:

cmake too old
protoc too old

看到 vlc/extra/tools 已经准备好了依赖的源码,顺手就给编译安装了。

重新 bootstrap,没问题了,不禁开始思考我的那么些流量都干了啥...

重新执行了一次 compile.sh ,看后面长度就知道,问题并没有解决。

3.2 尝试指定路径

前面提到了安装了很多iconv,所以感觉会不会是因为路径的问题,隐约记得之前有过冲突导致无法找到的案例:按路径找到了一个依赖,实际的定义却被覆盖到了另一个地方,导致的函数丢失。

在 vlc/configure 里注意到了有这样的参数:

  --with-libiconv-prefix[=DIR]  search for libiconv in DIR/include and DIR/lib
  --without-libiconv-prefix     don't search for libiconv in includedir and libdir

于是在compile-libvlc.sh中添加了

###########################
# VLC CONFIGURE ARGUMENTS #
###########################

VLC_CONFIGURE_ARGS="\
    --with-libiconv-prefix='/usr/local/bin/iconv' \
    ... "

强制指定了iconv的目录位置,很高兴的跑去重新compile.sh(甚至还顺手删了临时文件)

哥们你好,我们又见面了。

同理尝试了without-libiconv-prefix,结果依然。

3.3 去pkg-config看看

既然提到有使用pkg-config去进行定位,那自然应该留有对应的 .pc 文件作为线索,进入到保存索引的目录:vlc/contrib/arm-linux-androideabi/lib/pkgconfig,琳琅满目眼花缭乱的一堆pc文件里,唯独找不见iconv.pc

嗯...突然兴奋.jpg

立马比对着其他的pc文件写了一个iconv的(毕竟iconv除了pc都不缺)

prefix=/usr/local/bin/iconv
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: iconv
Description: GNU libiconv 1.15
Version: 1.15
Libs: -L${exec_prefix}/lib -liconv -lm
Cflags: -I${prefix}/include

手动添加了PKG_CONFIG_PATH之后尝试查找iconv:

hwren@hwren-PC:~/Documents/vlc-android/vlc-android$ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/home/hwren/Documents/vlc-android/vlc-android/vlc/contrib/arm-linux-androideabi/lib/pkgconfig
hwren@hwren-PC:~/Documents/vlc-android/vlc-android$ pkg-config --libs iconv
-L/home/hwren/Documents/vlc-android/vlc-android/vlc/contrib/arm-linux-androideabi/lib -liconv -lm

明显是找到了!

但依然不能解决问题...

大过年的,心塞......

3.4 尝试追踪check的过程

回到问题出现的原因,check的过程中无法找到iconv,那百般尝试失败后只能老老实实看一下到底是怎么check的iconv。

首先是起点:compile.sh,进入下一层的位置:

############
# Make VLC #
############

diagnostic "Configuring"
OPTS="-a ${ANDROID_ABI}"
if [ "$RELEASE" = 1 ]; then
    OPTS="$OPTS release"
fi
if [ "$CHROME_OS" = 1 ]; then
    OPTS="$OPTS -c"
fi
if [ "$ASAN" = 1 ]; then
    OPTS="$OPTS --asan"
fi
if [ "$NO_ML" = 1 ]; then
    OPTS="$OPTS --no-ml"
fi

./compile-libvlc.sh $OPTS

这里进入了第二层:compile-libvlc.sh,这个脚本首先设置了一大堆编译过程中需要的功能(作为Args),之后将这些Args加到脚本上进行编译

###########################
# Build buildsystem tools #
###########################

export PATH="`pwd`/extras/tools/build/bin:$PATH"
echo "Building tools"
cd extras/tools
./bootstrap
checkfail "buildsystem tools: bootstrap failed"
make $MAKEFLAGS
make $MAKEFLAGS .gas
checkfail "buildsystem tools: make"
cd ../..

#############
# BOOTSTRAP #
#############

if [ ! -f configure ]; then
    echo "Bootstraping"
    ./bootstrap
    checkfail "vlc: bootstrap failed"
fi

在这里执行了 bootstrap,参数为 VLC_BOOTSTRAP_ARGS,并把刚刚提到的一些缺失的依赖安装进去。之后继续执行Contribs,完成后进入Configure阶段:

if [ ! -e ./config.h -o "$RELEASE" = 1 ]; then
CFLAGS="${VLC_CFLAGS} ${EXTRA_CFLAGS}" \
CXXFLAGS="${VLC_CXXFLAGS} ${EXTRA_CFLAGS} ${EXTRA_CXXFLAGS}" \
CC="${CROSS_TOOLS}clang" \
CXX="${CROSS_TOOLS}clang++" \
NM="${CROSS_TOOLS}nm" \
STRIP="${CROSS_TOOLS}strip" \
RANLIB="${CROSS_TOOLS}ranlib" \
AR="${CROSS_TOOLS}ar" \
PKG_CONFIG_LIBDIR=$VLC_SRC_DIR/contrib/$TARGET_TUPLE/lib/pkgconfig \
PKG_CONFIG_PATH=$VLC_SRC_DIR/contrib/$TARGET_TUPLE/lib/pkgconfig \
PATH=../contrib/bin:$PATH \
sh ../configure --host=$TARGET_TUPLE --build=x86_64-unknown-linux \
    --with-contrib=${VLC_SRC_DIR}/contrib/${TARGET_TUPLE} \
    ${EXTRA_PARAMS} ${VLC_CONFIGURE_ARGS} ${OPTS}
checkfail "vlc: configure failed"
fi

这里补充了刚刚提到的PKG_CONFIG_PATH,带着一堆参数进入了 configure 里。

Configure啊...好长好长的,盯电脑盯到眼睛疼

其中主要涉及到LIBiconv的地方就是通过各种情况下的判断给LIBICONV路径赋值。

并不觉得有什么异常。

这个过程中突然发现一个很奇怪的现象:添加pkgconfig路径后把参数复制出来单独直接执行vlc源码编译,最终结果竟然成功通过了Configure!?

当然在make的过程中出现了新的错误:

access/live555.cpp:59:24: fatal error: liveMedia.hh: 没有那个文件或目录
 #include 

但这个现象很耐人寻味。

4 计划

很明显问题并没有解决完,师兄也把这次当做练手的机会基本不理我...搞清楚编译的整个过程对我而言算是研究入门很难的一关,但往往探索的过程总是会收获很多。接下来的计划嘛:

  • 考虑完全屏蔽掉vlc编译,使用单独的编译好的vlc作为依赖,直接生成 .so文件
  • 尝试不作任何更改,重新编译最原始的VLC-Android项目
  • 解决make过程中出现的新问题

明天就回家了,终于可以放过我的流量了。

你可能感兴趣的:(VLC - Android 学习笔记(二))