Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1047679
  • 博文数量: 288
  • 博客积分: 10306
  • 博客等级: 上将
  • 技术积分: 3182
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-12 17:00
文章分类

全部博文(288)

文章存档

2011年(19)

2010年(38)

2009年(135)

2008年(96)

我的朋友

分类: LINUX

2011-06-09 10:26:50

      由浅入深makefile

main:main.o fun.o
#命令前面的空白为Tab键,否则不能正常运行
 gcc main.o fun.o -o main
main.o:main.c fun.h
 gcc -c main.c -o main.o
fun.o:fun.c fun.h
 gcc -c fun.c -o fun.o
clean:
 rm -f main *.o
###############################################
OBJS=main.o fun.o
CC=gcc
CFLAGS=-c
main:$(OBJS)
 $(CC) $(OBJS) -o main
main.o:main.c fun.h
 $(CC) $(CFLAGS) main.c -o main.o
fun.o:fun.c fun.h
# $(CC) $(CFLAGS) fun.c -o fun.o
clean:
 rm -f main *.o
##################################################
OBJS=main.o fun.o
CC=gcc
CFLAGS=-c
main:$(OBJS)
 #$^ 所有依赖文件,$@目标文件
 $(CC) $^ -o $@
main.o:main.c fun.h
 #$< 第一个依赖文件
 $(CC) $(CFLAGS) $< -o $@
fun.o:fun.c fun.h
 $(CC) $(CFLAGS) $< -o $@
clean:
 rm -f main *.o
######################################################
OBJS=main.o fun.o
CC=gcc
CFLAGS=-c
main:$(OBJS)
 #$^ 所有依赖文件,$@目标文件
 $(CC) $^ -o $@
clean:
 rm -f main *.o
#########################################################
OBJS=main.o fun.o
CC=gcc
CFLAGS=-c
main:$(OBJS)
 #$^ 所有依赖文件,$@目标文件
 $(CC) $^ -o $@
#模式规则 %匹配零或若干个字符
%.o:%.c
 $(CC) $(CFLAGS) $< -o $@
clean:
 rm -f main *.o
#######################################################
 
#代表注释一行
@加在命令的前面 取消命令的回显 但仍然打印错误信息

 

 

 

      以前一直没意识到Makefile文件的重要性,最近在Linux下写一个C++的程序,用的是网上的开源包,每次编译都要一大堆的参数,然后才去了解了一下Makefile文件的编写,发现有了Makefile文件,确实是很方便。

假设我们有下面这样的一个程序,源代码如下:

