(一)GCC Makefile熟悉

一、GCC编译器

1、概念:

全称为GNU CC ,GNU项目中符合ANSI C标准的编译系统

  GNU  C and C++ compiler

  GNU compiler collection

2、特点:

1》可编译C、C++、Object C、Java、Fortran、Pascal、Modula-3和Ada等多种语言

2》GCC是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%

3》同时是交叉平台编译器 ,适合在嵌入式领域的开发编译

3、gcc如何编译程序:

1》单文件程序:


2》多文件程序:

(一)GCC Makefile熟悉_第1张图片

4、预处理:
1》去掉源程序中的注释
2》文件包含:包含的是头文件(.h)
将头文件中的内容复制到当前文件中
1)头文件在系统目录中(系统头文件)
#include <头文件名.h>
直接去系统的头文件目录下寻找该头文件
2)头文件在当前目录中(自己写的头文件)
#include "头文件名.h"
先在当前目录下寻找,找不到则去系统的头文件目录下寻找该头文件
3)头文件的内容:
----》包含其他头文件
----》定义全局变量
----》声明变量
----》声明函数
----》定义宏
----》写条件编译语句
----》内联函数
----》定义复杂的数据类型
4)头文件的作用:
在C语言中,主要是用于被.C的源文件包含,所以在编译语句中不会出现。
3》宏替换:
1)预定义宏:
__FILE__ 正在编译的文件名
__LINE__ 文件当前的行号
__func__ 当前所在的函数名
__DATE__ 预编译文件的日期
__TIME__ 预编译文件的时间
__STDC__ 判断编译器是否遵循ANSI C,是则为1
其中, __LINE__和__STDC__是整型常量,其余为字符串常量。


2)不带参数宏:
#define PI 3.14
#define SIZE 64
3)带参数宏:

#define MAX(a, b) (a) > (b) ? (a): (b)

#define FUN1(a, b) (a) * (b) + 3

4》条件编译:
1)第一种:
#ifdef 宏
代码块A;
#else
代码块B;
#endif
如果宏被定义,则编译代码块A;否则,编译代码块B;
一般用于测试代码块中,例如:

#include 
#define DEBUG
int fun(int a,int b)
{
      //......

      return  a + b;
}

#ifdef DEBUG
int main(void)
{
      printf("%d\n",fun(3,5));
}
#endif
2)第二种:
#ifndef 宏
代码块A;
#else
代码块B;
#endif
如果宏没有被定义,则编译代码块A;否则,编译代码块B;
一般用于头文件中,作用是:防止当前头文件被多次(重复)包含,例如:

#ifndef __HEAD_H__
#define __HEAD_H__

#include 

int xy = 100;

#endif

3)第三种:
#if 表达式(bool值)
代码块A;
#else
代码块B;
#endif
如果表达式为真,则编译代码块A;否则,编译代码块B;

一般用于注:


5、链接:
1》符号解析
解析每个.o文件中的符号有没有被定义,如果没有定义,则报错,如果有定义,则解析成功
2》重定位
将每个.o文件中对应段中的数据和代码,在可执行文件的对应段中重新分配地址。

二、GDB调试器
1、调试的目的:
当程序在运行过程中出现一些问题时,需要使用调试器进行调试
2、调试的方法:
通过在程序中设置断点,观察程序每一步运行的状态,分析与实际的结果的差别,找出问题,解决问题
3、调试的工具:
GDB调试器
4、GDB的使用:
GDB是命令行的调试器,所有的操作都是通过命令完成。
1》调试的条件:
编译时,需要加"-g"选项
2》调试的对象:
编译之后生成的可执行的程序
3》如何进入GDB调试器:
$ gdb 调试对象
4》GDB相关命令:
1)退出调试器: quit
2)查看代码: l
l 默认显示10行代码
l   n 显示以n为中间行的10行代码
l   n,m 显示从第n行到第m行的代码
3)设置断点:b
b  n n为行号
4)删除断点:d
d n n为断点编号
5)查看断点信息:info 
info   b
6)在gdb中运行程序:r
7)查看变量信息:p
p   变量名
8)单步运行:n,s
----》n:当遇到函数调用语句时,直接调用函数,停在函数调用语句的下一条语句,前提是该函数中没有断点
----》s:当遇到函数调用语句时,将进入被调用函数,然后单步执行
9)继续执行:continue

三、工程管理器:make
1、概念:
make:自动编译管理器,能够根据程序中每一个源文件的更新时间自动编译文件,从而提高编译的效率。
make必须通过读取Makefile文件中的内容来执行编译工作。
2、Makefile
是make的脚本文件,Makefile文件中写了make执行的流程,所以make的执行通过Makefile文件控制。
故:通过写Makefile文件可以控制make编译程序。
3、Makefile怎么写?
Makefile文件是由许多规则组成,这里的规则就类似于c语言中函数,具有一定的格式,格式如下:

目标体: 依赖文件列表

《Tab键》 命令(shell命令、编译的命令)

实例1

7_test:7_test.c

    gcc -o 7_test 7_test.c

实例2

(一)GCC Makefile熟悉_第2张图片

4、make如何读取Makefile文件内容?

(一)GCC Makefile熟悉_第3张图片

5、Makefile中的变量:
1》Makefile中,所有变量的值都是字符串,该字符串可以表示一下这些内容:
文件的名字 
给编译器的参数 
需要运行的程序 
需要查找源代码的目录 
需要输出信息的目录
你想做的其他事情
2》分类
1)自定义变量:
---》递归展开定义

(一)GCC Makefile熟悉_第4张图片

当引用变量时,如果变量在前面没有定义,可以向下寻找该变量的定义,并将值展开

---》简单定义

(一)GCC Makefile熟悉_第5张图片

2)预定义变量
在make中预先定义好的变量,如果有默认值,可以直接使用,如果没有默认值,则需要赋值后使用
CC C编译器的名称,默认值为cc。CPP  C预编译器的名称,默认值为$(CC) –E。
RM 文件删除程序的名称,默认值为rm -f
CFLAGS   C编译器的选项,无默认值。
实例3:

(一)GCC Makefile熟悉_第6张图片

3)自动变量:
$*   不包含扩展名的目标文件名称
$+   所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$<    第一个依赖文件的名称
$?    所有时间戳比目标文件晚的的依赖文件,并以空格分开
  $@    目标文件的完整名称
$^     所有不重复的目标依赖文件,以空格分开
$%      如果目标是归档成员,则该变量表示目标的归档成员名称
自动变量用在规则里的命令中,表示该规则中的目标体或者依赖文件。
实例:

(一)GCC Makefile熟悉_第7张图片

6、模式规则:模板
也叫模板规则,可以自动生成许多相似的规则,通过用%替代具体的文件名,例如:

(一)GCC Makefile熟悉_第8张图片

7、Makefile中的函数:

(一)GCC Makefile熟悉_第9张图片

 
  
 
  
 
  
 
  
 
  
 
  
 
 

你可能感兴趣的:(C语言进阶)