posts - 16,  comments - 34,  trackbacks - 0

一、 统一的预处理、编译、链接程序


        一、1. 有些程序同时具有如下功能:

1. 预处理C/C++源代码
2. 编译C/C++源代码
3. 链接C/C++目标代码

例如:GCC的gcc、g++,MSVC的cl.exe。


        一、2. 实际的情况也许更加复杂:

gcc、g++、cl.exe很有可能只是一个启动器
用户只需要使用它们, 它们内部再根据特定条件, 执行其他程序,比如:

1. gcc、g++编译C/C++代码时, 最终会执行cc1/cc1plus程序。
该程序可能才是真正的C/C++编译器。

2. gcc、g++在链接C/C++目标代码时,最终会执行ld程序。
该程序可能才是真正的链接器。

3. cl.exe程序自己处理C/C++代码的预处理与编译工作。

4. cl.exe程序链接时,将执行link.exe
该程序可能才是真正的链接器。


        一、3. 我们的关注点

——上述复杂的情况我们大多数情况下无须操心:

1. 我们只需要使用gcc、g++
即使以后GCC将cc1、cc1plus、ld改为别的名字也不会受影响。

2. 我们只需要使用cl
即使以后cl不再担任编译工作或者link.exe被改为别的名字,同样不受影响。


——我们需要关心这些统一的程序,是根据何种条件, 决定它们的操作的?

本文只讨论编译:
1. 它们默认是通过何种条件, 决定按C语法或按C++语法编译一个翻译单元的。
2. 如何显式指定按C语法或者按C++语法去编译一个翻译单元。



二、 默认情况

如果不显式指定操作, gcc、g++、cl都是按文件后缀名来决定操作的。

        二、1. 测试文件:
#ifndef __cplusplus
/* being treated as C translation unit */
#error !---  C  ---!
#else
// being treated as C++ translation unit
#error !--- C++ ---!
#endif

我们建一个没有后缀的文件,叫nosuffix, 写入如上内容。
而且, 我们也不需要编译出目标代码。
只需要测试__cplusplus宏(见《预定义__cplusplus宏》)是否存在,并且用#error报告即可。

然后建立一些内容完全一样的文件:

#include "nosuffix"


这些文件共有10个:
c.c、 cpp.cpp、txt.txt、UC.C、UCPP.CPP、cc.cc、cxx.cxx、inl.inl、c++.c++、cp.cp。
(UC和UCPP是为了测试大写后缀名)


        二、2. 测试方法

对GCC使用:
gcc(g++) filename >stdout.txt 2>stderr.txt

对MSVC使用:
cl filename >stdout.txt 2>stderr.txt


        二、3. 测试结果

gcc、g++、cl对以下后缀名文件的默认操作如下

 

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


对该表的几点说明:
1. 表中的obj表示该条件下, 统一程序将它们认作目标文件, 并打算执行链接工作。
这显然是错误的, 因为他们包含的是文本。

2. gcc、g++(编译代码)的区别
GCC认为带有.c、.cpp、.C、.CPP、.cc、.cxx、.c++、.cp(但不限于)后缀的文件是C/C++源文件。
gcc把带有.c后缀的文件, 当作C源文件, 把带有其他后缀名的文件当作C++源文件。
g++将带有上述所有后缀的文件,都当作C++源文件。

3. MSVC与GCC的区别
MSVC认为带有.c、.cpp、.C、.CPP、.cc、.cxx后缀的文件是C/C++源文件。
上述GCC相比, 排除了.c++和.cp

同时,windows下的文件名是不区分大小写的, 所以.c同.C,.cpp同.CPP是一样的。
与GCC相比, .C不再认为是C++源文件, 而是与.c一样作为C源文件处理。


        二、4. 测试小结

由上表以及说明, 如果我们打算编写跨平台的代码

1. 不推荐使用的后缀名
.c++、.cp
——因为它们不被MSVC支持
.C
——因为MSVC并不区别对待.c与.C


2. 可以使用的后缀名
——对C源文件
可以使用.c。

——对C++源文件
可以使用.cpp、.cc、.cxx。

——.CPP不推荐
因为在xnix上 a.CPP与a.cpp是2个文件, 而复制到Windows上就将发生重名。
如果只使用.cpp就可以避免该情况。


3. 关于.inl
有些文件内容确实是C/C++代码, 但是却不直接作为翻译单元,而是被其他翻译单元包含。
理论上说,它们取任何名字都没关系。但是将它们取为.inl会得到一些好处:
    ——  暗示该文件包含C/C++代码
    ——  一些编辑器会对其按C/C++语法进行高亮。




三、 显式指定

有时候需要覆盖默认情况,显式指定我们需要的操作。

        三、1. GCC “-x

GCC通过-x选项显式指定编译源代码的语言:
-x c(或-xc)
    ——  将源代码作为C源文件。
-x c++、(或-xc++)
    ——  将源代码作为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)选项, 显式指定将输入作为C(C++)源代码。

对“二”中的测试, 命令行:
cl /TC filename

对所有文件都将输出 error !---  C  --- !

 

命令行:
cl /TP filename

对所有文件都将输出 error !--- C++ ---!






四、总结

1. 使用“二、4”中推荐的方式,给源代码文件命名。
2. 覆盖默认情况,使用-x(GCC)或者/TC、/TP(MSVC)
3. 顺带提一点, gcc、g++用作链接时, 也有一些区别。
链接C++(或者C/C++混合)目标代码, 推荐使用g++。
因为GCC高版本中, gcc链接时默认不会导入C++需要的运行时库。





相关链接:

——源代码
http://immature.googlecode.com/svn/trunk/iMmature/sample/compiler_options/language

——《预定义__cplusplus宏
http://www.cppblog.com/ownwaterloo/archive/2009/04/20/predefined_macro___cplusplus.html




Creative Commons License
作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。

转载请注明 :
文章作者 - OwnWaterloo
发表时间 - 2009年04月20日
原文链接 - http://www.cppblog.com/ownwaterloo/archive/2009/04/20/compiler_options_language.html

posted on 2009-04-20 15:02 OwnWaterloo 阅读(2664) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(8)

随笔档案(16)

链接

搜索

  •  

积分与排名

  • 积分 - 196967
  • 排名 - 132

最新随笔

最新评论

阅读排行榜

评论排行榜