2013-01-15 52 views
2

我想通過Makefile.PL在linux主機上建立DBD :: Pg;我的要求是這樣的,我必須能夠動態鏈接到perl,但靜態鏈接到libpq.so(因爲它可能不適用於所有的盒子)。靜態鏈接DBD :: Pg(針對libpq.so)但動態地反對Perl?

有沒有簡單的方法來做到這一點?我試過改變Makefile.PL的LIBS指令中的鏈接選項,但MakeMaker忽略了我的選項。

回答

2

IMO你錯誤地指定了你的要求。

您不需要靜態鏈接到libpq,因爲它可能不適用於所有系統。

什麼,你通常應該做的,而不是爲動態鏈接到libq,要麼在一個包裝腳本設置LD_LIBRARY_PATH或使用rpath鏈接,這樣libpq可以找到。

要知道,雖然無論是靜態或動態鏈接,如果一些其它的模塊加載libpq到同一個Perl的你會要麼得到兩個不兼容的libpq s鏈接,進入同一個可執行文件(熱潮)或使用libpq一個模塊除了它被編譯的那個(也是繁榮)之外。如果您使用rpath鏈接,ld.so對鏈接範圍的瞭解可能會讓您放棄,但設置LD_LIBRARY_PATH幾乎肯定會導致問題。

您可能想用rpath$ORIGIN進行調查。

+0

我不確定我是否按照你的回答;我怎樣才能保證我的模塊在運行時工作(就擁有正確的庫而言)? – Blaskovicz

+0

使用'rpath'或'LD_LIBRARY_PATH'。 –

+0

不要同時以不同的方式修改庫的搜索路徑嗎?我在說我想在框X(它有libpq)上構建模塊並在框Y(它沒有libpq)上運行它。也許我沒有追隨;我不是非常精通任何方式進行鏈接/編譯。 – Blaskovicz

2

不幸的是,試圖做靜態鏈接的libpq不可能解決你的問題。

libpq本身很可能取決於libcglibc)。如果您將其靜態鏈接,但是其他模塊動態鏈接,則意味着您將擁有libc的兩個副本:一個在libpq之內,另一個由Perl本身引用並動態加載。這是非常危險的情況,特別是如果某些過程使用malloc分配內存並將指針傳回給調用者。如果你有一個由malloc從libc的一個拷貝分配的內存,但free由另一個拷貝拷貝,你的程序(和Per​​l)肯定會崩潰。

換句話說,如果你想要去的靜態,你必須一路通 - 一切,必須100%進行靜態編譯,所以libc只有一個副本使用你的應用程序。而事實恰恰相反 - 如果你是動態的,一切都應該是動態的,因爲只有使用libc的一個副本。這些規則僅適用於您的庫不使用libc(甚至不包括sprintf)中的任何內容。

即使您在靜態編譯libpq並且它將工作(不太可能),如果未安裝DBI會怎麼樣?我已經看到了足夠的Linux框,其中DBI默認不存在。你是否也靜態編譯DBI?如果Perl不存在(如果不是這種情況發生在Linux上),或者如果它很舊?

妥善解決是使用本地OS包管理器進行安裝:

sudo apt-get install libdbd-pg-perl # Ubuntu/Debian 
sudo yum install perl-DBD-Pg   # Redhat/Fedora 

如果你沒有在主機上根的問題,也許你應該考慮使用perlbrew - 在主目錄中安裝自己的Perl。有了這個,你應該能夠編譯你自己的libpq副本,並將它與動態提供的Perl鏈接perlbrew連接起來。

+0

對靜態鏈接+1的問題很好的解釋 –