makefile得简单制作和应用

 

一、制作规则

目标名:依赖

       命令

目标名:最终生成得目标文件名 

依赖:需要什么依赖来生成目标

命令:生成目标得指令(改行行需用tab键进行缩进)

例:app:main.c add.c sub.c

           gcc main.c add.c sub.c -o app


二、制作makefile

1、准备工作

准备main.c、add.c、sub.c、head.h

 

1 #include <stdio.h>
2 #include "head.h"
3 
4 int main(void)
5 {
6     int sum = add(1, 2);
7     printf("sum = %d\n", sum);
8     return 0;
9 }
                                   
 1 #include "head.h"
  2 
  3 int add(int a, int b)
  4 {
  5   int result = a + b;
  6   return result;
  7 }
  1 #include "head.h"
  2 
  3 int sub(int a, int b)
  4 {
  5   int result = a - b;
  6   return result;
  7 }
  1 #ifndef _HEAD_H_
  2 #define _HEAD_H
  3 
  4 int add(int a, int b);
  5 int sub(int a, int b);
  6 
  7 #endif

2、编写makefile

  • 入门式
1 app:main.c add.c sub.c
2     gcc main.c add.c sub.c -o app -I ./include
       

执行后:生成可执行文件app

  • 进阶式

上述得makefile生成得目标文件,每次修改都会把所有文件都编译一遍,如果只修改一个文件,我们希望只重新编译修改得文件,这样可以节省时间;

对上述得makefile做如下修改:

  1 app1:main.o add.o sub.o
  2     gcc main.o add.o sub.o -o app1 -I ./include
  3 main.o:main.c
  4     gcc -c main.c -I ./include
  5 add.o:add.c
  6     gcc -c add.c -I ./include
  7 sub.o:sub.c
  8     gcc -c sub.c -I ./include

第一行得app1;是整个文件得终极目标,执行make得话,最终会生成app1出来;第一行后面得依赖main.o等文件如果没有会往下面查找对应得文件,找到第三行,main.o:main.c会生成main.o来完成第一行得依赖,其他得.o依赖以此类推;好处:这样单独文件编译得优点是每次修改单个文件得时候,make得时候只会编译修改得文件

上面可以看出,完成makefile文件后,执行make,第一次所有得文件都编译一遍,然后我们对add.c文件进行修改,加上一行空行,再次执行make得时候只会编译add.c文件,其他得.o文件还是第一次生成得;原理:系统会默认对比:修改的文件时间和以此文件为依赖生成目标文件的时间,如果生成的目标文件的时间小于修改的依赖文件,目标文件会重新生成。这里,修改了add.c文件,其对应的目标文件为add.o的生成时间是第一make生成的时间,修改add.c时间大于旧的add.o的时间,所有需要重新生成新的add.o文件,保证add.o目标文件的生成时间大于其所依赖的文件。

  • 变量式

在makefile里面,跟编程类似,一类冗余的写法可以通过变量来进行优化,简捷写法

对进阶式的makefile更改如下:

  1 obj=main.o add.o sub.o
  2 target=app2
  3 lib_path=./include
  4 # makefile 中自己维护得变量,一般都是大写
  5 CC = gcc
  6 CPPLAGS = -I
  7 
  8 $(target):$(obj)
  9     $(CC) $(obj) -o $(target) $(CPPLAGS) $(lib_path)
 10 
 11 
 12 %.o:%.c
 13     gcc -c $< -o $@ $(CPPLAGS) $(lib_path)

这里对main.o等.o 文件用变量obj进行替代,获取obj的值,需要用$加上括号,类似:value = $(obj);自己定义的变量是小写,makefile有自己维护的变量,是大写字母的形式,获取方式和自己定义变量一样用$;

第12行的写法:

%o.%.c         //同理,第8行会往下找对应的.o文件,找到第12行的时候,会根据%去自动匹配这里,会自动把%匹配成main;

第13行的写法:

$< :指定第一个依赖,例:上面的%.o:%.c 匹配成main.o:main.c;这里的第一个依赖就是main.c;($^:指所有的依赖)

$@:指定目标名,例:上面的%.o:%.c 匹配成main.o:main.c;这里的目标就是main.o

  • 函数式

makefile中有一些自带的函数,这里简单介绍:wildcard 、patsubst的用法

wildcard:查找目录下文件;./*.c是作为参数,直接跟在wildcard后面的,即查找当前路径的所有.c文件

patsubst:替换文件,后面的参数,分别为:替换的原文件,替换的新文件,原文件的来源

  1 #obj=main.o add.o sub.o
  2 target=app2
  3 lib_path=./include
  4 # makefile 中自己维护得变量,一般都是大写
  5 # makefile中的函数使用
  6 
  7 src=$(wildcard ./*.c)
  8 obj=$(patsubst ./%.c, ./%.o, $(src))
  9 
 10 CC = gcc
 11 CPPLAGS = -I
 12 
 13 $(target):$(obj)
 14     $(CC) $(obj) -o $(target) $(CPPLAGS) $(lib_path)
 15 
 16 
 17 %.o:%.c
 18     gcc -c $< -o $@ $(CPPLAGS) $(lib_path)
 19 
 20 clean:
 21     rm $(obj) $(target)
 22 
 23 hello:
 24     echo "hello makefile"
 25 

上面的写法还涉及到clean、和hello;这两个没有后面的依赖,之后跟的是命令,这样的写法,是便于make clean;make hello的操作,这样只执行对应后面的操作;如果直接make生成的是终极目标:app2;跟下面的clean、hello没关系,只有当make clean 、make hello才执行对应后面操作;

在执行make clean时,如果有个文件名为clean,make clean 里面的操作不会执行,而是报出当前文件是最新的,我们需要在makefile里面是把clean设置为伪目标,就不会跟做更新的比较(即不会比较目标文件的生成和依赖文件的时间);

修改的makefile:在clean加上.PHONY:clean

  1 #obj=main.o add.o sub.o
  2 target=app2
  3 lib_path=./include
  4 # makefile 中自己维护得变量,一般都是大写
  5 # makefile中的函数使用
  6 
  7 src=$(wildcard ./*.c)
  8 obj=$(patsubst ./%.c, ./%.o, $(src))
  9 
 10 CC = gcc
 11 CPPLAGS = -I
 12 
 13 $(target):$(obj)
 14     $(CC) $(obj) -o $(target) $(CPPLAGS) $(lib_path)
 15 
 16 
 17 %.o:%.c
 18     gcc -c $< -o $@ $(CPPLAGS) $(lib_path)
 19 
 20 #.PHONY:clean
 21 clean:
 22     rm $(obj) $(target) -f  
 23 
 24 hello:
 25     echo "hello makefile"

上面再clean的操作后面加:-f;表示强制执行,不管当前存不存在删除的文件。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值