依睛(IT blog) 我回来了,PHP<-->C/C++ LINUX

笨鸟

统计

积分与排名

友情连接

最新评论

gcc 使用汇总

#########################text 1####################################
Gcc 是 linux 下面最常用的编译软件,通常用来编译 C 程序,但是也可以通过设置编译多种语言写成的程序。
下面简单介绍 gcc 常用的使用的参数。
-o  选择产生的目标文件的名称
-l  选择要使用到的链接库
-c  只编译不连接
 
例如 :编译一个多线程的程序可以使用命令:
gcc –lpthread –o test test.c
即将 test.c 文件编译,生成可执行文件 test, 加 -lpthread 的目的是使程序在连接的时候连接 pthread 库从而支持多线程的程序。要是程序里面没有使用线程可以将这个选项去掉。
########################text2######################################

在 为 Linux 开发应 用程序 时 , 绝 大多数情况下使用的都是 C 语 言,因此几乎 每 一位 Linux 程序 员 面 临 的首要 问题 都是如何灵活运用 C 编译 器。目前 Linux 下最常用的 C 语 言 编译 器是 GCC ( GNU Compiler Collection ),它是 GNU 项 目中符合 ANSI C 标 准的 编译 系 统 ,能 够编译 用 C 、 C++ 和 Object C 等 语 言 编 写的程序。 GCC 不 仅 功能非常 强 大, 结 构也异常灵活。最 值 得称道的一点就是它可以通 过 不同的前端模 块 来支持各 种语 言,如 Java 、 Fortran 、 Pascal 、 Modula-3 和 Ada 等。

开 放、自由和灵活是 Linux 的魅力所在,而 这 一点在 GCC 上的体 现 就是程序 员 通 过 它能 够 更好地控制整个 编译过 程。在使用 GCC 编译 程序 时 , 编译过 程可以被 细 分 为 四个 阶 段:
◆ 预处 理( Pre-Processing )
◆ 编译 ( Compiling )
◆ 汇编 ( Assembling )
◆ 链 接( Linking )
Linux 程序 员 可以根据自己的需要 让 GCC 在 编译 的任何 阶 段 结 束,以便 检查 或使用 编译 器在 该阶 段的 输 出信息,或者 对 最后生成的二 进 制文件 进 行控制,以便通 过 加入不同数量和 种类 的 调试 代 码 来 为 今后的 调试 做好准 备 。和其它常用的 编译 器一 样 , GCC 也提供了灵活而 强 大的代 码优 化功能,利用它可以生成 执 行效率更高的代 码 。
GCC 提供了 30 多条警告信息和三个警告 级别 ,使用它 们 有助于增 强 程序的 稳 定性和可移植性。此外, GCC 还对标 准的 C 和 C++ 语 言 进 行了大量的 扩 展,提高程序的 执 行效率,有助于 编译 器 进 行代 码优 化,能 够 减 轻编 程的工作量。
GCC 起 步
在学 习 使用 GCC 之前,下面的 这 个例子能 够 帮助用 户 迅速理解 GCC 的工作原理,并将其立即运用到 实际 的 项 目 开发 中去。首先用熟悉的 编辑 器 输 入清 单 1 所示的代 码 :
清 单 1 : hello.c
#include <stdio.h>
int main(void)
{
printf ("Hello world, Linux programming!\n");
return 0;
}

然后 执 行下面的命令 编译 和运行 这 段程序:
# gcc hello.c -o hello
# ./hello
Hello world, Linux programming!

从程序 员 的角度看,只需 简单 地 执 行一条 GCC 命令就可以了,但从 编译 器的角度来看,却需要完成一系列非常繁 杂 的工作。首先, GCC 需要 调 用 预处 理程序 cpp ,由它 负责 展 开 在源文件中定 义 的宏,并向其中插入 “#include” 语 句所包含的内容;接着, GCC 会 调 用 ccl 和 as 将 处 理后的源代 码编译 成目 标 代 码 ;最后, GCC 会 调 用 链 接程序 ld ,把生成的目 标 代 码链 接成一个可 执 行程序。
为 了更好地理解 GCC 的工作 过 程,可以把上述 编译过 程分成几个 步骤单 独 进 行,并 观 察 每步 的运行 结 果。第一 步 是 进 行 预编译 ,使用 -E 参数可以 让 GCC 在 预处 理 结 束后停止 编译过 程:
# gcc -E hello.c -o hello.i

