makefile

转载 2015年07月10日 08:40:20

1.hello.c

#include <stdio.h>
int main()
{
    printf("Hello World!\n");
    return 0;
}

2.Makefile

hello : hello.o
    cc -o hello hello.o

hello.o : hello.c
    cc -c hello.c

clean : 
    rm hello.o

说明:cc -o hello hello.o前面是一个tab的空格

3.执行make,产生可执行文件hello

输出如下:
cc -c hello.c
cc -o hello hello.o

4.执行make clean,删除产生的中间文件hello.o

输出如下:
rm hello.o


另转:http://hi.baidu.com/s_rlzheng/blog/item/4bc10a06892e217d030881ef.html

  本来早就应该学Makefile了,只是我偷懒,现在才学呵呵^_^makefile的好处叫我说,老实说我也说不出什么之所以然来,但是可以肯定的是它是linux平台的软件工程师都要必备的知识^_^

一、程序的编译及链接

    我们编译程序,无非是想要得到一个可执行文件,而这个过程则是经过这两步:

***.c->编译->***.o->链接->可执行文件。即.c经过编译得到.o文件,.o文件是一个中间文件,再对这些中间文件进行链接最终可得到可执行文件。

二、Makefile的规则

首先,来看一看Makefile的书写规则:

target ... : prerequisites ...

            command

            ...

            ...

    target也就是一个目标文件,可以是.o文件,也可以是执行文件,还可以是一个标签(Label)。

    prerequisites就是,要生成那个target所需要的文件或是目标。

    command也就是make需要执行的命令(任意的Shell命令)。这里要注意的是在命令前面要加上一个tab键,不是空格,是按一个tab键按出来的空格。

     这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比 target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则,也就是Makefile中最核心的内容。这是Makefile的主线和核心,但要写好一个Makefile还得继续努力。

三、一个最简单的Makefile例子

如有一个工程,含有3个头文件及四个c文件,那为了生成所需的可执行文件,这时的Makefile可以这样写:

test:main.o t1.o t2.o t3.o

     gcc –o test main.o t1.o t2.o t3.o

main.o:main.c

     gcc –c main.c

t1.o:t1.c t1.h

     gcc –c t1.c

t2.o:t2.c t2.h

     gcc –c t2.c

t3.o:t3.c t3.h

     gcc –c t3.c

clean:

     rm test main.o t1.o t2.o t3.o

到这里一个最简单的makefile就写好了,把它的名字保存为Makefile就可以了,这时你只要在终端敲一下make,它就自动帮你编译链接了^_^如果敲入make clean,它将删掉那些中间文件及可执行文件。

***************************************************************************

工程中的代码分别存放在add/add_int.c、add/add_float.c、add/add.h、sub/sub_int.c、sub/sub_float.c、sub/sub.h、main.c中。

Makefile的一个具体的实例

 

文件main.c

#include <stdio.h>

#include "add.h"            

#include "sub.h"

intmain(void)

{

      int input = 0;

      int a = 10, b = 12;

      float x= 1.23456,y = 9.87654321;

      

      printf("int a+b IS:%d\n",a+b);

      printf("int a-b IS:%d\n",a-b);

      printf("float x+y IS:%f\n",x+y);

      printf("float x-y IS:%f\n",x-y);

 

 

      return 0;      

}

加操作 

#ifdef __ADD_H__

#define __ADD_H__

extern int add_int(int a, int b);

extern float add_float(float a, float b);

#endif  

float add_float(float a, float b)

