makefile工作管理

该文章转载于http://blog.csdn.net/yx_l128125/article/details/7607692,在此感谢尹哥。

一.为什么使用 make

Linux 程序员必须学会使用GNU make 来构建和管理自己的软件工程。GNU的make能够使整个软件工程的编译、链接只需要一个命令就可以完成。make工具可以解决重新编译所受改动影响的源文件带来的问题。 

二.makefile

Make在执行时,需要一个命名为Makefile的文件。Makefile文件描述了整个工程的编译,连接等规则。

其中包括:

1.工程中的哪些源文件需要编译以及如何编译;

2需要创建哪些库文件以及如何创建这些库文件;

3如何最后产生我们想要的可执行文件;

三.makefile的语法

文件名默认应该为:GNUmakefile      makefile        或者Makefile然后执行make命令进行自动执行文件,并定义了源文件的依赖关系(当同一个目录下同时有这三个文件,则按照GNUmakefile     makefile         Makefile顺序优先执行)

 Makefile(术语)

规则:用于说明如何生成一个或者多个目标文件,规则格式如下:

目标:依赖文件

(以tab空格)命令

例如:

main.o :main.c

       gcc –c main.c  -o main.o   (这是依赖文件通过命令转换为目标)

目标:

Makefile中,规则的顺序是很重要的,因为,Makefile中只应该有一个最终目标,其他的目标都是被这个目标所连带出来的,所以一定要让make知道你的最终目标是什么。

      一般来说,定义在Makefile中的目标可能会有很多,但是第一条规则中的目标被确立为最终目标。

文件名:

Make命令默认在当前目录下寻找名字为makefile或者Makefile的工程文件,当名字不为这两者之一时,可以使用如下方法指定

                                          make  -f 文件名

测试源码

/*文件:fun.h*/
#include <stdio.h>
extern int max_fun(int x,int y);

/*文件:fun.c*/
#include "fun.h"
int max_fun(int x,int y)
{
    if(x>=y)
		return x;
	else
		return y;
}

/*文件:main.c*/
#include "fun.h"
int main(void)
{
    int a,b;
	printf("Please enter the number a an b\n");
	scanf("%d,%d",&a,&b);
	int max=0;
	max=max_fun(a,b);
	printf("The max number is %d\n",max);
	return 0;
}
自己编写基于main.c 、fun.h  、fun.c的makefile



