makefile 文件的书写。
总结下make 执行过程
1)make 在当前目录下找 "Makefile"或"makefile"的文件
2)如果找到,则会找文件中第一个目标文件(target)。
3)如果 main 命令的执行,依赖后面命令执行所产生的文件,则先执行后面命令
4)当main 命令需要的文件生成完毕,则执行main 命令
makefile:
#开头的都是注释
一般的格式是:
target:components
rule
第一行表示的是依赖关系,第二行是所需文件齐全后得出目标所用的语句。
main:main.o mytool1.o mytool2.o
gcc -o main main.o mytool1.o mytool2.o
main.o:main.c mytool1.h mytool2.h
gcc -c main.c
mytool1.o:mytool1.c mytool1.h
gcc -c mytool1.c
mytool2.o:mytool2.c mytool2.h
gcc -c mytool2.c
clean:
rm -rf *.o main
Makefile有三个非常有用的变量。分别是$@,$^,$< 代表的意义分别是:
$@ 目标文件
$^ 所有的依赖文件
$< 第一个依赖文件
这样就可以把文件简化为
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
main.o:main.c mytool1.h mytool2.h
gcc -c $<
mytool1.o:mytool1.c mytool1.h
gcc -c $<
mytool2.o:mytool2.c mytool2.h
clean:
rm -rf *.o main
首先C语言的编译过程为
1.预处理阶段
2.语法词法分析阶段
3.编译阶段,首先编译成汇编语言,再将之编译成与CPU相关的二进制码,生成目标文件 .o ( .obj文件)。 // gcc -c
4.连接阶段,连接各个.o目标文件,生成特定平台相关的可执行文件。
#默认的头文件目录为/usr/include 和/usr/src/linux-headers-x.xx.0-xx/include/
头文件
//另一个角度分析编译过程。
gcc -c 命令只编译不链接的过程。
程序开始#include“xxx” 头文件,编译器寻找xxx头文件并把此行删掉,用xxx文件替换。(所以建议.h文件只放声明和定义,不放具体实现,影响效率)
没有语法错误及变量重名,则产生对应 .o 文件。此时还不检查.h中实现的函数,只要有.h文件就可。
接下来就有一个问题是,哪个文件对应实现了xxx.h 内声明的函数。这里其实不用把对应实现的命名为xxx.c,即可以随便起名。
因为C语言规定声明在实现前,则对应实现xxx.h的xxx.c文件如果函数之间有调用就在之前#include “xxx.h”。 如果互相间没有调用,就不用includ任何文件。
之后用gcc -c编译所有.c文件,得到.o文件(.h文件不用编译)。Link时 指定.h文件的对应实现文件.o即可(不用一一对应,指出需要的.o文件即可)
这里有篇不错的讲解:
查看stdio.h文件,得到scanf的定义
extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。
通常为了不重复包含相同的头文件,会声明与自己头文件名类似的常量,作为已经包含此头文件的标识。
一般规则为大写,并用下划线代替. 在前面加下划线。 比如stdio.h 声明了 _STDIO_H ,
运行结果为
则防止重复定义的方式为
#ifndef _STDIO_H
// 如果之前包含过stdio.h ,则此处 _STDIO_H 一定会有定义
#include <stdio.h>
#endif
测试:
test.h 文件
main.c 文件
输出 23
自己实现头文件时,注意引用时要写include "mylib.h"
尖括号< >直接去库中查找头文件,双引号“ ”先在源文件所在文件在寻找,再去库中寻找。
附录:
Linux 命令 locate find whereis which 的区别
find:在磁盘上查找文件。默认为在当前文件夹下查找。
find -name *.xml //当前目录递归查找文件名 *.xml
locate:系统维护一个数据库,在数据库中查找,效果比较好! // 数据库大约一周更新一次。
which:在PATH变量下寻找可执行文件。
whereis:也在数据库上寻找,但只能查找源代码,指令手册等。