簡體   English   中英

如何在鏈接到可執行文件時強制將對象文件包含在靜態庫中?

[英]How to force inclusion of an object file in a static library when linking into executable?

我有一個C ++項目,由於其目錄結構被設置為靜態庫A ,它鏈接到共享庫B ,它鏈接到可執行文件C (這是一個使用CMake的跨平台項目,所以在Windows上我們得到A.libB.dllC.exe ,在Linux上我們得到libA.alibB.soC )圖書館A有一個init函數( A_init ,在A/initA.cpp定義),從庫B的init函數( B_init ,在B/initB.cpp定義)調用,從C的main調用。 因此,在連接時BA_init (和中定義的所有符號initA.cpp )被鏈接到B (這是我們所希望的行為)。

問題在於A庫還定義了一個動態加載的函數( Af ,在A/Afort.f定義)(即Windows上的LoadLibrary / GetProcAddress和Linux上的dlopen / dlsym )。 由於庫B中沒有對Af引用,因此A/Afort.o中的符號不​​包括在B 在Windows上,我們可以通過使用pragma人工創建引用:

#pragma comment (linker, "/export:_Af")

由於這是一個pragma,它只適用於Windows(使用Visual Studio 2008)。 為了使它在Linux上運行,我們嘗試將以下內容添加到A/initA.cpp

extern void Af(void);
static void (*Af_fp)(void) = &Af;

這不會導致符號Af包含在B的最后一個鏈接中。 我們如何強制將符號Af鏈接到B

事實證明我最初的嘗試主要在那里。 以下作品:

extern "C" void Af(void);
void (*Af_fp)(void) = &Af;

對於那些想要一個自包含的預處理器宏來封裝它的人:

#if defined(_WIN32)
# if defined(_WIN64)
#  define FORCE_UNDEFINED_SYMBOL(x) __pragma(comment (linker, "/export:" #x))
# else
#  define FORCE_UNDEFINED_SYMBOL(x) __pragma(comment (linker, "/export:_" #x))
# endif
#else
# define FORCE_UNDEFINED_SYMBOL(x) extern "C" void x(void); void (*__ ## x ## _fp)(void)=&x;
#endif

因此使用的是:

FORCE_UNDEFINED_SYMBOL(Af)

MSVC #pragma comment(linker, "/include:__mySymbol")

gcc -u symbol

有一種更好的方法來編寫FORCE_UNDEFINED_SYMBOL宏。 只需將該函數指針強制轉換為void *即可。 然后它適用於任何功能 - 或者數據。 此外,當宏的gcc部分也適用於MSVC時,為什么還要使用MSVC編譯指示。 所以我的簡化版本是:

#define FORCE_UNDEFINED_SYMBOL(x) void* __ ## x ## _fp =(void*)&x;

因此使用的是:

FORCE_UNDEFINED_SYMBOL(Af)

但它必須在包含其符號被剝離的庫的程序中使用。

您可以在構建B時使用--undefined選項:

g++ -Wl,--undefined,Af -o libB.so ...

嘗試將這些行放入B/initB.cpp以便它們(希望)在鏈接時強制進入libB.so庫。

但是你為什么要以這種方式去做呢? 你不能設置它,以便可執行文件引用該函數(或它的調用者),導致鏈接器自動執行正確的操作嗎?

如果你可以使用gcc的C ++ 0x特性( -std = c ++ 0x ),那么函數默認模板參數就可以了。 從當前的c ++標准來看,函數模板不允許使用默認參數。 在c ++ 0x中啟用這些功能后,您可以執行以下操作: -

在靜態庫的一些頭文件中......

template< class T = int >
void Af()
{
}

然后在其對應的cpp文件中使用顯式模板實例化...

template void Af();

這將生成函數Af的符號,盡管它尚未被調用/引用。 這不會影響調用者,因為由於默認模板參數,您無需指定類型。 只需在函數聲明之前添加template <class T = int > ,並在其實現文件中顯式實例化它。

HTH,

暫無
暫無

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

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