Gcc的编译过程
总过程
- 源代码.c文件同头文件.h进入预处理器进行预处理;
- 预处理器生成的文件进入编译器进行编译生成编译文件(目标代理.o文件);
- .o文件再进入链接器将库代码与.o文件进行链接,生成可执行文件。
- 如:gcc -o hello hello.c。hello.c文件生成hello的可执行文件。
- 输入命令:ldd hello可以查看该可执行文件链接了那些库文件
- 输入命令:nm hello可以看到该可执行文件一共用了哪些函数
- gcc只是一个编译器,使用Gcc一定要自己控制这三个部分,而在windows中如VS这么一个IDE中,其将编译的三个部分集成在一起了,所以不用人为去做。
预编译
- gcc -o hello.e -E hello.c
- 这行代码告诉gcc对源程序hello.c进行预编译,预编译的结果输出到hello.e文件中
- 对比hello.c和hello.e文件会发现,hello.e就是把hello.c中头文件的内容全部加载进去
编译
- gcc -o hello.o -c hello.c
- 只编译不链接,生成的hello.o文件不能执行,因为还没有链接程序当中调用的库函数,hello.o是当前程序机器语言
链接
- gcc -o hello hello.c
- 生成可执行文件hello,就是对上一步的编译文件进行链接
必要性
-
一般情况下预编译不需要干预
-
当有多个.c文件一起使用时,需要对这多个.c文件进行编译生成.o文件
-
这多个.c文件里面的函数互相调用,所以需要将编译生成的多个.o文件进行链接,生成一个可执行文件
-
如有:hello.c add.c add.h文件,add.h文件对add.c里面的函数进行声明,其中hello.c包含add.h头文件,在里面调用了add.c里面的函数,编译过程如下:
gcc -o hello.o -c hello.c ;
gcc -o add.o -c add.c ;
gcc -o hello add.o hello.o ;
Gcc常用选项
Gcc文件类型
C与C++是两种不同的语言,在Gcc的链接过程中默认只链接c的标准库,并不链接C++的标准库,在变异.cpp文件时,需要指定链接的库文件,使用 -l参数:
如:gcc -o hello hello.cpp -lstdc++
或gcc -lstdc++ -o hello hello.cpp
安装g++
rpm -ivh libstdc++-devel-4.4.6-4.e16.i686.rpm
rpm -ivh gcc-c++-4.4.6-4.e16.i686.rpm
C++程序使用g++来编译,以避免gcc默认链接C的标准库
make
make的存在
- 除非最简单的项目,任何一个商业项目都会包含多个源代码,而且在编译的时候会有很长很复杂的指令
- 编译过程中还需要使用那些很少而且很难记忆的编译选项
- make是控制编译或者重复编译软件的工具
- make可以自动管理软件的编译内容、方式和时机,从而使程序员把更多的精力集中在编写代码上
make是怎样完成工作的
-
makefile 是一个文本形式的脚本文件,其中包含一些规则告诉make编译那些文件,怎么样编译以及在什么条件下编译
-
makefile规则遵守以下通用形式:
target:dependency [dependency[···]]
command
command
[···]
每一个command第一个字符必须是tab键,而不是空格键,不然make会报错停止
target是标号,dependency是依赖关系,make每次只执行第一个标号后的命令,后面的标号如果没有依赖关系不会执行,除非是在make时添加需要执行的标号作为参数 -
用vi编辑一个简单的makefile,内容如下:
start:
gcc -o hello hello.c
输入make,makefile的内容就执行了 -
稍微复杂一点:
start:hello.o
gcc -o hello hello.o
hello.o:
gcc -o hello.o -c hello.c
start是标号,后面的hello.o代表依赖关系,make先执行了hello.o后面的命令,在执行start后面的命令 -
进一步完善:
start:hello.o
gcc -o hello hello.o
@echo'-------------OK-----------'
hello.o:
gcc -o hello.o -c hello.c
clean:
rm -f hello.o
增加@echo,显示编译成功语句,为了不将语句本身输出,所以前面加@符号
增加了target clean
输入make clean,make会直接执行clean其下的command -
为了简化编辑和维护makefile,可以在makefile中使用变量。
varname=some_text
把变量用括号括起来,前面加KaTeX parse error: Expected 'EOF', got '&' at position 16: 就可以引用该变量的值。 &̲emsp;(varname)
按照惯例makefile的变量都是大写(只是习惯而已,不是必须的)。
在makefile中使用变量:
CC=gcc
SRCS=hello.c
OBJS=$(SRCS:.c=.o)
EXEC=hello
start:hello.o
$(CC) -o $(EXEC) $(OBJS)
@echo '---------------ok---------------'
hello.o:
$(CC) -o $(OBJS) -c $(SRCS)
clean:
rm -f hello.o
增加变量SRCS、OBJS、EXEC,每个引用变量CC的地方的展开成变量的值
OBJS=$(SRCS:.c=.o),意思是将SRCS变量中的.c替换为.o -
模式规则
.SUFFIXES:.c .o
表示任何的x.c文件与x.o关联
-.c.o:
表示make定义了一些规则,任何x.o文件都从x.c编译而来
make定义了一些有用的预定义变量
-
在makefile使用自动变量和模式规则的例子
.SUFFIXES:.c .o ##SUFFIXES是后缀的意思
CC=gcc
SRCS=hello.c\
pub.c
OBJS=$(SRCS:.c=.o)
EXEC=hello
strat:$(OBJS)
$(CC) -o $(EXEC) $(OBJS)
@echo'------------OK---------------'
.c.o:
$(CC) -o $@ -c $<
clean:
rm -f $(OBJS)
-
常见的make出错信息:
No rule to make target ‘target’.Stop
makefile中没有包含创建指定target所需要的规则,而且也没有默认规则可用。
‘target’ is up to date
指定的target相关文件没有变化。
command:Command not found
make找不到命令,通常是因为命令被拼写错误或者不在$PATH路径下。