#########################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
将会把
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
参数,编辑器将列出所有的警告信息。这样,您就可以知道您的代码中有多少可能会在其他操作系统下出错的地方了。
(
用这个指令看看你的代码有多少地方写的不怎么合适。
)
编译连接时,加入调试代码
正如同
VC
有
debug
编译模式一样,
GCC
也有
debug
模式。添加了
-g
参数编译的可执行程序比普通程序略为大一些,其中添加了一些调试代码。这些代码将被
gdb
所支持。
连接时缩小代码体积
这个参数,似乎我没有在
Unix
环境下看到过。也不知道具体什么作用。因为有人说
Visual-MinGW
生成的代码小,于是研究了一下她的编译参数,发现
release
模式的编译参数就加了这一项。貌似编译后的代码的确缩小了很多。
获得帮助
这条指令从意思上就能看出,获得
gcc
的帮助信息。如果您有什么特殊需要,也许这个指令能帮上点小忙。
第三节 如何写一个简单的
Makefile
说了半天
Makefile
管理项目,我想现在该说一下如何写了。其实,
Makefile
文件总体还是比较容易写的,基本只要你会使用命令行,就可以写
Makefile
。下面我简单介绍一下
Makefile
的构成和书写。
一个输出
HelloWorld
的简单
Makefile
这个
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
通常情况下,不用
-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