我很难尝试创建一个共享库,其中ffmpeg库作为静态库“烘焙”。
考虑以下目录架构:
include/
my own .h files
ext/
ffmpeg .h files
lib/
libav*.a archive files (softlinks to the actual .a files)
libValkka.so (my shared library)
test/
mytest.cpp
bin/
(binaries appear here)
我已经走了很长的路(见Including objects to a shared library from a C++ archive (.a))并且库编译好了:( [STUFF]为简洁起见省略了)
/ usr / bin / c ++ -fPIC -std = c ++ 14 -pthread -Iinclude / ext -I / usr / include / libdrm -g -shared -Wl,-soname,libValkka.so -o lib / libValkka .so CMakeFiles / Valkka.dir / src / avthread.cpp.o CMakeFiles / Valkka.dir / src / opengl.cpp.o CMakeFiles / Valkka.dir / src / openglthread.cpp.o [STUFF] CMakeFiles / Valkka.dir / src / filters.cpp.o -lX11 -lGLEW -lGLU -lGL -Wl, - allow-multiple-definition -Wl,-Bsymbolic -Wl, - whole-archive -Wreorder lib / libavdevice.a lib / libavfilter.a lib / libavformat.a lib / libavcodec.a lib / libavutil.a lib / libswscale.a lib / libswresample.a -Wl, - no-whole-archive
然而,在创建可执行文件时 - 他们的源代码不使用任何ffmpeg api(只是我自己的api) - 用:
c ++ -std = c ++ 14 -pthread -Iinclude -Iinclude / ext -Llib test / mytest.cpp -lValkka -g -o bin / mytest
我收到了关于缺少ffmpeg依赖项的大量错误。并非所有东西都缺失,只是一些奇怪的东西:
lib/libValkka.so: undefined reference to `pa_stream_get_index'
lib/libValkka.so: undefined reference to `deflateInit_'
lib/libValkka.so: undefined reference to `pa_stream_get_state'
lib/libValkka.so: undefined reference to `lzma_stream_decoder'
lib/libValkka.so: undefined reference to `BZ2_bzDecompress'
lib/libValkka.so: undefined reference to `vaInitialize'
lib/libValkka.so: undefined reference to `pa_stream_unref'
lib/libValkka.so: undefined reference to `deflateInit2_'
lib/libValkka.so: undefined reference to `snd_pcm_close'
...
lib/libValkka.so: undefined reference to `vaGetDisplayDRM'
lib/libValkka.so: undefined reference to `vaMaxNumEntrypoints'
lib/libValkka.so: undefined reference to `uncompress'
lib/libValkka.so: undefined reference to `pa_stream_drop'
lib/libValkka.so: undefined reference to `pa_context_connect'
lib/libValkka.so: undefined reference to `FT_Get_Kerning'
lib/libValkka.so: undefined reference to `ass_free_track'
lib/libValkka.so: undefined reference to `pa_operation_unref'
lib/libValkka.so: undefined reference to `FT_Stroker_Done'
lib/libValkka.so: undefined reference to `vaTerminate'
lib/libValkka.so: undefined reference to `ass_new_track'
lib/libValkka.so: undefined reference to `jack_client_close'
...
lib/libValkka.so: undefined reference to `xcb_xfixes_query_version'
lib/libValkka.so: undefined reference to `xcb_shape_rectangles'
lib/libValkka.so: undefined reference to `pa_mainloop_free'
lib/libValkka.so: undefined reference to `snd_device_name_hint'
lib/libValkka.so: undefined reference to `vaCreateImage'
lib/libValkka.so: undefined reference to `vaBeginPicture'
lib/libValkka.so: undefined reference to `DtsSetColorSpace'
lib/libValkka.so: undefined reference to `vaDestroyConfig'
lib/libValkka.so: undefined reference to `pa_stream_writable_size'
lib/libValkka.so: undefined reference to `snd_pcm_hw_params_get_buffer_size_max'
lib/libValkka.so: undefined reference to `ass_read_file'
这非常令人沮丧,特别是当我可以看到这些名称包含在共享库中时!...
nm lib / libValkka.so | grep“vaBeginPicture”
给出
U vaBeginPicture
等。我认为这可能是关于归档.a文件的依赖顺序的问题,并且还尝试使用:
..... -Wl, - allow-multiple-definition -Wl,-Bsymbolic -Wl, - start-group -Wl, - whole-archive -Wreorder lib / libavdevice.a lib / libavfilter。 lib / libavformat.a lib / libavcodec.a lib / libavutil.a lib / libswscale.a lib / libswresample.a -Wl, - no-whole-archive -Wl, - end-group
但问题仍然存在。
我已经成功创建了一个共享库,它可以不“烘焙”那些.a档案,即动态依赖于ffmpeg库,并且没有这样的问题。
我感到困惑。我是否误解了一些基本的东西,忘记了一些恼人的链接选项,或两者兼而有之?帮助赞赏!
答案 0 :(得分:2)
您需要将您的共享库链接到ffmpeg所需的第三方/系统库:libbz2,libva,libxcb,libass,freetype2等。实际列表应该位于ffmpeg分发/构建工件中的某个位置(automake' s .pc文件)
忽略 - 一切都不是一个好主意;您的应用程序可能运行正常,但这些未解决的项目仍然存在;一旦击中它们中的任何一个就会崩溃。我的猜测是,他们中的大多数都不会被击中,因为它们是用于你可能不会使用的libavdevice,但仍然是一个坏主意。另外,检查你是否真的需要libavdevice库 - 如果你摆脱那个库,你可能会修剪一下所需库的列表。
答案 1 :(得分:0)
在创建可执行文件时,告诉链接器忽略未解析的符号可以解决问题:
c ++ -std = c ++ 14 -pthread -Iinclude -Iinclude / ext -Llib test / mytest.cpp -lValkka -g -o bin / mytest -Wl, - unresolved-symbols = ignore-all
生成的可执行文件也运行正常。
然而..使用这样的链接器标志让我错误的方式。也许有更好的选择?为什么首先找不到这些符号?
修改强>
根据Andrey的建议,我借助ffmpeg的configure脚本从ffmpeg中剥离了所有外部库。这是一个有点尴尬的过程,所以我创建了一个很好的python脚本,自动完成它。这可能有点矫枉过正,但在这里:
#!/usr/bin/python3
"""
* Creates script "run_configure.bash" that launches ffmpeg's "configure" script with correct parameters (enabling/disabling stuff)
* Run in the same directory where you have ffmpeg's configure script
"""
import subprocess
import os
import re
def features(switch, adstring="", remove=[]):
p=subprocess.Popen(["./configure",switch],stdout=subprocess.PIPE)
st=p.stdout.read()
fst=""
for s in st.split():
ss=s.decode("utf-8")
ok=True
for rem in remove:
if (ss.find(rem)!=-1):
ok=False
if ok: fst+=adstring+ss+" "
return fst
def disable_external():
p=subprocess.Popen(["./configure","-h"],stdout=subprocess.PIPE)
st=p.stdout.read().decode("utf-8")
# find some text tags from the configure output:
# i1=st.find("External library support:")
i1=st.find("themselves, not all their features will necessarily be usable by FFmpeg.")
i2=st.find("Toolchain options:")
st=st[i1:i2]
""" # debugging ..
print(st)
stop
"""
p=re.compile('--(enable|disable)-(\S*)')
switches=[]
for sw in p.findall(st):
if (sw[1] not in switches):
# print(sw[1]) # debugging
switches.append(sw[1])
fst=""
for sw in switches:
fst+="--disable-"+sw+" "
return fst
st ="./configure "
st+="--disable-everything --disable-doc --disable-gpl --disable-pthreads --enable-static --enable-shared "
st+= disable_external()
st+= features("--list-decoders",adstring="--enable-decoder=", remove=["vdpau","crystalhd","zlib"])
st+= features("--list-muxers", adstring="--enable-muxer=")
st+= features("--list-demuxers",adstring="--enable-demuxer=")
st+= features("--list-parsers", adstring="--enable-parser=")
f=open("run_configure.bash","w")
f.write("#!/bin/bash\n")
f.write(st+"\n")
f.close()
os.system("chmod a+x run_configure.bash")
print("\nNext run ./run_configure.bash\n")
"""
For cleaning up .a and .so files, use
find -name *.a -exec ls {} \;
find -name *.so* -exec ls {} \;
"""
希望有人发现它很有用。用python3运行。