//*********list class.h**********
class tdate {
private:
int month;
int day;
int year;
public:
tdate();
tdate(int t_month, int t_day, int t_year) {
……
}
//tdate(const tdate &obj)
//{}
void display();
};
//********list class.c++:************
#include "class.h"
void tdate::display() {
int main()
{
tdate t1(12,30,2007);
t1.display();
return 0;
}

当然由于这个程序很短,我们可以这样来编译:
g++ -c class.c++
g++ -o main1 main1.c++ class.o
这样的话我们也可以产生main程序,而且也不是很麻烦。但是如果我们的程序有几百个源程序的时候,难道也要编译器重新一个一个的去编译?因为SHELL脚本将全部编译作任何源文件,包括那些不必要重新编译的源文件,而make工具则可根据目标上一次编译的时间和目标文件所依赖的源文件的更新时间而自动判断应当编译哪个源文件
现在我们来编写这个makefile文件
(文件名为makefile)
**********list makefile*******
# 这是上面那个程序的Makefile文件:
main1:main1.o class.o
g++ -o main1 main1.o class.o
main1.o: main1.c++ class.h
g++ -c main1.c++
class.o: class.c++ class.h
g++ -c class.c++
clean:
rm *.o
*******it is over**********
现在只要在shell下输入make命令,就能完成编译过程。再输入./main1就可以运行程序

有了这个Makefile文件,不论我们什么时候修改了源程序当中的什么文件,我们只要执行make命令,我们的编译器都只会去编译和我们修改的文件有关的文件,其它的文件它连理都不想去理的。如果程序没有改动,它就会提示你“main1 is up to date”,然后不会编译。

下面我们学习Makefile是如何编写的。
在Makefile中以#开始的行都是注释行。Makefile中最重要的是描述文件的依赖关系的说明。
一般的格式是:
target:dependency [dependency [........] ]
command
command
[.............]
目标(target):make最终要创建的文件
依赖关系列表(dependency): 通过这张列表可以知道编译目标需要用到的文件
命令列表(command): 为了从指定的依赖关系创建创建出目标文件而需要执行的命令。这些命令不仅是编译命令,还可以shell命令。
第一行表示的是依赖关系。第二行是命令。
比如说我们上面的那个Makefile文件的第一行。
main1:main1.o class.o
表示我们的目标(target)main的依赖对象(dependency)是main1.o class.o 当依赖的对象在目标修改后修改的话,就要去执行规则一行所指定的命令。就象我们的上面那个Makefile第二行所说的一样要执行 g++ -o main1 main1.o class.o

注意:命令行是以TAB键开始的
Makefile有三个非常有用的变量。分别是$@,$^,$#' are comments
$@ --目标文件 
$^ --所有的依赖文件 
$< --第一个依赖文件

如果我们使用上面三个变量,那么我们可以简化我们的Makefile文件为:

这是简化后的Makefile (提示:要用变量,就所有的都用变量,不然就不能正常运行)

main1main1.o class.o

g++ -o $@ $^

main1.omain1.c++ class.h

g++ -c $<

class.o: class.c++ class.h

g++ -c $<

clean:

        rm *.o

经过简化后,我们的Makefile是简单了一点,不过人们有时候还想简单一点。这里我们学习一个Makefile的缺省规则

.c++.o

g++ -c $<

这个规则表示所有的 .o文件都是依赖与相应的.c++文件的。例如class.o依赖于class.c++这样Makefile还可以变为:

这是再一次简化后的Makefile

main1main1.o class.o

g++ -o $@ $^

.c++.o

g++ -c $<

clean:

        rm *.o

其实,如果有很多个程序,而又是跨平台时,那就得修改命令,如上面的,假如要修改g++ -c,不知要修改多少呀,为了修改方便,我们可以用变量来代替。如下:

*******makefile*********

#started with '#' are comments

gx="g++ -c"

main1: main1.o class.o

        #g++ -o main1 main1.o class.o

        g++ -o $@ $^

main1.o: main1.c++ class.h

       #g++ -c main1.c++

        #g++ -c $<

        $(gx) $<

class.o: class.c++ class.h

        g++ -c $<

clean:

        rm *.o

**********************************************************************************
下面是我在用的Makefile文件,带有一些参数。从OCCI带的例子里面改过来的。
***********************************************************************************
###########################################

ORACLE_INCLUDES=-I$(ORACLE_HOME)/rdbms/public \
-I$(ORACLE_HOME)/plsql/public \
-I$(ORACLE_HOME)/network/public \
-I$(ORACLE_HOME)/precomp/public

ORACLE_LIBS=-L$(ORACLE_HOME)/lib -L$(ORACLE_HOME)/rdbms/lib
CC=g++
#CC_FLAG=-Wno-deprecated -fPIC -march=i486
CC_FLAG=-Wall
INC=$(ORACLE_INCLUDES)
LIB=$(ORACLE_LIBS) -lclntsh -locci -lxerces-c -lpthread

PRG=occi
SRC=occi.cpp
OBJ=occi.o

$(PRG):    $(OBJ)
@echo "Link $(OBJ) to $(PRG) begin......"
$(CC) $(CC_FLAG) $(INC) $(LIB) -o $@ $<
@echo "Link $(OBJ) to $(PRG) end......"

$(OBJ):    $(SRC)
@echo "Compile $(OBJ) begin......"
$(CC) $(CC_FLAG) $(INC) $(ORACLE_LIBS) -c $<
@echo "Compile $(OBJ) end......"


clean:
@echo "Removing linked and compiled files......"
rm -f $(OBJ) $(PRG)
阅读(1010) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~