2017-10-08 179 views
0

我很難嘗試創建一個共享庫,並將ffmpeg庫「烘烤」爲靜態庫。創建一個靜態包含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。所以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 -lX1 1 -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輪候冊, - 無全歸檔

但是,在創建可執行文件時, - 他們的源代碼,不使用任何ffmpeg的API(只我自己的API) - 與:

C++ -std = C++ 14 -pthread -Iinclude -Iinclude/EXT -llib測試/ mytest.cpp -lValkka -g -o倉/ 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」

üvaBeginPicture

等等。我想這可能是關於相關性順序.a文件歸檔中的問題,也試圖與:

.....輪候冊, - 允許用多重定義-Wl,-Bsymbolic -Wl, - 啓動組輪候冊, - 全存檔-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 -Wl, - end-group

但問題依然存在。

我已經成功創建了一個共享庫,它不會而是「烘烤」那些.a檔案,即只是動態地依賴於ffmpeg庫,並且沒有這樣的問題。

我很困惑..我誤解了一些基本的東西,忘記了一些惱人的鏈接選項,或兩者兼而有之?幫助讚賞!

回答

2

您需要將共享庫與ffmpeg的要求第三方/系統庫鏈接:libbz2,libva,libxcb,libass,對FreeType2等實際列表應該ffmpeg的分佈在某個地方/構建工件(automake的的.PC文件)

忽略 - 一切都不是一個好主意;你的應用程序可能運行正常,但這些未解決的項目仍然存在;一旦命中任何一個,它就會崩潰。我的猜測是,他們中的大多數不會被擊中,因爲他們是libavdevice,你甚至可能沒有使用,但仍然是一個壞主意。另外,檢查你是否真的需要這個libavdevice庫 - 如果你擺脫了那個,你可能會修剪一些需要的庫。

+0

嘗試刪除libavdevice,但它沒有解決問題。因此,從靜態編譯的「.a」檔案(烘焙到我的共享庫)到另一個庫的任何引用都將被打破,然後......?也就是說,「依賴鏈」一般會在鏈條中存在靜態庫時被打破。這裏有一些討論.. https://stackoverflow.com/questions/7841920/how-do-static-libraries-do-linking-to-dependencies ..任何提示ffmpeg的配置腳本創建一個庫(幾乎)沒有依賴呢? –

+0

ffmpeg作爲靜態庫對其他庫中的許多依賴項沒有明確存在於歸檔文件中;任何具有外部引用的靜態庫都是這種情況。猜猜這是你的意思是破壞依賴鏈?無論如何,您需要手動鏈接您的共享庫和這些依賴關係(或者使用automake/cmake /任何可以爲您完成的構建系統)。刪除libavdevice不會刪除所有這些依賴關係,但它會刪除一些(至少是jack,oss,pulseaudio)。您可以在沒有大多數庫的情況下構建ffmpeg,但它將會非常小構建 –

+0

因此,當創建我的共享庫時,我必須在那裏放置所有鏈接到例如pulseaudio,oss的「-L」和「-l」開關,vdpau-thingies等?好的.. thx! –

0

告訴接頭忽略未解析的符號創建可執行文件是卓有成效的時:

C++ -std = C++ 14 -pthread -Iinclude -Iinclude/EXT -llib測試/ mytest.cpp -lValkka - g -o bin/mytest -Wl, - unresolved-symbols = ignore-all

生成的可執行文件也運行正常。

但是,使用這樣的鏈接器標誌擦我錯了。也許有更好的選擇?爲什麼這些符號不是首先找到的?

編輯

繼安德烈的建議下,我去除了所有外部庫從ffmpeg的,與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運行。