VS2017也推出很久了,在單位的時候寫linux的服務端程序只能用vim,這讓用慣了IDE的我很難受。
加上想自己擼一套linux上的輪子,決定用VS開工遠程編寫調試linux程序。
在windows下編寫靜態庫並在另一個項目中引用很簡單
新建項目的時候選擇靜態庫,進去把代碼擼好,即可編譯出靜態庫*.lib
隨后在希望使用該靜態庫的項目中設置一下鏈接器“附加庫目錄”為"../Debug"(和你的輸出路徑有關),然后添加"附加依賴項"靜態庫名.lib",然后就可以順利的編譯靜態庫了。
但是在linux下這件事卻讓我頭疼了幾天,我一開始也准備按照windows下的套路來解決,解決在新建項目的時候壓根沒看到靜態庫這一選項……
不過還好在常規里面找到了“配置類型”選項,設置成“靜態庫(.a)”就可以了。
在准備使用靜態庫的時候,真正的麻煩來了,一開始我按照windwos下的思路,當前項目鏈接時的工作目錄就是解決方案的路徑,所以按照編譯出來的文件結構寫下了“附加庫目錄”(../common/bin/x64/Debug),然后去填寫“附加依賴項”(“libcommon.a”),編譯的時候就華麗麗的出錯了,提示沒有這個文件……
后來嘗試過吧“libcommon.a”改成““common””、“附加庫目錄”直接指定成linux上的絕對地址等方案,但是很可惜沒有任何一個方案可以。
在linux下自己寫參數指定絕對地址能夠順利將靜態庫鏈接成功,但是用vs的環境卻總是失敗,這個時候有點讓我懷疑人生了。
甚至一度想用VS寫好代碼然后去linux下寫MAKEFILE,手動編譯。但是轉念一想,這豈不是回到遠古時代了?不行,我得干掉這個問題。
后來突發奇想,寫了一個小程序myhelp,放進了usr/bin/中

int main(int argc,char **argv) { char buf[80]; getcwd(buf, sizeof(buf)); std::ofstream f; f.open("/home/reskai/work.txt"); if (f) { f << buf; f << "\r\n"; while (argc-- > 0) { f << *argv++ << "\r\n"; } f.close(); } return 0; }
myhelp用來獲取當前的工作目錄,以及將調用的參數全部輸出到文件當中。
隨后更改項目的鏈接器,用myhelp替換掉g++來當鏈接器,得到了一些有意思的信息
/home/reskai myhelp -o /home/reskai/projects/projectK/bin/x64/Debug/projectK.out -Wl,--no-undefined -Wl,-L../common/bin/x64/Debug -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack /home/reskai/projects/projectK/obj/x64/Debug/main.o libcommon.a
在遠程調用linux的時候,當前的工作目錄不是項目路徑而是~/……恩……就是這個我想當然的原因導致我一直沒能夠成功編譯
然后我就去改了“附加庫目錄”,設置到了正確的位置,隨后重新鏈接……我再次懷疑人生,仍然無法找到文件。(其實這個時候應該想到的,之前我設置附加庫目錄為絕對地址仍然無法鏈接說明了這個選項還是有bug的)
最后沒有辦法的情況下,我試着將“附加庫目錄”給刪除了,然后在"附加依賴項"中直接填入完整的靜態庫路徑“./projects/common/bin/x64/Debug/libcommon.a”,這次終於通過鏈接了。
用此文記錄下我遇到的這個問題與思考方法以及最終的解決方案。
都過了半年了……不過找到了一個完美的解決方案,順手來記錄一下吧
鏈接器-常規-附加庫目錄 里面填上完整靜態庫的目錄,因為默認工作目錄是~,所以填 ./projects/outBin/staticLib/
然后鏈接器-輸入-庫依賴項 里面一行填一個靜態庫的名稱。
因為我生成了兩個靜態庫libnetX64D.a libcommonX64D.a,其中net庫依賴common,common又依賴的pthread,所以填入
netX64D
commonX64D
pthread
必須一行一行的填……VS傻傻的給每一行前面加上一個-l