簡體   English   中英

將共享庫與靜態庫鏈接:靜態庫的編譯方式必須與應用程序鏈接它的方式不同嗎?

[英]Linking a shared library against a static library: must the static library be compiled differently than if an application were linking it?

至少在Linux和Solaris上,靜態庫實際上只是一堆編譯好的.o文件被扔進一個大文件中。 編譯靜態庫時,通常會忽略-fpic標志,因此生成的代碼與位置有關。

現在說我的靜態庫是B.我已經構建了它並且得到了.a文件,它實際上只是所有位置相關的.o文件的全局。 現在我有一個我想構建的共享庫,A,我希望它靜態鏈接B.當我構建A時,我自然會使用-fpic標志使生成的代碼位置獨立。 但是,如果我鏈接B,我不是混合位置依賴和位置獨立的目標文件?

除非我還指定-mimpure-text,否則我會收到很多文本重定位錯誤,我認為這可能是原因。 看來,當我編譯一個庫時,我真的需要編譯它3次,共享版本,靜態版本和靜態 - 可以使用的共享庫版本。 我對嗎? 我可以繼續使用-mimpure-text,但g ++手冊頁說如果你這樣做,對象實際上並沒有最終被共享(不清楚它是否全部未被共享或只是靜態鏈接的部分,但有人知道嗎?) 。

您不必在共享對象中使用PIC代碼(因為您發現可以使用-mimpure-text選項來允許)。

也就是說,共享對象中的非PIC代碼更重要。 使用PIC代碼,內存中的文本頁面只是磁盤上文本頁面的直接內存映射。 這意味着如果多個進程正在使用共享對象,則它們可以共享內存頁面。

但是,如果您沒有PIC代碼,則當運行時鏈接程序加載共享對象時,它必須將修正應用於文本頁面。 這意味着使用共享對象的每個進程都將擁有其自身唯一版本的任何文本頁面,該文本頁面上有一個修復程序(即使共享對象加載到與寫入時復制相同的地址,也只注意到該頁面是修改,而不是以相同的方式修改)。

對我來說,重要的問題是你是否會同時運行多個進程,每個進程都加載共享對象。 如果你這樣做,絕對值得確保SO中的所有代碼都是PIC。

但如果情況並非如此,並且只有一個進程加載了共享對象,那么它就不那么重要了。

我在鏈接階段為靜態庫的共享對象庫版本執行以下操作:g ++ -shared -o libshared.so -Wl, - whole-archive -fPIC -lstatic -Wl, - no-whole-archive。 由於--whole-archive鏈接(列表)靜態庫(形式為libstatic.a)中的每個對象,我相信在(list)之前使用-fPIC是所有OP需要做的。

作為替代方法,運送兩個庫:您的共享庫和您要鏈接的靜態庫。 它們應該正確鏈接到最終的可執行文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM