一、GCC编译器
1、GCC的执行过程
在Linux写生成最终的文件是ELF文件(可执行文件) 分解由预处理、编译、汇编和链接。 执行过程:.c文件 —> .i文件 —> .s文件 —> .o文件 —> .elf文件
2 、逐步了解GCC的过程
$ gcc hello.c -o hello.i -E
$ gcc hello.i -o hello.s -S
$ gcc hello.s -o hello.o -c
$ gcc hello.o -o hello -lc -lgcc
3、GCC的中间产物 *.o 文件
hello.o的ELF格式
对应各个段的解释: .text段 存放运行代码 .data段 已经初始化的全局变量和静态局部变量 .rodata段 存放程序中所有的常量等 例如.text段和.rodata段只具有只读权限,所以后期会合并在一起
4、GCC的各个参数
选项
作用
示例
-o < file >
指定输出文件名
gcc a.c -o a
-E
输出预处理后的代码文件
gcc a.c -o a.i -E
-S
输出编译后的汇编代码文件
gcc a.c -o a.s -S
-c
输出链接后的可重定向文件
gcc a.c -o a.o -c
-g
在编译结果中加入调试信息
gcc a.c -o a -g
-I< path >
指定头文件路径
gcc a.c -o a -I./inc
-L< path >
指定库文件路径
gcc a.c -o a -L./lib
-O< rank >
指定优化等级
gcc a.c -o a -O2
-static
使用静态链接
gcc a.c -o a lxxx -static
-Wall
打开所有的警告
gcc a.c -o a -Wall
可用的优化等级有4个,分别是O0、O1、O2和O3。 优化等级越高,编译速度越慢,相对而言程序运行速度越快,调试难度越大。 其中O0是关闭所有优化项目。
链接库文件xxx时,如果系统中同时出现存在其对应的静态库和动态库,使用此选项可以使得程序链接静态库,使程序编译之后不依赖该库文件。
二、gdb调试
$ gdb
GNU gdb ( Ubuntu 7.11 .1-0ubuntu1~16.5) 7.11 .1
Copyright ( C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later < http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu" .
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
< http://www.gnu.org/software/gdb/bugs/> .
Find the GDB manual and other documentation resources online at:
< http://www.gnu.org/software/gdb/documentation/> .
For help, type "help" .
Type "apropos word" to search for commands related to "word" .
( gdb)
gdb的指令说明
三、Makefile编写
1、GCC的4部曲
hello:hello.o
gcc hello.o -o hello -lc -lgcc
hello.o:hello.s
gcc -c hello.s -o hello.o
hello.s:hello.i
gcc -S hello.i -o hello.s
hello.i:hello.c
gcc -E hello.c -o hello.i
.PHONY: clean
clean:
rm -rf hello.i hello.s
run:
./hello
2、变量的理解
VAR =A
VARB=$( VAR ) B
VAR = AA
VIR_A := A
VIR_B :=$( VIR_A) B
VIR_A = AA
P0 = 张三
PP ?= new_value
P0 = 李四
str =C
str += 语言
str1 = C语言
all:
echo $( VARB)
echo $( VIR_B)
echo $( P0)
echo $( PP)
echo $( str)
echo $( str1)
3、伪命令的编写和链接文件
CC = gcc
SRC = 1. c 2. c 3. c main. c
TARGET = main
TARGET:
@$( CC) $( SRC) - o $( TARGET) - I . . /
. PYONY:
clean:
@rm $( TARGET)
run:
@. / main
4、系统默认函数的使用
OBJDIR=obj/
obj0 =$( wildcard * . c src/* . c)
obj1 =$( notdir $( obj0) )
obj2 =$( addprefix $( OBJDIR) , $( obj3) )
obj3 =$( patsubst % . c, % . o, $( obj1) )
obj4 =$( obj1:% . c=% . i)
obj5 =$( obj4:% . i=% . S)
obj6 =$( obj5:% . S=% . o)
all:
@echo $( obj0)
@echo $( obj1)
@echo $( obj2)
@echo $( obj3)
@echo $( obj4)
@echo $( obj5)
@echo $( obj6)
. PHONY: run
run:
@
@
@
@
@
gcc . / src/1. c - c - o 1. o - I . / inc/
gcc . / src/2. c - c - o 2. o - I . / inc/
gcc . / src/3. c - c - o 3. o - I . / inc/
gcc . / src/main. c - c - o main. o - I . / inc/
@
gcc $( obj3) - o main
@
@rm - rf $( obj3)
. / main
5、自定义函数和override的使用
. PHONY : test
define fun1
@echo "My name is $( 0) "
endef
define fun2
@echo "My name is $( 0) , param is $( 1) "
endef
test:
$( call fun1)
$( call fun2, hello Makefile)
override ClA += - Wall
override ClA += - DBUG
define CLA_FUN0
echo "I love C!"
endef
override define CLA_FUN0
echo "I love C语言!"
endef
. PTONY: all
all:
echo $( ClA)
cc $( ClA) zhangsan. c - o zhangsan
$( call CLA_FUN0)
@echo "OK"
自动变量的参数
通配符
使用说明
*
匹配0个或者是任意个字符
?
匹配任意一个字符
[ ]
我们可以指定匹配的字符放在“[]”中
. PHONY:clean
clean:
rm - rf * . o test
test:* . c
gcc - o $@ $^
OBJ=* . c
test:$( OBJ)
gcc - o $@ $^
7、文件的路径变动
TARGET = main
CC := gcc
DIRS = . / src
CFLAGS = - I / mnt/hgfs/linux/include
SRCS = $( foreach dir , $( DIRS) , $( wildcard $( dir ) / * . c) )
OBJ = $( patsubst % . c, % . o, $( SRCS) )
RMRF := rm - rf
$( TARGET) :$( OBJ)
$( CC) $^ - o $@
. PHONY:
clrearall:
$( RMRF) $( OBJ) $( TARGET)
clrear:
$( RMRF) $( OBJ)