在LINUX下用靜態庫進行鏈接的時候經常會碰到如下情況:存在與靜態庫名一樣的動態庫。以MKL為例,在目錄/MKLROOT/lib/em64t下,庫libmkl_core.a和庫libmkl_core.so同名。這樣的話我們如果在鏈接時加入鏈接的庫名-lmkl_core,編譯器只同動態庫libmkl_core.so鏈接,而屏避掉靜態庫文件libmkl_core.a。所以靜態庫文件里的對象文件無法被鏈接。解決這一問題有兩個辦法:
1. 直接將靜態庫的絕對路徑加到編譯過程中去:
gcc -I$(INCLUDE) -L$(LIB) main.c /MKLROOT/lib/em64t/libmkl_core.a -o a.out
這樣的話編譯器就會根據指定的文件進行編譯鏈接,不過這種做法在靜態庫文件少的時候可用,如果文件一多,就會讓整個指令冗長,可讀性差。下面是一種比較可取的方法。
2. 在目錄/MKLROOT/lib/em64t下用vi編輯器打開一個與所有庫文件都不重名的庫,例如libmkl.a。然后在該文件中加入下面的一行:
GROUP (libmkl_*.a libmkl_*.a libmkl_*.a ............... libmkl_*.a)
(GROUP一定要大寫)
保存退出。之后在編譯程序的時候只要將該文件加入鏈接項就OK了。命令如下:
gcc -I$(INCLUDE) -L$(LIB) main.c -lmkl -o a.out
上面的選項(-lmkl)就相當于讓編譯器gcc到文本文件libmkl.a指定的靜態庫文件中尋找.o文件進行鏈接,而不用人工地將每個靜態庫地址都輸進行。查找.o對象文件的順序從左到右,所以應該將最低層的靜態庫放到最右邊,把需要調用右邊庫里的對象的庫放到左邊,否則會出現找不到對象文件,導致報函數沒定義的錯誤。