GCC
再linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件。
gcc编译可以经过四个阶段:
(1)预处理:c/c++源文件中,以“#”开头的命令被称为预处理命令,如包含命令“#include”,宏定义命令“#define”,条件编译命令“#if”、“#ifdef”等。预处理就是将要包含(include)的文件插入源文件中、将宏定义展开,根据条件编译命令选择要使用的代码,最后将这些代码输入到一个“.i”的文件中等待进一步处理。预处理将用到arm-linux-cpp工具。
(2)编译:把c/c++代码(比如上述的“.i”文件)翻译成汇编代码,所用到的工具为ccl。
(3)汇编:将(2)输出的汇编代码翻译成符合一定格式的机器代码,在linux系统上一般表现为ELF目录文件(OBJ文件),用到的工具为arm-linux-as。
(4)连接:就是将上步生成的OBJ文件和系统库的OBJ文件、库文件连接起来,最终生成可以在特定平台运行的可执行文件,用到的工具为arm-linux-ld。
文件类型:
.a:为由目标文件构成的库文件
.i:已经预处理过的c源代码文件
.ii:已经预处理过的c++源代码文件
.s:汇编语言源代码文件
gcc [operation] filename
gcc -o filename: 指定编译后生成的可执行文件名称,如果不给出,gcc就会给出预设的可执行文件a.out。
-c:只编译。将filename.c文件编译为filename.o。
-g:产生gdb所必要的符号信息,要想对编译后的程序进行调试,就必须加入这个选项。
-O:对程序进行优化编译、链接,可以提高可执行文件的速率。
-O2:比-O更好的优化编译、链接,执行文件的速度更快。
time./文件(可执行):测试可执行文件的运行时间。
gcc foo.c -I/home/include -o foo
-I/home/include这个选项告诉gcc如果在当前目录没有找到需要的头文件,就到指定的文件/home/include中去寻找。
-Ldirname:将dirname所指向的目录加入到库文件的目录列表中。在默认状态下,链接程序ld在系统的预设路径中(/usr/lib)寻找所需要的库文件,这个选项告诉连接程序,首先到-L指定的目录中去寻找,然后再去系统预设路径中寻找。
-Iname:在连接时,装载名字为“libname.a”的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。
例:gcc test.c
-static:静态链接库文件
例:gcc -static hello.c -o hello
缺省操作为动态链接库文件
静态链接可执行文件要比动态链接的大的多,这自己可以使用ll去查看。
-Wall:生成所有警告信息
-w:不生成任何警告信息
-DMACRO:等价于在程序中使用#define MACRO
GDB的调试使用:
1、gcc
2、gdb test
3、break main
4、run
5、next
6、continue
启动 1、gdb test
gdb中的命令:
list(l) 查看程序
break(b) 函数名 在函数入口处设置断点
b 行号
info b: 查看所有设置断点
run(r)运行
step(s)单步运行程序(进入子函数)
continue(c)继续运行程序
printf(p)变量名:
finish 运行程序,直到当前函数结束
watch 变量名:对指定变量进行监控
quit(q):退出gdb
Makefile的使用方法
目标 :依赖
<Tab>命令
例子:
makefile(Makefile)
hello : main.o fun1.o func2.o
main.o : main.c
.PHONY :
makefile中只应该有一个最终目标。
make命令默认在当前目录下寻找名字为makefile或Makefile的工程文件,当名字不为两者之一时,可以通过下面方法指定:
这样变量修改方便:
obj = main.o func1.o func2.o func3.o
hello : $(obj)
gcc $(obj) -o hello
makefile中的“#”字符后面被视为注释
hello : hello.c
@ gcc hello.c -o hello
@:取消回显