美文网首页视频编码学习之路我爱编程
VLC - Android 学习笔记(二)

VLC - Android 学习笔记(二)

作者: 团不慌 | 来源:发表于2018-02-18 22:18 被阅读145次

    狗年的初一大概是我过的最纠结的一次新年了。一个看起来毫不讲理的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里:


    心疼我的流量

    里面明显是有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 <http://gnu.org/licenses/gpl.html>
    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编译说明中有这么一条说明:

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

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


    心疼流量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 <liveMedia.hh>
    

    但这个现象很耐人寻味。

    4 计划

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

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

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

    相关文章

      网友评论

        本文标题:VLC - Android 学习笔记(二)

        本文链接:https://www.haomeiwen.com/subject/vxpbtftx.html