zoukankan      html  css  js  c++  java
  • make和makefile

    概念

    make 是一个应用程序

    • 解析源程序之间的依赖关系
    • 根据依赖关系自动维护编译工作
    • 直行宿主操作系统中的各种命令

    makefile 是一个描述文件

    • 定义一系列的规则来制定源文件编译后的先后顺序
    • 拥有特定的语法规则,支持函数定义和函数调用
    • 能够直接集成操作系统中的各种命令

    make makefile之间的关系

    • make makefile 中描述用于指导make 程序如何完成工作

    • make根据makefile中的规则执行命令,最后完成编译输出

    makefile入门

    2.1.1 简单示例

    make的示例

      

    注意:

      目标后的命令需要用Tab键(不是四个空格)隔开

    hello : 
        echo "hello makefile"

    make的使用示例

    make  -f mf.txt hello

    功能说明:

      以hello为关键字作为目标查找mf.txt文件并指令hello处的命令

    结果:

    echo "hello makefile"
    hello makefile

    第一行是make 要直行的命令 第二行是结果。

    2.1 helloworld

      在linux中直行sudo vim makefile 回车

      在文件中输入

    hello : 
        echo "hello makefile"

      然后打开底行模式,输入wq!退出直行

    1 make hello
    2 make 

    第一行的功能说明:

      以hello为关键字作为目标查找makefile或makefile文件,并且直行hello处的命令

    第一行的功能说明: 

      查找makefile 或者makefile文件中最顶层目标,并执行最顶层目标的命令

    结果:

      两种方法此makefile的结果自然是一样的

    1 hello : 
    2     echo "hello makefile"
    3     
    4 test : 
    5     echo "test"
    6     pwd
    7     ls

    执行

    1 make
    2 make hello
    3 make test

    观察结果

    2.2 初识makefile的结构

    makefile的意义

      makefile 用于定义源文件间的依赖关系

      makefile  说明如何编译各个源文件并生成可执行文件

    依赖的定义

     makefile中的元素含义

    • targets 通常是需要生成的目标文件名 make 所需执行的命令名称
    • prerequisities 当前目标所依赖的其他目标或者文件
    • command 完成目标所需要执行的命令

         规则中的注意事项

    • targets 可以包含多个目标 使用空格对多个目标名进行分隔
    • prerequisities 可以包含多个依赖,使用空格对多个依赖进行分隔
    • [tab]键 :‘ ’ 每个命令行必须以[tab]字符开始,[tab]字符告诉make此行是一个命令行
    • 续行符: 可以姜内容分开写到下一行,提高可读性

    示例1

    1 hello :test
    2     echo "hello"
    3 test :
    4     echo "test"

    结果实现打印 test hello的依赖是test,所以先执行test,test 没有依赖 所以执行对应的命令

    依赖规则:

    • 当目标对应的文件不存在,执行对应命令
    • 当依赖在时间上比目标新,执行对应命令
    • 当依赖关系发生时,对比依赖上的每一个目标 

    技巧:makefile中可以在命令前加上@符号,作用位命令无回显

    示例2

     1 //func.c
     2 
     3 #include<stdio.h>
     4 
     5 void func()
     6 {
     7      printf("func 
    "); 
     8      return ;      
     9 }
    10 
    11 //main.c
    12 
    13 #include<stdio.h>
    14 
    15 int main()
    16 {
    17     func();
    18      printf("main
    "); 
    19      return 0;      
    20 }  

    如上,我们目前有了两个.c文件

    1 hello.out : main.o func.o
    2     gcc -o hello.out main.o func.o
    3 main.o : main.c
    4     gcc -o main.o main.c
    5 func.o : func.c
    6     gcc -o func.o func.c

    执行make ,func.c main.c的打印都打出来了

    当依赖在时间上比目标新,执行对应命令,反之,得不执行命令;在次执行make我们可以根据命令的回显,func.o main.o 两条命令没有执行。

    因为我们没有修改这个.c文件,func.o main.o的时间比对应的.c文件新,所以没有必要执行命令,这个也比较好理解。但是我们再次执行make

     hello.out 对应的指令又执行了。

    技巧:工程中开发可以将最终可执行文件名和all同时作为makefile的第一条规则的目标

    1 hello.out all : main.o func.o
    2     gcc - o hello.out main.o func.o

    如果代码没有修改,多次make,也不会执行命令了。

    3.1伪目标

     默认情况下

      make认为目标对应这一个文件

      make比较目标文件和依赖关系的新旧关系,决定是否执行命令

      make以文件处理作为第一优先级

    1 clean :
    2     rm *.o hello.out
    3     
    4 #执行make
    5  make clean
    6     

    此目录中如果有一个clean文件,如果执行make clean 则会一直提示clean 是最新的没有更新,如果没有clean文件,此目录

    下面的*.o将会被删除。

     伪目标

      通过.PHONY 关键字生命一个伪目标

      伪目标不对应任何实际的文件

      不管伪目标的依赖是否更新,命令总是执行

     伪目标的的语法 先声明,后使用

      本质: 

           伪目标是make中特殊目标.PHONY的依赖

      

    1 .PHONY : clean
    2  clean :
    3     sudo rm *.o hello.out

    执行make clean的时候 会把.o hello.out删掉,ls ll 下确实没有.o .out 文件

    伪目标的妙用:规则调用(函数调用)

    1 .PHONY : clean rebuild all
    2  rebulid : clean all

    执行make rebuild的时候会先执行clean  然后执行all 对应的命令

    原理:当一个目标的依赖包含伪目标时,伪目标所定义的命令总会被执行

    技巧:绕开.PHONY关键字作为伪目标

    clean : FORCE
        sudo rm *.o hello.out
    FORCE :

    原理:

    如果一个规则没有命令或者依赖,并且他的目标不是一个存在的文件名;在执行此规则时,目标总会被认为是最新的。

    4 变量与赋值方式

    4.1makefile变量

    • makefile中支持程序设计语言的变量的概念
    • makefile中的变量只代表文本数据(字符串)
    • makefile中变量名规则
      • 变量名可以包含字符,数字,下划线
      • 不能包含 “:” ,“#” ,“=” 或 “ ”
      • 变量名大小写敏感

      变量的定义和使用

          

     代码示例

     1 CC := gcc
     2 TARGET := hello-world.out
     3 
     4 $(TARGET) : func.o main.o
     5     $(CC) -o $(TARGET) func.o main.o
     6 
     7 func.o : func.c
     8     $(CC) -o func.o -c func.c
     9 
    10 main.o : main.c
    11     $(CC) -o main.o -c main.c
    12 
    13 .PHONY : rebuild clean all
    14 
    15 rebuild : clean all
    16 
    17 
    18 all : $(TARGET)
    19 
    20 clean :
    21     rm *.o $(TARGET)
    22 
    23     

    CC 此处是gcc 我们可以修改成g++ 或交叉编译(arm-linux-gccXXXX)这样就很方便了,不用挨着修改

    目标名也是,如果想换一个目标名,那我们可以修改变量的值就行了。

    4.2makefile中变量的赋值方式

    • 简单赋值(:=)  (可以理解为c语言中=)
    • 递归赋值(=)     (可以理解为c语言指针赋值)  
    • 条件赋值 (?=) (可以理解为C++的引用赋值)
    • 追加赋值 (+=)  (可以理解为c语言+=)

      

      

     

     

     

     

     

      

      

      

      

      

     

    时间不会留下一切,只有记忆记录了过去!
  • 相关阅读:
    spring boot 扫描不到自定义Controller
    SpringBoot+Maven多模块项目(创建、依赖、打包可执行jar包部署测试)完整流程
    spring boot 中使用 jpa以及jpa介绍
    java8 快速实现List转map 、分组、过滤等操作
    Mysql 创建函数出现This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA
    Spring mvc @initBinder 类型转化器的使用
    @RequestMapping 和@ResponseBody 和 @RequestBody和@PathVariable 注解 注解用法
    ssm的自动类型转换器
    如果将get请求转换成post请求
    如何将post请求转换成put和delete请求
  • 原文地址:https://www.cnblogs.com/itxiaoye/p/14944677.html
Copyright © 2011-2022 走看看