总结:要注意的几点:

      1.每一个命令行必须以[Tab]字符开始,[Tab]字符告诉make此行是一个命令行。make按照命令完成相应工作

      2.Makefile中“#”字符后的内容被视作注释。

      3.Hello :hello.c

                   @gcc  hello.c  -o  hello

          注:@:取消回显  (不显示执行的命令:gcc  hello.c  -o  hello)

      4、伪目标:

            Makefile 中把那些没有任何依赖只有执行动作的目标称为“伪目标”(phony targets.

            .PHONY : clean

            clean :

                        rm  -f  hello  main.o  fun1.o   fun2.o

         注:“.PHONY”将“clean”目标声称为伪目标

      5、变量:

          在makefile 中,存在系统默认的自动变量

          (1)  $^ :代表所有的依赖文件

          (2)   $@ :代表目标

          (3)  $< :代表第一个依赖文件

         例:

          hello : main.o  fun1.o  fun2.o

                  gcc  main.o  fun1.o  fun2.o  -o  hello

          等效于:hello : main.o  fun1.o  fun2.o

                                gcc  $^  -o   $@ 

 四.makefile 文件中的宏

       makefile为什么使用宏定义?假设编译器的名字为gcc,而其他系统的UNIX系统的编译器的名字为cc 或者c89.如果想将makefile文件移植到另一版本的UNIX系统中,或在现有系统中使用另一个编译器,为了使其工作,我们不得不修改makefile文件中许多行内容。而宏用来收集所有这些与系统相关内容的好方法,通过使用宏定义,可以方便地修改这些内容

       下面是自己利用宏定义编写的makefile。make 命令将$(CC)、$(CFLAGS)和$(OBJ)替换为相应的定义,这与C语言编译器对#define语句的处理方式一样。现在,想改变编译器命令,我们只需修改makefile文件找那个的一行即可。CC=XXX


五.多个目标(待验证)

       通常我们所需的目标文件不只一个,或者我们希望将多个命令集中到一个位置来执行,通过扩展makfile文件即可达到这一目的。下面我们在makfile文件中增加clean选项来删除不需要的目标文件,增加install选项来编译成功的应用程序转移到另一个目录下。

实验:多个目标 

  1. all: myapp  
  2.   
  3. # Which compiler  
  4. CC = gcc  
  5.   
  6. # Where to install  
  7. INSTDIR = /usr/local/bin  
  8.   
  9. # Where are include files kept  
  10. INCLUDE = .  
  11.   
  12. # Options for development  
  13. CFLAGS = -g -Wall -ansi  
  14.   
  15. # Options for release  
  16. # CFLAGS = -O -Wall -ansi  
  17.   
  18.   
  19. myapp: main.o 2.o 3.o  
  20.     $(CC) -o myapp main.o 2.o 3.o  
  21.   
  22. main.o: main.c a.h  
  23.     $(CC) -I$(INCLUDE) $(CFLAGS) -c main.c  
  24.   
  25. 2.o: 2.c a.h b.h  
  26.     $(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c  
  27.   
  28. 3.o: 3.c b.h c.h  
  29.     $(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c  
  30.   
  31.   
  32. clean:  
  33.     -rm main.o 2.o 3.o  
  34.   
  35. install: myapp  
  36.     @if [ -d $(INSTDIR) ]; \  
  37.     then \  
  38.         cp myapp $(INSTDIR);\  
  39.         chmod a+x $(INSTDIR)/myapp;\  
  40.         chmod og-w $(INSTDIR)/myapp;\  
  41.         echo "Installed in $(INSTDIR)";\  
  42.     else \  
  43.         echo "Sorry, $(INSTDIR) does not exist";\  
  44.     fi  
all: myapp

# Which compiler
CC = gcc

# Where to install
INSTDIR = /usr/local/bin

# Where are include files kept
INCLUDE = .

# Options for development
CFLAGS = -g -Wall -ansi

# Options for release
# CFLAGS = -O -Wall -ansi


myapp: main.o 2.o 3.o
	$(CC) -o myapp main.o 2.o 3.o

main.o: main.c a.h
	$(CC) -I$(INCLUDE) $(CFLAGS) -c main.c

2.o: 2.c a.h b.h
	$(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c

3.o: 3.c b.h c.h
	$(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c


clean:
	-rm main.o 2.o 3.o

install: myapp
	@if [ -d $(INSTDIR) ]; \
	then \
		cp myapp $(INSTDIR);\
		chmod a+x $(INSTDIR)/myapp;\
		chmod og-w $(INSTDIR)/myapp;\
		echo "Installed in $(INSTDIR)";\
	else \
		echo "Sorry, $(INSTDIR) does not exist";\
	fi

     这个makefile文件中有几处需要注意。首先,特殊目标all仍然只定义了myapp这一目标。因此,如果在执行make命令时未指定目标,它的默认行为就是创建目标myapp.

     另外一个值得关注的地方是两个新增加的目标:clean和install .目标clean用rm命令来删除目标文件。rm命令以减号-开头,减号的含义是让make命令忽略rm命令执行的结果,这意味着即使由于目标文件不存在而导致rm命令返回错误,执行命令make clean 也会成功。

       目标install依赖于myapp,所以make命令知道它必须首先创建myapp,然后才能执行制作该目标所需要的其他命令。用于制作install目标的规则有几个shell脚本命令组成。由于make命令在执行规则时会调用一个shell,并且会针对每个命令使用一个新的shell,所以我们必须在上面每行代码的结尾加上一个反斜杠\,让所有这些shell脚本命令在逻辑上处于同一行,并作为一个整体值传递给一个shell执行。这个命令以符号@开头,表示make在执行这些规则之前不会在标准输出上显示命令本身。

        目标install顺序执行多个命令以应用程序安装到其最终位置。它并不在执行下一个命令前检查前一命令的执行是否成功。如果这点很重要,我们可以将这些命令用符号&&连接起来,如下所示:

  1. @if [ -d $(INSTDIR) ]; \  
  2.     then \  
  3.         cp myapp $(INSTDIR)&&\  
  4.         chmod a+x $(INSTDIR)/myapp&&\  
  5.         chmod og-w $(INSTDIR)/myapp&&\  
  6.         echo "Installed in $(INSTDIR)";\  
  7.     else \  
  8.         echo "Sorry, $(INSTDIR) does not exist";\  
  9.     fi  
@if [ -d $(INSTDIR) ]; \
	then \
		cp myapp $(INSTDIR)&&\
		chmod a+x $(INSTDIR)/myapp&&\
		chmod og-w $(INSTDIR)/myapp&&\
		echo "Installed in $(INSTDIR)";\
	else \
		echo "Sorry, $(INSTDIR) does not exist";\
	fi

&&就是“与”的意思,即每个后续命令只在前面的命令都执行成功的前提下才会被执行。
你可能不能以普通用户的身份将新命令安装到目录/usr/local/bin下,在执行命令make  install之前,可以修改makefile文件以选择另一安装目录,或是改变该目录的权限,或是通过命令su切换用户身份到超级用户root

# rm  *.o   myapp

# make  -f  makefile

gcc  -I  -g  - Wall  -ansi  -c  main.c

gcc  -I  -g  - Wall  -ansi  -c   2.c

gcc  -I  -g  - Wall  -ansi  -c   3.c

gcc  -o  myapp  main.o  2.o   3.o

# make  -f   makefile

make: nothing  to be  done  for  ‘all’

# rm  myapp

#make  -f  makefile3  install

gcc  -o  myapp  main.o  2.o   3.o

installed  in  /usr/local/bin

# make  -f   makefile3   clean

rm  main.o  2.o  3.o

实验解析:

首先,删除myapp和所有其他目标文件。单独执行make命令将使用默认目标all,并创建可执行程序mapp.然后再次运行make命令,但因为myapp已经是最新的,所以make命令未作任何事。接下来,删除myapp并执行命令make  install, 它重新创建二进制文件myapp并将其拷贝到安装目录中。最后,运行命令make clean 来删除目录下所以目标文件。

六、学习过程遇到makefile使用

1、if函数

      if函数的语法是:
              $(if <condition>,<then-part> )  或    $(if <condition>,<then-part>,<else-part> )

             等同 C语言  if( condition) {  语句一 }; 或  if( condition) { 语句一  }; 

                                                                                   else { 语句二}
             可见,if函数可以包含“else”部分,或是不含(即if函数的参数可以是两个,也可以是三个)。而if函数的返回值是,如果<condition>为真(非空字符串),那个<then-part>会是整个函数的返回值,如果<condition>为假(空字符串),那么<else-part>会是整个函数的返回值,此时如果<else-part>没有被定义,那么,整个函数返回空字串。
所以,<then-part>和<else-part>只会有一个被计算。

2、变量引用

 


 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值