from http://blog.csdn.net/liang13664759/article/details/1771246
编译与链接
无论是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),在VC下,这种错误一般是:Link 2001错误,意思说是说,链接器未能找到函数的实现。你需要指定函数的Object File.
Makefile 介绍
———————
make命令执行时,需要一个 Makefile 文件,以告诉make命令需要怎么样的去编译和链接程序。
首先,我们用一个示例来说明Makefile的书写规则。以便给大家一个感兴认识。这个示例来源于GNU的make使用手册,在这个示例中,我们的工程有8个C文件,和3个头文件,我们要写一个Makefile来告诉make命令如何编译和链接这几个文件。我们的规则是:
1)如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。
3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。
只要我们的Makefile写得够好,所有的这一切,我们只用一个make命令就可以完成,make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译,从而自己编译所需要的文件和链接目标程序。
快速编译: make -j10
写法:
五、makefile文件是被make命令调用的,用于描述系统中模块之间的相互依赖关系,以及产生目标文件所要执行的命令(规则)。
编写规则通用形式:
target: dependency [depenency [...] ]
command
command
[...]
注:command前是tab键,而非空格
main: main.o f1.o f2.o
main.o:main.c def1.h
f1.o: f1.c def1.h def2.h
f2.o: f2.c def2.h def3.h
规则:描述如何生成目标,或者说使用哪些命令来根据依赖模块产生目标。这就是command,这里的command即可以是gcc/g++编译命令,也可以是shell命令或是其他可执行文件。
makefile文件(命令行以tab键开始)
main: main.o f1.o f2.o
gcc -o main main.o f1.o f2.o
main.o: main.c def1.h
gcc -c main.c
f1.o: f1.c def1.h def2.h
gcc -c f1.c
f2.o: f2.c def2.h def3.h
gcc -c f2.c
-------------------badcase---请忽略---------------------------
自己的试验./etts-common/inc/etts_include.h
mem_pool.cpp mem_pool.h
main.cpp
自己写的Makefile:
main: main.o mem_pool.o mem_pool.h
g++ -o main -I ./etts-common/inc/ main.o mem_pool.o
main.o: main.cpp mem_pool.h
g++ -o main.o -I ./etts-common/inc/ main.cpp
mem_pool.o: mem_pool.cpp
g++ -o mem_pool.o -I ./etts-common/inc/ mem_pool.cpp
报错 main中调用mem_pool中函数,未定义的引用
网上参照的Makefile:
C=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-I ./etts-common/inc/ -g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=main.cpp mem_pool.cpp
OBJS=$(subst .cpp,.o,$(SRCS))
all: main
main: $(OBJS)
$(CXX) $(LDFLAGS) -o main $(OBJS) $(LDLIBS)
main.o: main.cpp mem_pool.h
mem_pool.o: mem_pool.h mem_pool.cpp
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) main
这个编译是okay的。