kinzess / blog

just a blog
3 stars 1 forks source link

ubuntu 18.04下编译windows版本的VLC 3.0.8 #6

Open kinzess opened 4 years ago

kinzess commented 4 years ago

第一次尝试在linux下编译windows的程序,踩了不少坑,特此记录一下。

VLC本身比较难编译,看了很多中文的教程,都吐槽说官方教程不靠谱,但我编译到最后,发现还是官方教程最靠谱。照着官方教程做下来,坑是最少的。 此处附上官方教程地址: https://wiki.videolan.org/Win32Compile/

一开始使用的是ubuntu 16.04,发现很多依赖包版本太老,就换成了18.04。 安装的是Mingw-w64环境,编译64版本。 这里注意官方教程有一句话:

NB: you need mingw-w64 version 5.0.1 to compile it.

而18.04默认安装的mingw是5.0.3,但对应的gcc7.3,编译到后面会出现问题,建议先升级到19.04的6.0.0。 具体升级方法看后文。 如果不想浪费时间,一定要先升级! 此处可能把ubuntu换成19.04更好。但因为一开始不知道,ubuntu还是使用18.04,只是升级了mingw到19.04的版本。

首先编译第三方库,注意因为编译的是3.0.8版本的VLC,必须使用Manually built方式,不能使用Prebuilt方式。 一路安装下来,如果提示缺少包,直接apt安装即可。大部分依赖都可以用这种方式安装。 如果遇到提示安装meson的版本太低,则可以卸载apt安装的版本,然后用pip3安装即可。

一个比较坑的问题,是在编译gcrypt的时候,提示syntax error:

/bin/bash ../libtool --mode=compile --tag=RC x86_64-w64-mingw32-windres -DHAVE_CONFIG_H -I. -I../../src -I..     -i "versioninfo.rc" -o "versioninfo.lo"
libtool: compile:  x86_64-w64-mingw32-windres -DHAVE_CONFIG_H -I. -I../../src -I.. -i versioninfo.rc  -o .libs/versioninfo.o
x86_64-w64-mingw32-windres: versioninfo.rc.in:21: syntax error
Makefile:1240: recipe for target 'versioninfo.lo' failed
make[2]: *** [versioninfo.lo] Error 1

原因是configure.ac里,写死了一些git的操作。而vlc编译的源码,是tar包,没有git的相关信息,导致编译失败。具体可以参考https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=814954

