首先從Linux下開始講起,因為Linux編程對程序的理解要清楚一些,相比之下VC就比較容易糊塗。
當動態編譯時,你發布的程序體積較小,在運行的時候需要同時提供你用到的dll / so文件。
當靜態編譯時,你發布的程序體積較大,包含所有符號,運行時不需要其他的 dll / so的支持,可以獨立運行。
靜態編譯的目的是使發布的程序可以獨立運行,不依賴於其他*.so,在技術上是把所有依賴的符號打包鏈接進了目標程序。這時候你會發現編譯出來的程序的體積要大一些(Link的速度也會慢一些)。
編譯過程分為compile和link,所謂靜態編譯和動態編譯說的是Link過程的選項。
Linux下默認是動態編譯,當使用 -static 或者直接指定全路徑的方式來引入static library。在Linux下,可以很清楚的看到某個符號(函數或全局變量)是否在程序中。使用nm命令可以查看所有符號,或者用objdump命令可以看得更詳細一些。
nm helloword
以T標識的符號表示在該文件中有具體的代碼,在D標識的符號表示此符號是外部符號,定義在其他*.so庫裡。我們在編譯過程中的undifined reference錯誤,就是指的是這個問題。
調試符號: 一個程序使用 -g 參數編譯時,編譯出來的程序可以被gdb來調試。其中-g的意思是指示g++/gcc在編譯的時候把調試信息一並寫到輸出文件裡。
用objdump -h 命令可以查看一個程序裡面有沒有調試符號(即有沒有.debug開頭的若干segment存在)
------------------------------------------------------------------------------------
在VC下面,有4個參數是跟靜態/動態編譯有關的。 /MD /MDd /MT /MTd
其中, MT , MTd可以認為是靜態編譯。也就是說,設置成MT, MTd後編譯出來的*.exe程序在運行時是帶了符號的。而MD MDd是不帶符號的。後面的小寫的d表示是否允許調試,允許調試的含義是在編譯這個程序的同時把調試信息(函數名、位置、變量信息)加到輸出程序裡了,使得該程序可以被debug斷點跟蹤。 這個相當於 Linux下的-g選項。
如果以MD MDd編譯,則你的程序不能在別人的機器上運行,除非別人的機器先安裝了所依賴的庫(又叫runtime dll 運行時庫),即以下幾個文件:
msvcm90.dll
msvcp90.dll
msvcr90.dll
Microsoft.VC90.CRT.manifest
注意那個manifest也是必須的,錯了也不行。
以MT, MTd編譯的程序是不需要這些runtime dll的。不過如果你在程序中調用了其他第3方dll,而那些dll還是要附上的。進一步的,如果那些dll是以MD編譯的話,你還是要把上術runtime dll安裝上(因為你依賴的dll又依賴了runtime dll)。不過正常情況下發布的dll應該是MT編譯的,所以不用擔心人家的dll有什麼問題,把自己的程序編好再說。
Linux下靜態編譯Qt http://www.linuxidc.com/Linux/2011-05/35581.htm
模塊靜態編譯到內核和編譯成模塊實例 http://www.linuxidc.com/Linux/2011-09/42068.htm