此 时 若 查 看 hello.cpp 文件中的内容,会 发现 stdio.h 的内容确 实 都插到文件里去了,而其它 应 当被 预处 理的宏定 义 也都做了相 应 的 处 理。下一 步 是将 hello.i 编译为 目 标 代 码 , 这 可以通 过 使用 -c 参数来完成:
# gcc -c hello.i -o hello.o

GCC
默 认 将 .i 文件看成是 预处 理后的 C 语 言源代 码 ,因此上述命令将自 动 跳 过预处 理 步骤 而 开 始 执 行 编译过 程,也可以使用 -x 参数 让 GCC 从指定的 步骤开 始 编译 。最后一 步 是将生成的目 标 文件 链 接成可 执 行文件:
# gcc hello.o -o hello

在采用模 块 化的 设计 思想 进 行 软 件 开发时 ,通常整个程序是由多个源文件 组 成的,相 应 地也就形成了多个 编译单 元,使用 GCC 能 够 很好地管理 这 些 编译单 元。假 设 有一个由 foo1.c 和 foo2.c 两个源文件 组 成的程序, 为 了 对 它 们进 行 编译 ,并最 终 生成可 执 行程序 foo ,可以使用下面 这 条命令:
# gcc foo1.c foo2.c -o foo

如果同 时处 理的文件不止 一个, GCC 仍然会按照 预处 理、 编译 和 链 接的 过 程依次 进 行。如果深究起来,上面 这 条命令大致相当于依次 执 行如下三条命令:
# gcc -c foo1.c -o foo1.o
# gcc -c foo2.c -o foo2.o
# gcc foo1.o foo2.o -o foo

在 编译 一个包含 许 多源文件的工程 时 ,若只用一条 GCC 命令来完成 编译 是非常浪 费时间 的。假 设项 目中有 100 个源文件需要 编译 ,并且 每 个源文件中都包含 10000 行代 码 ,如果像上面那 样仅 用一条 GCC 命令来完成 编译 工作,那 么 GCC 需要将 每 个源文件 都重新 编译 一遍,然后再全部 连 接起来。很 显 然, 这样 浪 费 的 时间 相当多,尤其是当用 户 只是修改了其中某一个文件的 时 候,完全没有必要将 每 个文件都重新 编译 一遍,因 为 很多已 经 生成的目 标 文件是不会改 变 的。要解决 这 个 问题 , 关键 是要灵活运用 GCC ,同 时还 要借助像 Make 这样 的工具。
警告提示功能
GCC 包含完整的出 错检查 和警告提示功能,它 们 可以帮助 Linux 程序 员 写出更加 专业 和 优 美的代 码 。先来 读读 清 单 2 所示的程序, 这 段代 码 写得很糟糕,仔 细检查 一下不 难 挑出很多毛病:
◆ main 函数的返回 值 被声明 为 void ,但 实际 上 应该 是 int ;
◆ 使用了 GNU 语 法 扩 展,即使用 long long 来声明 64 位整数,不符合 ANSI/ISO C 语 言 标 准;
◆ main 函数在 终 止前没有 调 用 return 语 句。
清 单 2 : illcode.c
#include <stdio.h>
void main(void)
{
long long int var = 1;
printf("It is not standard C code!\n");
}

下面来看看 GCC 是如何帮助程序 员 来 发现这 些 错误 的。当 GCC 在 编译 不符合 ANSI/ISO C 语 言 标 准的源代 码时 ,如果加上了 -pedantic 选项 ,那 么 使用了 扩 展 语 法的地方将 产 生相 应 的警告信息:
# gcc -pedantic illcode.c -o illcode
illcode.c: In function `main':
illcode.c:9: ISO C89 does not support `long long'
illcode.c:8: return type of `main' is not `int'

需要注意的是, -pedantic 编译选项 并不能保 证 被 编译 程序与 ANSI/ISO C 标 准的 完全兼容,它 仅仅 只能用来帮助 Linux 程序 员 离 这 个目 标 越来越近。或者 换 句 话说 , -pedantic 选项 能 够 帮助程序 员发现 一些不符合 ANSI/ISO C 标 准的代 码 ,但不是全部,事 实 上只有 ANSI/ISO C 语 言 标 准中要求 进 行 编译 器 诊 断的那些情况,才有可能被 GCC 发现 并提出警告。
除了 -pedantic 之外, GCC 还 有一些其它 编译选项 也能 够产 生有用的警告信息。 这 些 选项 大多以 -W 开头 ,其中最有价 值 的当数 -Wall 了,使用它能 够 使 GCC 产 生尽可能多的警告信息:
# gcc -Wall illcode.c -o illcode
illcode.c:8: warning: return type of `main' is not `int'
illcode.c: In function `main':
illcode.c:9: warning: unused variable `var'

