一、 統(tǒng)一的預(yù)處理、編譯、鏈接程序
一、1. 有些程序同時(shí)具有如下功能:
1. 預(yù)處理C/C++源代碼
2. 編譯C/C++源代碼
3. 鏈接C/C++目標(biāo)代碼
例如:GCC的gcc、g++,MSVC的cl.exe。
一、2. 實(shí)際的情況也許更加復(fù)雜:
gcc、g++、cl.exe很有可能只是一個(gè)啟動(dòng)器。
用戶只需要使用它們, 它們內(nèi)部再根據(jù)特定條件, 執(zhí)行其他程序,比如:
1. gcc、g++編譯C/C++代碼時(shí), 最終會(huì)執(zhí)行cc1/cc1plus程序。
該程序可能才是真正的C/C++編譯器。
2. gcc、g++在鏈接C/C++目標(biāo)代碼時(shí),最終會(huì)執(zhí)行ld程序。
該程序可能才是真正的鏈接器。
3. cl.exe程序自己處理C/C++代碼的預(yù)處理與編譯工作。
4. cl.exe程序鏈接時(shí),將執(zhí)行link.exe。
該程序可能才是真正的鏈接器。
一、3. 我們的關(guān)注點(diǎn)
——上述復(fù)雜的情況我們大多數(shù)情況下無須操心:
1. 我們只需要使用gcc、g++
即使以后GCC將cc1、cc1plus、ld改為別的名字也不會(huì)受影響。
2. 我們只需要使用cl
即使以后cl不再擔(dān)任編譯工作或者link.exe被改為別的名字,同樣不受影響。
——我們需要關(guān)心這些統(tǒng)一的程序,是根據(jù)何種條件, 決定它們的操作的?
本文只討論編譯:
1. 它們默認(rèn)是通過何種條件, 決定按C語法或按C++語法編譯一個(gè)翻譯單元的。
2. 如何顯式指定按C語法或者按C++語法去編譯一個(gè)翻譯單元。
二、 默認(rèn)情況
如果不顯式指定操作, gcc、g++、cl都是按文件后綴名來決定操作的。
二、1. 測(cè)試文件:
#ifndef __cplusplus
/* being treated as C translation unit */
#error !--- C ---!
#else
// being treated as C++ translation unit
#error !--- C++ ---!
#endif
我們建一個(gè)沒有后綴的文件,叫nosuffix, 寫入如上內(nèi)容。
而且, 我們也不需要編譯出目標(biāo)代碼。
只需要測(cè)試__cplusplus宏(見《預(yù)定義__cplusplus宏》)是否存在,并且用#error報(bào)告即可。
然后建立一些內(nèi)容完全一樣的文件:
#include "nosuffix"
這些文件共有10個(gè):
c.c、 cpp.cpp、txt.txt、UC.C、UCPP.CPP、cc.cc、cxx.cxx、inl.inl、c++.c++、cp.cp。
(UC和UCPP是為了測(cè)試大寫后綴名)
二、2. 測(cè)試方法
對(duì)GCC使用:
gcc(g++) filename >stdout.txt 2>stderr.txt
對(duì)MSVC使用:
cl filename >stdout.txt 2>stderr.txt
二、3. 測(cè)試結(jié)果
gcc、g++、cl對(duì)以下后綴名文件的默認(rèn)操作如下表:
|
nosuffix
|
.c
|
.cpp
|
.txt
|
.C
|
.CPP
|
.cc
|
.cxx
|
.inl
|
.c++
|
.cp
|
gcc
|
obj
|
C
|
C++
|
obj
|
C++
|
C++
|
C++
|
C++
|
obj
|
C++
|
C++
|
g++
|
obj
|
C++
|
C++
|
obj
|
C++
|
C++
|
C++
|
C++
|
obj
|
C++
|
C++
|
cl
|
obj
|
C
|
C++
|
obj
|
C
|
C++
|
C++
|
C++
|
obj
|
obj
|
obj
|
對(duì)該表的幾點(diǎn)說明:
1. 表中的obj表示該條件下, 統(tǒng)一程序?qū)⑺鼈冋J(rèn)作目標(biāo)文件, 并打算執(zhí)行鏈接工作。
這顯然是錯(cuò)誤的, 因?yàn)樗麄儼氖俏谋尽?br>
2. gcc、g++(編譯代碼)的區(qū)別
GCC認(rèn)為帶有.c、.cpp、.C、.CPP、.cc、.cxx、.c++、.cp(但不限于)后綴的文件是C/C++源文件。
gcc把帶有.c后綴的文件, 當(dāng)作C源文件, 把帶有其他后綴名的文件當(dāng)作C++源文件。
g++將帶有上述所有后綴的文件,都當(dāng)作C++源文件。
3. MSVC與GCC的區(qū)別
MSVC認(rèn)為帶有.c、.cpp、.C、.CPP、.cc、.cxx后綴的文件是C/C++源文件。
上述GCC相比, 排除了.c++和.cp
同時(shí),windows下的文件名是不區(qū)分大小寫的, 所以.c同.C,.cpp同.CPP是一樣的。
與GCC相比, .C不再認(rèn)為是C++源文件, 而是與.c一樣作為C源文件處理。
二、4. 測(cè)試小結(jié)
由上表以及說明, 如果我們打算
編寫跨平臺(tái)的代碼:
1. 不推薦使用的后綴名
.c++、.cp
——因?yàn)樗鼈儾槐籑SVC支持
.C
——因?yàn)镸SVC并不區(qū)別對(duì)待.c與.C
2. 可以使用的后綴名
——對(duì)C源文件
可以使用.c。
——對(duì)C++源文件
可以使用.cpp、.cc、.cxx。
——.CPP不推薦
因?yàn)樵趚nix上 a.CPP與a.cpp是2個(gè)文件, 而復(fù)制到Windows上就將發(fā)生重名。
如果只使用.cpp就可以避免該情況。
3. 關(guān)于.inl
有些文件內(nèi)容確實(shí)是C/C++代碼, 但是卻不直接作為翻譯單元,而是被其他翻譯單元包含。
理論上說,它們?nèi)∪魏蚊侄紱]關(guān)系。但是將它們?nèi)?inl會(huì)得到一些好處:
—— 暗示該文件包含C/C++代碼
—— 一些編輯器會(huì)對(duì)其按C/C++語法進(jìn)行高亮。
三、 顯式指定
有時(shí)候需要覆蓋默認(rèn)情況,顯式指定我們需要的操作。
三、1. GCC “
-x”
GCC通過-x選項(xiàng)顯式指定編譯源代碼的語言:
-x c(或-xc)
—— 將源代碼作為C源文件。
-x c++、(或-xc++)
—— 將源代碼作為C++源文件。
對(duì)于“二”中的測(cè)試, 只要將命令行改為:
gcc(g++) -x c (-xc) filename
所有文件都將被作為C源文件處理, 并輸出 error !--- C ---!
而使用如下命令行:
gcc(g++) -x c++ (-xc++) filename
所有文件都將被作為C++源文件處理, 并輸出 error !--- C++ ---!
三、2. MSVC “/TC” “/TP”
MSVC通過/TC(/TP)選項(xiàng), 顯式指定將輸入作為C(C++)源代碼。
對(duì)“二”中的測(cè)試, 命令行:
cl /TC filename
對(duì)所有文件都將輸出 error !--- C --- !
命令行:
cl /TP filename
對(duì)所有文件都將輸出 error !--- C++ ---!
四、總結(jié)
1. 使用“二、4”中推薦的方式,給源代碼文件命名。
2. 覆蓋默認(rèn)情況,使用-x(GCC)或者/TC、/TP(MSVC)
3. 順帶提一點(diǎn), gcc、g++用作鏈接時(shí), 也有一些區(qū)別。
鏈接C++(或者C/C++混合)目標(biāo)代碼, 推薦使用g++。
因?yàn)镚CC高版本中, gcc鏈接時(shí)默認(rèn)不會(huì)導(dǎo)入C++需要的運(yùn)行時(shí)庫(kù)。
相關(guān)鏈接:
——源代碼
http://immature.googlecode.com/svn/trunk/iMmature/sample/compiler_options/language
——《
預(yù)定義__cplusplus宏》
http://m.shnenglu.com/ownwaterloo/archive/2009/04/20/predefined_macro___cplusplus.html

本作品采用知識(shí)共享署名-非商業(yè)性使用-相同方式共享 2.5 中國(guó)大陸許可協(xié)議進(jìn)行許可。
轉(zhuǎn)載請(qǐng)注明 :
文章作者 - OwnWaterloo
發(fā)表時(shí)間 - 2009年04月20日
原文鏈接 - http://m.shnenglu.com/ownwaterloo/archive/2009/04/20/compiler_options_language.html
posted on 2009-04-20 15:02
OwnWaterloo 閱讀(2712)
評(píng)論(0) 編輯 收藏 引用