2015-07-19 155 views
3

我將一個AutoTools項目移植到CMake。CMake將共享庫鏈接到靜態庫

自動工具的作用:

  • 建立一些靜態庫
  • 建立一些共享庫和靜態的鏈接到共享
  • 建立一個可執行文件,它鏈接到共享庫

什麼我設法做CMake:

  • 建立一些靜態庫 - add_library(staticfoo <src>)
  • 建一些共享庫 - add_library(sharedfoo SHARED <src>)並將其鏈接 - target_link_libraries(sharedfoo staticfoo)
  • 建立一個可執行文件,它鏈接到共享庫 - target_link_libraries(exe sharedfoo),但拖累再次靜態庫了。

因此,除了共享之外,可執行文件的結果鏈接命令還具有靜態庫。這與AutoTools項目生成的命令不符。

我試過target_link_libraries(sharedfoo PRIVATE staticfoo),但是沒有從靜態庫中獲取符號到共享庫的接口中。

如何獲得沒有「傳遞」行爲的符號?

(以平臺無關的方式)

回答

3

據我所知,CMake的不允許混用靜態和共享庫。

如果您staticfoo庫僅用作其他庫/可執行文件的一部分,你可以將它定義爲

add_library(staticfoo OBJECT <src>) 

,然後使用作爲某種形式的來源時構建其他庫:

add_library(sharedfoo SHARED <src> $<TARGET_OBJECTS:staticfoo>) 

欲瞭解更多信息,請參閱documentation on add_library

+0

CMake不關心你試圖鏈接靜態/動態/混合的類型的庫......這將成爲特定平臺鏈接器的問題。 – zaufi

+0

在窗口上,鏈接器通過鏈接已保存的對象/靜態庫來丟棄導出符號,但解壓縮的對象可以工作。這是爲什麼將對象庫添加到cmake中的主要原因之一。 – Youka

+0

事實上,這是轉換自動工具項目中找到的模式的好方法。對於替代品和他們的問題,看到這個詳細的問題:http://stackoverflow.com/questions/5136184/linking-windows-dll-files-from-static-libraries-using-cmake-without-hand-craftin –

2

要解決這種情況下,你需要做的幾件事情:

  • 首先,確保你已經編譯靜態庫W/-fPIC,所以他們會包含一個重定位代碼(這將是一個部分以後,你需要在編譯所有庫時控制符號的可見性,所以作爲共享庫的一部分,符號來自靜態的將會是可見的
  • 最後,是的,你需要鏈接您的共享庫時指定PRIVATE <static libs>,因此執行程序的鏈接器命令行表不會有任何靜態庫
+0

因此,如何'控制符號可見度'? – Velkan

+0

最明顯的方法是使用'-fvisibility' [編譯器選項](https://gcc.gnu.org/wiki/Visibility)。 CMake> = 3.x具有['CMAKE_ _VISIBILITY_PRESET'](http://www.cmake.org/cmake/help/v3.0/variable/CMAKE_LANG_VISIBILITY_PRESET.html)變量(和相應的[目標屬性](http: //www.cmake.org/cmake/help/v3.0/prop_tgt/LANG_VISIBILITY_PRESET.html))。但不幸的是,它不影響靜態庫。這是一個缺陷,將在即將發佈的[CMake 3.3](http://www.kitware.com/blog/home/post/934)中得到修復。 – zaufi

1

我創建了一個小例子,這不正確的方式,在這裏:https://github.com/CarloWood/cmaketest

它顯示了兩個「靜態」庫,一個有兩個明顯的符號,都與默認情況下,隱藏的符號被添加到共享庫,然後用於鏈接可執行文件。

使用的方法是@Tsyvarev,與@Zaufi提到的VISIBILITY目標屬性相結合。

唯一的非平臺特定的事情(我認爲)是使用__EXPORT宏。如果有人知道如何解決,那也是很好的。

0

查看我的回答here。基本上將/WHOLEARCHIVE,-all_load--whole-archive添加到鏈接器標誌。