一、程序的编译和链接
1、见图
2、一般来说,无论是 C、C++、还是 pas,首先要把源文件编译成中间代码文件,在 Windows 下也就是 .obj 文件,UNIX 下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的 Object File 合成执行文件,这个动作叫作链接(link)。 编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在 C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O 文件或是 OBJ 文件)。链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(O 文件或是 OBJ文件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件打个包,在 Windows 下这种包叫“库文件”(Library File),也就是 .lib 文件,在 UNIX下,是 Archive File,也就是 .a 文件。总结一下,源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器只检测程序语法,和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成 Object File。而在链接程序时,链接器会在所有的 Object File 中找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error)
二、Makefile介绍
1、Makefile的核心
文件依赖关系是Makefile的核心!根据依赖关系,执行对应的命令,最后生成目标文件。
2、Makefile的规则
//
target ... : prerequisites ...
command
...
...
//
注意:command可以写在依赖后面,如果不写在依赖后面,则必须以“Tab”键开始
target 也就是一个目标文件,可以是 Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,请见“伪目标”。prerequisites 就是,要生成那个 target 所需要的文件或是目标。command 也就是 make 需要执行的命令。(任意的 Shell 命令)
3、一个示例
4、make是如何工作的
(1)首先判断目标文件有没有,没有执行对应的命令。
(2)目标文件有的情况下,根据目标文件和依赖文件的文件时间来决定;
(3)只要依赖文件的文件日期比目标文件时间更新,对应的命令就会执行!
注意:make 只管文件的依赖性。
5、Makefile 中使用变量
(1)为了 makefile 的易维护,在 makefile 中我们可以使用变量。makefile 的变量也就是一个字符串,理解成 C 语言中的宏可能会更好。比如,我们声明一个变量,叫 objects, OBJECTS, objs, OBJS, obj, 或是 OBJ,反正不管什么啦,只要能够表示 obj 文件就行了。我们在 makefile 一开始就这样定义:objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o 于是,我们就可以很方便地在我们的 makefile 中以“$(objects)”的方式来使用这个变量了。
四、示例(from 实验楼)
1、main.c
/* main.c */
#include <stdio.h>
#include "complicated.h"
int main()
{
printf("%s\n", HELLO_STRING);
complicated();
return 0;
}
2、complicated.h
/* complicated.h */
#ifndef __COMPLICATED_H__
#define __COMPLICATED_H__
#define HELLO_STRING "Hi !"
#define PROJECT_NAME "complicated"
extern void complicated(void);
#endif
3、complicated.c
/* complicated.c */
#include <stdio.h>
#include "complicated.h"
void complicated(void)
{
printf("This is a %s project\n", PROJECT_NAME);
}
4、Makefile
#描述:complicated 项目 makefile文件
#版本:v1.0
#修改记录:
#1.使用变量改进makefile
#2.使用静态模式规则,简化makefile
#3.使用伪目标加上clean
#4.引进wildcard函数,自动扫描当前目录下的源文件
#5.加入自动规则依赖
#定义可执行文件变量
executable := complicated
#引进wildcard函数扫描源文件,定义源文件列表变量
sources := $(wildcard *.c)
#使用变量的引用替换,定义object文件列表
objects := $(sources:.c = .o)
#使用变量的引用替换,定义依赖描述文件列表
deps := $(soueces:.c = .d)
#定义编译命令变量
CC := gcc
RM := rm -rf
#终极目标规则,生成complicated可执行文件
$(executable): $(objects)
#使用自动化变量改造我们的编译命令
$(CC) -o $@ $^
#静态模式规则简化main.o complicated.o 生成规则
$(objects): %.o : %.c
$(CC) -o $@ -c %<
#使用伪目标添加clean规则
.PHONY: clean
clean:
$(RM) $(executable) $(objects) $(deps)
#自动规则依赖
include $(deps)
$(deps): %.d : %.c
$(CC) -MM $< > $@
5、下载链接
致谢
1、《Makefile》 作者 陈皓,整理 祝冬华
2、生成可执行文件的makefile,生成静态链接库的makefile,生成动态链接库的makefile。
3、Makefile 使用总结(prefect)