--- a/configure.ac
+++ b/configure.ac
@@ -39,7 +39,7 @@
 m4_define(mym4_version,
           [mym4_version_major.mym4_version_minor.mym4_version_micro])
 m4_define([mym4_revision],
-          m4_esyscmd([git rev-parse --short HEAD | tr -d '\n\r']))
+          m4_esyscmd([printf %x $(wc -l < debian/changelog)]))
 m4_define([mym4_revision_dec],
           m4_esyscmd_s([echo $((0x$(echo ]mym4_revision[|head -c 4)))]))
 m4_define([mym4_betastring],

修改configure.ac,跳过git操作即可。

另一个比较坑的问题,是在编译glew的时候,提示找不到依赖库:

x86_64-w64-mingw32-ld -o lib/glew32.dll src/glew.o -L/mingw/lib -lglu32 -lopengl32 -lgdi32 -luser32 -lkernel32
x86_64-w64-mingw32-ld: cannot find -lglu32
x86_64-w64-mingw32-ld: cannot find -lopengl32
x86_64-w64-mingw32-ld: cannot find -lgdi32
x86_64-w64-mingw32-ld: cannot find -luser32
x86_64-w64-mingw32-ld: cannot find -lkernel32
Makefile:101: recipe for target 'lib/glew32.dll' failed

查了很久才发现,是“-L/mingw/lib”的问题。在windows下用mingw编译,路径就是“/mingw/lib”,但是,在linux下编译,路径就不是这个了。 首先使用x86_64-w64-mingw32-ld命令,通过SEARCH_DIR确定mingw的lib路径:

$ x86_64-w64-mingw32-ld --verbose | grep SEARCH_DIR | tr -s ' ;' \\012
SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu")
SEARCH_DIR("=/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/local/lib")
SEARCH_DIR("=/lib")
SEARCH_DIR("=/usr/lib")
SEARCH_DIR("=/usr/x86_64-w64-mingw32/lib")

可以看到,路径是“/usr/x86_64-w64-mingw32/lib”。 查到路径后,修改glew/config/Makefile.mingw文件,把里面的“/mingw/lib”修改成“/usr/x86_64-w64-mingw32/lib”,就可以继续编译了。

编译完第三方库,按照教程,继续编译VLC。 但一部分插件会无法编译,错误如下:

CXXLD libdcp_plugin.la
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_Z35_txnal_cow_string_C1_for_exceptionsPvPKcS_+0x2c): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_ITM_RU1'
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_Z35_txnal_cow_string_C1_for_exceptionsPvPKcS_+0x39): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `transaction clone for operator new[](unsigned long long)'
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_Z35_txnal_cow_string_C1_for_exceptionsPvPKcS_+0x5d): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_ITM_memcpyRtWn'
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_Z23_txnal_cow_string_c_strPKv+0x1): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_ITM_RU8'
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_Z23_txnal_sso_string_c_strPKv+0x1): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_ITM_RU8'
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_Z20_txnal_cow_string_D1Pv+0x5): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_ITM_RU8'
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_Z20_txnal_cow_string_D1Pv+0x1e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_ITM_addUserCommitAction'
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_ZGTtNSt11logic_errorC1EPKc+0x2e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_ITM_memcpyRnWt'
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_ZGTtNSt11logic_errorC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+0x2e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_ITM_memcpyRnWt'
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_ZGTtNSt11logic_errorC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+0x36): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_ITM_RU8'
/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/libstdc++.a(cow-stdexcept.o):(.text$_ZGTtNSt11logic_errorD0Ev+0x1a): additional relocation overflows omitted from the output
collect2: error: ld returned 1 exit status
Makefile:13212: recipe for target 'libdcp_plugin.la' failed

这是一个存在于6和7版本gcc的bug,gcc8已经修复。 详细信息可以查看论坛:https://forum.videolan.org/viewtopic.php?t=144693 而18.04安装的gcc版本是7.3,所以会碰到这个bug。 修复方法是升级gcc,或者修改libstdc++的os_defines.h文件,并重新编译工具链。 这里我采用的是升级gcc7到gcc8的方法。 卸载所有mingw的包,直接下载安装ubuntu 19.04的mingw安装包即可。 可以直接使用包名去搜索,很容易就能搜索到下载地址。此处不提供下载地址。 注意mingw的gcc包换了,那对应的mingw包也要换,不然头文件会冲突。

gcc-mingw-w64-base_8.3.0-6ubuntu1+21.1build2_amd64.deb
gcc-mingw-w64-x86-64_8.3.0-6ubuntu1+21.1build2_amd64.deb
g++-mingw-w64-x86-64_8.3.0-6ubuntu1+21.1build2_amd64.deb
mingw-w64-common_6.0.0-3_all.deb
mingw-w64-tools_6.0.0-3_amd64.deb
mingw-w64-x86-64-dev_6.0.0-3_all.deb

替换上述6个包后,必须从头开始,从第三方库开始编译,不然也会出现问题。T_T... 如果还需要编译32位的vlc,则还需要安装以下几个包:

gcc-mingw-w64-i686_8.3.0-6ubuntu1+21.1build2_amd64.deb
g++-mingw-w64-i686_8.3.0-6ubuntu1+21.1build2_amd64.deb
mingw-w64-i686-dev_6.0.0-3_all.deb

安装方法是:

$ sudo dpkg -i *.deb
$ sudo apt install -f

另外,在编译的时候,如果系统安装了protobuf,则需要检查是不是3.1.0版本,不然会出现以下问题:

make[4]: Entering directory 'vlc-3.0.8-win64-gcc8.3/win32/modules'
  CXX      stream_out/chromecast/libstream_out_chromecast_plugin_la-cast.lo
In file included from vlc-3.0.8-win64-gcc8.3/contrib/x86_64-w64-mingw32/include/google/protobuf/stubs/common.h:40,
                 from stream_out/chromecast/cast_channel.pb.h:9,
                 from ../../extras/package/win32/../../../modules/stream_out/chromecast/chromecast.h:45,
                 from ../../extras/package/win32/../../../modules/stream_out/chromecast/cast.cpp:33:
vlc-3.0.8-win64-gcc8.3/contrib/x86_64-w64-mingw32/include/google/protobuf/stubs/port.h:56:7: warning: "_MSC_VER" is not defined, evaluates to 0 [-Wundef]
   #if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
       ^~~~~~~~
In file included from ../../extras/package/win32/../../../modules/stream_out/chromecast/chromecast.h:45,
                 from ../../extras/package/win32/../../../modules/stream_out/chromecast/cast.cpp:33:
stream_out/chromecast/cast_channel.pb.h:17:2: error: #error This file was generated by an older version of protoc which is
 #error This file was generated by an older version of protoc which is
  ^~~~~
stream_out/chromecast/cast_channel.pb.h:18:2: error: #error incompatible with your Protocol Buffer headers. Please
 #error incompatible with your Protocol Buffer headers.  Please
  ^~~~~
stream_out/chromecast/cast_channel.pb.h:19:2: error: #error regenerate this file with a newer version of protoc.
 #error regenerate this file with a newer version of protoc.
  ^~~~~
Makefile:25318: recipe for target 'stream_out/chromecast/libstream_out_chromecast_plugin_la-cast.lo' failed

就是vlc需要用到的protobuf版本和系统安装的版本不一致。 运行命令可以检查是否安装了其他版本的protobuf:

$ locate protobuf
$ dpkg -l |grep protobuf

检查后,系统的确安装了protobuf,需要卸载: sudo apt autoremove libprotoc10 libprotobuf10 protobuf-compiler 注意这里会把protobuf-compiler卸载掉,会导致第三方库里的projectM无法编译。 需要自己编译安装protobuf的3.1.0版本,简单的方法是:

$ cd protobuf-3.1.0
$ ./autogen.sh
$ ./configure --prefix=/usr
$ make
$ make check
$ sudo make install

安装好之后,继续需要从头开始,从第三方库开始编译T_T...

一切顺利的话,vlc就编译好了。 然后打包: $ make package-win-common 因为我的源码是直接下载的压缩包,里面没有hrtfs目录下的文件,所以不能打包。 从git下载后,放到对应目录,再运行打包命令就可以了。 打包完成后,里面多了一个目录vlc-3.0.8,比起直接安装的vlc,里面的dll都带了调试信息,也多了一个sdk的目录,里面包括头文件和lib文件。 这是用来二次开发的,如果不需要,可以运行其他打包命令。

至此,vlc算是编译完成了。 花了2天的时间才搞定,整体来说难度不小。 主要还是要沉下心来,遇到一个问题解决一个,才能编译成功。

后续还要进行二次开发,有问题再更新把。

qdzhaozx commented 3 years ago

哥们,牛逼

HelloTodayWolrd commented 2 years ago

帮了大忙,感谢!