GCC
给 出的警告信息 虽 然从 严 格意 义 上 说 不能算作是 错误 ,但却很可能成 为错误 的栖身之所。一个 优 秀的 Linux 程序 员应该 尽量避免 产 生警告信息,使自己的代 码 始 终 保持 简洁 、 优 美和健壮的特性。
在 处 理警告方面,另一个常用的 编译选项 是 -Werror ,它要求 GCC 将所有的警告当成 错误进 行 处 理, 这 在使用自 动编译 工具(如 Make 等) 时 非常有用。如果 编译时带 上 -Werror 选项 ,那 么 GCC 会在所有 产 生警告的地方停止 编译 ,迫使程序 员对 自己的代 码进 行修改。只有当相 应 的警告信息消除 时 ,才可能将 编译过 程 继续 朝前推 进 。 执 行情况如下:
# gcc -Wall -Werror illcode.c -o illcode
cc1: warnings being treated as errors
illcode.c:8: warning: return type of `main' is not `int'
illcode.c: In function `main':
illcode.c:9: warning: unused variable `var'

对 Linux 程序 员 来 讲 , GCC 给 出的警告信息是很有价 值 的,它 们 不 仅 可以帮助程序 员 写出更加健壮的程序,而且 还 是跟踪和 调试 程序的有力工具。建 议 在用 GCC 编译 源代 码时 始 终带 上 -Wall 选项 ,并把它逐 渐 培 养 成 为 一 种习惯 , 这对 找出常 见 的 隐 式 编 程 错误 很有帮助。
库 依 赖
在 Linux 下 开发软 件 时 ,完全不使用第三方函数 库 的情况是比 较 少 见 的,通常来 讲 都需要借助一个或多个函数 库 的支持才能 够 完成相 应 的功能。从程序 员 的角度看,函数 库实际 上就是一些 头 文件( .h )和 库 文件( .so 或者 .a )的集合。 虽 然 Linux 下的大多数函数都默 认 将 头 文件放到 /usr/include/ 目 录 下,而 库 文件 则 放到 /usr/lib/ 目 录 下,但并不是所有的情况都是 这样 。正因如此, GCC 在 编译时 必 须 有自己的 办 法来 查 找所需要的 头 文件和 库 文件。
GCC 采用搜索目 录 的 办 法来 查 找所需要的文件, -I 选项 可以向 GCC 的 头 文件搜 索路径中添加新的目 录 。例如,如果在 /home/xiaowp/include/ 目 录 下有 编译时 所需要的 头 文件, 为 了 让 GCC 能 够顺 利地找到它 们 ,就可以使用 -I 选项 :
# gcc foo.c -I /home/xiaowp/include -o foo

同 样 ,如果使用了不在 标 准位置的 库 文件,那 么 可以通 过 -L 选项 向 GCC 的 库 文件搜索路径中添加新的目 录 。例如,如果在 /home/xiaowp/lib/ 目 录 下有 链 接 时 所需要的 库 文件 libfoo.so , 为 了 让 GCC 能 够顺 利地找到它,可以使用下面的命令:
# gcc foo.c -L /home/xiaowp/lib -lfoo -o foo

值 得好好解 释 一下的是 -l 选项 ,它指示 GCC 去 连 接 库 文件 libfoo.so 。 Linux 下的 库 文件在命名 时 有一个 约 定,那就是 应该 以 lib 三个字母 开头 ,由于所有的 库 文件都遵循了同 样 的 规 范,因此在用 -l 选项 指定 链 接的 库 文件名 时 可以省去 lib 三个字母,也就是 说 GCC 在 对 -lfoo 进 行 处 理 时 ,会自 动 去 链 接名 为 libfoo.so 的文件。
Linux 下的 库 文件分 为 两大 类 分 别 是 动态链 接 库 (通常以 .so 结 尾)和静 态链 接 库 (通常以 .a 结 尾),两者的 差 别仅 在程序 执 行 时 所需的代 码 是在运行 时动态 加 载 的, 还 是在 编译时 静 态 加 载 的。默 认 情况下, GCC 在 链 接 时优 先使用 动态链 接 库 ,只有当 动态链 接 库 不存在 时 才考 虑 使用静 态链 接 库 ,如果需要的 话 可以在 编译时 加上 -static 选项 , 强 制使用静 态链 接 库 。例如,如果在 /home/xiaowp/lib/ 目 录 下有 链 接 时 所需要的 库 文件 libfoo.so 和 libfoo.a , 为 了 让 GCC 在 链 接 时 只用到静 态链 接 库 ,可以使用下面的命令:
# gcc foo.c -L /home/xiaowp/lib -static -lfoo -o foo

 ###############################text3################################################

GCC for Win32 开发环境介绍 (4)


第三章 GCC 粗探—— GCC 的组成与附加参数


第一节 GCC 的家族成员


总的来说, GCC 应该是一个编译器。可是,为什么我还要在这里介绍 GCC 的家族成员呢?其实,整套的 GCC 环境并不是由 GCC 构成的,他是由多个包所组成的。这些包的互相作用产生了 GCC 的开发环境。其中,有一些包是你开发应用程序所必备的基本包。离开这些包你将无法正常使用 GCC 。


GCC 的基本包列表。


GCC 的基本开发环境,主要由一下几个包构成。 Binutils ,这个是辅助 GCC 的工具包,里面包含了连接器,汇编器,动态静态库生成程序,等等。 GCC ,这个包是 GCC 本身。当然 GCC 包中还包括一下几个包,如 core,java,ada 等,每个包都代表了一种语言。然后,就是 win32api,mingw-runtime ,这个是在 Win32 下使用的标准函数包。如果,你使用的是 Cygwin 或者是在 Unix 环境下,那么这个包就是 GlibC 。


所以,由上所述。 GCC 的基本包有: binutils gcc glibc/[win32api,mingw-runtime] 有了这些包。你基本能够开始编译应用程序了。


当然,如果说你想要写一个小程序。自然这些包已经够了。但是如果你要写一个较大的工程。那么,这些包也许就不能很好的胜任你的工作了。因为,对于一个大的项目,需要编译的文件不只一个,而且还有依赖关系等等。

所以, GCC 中还包括 gmake 包用于管理项目。当然,还有 automake 。但是我个人还是不太喜欢 automake , automake 其实是帮助你自动的管理你的项目,当然实现这个自动也是比较麻烦的,所以与其用 automake 管理中小型项目,不如用 gmake 自己写个脚本。不过, automake 通常用于源代码发布的应用,如果在开发时使用会延长开发周期。

Gmake,automake ,都是通过编译脚本来批量的编译程序。他们能够更具你所给定的依赖关系,来自动的判断需要重新编译的源代码,然后编译。这点的确可以帮助开发人员减轻不少的人力和开发周期。比如,你用 Makefile 管理一个项目,那么在你第一次编译程序以后,如果你的源代码没有做过任何编辑,那么下次再调用 gmake 的程序时, gmake 就不会再去一一编译每个文件。而是简单的连接一下主程序,或者什么都不作的退出 ( 这要取决于你写的 Makefile 脚本 )


但是,对于有些开发人员来说,上面这些包还是不能满足他们的要求。因为他们要调试程序。所以, GCC 还包括另一个包。那就是 GDB , gdb 是 GCC 开发的,用于跟踪调试的,命令符型调试器。它的功能还是比较强大的。基本,你能在 VC 下做到的, GDB 也可以。不过, GDB 的命令还是比较多的。掌握一些基本的调试命令一般就够使用了。


总结

GCC 开发环境包括如下几大包。

binary

基本包

提供基本的汇编器,连接器等

gcc

基本包

各种语言的编译器,包括 C,C++,Ada,Java 等

Win32api,mingwi-runtime/glibc

基本包

系统函数库

Gmake/automake

需要包

管理项目编译的程序

gdb

附加包

调试程序


第二节 GCC 的常用编译参数


同 VC,TC 等编译器不同, GCC 其实是可以很方便的在提示符下编译程序的。 GCC 在提示符下编译程序,并没有如同 VC 那样的冗长而晦涩的编译参数。相反,却有着比 VC 更灵活且简短的参数。

不得不承认,不懂 GCC 编译参数的人,确实会损失一些 GCC 的强大功能。所以,我下面简单介绍一下 GCC 的一些基本编译参数。这里,我以 C 编译器为例。


编译二进制代码

$gcc -c yours.c -o yours.o

使用这段指令, GCC 将会把 yours.c 编译成 yours.o 的二进制代码。其中, yours.o 就类似于 VC,TC 中的 .obj 文档。


编译最简单的小程序。

$gcc -o yours yours.c

通过这条指令, GCC 将会把 yours.c 源代码编译成名为 yours 的可执行程序。当然,您也可以将 yours.c 改成我们刚才介绍的 yours.o 文件。这样, gcc 将使用编译刚才编译好的二进制文档来链接程序。这里,格式的特点是, -o 后面是一串文件列表,第一个参数是所编译程序的文件名,从第二个开始,就是您编译和连接该可执行程序所需要的二进制文档或者源代码。


编译时将自己的头文件目录设为默认头文件目录

$gcc -I”Your_Include_Files_Document_Path” -c yours.c -o yours.o

这条指令中的 -I 参数将会把 Your_Include_Files_Document_Path 添加到你默认的头文件目录中。这样您将可以使用 #include <your_include.h> 来导入头文件。


编译时使用自己的静态库存放目录

$gcc -L”Your_Lib_Files_Document_Path” -o yours yours.o

这条指令将会让 GCC 在连接时除了在默认 Lib 存放目录中搜索指定的静态库以外,还会在 Your_Lib_Files_Document_Path 中搜索。


编译时使用静态连接库

$gcc -lyour_lib -o yours yours.o

这条指令将会让 GCC 在连接时把 libyour_lib.a 中您所用到的函数连接到可执行程序中。此处注意, GCC 所使用的静态连接库是 lib*.a 格式的。在连接时,只且仅需要提供 * 的内容就可以了。


编译时使用优化

$gcc -O2 -c yours.c -o yours.o

使用优化方式编译程序,其中除了 -O2 以外,还有 -O3 -O1 等等。他们代表不同的优化等级。最常用的,是 -O2 优化。当然,还有针对特殊 CPU 的优化,这里就不介绍了。


编译时显示所有错误和警告信息

$gcc -Wall -c yours.c -o yours.o

GCC 在默认情况下,将对一些如变量申请未使用这样的问题或者申请了没有给予初始值的问题忽略。但是,如果使用了 -Wall 参数,编辑器将列出所有的警告信息。这样,您就可以知道您的代码中有多少可能会在其他操作系统下出错的地方了。 ( 用这个指令看看你的代码有多少地方写的不怎么合适。 )


编译连接时,加入调试代码

$gcc -g -o yours yours.c

正如同 VC 有 debug 编译模式一样, GCC 也有 debug 模式。添加了 -g 参数编译的可执行程序比普通程序略为大一些,其中添加了一些调试代码。这些代码将被 gdb 所支持。


连接时缩小代码体积

$gcc -s -o yours yours.o

这个参数,似乎我没有在 Unix 环境下看到过。也不知道具体什么作用。因为有人说 Visual-MinGW 生成的代码小,于是研究了一下她的编译参数,发现 release 模式的编译参数就加了这一项。貌似编译后的代码的确缩小了很多。


获得帮助

$gcc --help

这条指令从意思上就能看出,获得 gcc 的帮助信息。如果您有什么特殊需要,也许这个指令能帮上点小忙。


第三节 如何写一个简单的 Makefile


说了半天 Makefile 管理项目,我想现在该说一下如何写了。其实, Makefile 文件总体还是比较容易写的,基本只要你会使用命令行,就可以写 Makefile 。下面我简单介绍一下 Makefile 的构成和书写。


一个输出 HelloWorld 的简单 Makefile

all:

echo HelloWorld

这个 Makefile 代码,运行后将在屏幕上打印一个 HelloWorld 。 all 其实是类似 C 代码中的 main 函数。 gmake 程序将在运行 Makefile 代码时,首先运行此处的代码。注意,此处 echo 前面的是 <tab> 。 GCC 对空格很敏感的。


添加依赖项的 Makefile

all:depend

@echo I am the main

depend:closeecho

@echo I am the depend

closeecho:

@echo off

这个 Makefile 代码,的作用还是输出句子。不同的是她添加了几个指令块之间的依赖关系。其中 all 依赖于 depend , depend 依赖于 closeecho 。这样,程序在编译时将根据脚本的依赖关系来判断文件编译的先后顺序。


执行 Makefile

$make -f Makefile

通常情况下,不用 -f 参数, make 程序将在当前目录下搜索名为 Makefile 的文件作为需要执行的文件。而使用 -f 将指定 Makefile 的文件名。


一个完整的 Makefile

all:yours

@echo OK

yours:yours.o

gcc -o yours yours.o

yours.o:yours.c

gcc -c yours.c -o yours.o


更多有关 Makefile 的详细内容请查相关资料。



http://blog.csdn.net/inbskywalker/archive/2006/09/30/1310592.aspx

posted on 2007-08-31 14:17 向左向右走 阅读(310) 评论(0)  编辑 收藏 引用 所属分类: Linux 学习库

只有注册用户登录后才能发表评论。