{

      return a+b;  

 

intadd_int(int a, int b)

{

      return a+b;  

}

减操作

#ifdef __ADD_H__

#define __ADD_H__

extern float sub_float(float a, float b);

extern int sub_int(int a, int b);

#endif 

float sub_float(float a, float b)

{

      return a-b;   

intsub_int(int a, int b)

{

      return a-b;   

}

命令行编译程序:

#gcc-c add/add_int.c -o add/add_int.o     #生成add_int.o目标函数

#gcc-c add/add_float.c -o add/add_float.o   #生成add_float.o目标函数

#gcc-c sub/sub_int.c -o sub/sub_int.o      #生成sub_int.o目标函数

#gcc-c sub/sub_float.c -o sub/sub_float.o    #生成sub_float.o目标函数

#gcc-c main.c -o main.o                 #生成main.o目标函数

#gcc-o casu add/add_int.o add/add_float.o sub/sub_int.o sub/sub_float.omain.o

#链接生成cacu

多文件的makefile:

#生成casu,“;”右边为目标

casu:add_int.o add_float.o sub_int.o sub_float.omain.o

      gcc -o casu add/add_int.o add/add_float.o \          #\为连接符

                    sub/sub_int.o sub/sub_float.o main.o    

#生成add_int.o的规则,将add_int.c编译生成目标文件add_int.o

add_int.o:add/add_int.c add/add.h

      gcc -c -o add/add_int.o add/add_int.c

#生成add_float.o的规则

add_float.o:add/add_float.c add/add.h

      gcc -c -o add/add_float.o add/add_float.c

#生成sub_int.o的规则

sub_int.o:sub/sub_int.c sub/sub.h

      gcc -c -o sub/sub_int.o sub/sub_int.c

#生成sub_float.o的规则

sub_float.o:sub/sub_float.c sub/sub.h

      gcc -c -o sub/sub_float.o sub/sub_float.c

#生成main.o的规则

main.o:main.c add/add.h sub/sub.h

      gcc -c -o main.o main.c -Iadd -Isub

      

#清理规则

clean:

      rm -f casu add/add_int.o add/add_float.o \

           sub/sub_int.o sub/sub_float.o main.o

使用自定义变量的makefile文件:

CC = gcc                                #CC定义成gcc

CFLAGES =   -Iadd -Isub -O2   #加入头文件搜索路径subaddO2为优化#目标文件

OBJS = add/add_int.o add/add_float.o \

             sub/sub_int.o sub/sub_float.o main.o

TARGET = casu                          #生成的可执行文件

RM = rm -f                              #删除的命令

$(TARGET):$(OBJS)                      #TARGET目标,需要先生成OBJS目标

      $(CC) -o $(TARGET) $(OBJS) $(CFLAGES)   #生成可执行文件

$(OBJS):%.o:%.c         #OBJS中所有扩展名为.o的文件替换成扩展名为.c的文件

      $(CC) -c $(CFLAGES) $< -o $@       #采用CFLAGS指定的选项编译生成目标文件

clean:                              #清理

      -$(RM) $(TARGET) $(OBJS)          #删除所有的目标文件和可执行文件

使用预定义变量的makefile文件:

CFLAGES =   -Iadd -Isub -O2              #编译选项

OBJS= add/add_int.o add/add_float.o \

               sub/sub_int.osub/sub_float.o main.o

TARGET = casu                         #生成的可执行文件

$(TARGET):$(OBJS)                      #TARGET目标,需要先生成OBJS目标

      $(CC) -o $(TARGET) $(OBJS)$(CFLAGES)  #生成可执行文件

$(OBJS):%.o:%.c         #OBJS中所有扩展名为.o的文件替换成扩展名为.c的文件

      $(CC) -c $(CFLAGES)$< -o $@       #采用CFLAGS指定的选项编译生成目标文件

clean:                              #清理

      -$(RM) $(TARGET)$(OBJS)          #删除所有的目标文件和可执行文件

使用自动变量的makefile文件:

CFLAGES =   -Iadd -Isub -O2              #编译选项

OBJS= add/add_int.o add/add_float.o \

               sub/sub_int.osub/sub_float.o main.o

TARGET = casu                          #生成的可执行文件

$(TARGET):$(OBJS)                      #TARGET目标,需要先生成OBJS目标

      $(CC) -o  $@  $^$(CFLAGES)         #生成可执行文件

$(OBJS):%.o:%.c         #OBJS中所有扩展名为.o的文件替换成扩展名为.c的文件

      $(CC) -c $<  $(CFLAGES) -o$@     #采用CFLAGS指定的选项编译生成目标文件

clean:                              #清理

      -$(RM) $(TARGET) $(OBJS)          #删除所有的目标文件和可执行文件

使用搜索路径的makefile文件:

CFLAGES =   -Iadd -Isub -O2  

OBJSDIR = .objs

VPATH = add:sub:.        

OBJS= add_int.o add_float.o sub_int.o sub_float.o main.o

TARGET = casu                          

$(TARGET):$(OBJSDIR) $(OBJS)     #先检测OBJSDIROBJS依赖项是否存在                

      $(CC) -o $(TARGET) $(OBJSDIR)/*.o $(CFLAGES)

 #OBJSDIR目录中所有的.o文件链接成casu          

$(OBJS):%.o:%.c         

      $(CC) -c $< $(CFLAGES) -o $(OBJSDIR)/$@ #生成目标文件,存放在OBJSDIR目录中

$(OBJSDIR):

      mkdir -p ./$@           #建立目录,-p选项可以忽略父目录不存在的错误

clean:                                

      -$(RM) $(TARGET)       #删除casu

      -$(RM) $(OBJSDIR)/*.o   #删除OBJSDIR目录下的所有.o文件

使用自动推导规则的makefile:

CFLAGS = -Iadd -Isub -O2        # 用户自定义变量

VPATH=add:sub               #搜索路径

OBJS= add_int.o add_float.o sub_int.o sub_float.o main.o

TARGET = cacu

$(TARGET):$(OBJS)            #OBJS依赖项的规则自动生成

      $(CC) -o $(TARGET) $(OBJS) $(CFLAGS)    #链接文件

clean:

      -$(RM) $(TARGET)        #-”表示当前操作失败时不报错,命令继续执行

      -$(RM) $(OBJS)

使用函数的makefile文件:

CC =gcc                              #CC定义成gcc

VPATH =add:sub

CFLAGES =   -Iadd -Isub -O2    #加入头文件搜索路径subaddO2为优化#目标文件

TARGET = casu                        #生成的可执行文件

DIRS= sub add .                    #DIRS字符串的值为目录addsub和当前目录

FILES = $(foreach dir, $(DIRS),$(wildcard$(dir)/*.c))  #查找所用目录下的.c文件

OBJS = $(patsubst %.c,%.o,$(FILES))          #.c替换成.o

$(TARGET):$(OBJS)                       #TARGET目标,需要先生成OBJS目标

      $(CC) -o $(TARGET) $(OBJS) $(CFLAGES)  #生成可执行文件

clean:                                 #清理

      -$(RM) $(TARGET) $(OBJS)             #删除所有的目标文件和可执行文件



makefile 详细用法之二

最近在学习Linux下的C编程,买了一本叫《Linux环境下的C编程指南》读到makefile就越看越迷糊,可能是我的理解能不行。             于是google到了以下这篇文章。通俗易懂...
  • dapengbusi
  • dapengbusi
  • 2016年09月18日 16:37
  • 1140

Linux下C++的通用Makefile与解析

本文给出万能Makefile的具体实现,以及对其中的关键点进行解析。所谓C++万能Makefile,即可编译链接所有的C++程序,而只需作很少的修改。 号称万能Makefile,一统江湖。我对原版的...
  • zhoujiaxq
  • zhoujiaxq
  • 2014年05月16日 13:54
  • 10378

多层级的makefile编写——递归调用makefile

文件层级结构: │  Makefile │  tmp │ ├─include │      public.h │ └─src     ├─moda     │      Makefile     │ ...
  • wangyuling1234567890
  • wangyuling1234567890
  • 2014年03月25日 23:52
  • 2410

makefile常用写法和简易写法

先说长用到的-l: 小写的l就是依赖的lib库,lib首字母,很好记。 -L: 引用的三方lib库所在目录,lib首字母大写就是目录,也好记。 -I: 少不了头文件目录,还是老路子,include...
  • persitail
  • persitail
  • 2016年09月20日 12:36
  • 675

Linux下Makefile的编写及四个特殊符号的意义@、$@、$^、$<

我们先看三段C++程序: 一、line1的源码 line1.h #ifndef _LINE_1_H #define _LINE_1_H void line1_print(const char...
  • runfarther
  • runfarther
  • 2015年11月25日 14:47
  • 4672

Makefile 实际用例分析(一) ------- 比较通用的一种架构

这里不再说Makefile的基本知识,如果需要学习,那么请参考: 下载:makefile 中文手册 或者 点击打开链接 或者 跟我一起写Makefile( 陈皓 ) 这里说的是一般的实际的一个工...
  • shanshanpt
  • shanshanpt
  • 2013年12月08日 12:20
  • 5450

一点一点学写Makefile(3)-增加第三方库和头文件

我们在写代码的时候不一定都是有自己来完成,一个工程中会大量使用一些比较优秀的动态库、静态库等,我们在使用这些库完成所有的代码后,需要在编译的时候将这些库使用的头文件添加到我们的工程上,将他的库文件也添...
  • qq849635649
  • qq849635649
  • 2016年06月02日 10:19
  • 3897

Makefile 入门与基本语法

在我看来,学会写简单的Makefile,阅读较复杂的makefile,是每一个Linux程序员都必须拥有的基本素质。Makefile可以自动识别哪些源文件被更改过,需要重新编译,那些不需要。从而节省大...
  • Paul_C_V
  • Paul_C_V
  • 2015年05月18日 11:16
  • 6117

编写通用Makefile

近期在看韦东山的数码相框视频,有讲到怎么写一个通用的
  • ymangu
  • ymangu
  • 2014年04月06日 14:37
  • 1276

makefile总结 (可做手册使用)

自己补充两个概念: make:一种控制编译或者重复编译软件的工具 makefile:是一个文本形式的脚本文件,包含一些规则,具体告诉make编译哪些文件,怎么编译。 Makefile 是和 make ...
  • qq_33850438
  • qq_33850438
  • 2016年07月14日 22:02
  • 679
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:makefile
举报原因:
原因补充:

(最多只允许输入30个字)