2012-01-01 70 views
13

我想知道gcc的靜態選項。我編譯某些應用程序時需要這個選項,但是當我做我得到以下錯誤:-gcc的靜態選項?

gcc -static -O3 -o prog prog.c 
/usr/bin/ld: cannot find -lc 
collect2: ld returned 1 exit status 

需要怎樣安裝?

GCC版本:

[[email protected] dir]$ gcc -v 
Using built-in specs. 
COLLECT_GCC=gcc 
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.6.1/lto-wrapper 
Target: x86_64-redhat-linux 
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux 
Thread model: posix 
gcc version 4.6.1 20110908 (Red Hat 4.6.1-9) (GCC) 

回答

-23

你通常應該避免靜態鏈接你的應用程序(你應該向我們解釋爲什麼你不想通常的動態鏈接)。我建議至少動態鏈接系統庫(特別是libc) - 如果你絕對想要,你可以靜態鏈接不常用的庫。爲什麼你想靜態鏈接你的應用程序?這通常是一個錯誤(因爲你不會從更新系統動態庫中獲益)。特別是來自libcname service switch設施需要動態庫。

您的系統應該已經安裝了提供靜態libc庫的軟件包。在Debian上,它是libc-dev包,但我不知道它在RedHat上是什麼。

要找出gcc呢,它傳遞-v標誌像

gcc -v -static -O3 -o prog prog.c 

但你不應該靜態鏈接您的程序。在我的Debian發行版中,/usr/bin中有700多個程序,並且只有一個是靜態鏈接的。

+0

我不確定它做了什麼。我正在使用一個預先存在的應用程序,出於某種原因,它的makefile中有這個選項。在這一點上,我認爲它不應該再重要。謝謝。 – sj755 2012-01-01 07:25:27

+29

-1:隱藏答案的主要內容是有限的支持事實。 – mattnz 2014-08-29 01:32:17

5

-static標誌強制鏈接只接受靜態庫,而不是任何共享庫。

如果你想使用-static,你必須確保你已經安裝了一個靜態版本的C庫,這可能很難找到(大多數系統不再有靜態C庫)。或者你必須取消-static的效果。然而,在這個例子中,由於鏈接的唯一庫(隱含地)是C庫,所以這會破壞-static的目的。

+1

是否有任何特殊的原因,爲什麼它不應該可以簡單地讓鏈接器靜態連接來自鏈接器可用庫的代碼?即使代碼中的引用被格式化爲必須在運行時解析它們,我認爲應該可以將適當的例程附加到可執行文件,並修補引用,以便它們指向可執行文件內的代碼。 – supercat 2014-08-29 02:23:15

+0

@supercat:在一個普通的歸檔庫中,單獨的對象文件是可單獨識別的,並且可以很容易地從庫中提取並鏈接到可執行文件中。我的印象(半知情)是共享庫不以同樣的方式包含單獨的目標文件,所以你得到了全部或者什麼都沒有。我敢說可能只是將整個共享庫鏈接到可執行文件中,但也可能導致大量未使用的代碼被內置。我知道一些大公司更喜歡使用靜態鏈接來降低意外變化的風險。 – 2014-08-29 05:03:23

+1

即使代碼最終不得不動態加載,我會建議安裝的應用程序默認情況下應該自動獲得大多數庫的副本。如果圖書館需要升級,可以通過讓操作系統爲每個程序設置「升級設置」來處理。如果使用FooLib 1.7的程序注意到安裝了「FooLib 1.8」,它可以允許用戶使用1.7或1.8運行它,並將選擇保存爲默認值]。這樣,如果一個程序有FooLib相關的問題,用戶可以升級它,但事情不會自發改變。 – supercat 2014-08-29 14:53:06

33

-static選項靜態鏈接一個程序,換句話說,它不需要運行時依賴動態庫以運行。

要實現靜態鏈接,需要系統上存在您的庫的存檔(.a)版本。所以/usr/lib/libc.a /usr/lib/crt1.o等...

在現代linux系統上(當你使用紅帽子):當一個二進制鏈接在一起它1)要麼把代碼通過.o和.a文件進入可執行文件,或者2)引入由/lib/ld-linux.so(或/ lib64/ld-linux = x86-64)解析的動態庫(.so)文件。所以)總是在一個衆所周知的地方。

對於您的特定系統,如果某個程序專門爲其創建靜態版本,那麼您需要安裝開發工具的靜態版本。至少需要glibc-static包。你也可能需要libstdC++ - 靜態包。