2012-03-18 60 views
1

在條件編​​譯特定於平臺的代碼後,我收到了multiple definition鏈接錯誤。與CMake獲取鏈接錯誤

我的項目是佈局是這樣的:

/ 
|__+ include/ 
| |__+ native/ 
| | |__ impl.h 
| | 
| |__ general.h 
| 
|__+ src/ 
    |__+ native/ 
    | |__ impl.linux.c 
    | |__ impl.win32.c 
    | 
    |__ general.c 

general.c文件的頂部:

#if defined(LIBRARY_PLATFORM_LINUX) 
    #include "native/impl.linux.c" 
#elsif defined(LIBRARY_PLATFORM_WIN32) 
    #include "native/impl.win32.c" 
#endif 

我爲了檢測操作系統並定義設置自省中的CMake對應的常量。關鍵是,我不想保持在每個目錄一個CMakeLists.txt文件,所以我乾脆晶片被保護所有.c文件as suggested in this answer

file(GLOB_RECURSE LIBRARY_SOURCE_FILES "${PROJECT_SOURCE_DIR}/src/*.c") 

顯然,這是什麼原因造成的問題。它似乎在編譯general.c中的代碼#include d以及個別的src/native/impl.*.c文件。

CMakeFiles/lib.dir/src/native/impl.linux.c.o: In function `declared_in_impl_h': 
impl.linux.c:(.text+0x0): multiple definition of `declared_in_impl_h' 
CMakeFiles/lib.dir/src/general.c.o:general.c:(.text+0x0): first defined here 

如何解開這種情況?

+0

對你的'impl。*'文件使用不同的擴展名。 – 2012-03-18 04:59:43

回答

2

這種跨平臺情況的最佳實踐是創建兩個庫,一個用於Linux,另一個用於Windows並停止執行條件包含。每個平臺只編譯和鏈接相關的圖書館。

推薦使用cmake做到這一點的方法是停止通配,幷包含每個文件。在某些情況下,它可能會使感到困惑,並且沒有意識到它需要重新編譯。你可以說一個不變的遺留代碼不會有這個問題。

如果你真的想避免做這些事情之一,我會把包含的代碼放在一個頭文件而不是c文件。你並不是真的想要包含這些守衛,這樣人們就不會對它應該像普通頭部一樣使用的東西感到困惑。在文件中加入一些評論,以警告他們的行爲。

+0

我沒有考慮過。現在你提到它了,單獨的庫聽起來更有效率。請,你能詳細說明一下嗎?讓實現本身在同一個項目中共享庫是否合理?他們應該靜態鏈接? – 2012-03-18 05:32:53

+0

@MatheusMoreira赫赫,不知道高效。每個文件都有一個具體的事情,所以你對所發生的事情不會感到困惑。通常你會在自己的庫中有每個實現,然後讓cmake只包含一個或另一個。靜態通常是較少移動的部分,但它並不重要。無論你認爲什麼對項目最有意義。 – 2012-03-18 05:51:58

+0

@MatheusMoreira我更像一個C++的人,所以標註C的最佳實踐可能是過度銷售。我可以看到哪些情況可能會與C很棘手。 – 2012-03-18 05:57:02