• makefile学习(1)


     GNU Make / Makefile 学习资料

    
    GNU Make学习总结(一)
    GNU Make学习总结(二)
    这篇学习总结,从一个简单的小例子开始,逐步加深,来讲解Makefile的用法。
    最后用上面总结过的知识,给出了一个通用的C/C++ Makefile
    文中提到《GNU 项目管理》一书,有280页。我觉得初学没必要看这么厚的书。豆瓣上对其评价也是不太实用。等以后有更深层次的需求时,再去看。
    另外还有:
    阮一峰-Make命令教程
    这篇写的很简单,不过其中提到了一点很重要:每一行"命令"是独立的Shell。第二篇《使用Make构建网站》不需要看,是针对node.js的。
    陈皓-跟我一起写Makefile
    这本读起来很轻松,同时也比较全面。
    徐海兵翻译-GNU make手册
    官方文档通常是深入浅出的,非常推荐。就是比较罗嗦,也很厚,放最后看好了。
    
    作者:Hexus
    链接:https://www.jianshu.com/p/d63aff959d3d
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
    

     

      

    今天学习了makefile的基本语法,特此总结一下。

    主要的学习网站:https://www.jianshu.com/p/d63aff959d3d
    原文:

    GNU Make / Makefile 学习资料
    
    GNU Make学习总结(一)
    GNU Make学习总结(二)
    这篇学习总结,从一个简单的小例子开始,逐步加深,来讲解Makefile的用法。
    最后用上面总结过的知识,给出了一个通用的C/C++ Makefile
    文中提到《GNU 项目管理》一书,有280页。我觉得初学没必要看这么厚的书。豆瓣上对其评价也是不太实用。等以后有更深层次的需求时,再去看。
    另外还有:
    阮一峰-Make命令教程
    这篇写的很简单,不过其中提到了一点很重要:每一行"命令"是独立的Shell。第二篇《使用Make构建网站》不需要看,是针对node.js的。
    陈皓-跟我一起写Makefile
    这本读起来很轻松,同时也比较全面。
    徐海兵翻译-GNU make手册
    官方文档通常是深入浅出的,非常推荐。就是比较罗嗦,也很厚,放最后看好了。
    
    作者:Hexus
    链接:https://www.jianshu.com/p/d63aff959d3d
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

     


    引用阮一峰的话:

    代码变成可执行文件,叫做编译(compile);先编译这个,还是先编译那个(即编译的安排),叫做构建(build)。

    Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目。但是实际上 ,任何只要某个文件有变化,就要重新构建的项目,都可以用Make构建。

    入门
    简介
    Make是一种将源代码转换成可执行文件的自动化工具,通过Make语言,描述了源文件、中间文件、可执行文件之间的关系。与此同时,Make工具可以对编译过程进行优化,在重新编译时会根据时间戳来决定哪些文件需要重新生成,在编译大型工程时,这会省下不少时间(每次第一次编内核都是输完Make后先睡一觉再说...)。Make有多种变种,其中GNU Make使用相对广泛,在大多Linux/UNIX系统都对其提供支持。

    Make一般将细节放在Makefile中,make命令会自动在当前文件夹下找到Makefile并执行,而Makefile的核心内容就是规则,它是Makefile的主要组成。每项规则可以由三部分组成:目标(target),必要条件(prerequisite),命令(command)。书写格式如下所示,目标和条件之间由冒号隔开,命令写在下一行,并以TAB开头,每条规则中可以有多个目标,多个条件以及多条命令。

    target1 target2: prereq1 prereq2
          command1
          command2

     


    tab开头请别忘记!!

    自己写的案例:

     1 #include "integrate.h"
     2 
     3 float collect(float s,float t,int n,float (*p)(float x))
     4 {
     5 int i;
     6 float f,h,x,y1,y2,area;
     7 f=0.0;
     8 h=(t-s)/n;
     9 x=s;
    10 y1=(*p)(x);
    11 
    12 for(i=1;i<=n;i++)
    13 {
    14 x=x+h;
    15 y2=(*p)(x);
    16 area=(y1+y2)*h/2;
    17 y1=y2;
    18 f=f+area;
    19 }
    20 return (f);
    21 }
    22 float fun1(float x)
    23 {
    24 float fx;
    25 fx=x*x-2.0*x+2.0;
    26 return(fx);
    27 }
    28 float fun2(float x)
    29 {
    30 float fx;
    31 fx=x*x*x+3.0*x*x-x+2.0;
    32 return(fx);
    33 }
    34 float fun3 (float x)
    35 {
    36 float fx;
    37 fx=x*sqrt(1+cos(2*x));
    38 return(fx);
    39 }
    40 float fun4(float x)
    41 {
    42 float fx;
    43 fx=1/(1.0+x*x);
    44 return(fx);
    45 }
    46 
    47 
    48 #include <stdio.h>
    49 #include <math.h>
    50 #include "integrate.h"
    51 
    52 int main()
    53 {
    54 int n,flag;
    55 float a,b,v=0.0;
    56 
    57 printf("Input the count range(from A to B)and the number of sections.
    ");
    58 scanf("%f%f%d",&a,&b,&n);
    59 printf("Enter your choice: '1' for fun1,'2' for fun2,'3' for fun3,'4' for fun4==>");
    60 scanf("%d",&flag);
    61 
    62 if(flag==1)
    63 v=collect(a,b,n,fun1);
    64 else if(flag==2)
    65 v=collect(a,b,n,fun2);
    66 else if(flag==3)
    67 v=collect(a,b,n,fun3);
    68 else
    69 v=collect(a,b,n,fun4);
    70 printf("v=%f
    ",v);
    71 return 0;
    72 }
    73 
    74 
    75 //------------integrate.h------------
    76 #ifndef _INTEGRATE_H_
    77 #define _INTEGRATE_H_
    78 
    79 #include <stdio.h>
    80 #include <math.h>
    81 
    82 
    83 float collect( float s, float t, int m, float (*p)(float x) );
    84 float fun1(float x);
    85 float fun2(float x);
    86 float fun3(float x);
    87 float fun4(float x);
    88 
    89 #endif

     

    首先;三个文件都在一个目录下
    两个C文件,一个h文件。
    最简单的makefile

    main: main.o integrate.o
          gcc integrate.o main.o -o main
    
    main.o: main.c integrate.h
         gcc -c main.c
    
    integrate.o: integrate.c integrate.h
         gcc -c integrate.c

     

    #为了避免这种情况,可以明确声明clean是"伪目标",写法如下。声明clean是"伪目标"之后,make就不会去检查是否存在一个叫做clean的文件,而是每次运行都执行对应的命令。像.PHONY这样的内置目标名还有不少,
    .PHONY: clean
    clean:
    rm *.o *.exe
    点击make后,显示如下命令:

    gcc -c main.c
    gcc -c integrate.c
    gcc integrate.o main.o -o main
    

    这个比较简单。

    复杂一点:

     

    #这一章主要对生成规则进行了详细介绍,主要分为具体规则、模式规则、静态模式规则、隐含规则、后缀规则等等。在了解这些规则之前,首先了解一些其它的前提知识。
    
    #变量及自动变量
    #在Makefile中,使用x,$(xx)。关于变量的使用会在下一章详细介绍,这里主要说一下自动变量。自动变量一般用在命令中,会根据目标和条件自动替换成对应的内容。以下是几个常用的自动变量:
    
    #$@	目标文件名
    #$%	档案文件成员,是指以a.o(b.o)这种形式作为目标时,括号中的内容
    #$<	第一个必要条件文件名
    #$?	时间戳在目标文件之后的所有必要条件文件名,空格隔开
    #$^	所有必要条件的文件名,空格隔开,这份列表删除了重复的文件名
    #$+	和$^一样,只是未删除重复的文件名
    #$*	目标的主文件名(即不包括后缀)
    #以上变量都有两个变体,加D表示文件的目录部分,加F表示文件的文件名部分,注意要加括号,如($F)等。
    #我们可以使用自动变量来修改之前的Makefile,简化命令部分的书写
    
    main: main.o integrate.o
        gcc $^ -o $@
    
    main.o: main.c integrate.h
        gcc -c $<
    
    integrate.o: integrate.c integrate.h
        gcc -c $<
    
    .PHONY: clean all
    all:main
    clean:
    rm *.o *.exe
    

      

    $<,$@是自动变量,解释看上面的说明,
    all:main可以在命令行中,等同于make,即make all等同于make。

    显示结果:

    gcc -c main.c
    gcc -c integrate.c
    gcc main.o integrate.o -o main
    

     版本三,更加难一点 

    CC=gcc
    CFLAGS=-I.
    DEPS = integrate.h
    OBJ = integrate.o main.o
    
    %.o: %.c $(DEPS)
        $(CC) $(CFLAGS) -c $< -o $@
    
    main: $(OBJ)
        $(CC) $(CFLAGS) $^ -o $@
    
    .PHONY: clean
    all:main
    clean:
    rm *.o *.exe
    

     参考自:http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/

    Makefile 4

    CC=gcc
    CFLAGS=-I.
    DEPS = hellomake.h
    OBJ = hellomake.o hellofunc.o
    
    %.o: %.c $(DEPS)
        $(CC) -c -o $@ $< $(CFLAGS)
    
    hellomake: $(OBJ)
        $(CC) -o $@ $^ $(CFLAGS)
    

      

    前四行是内置变量,应该不难理解。
    模式规则
    在gcc编译器中一般使用后缀表示文件类型,gcc会将x.c文件认为是C源文件,并翻译成对应的x.o,这种文件名的对应关系是模式规则的基础,使得Makefile对于目标x.o会自动去寻找对应的x.c文件,因此对于很多规则,我们都可以简化。
    在一个规则中,如果主文件名中包含了%就表示这是一个模式规则。所谓模式规则,是指对符合这个模式的目标都采用这个规则,注意%和通配符的不同,在Makefile中是可以使用通配符的,*.c表示的是所有以c结尾的文件的集合,而%.c表示所有以c结尾的文件都匹配这条规则,一定要注意区分。
    所有的内置规则都是模式规则,使用make -p可以看到这些内置规则,用其中生成%.o的这一条作为例子

    %.o: %.c
    #commands to execute (built-in): 这个是注释
    $(COMPILE.c) $(OUTPUT_OPTION) $<

    所有c文件结合h文件都要编译成相应的.o文件
    %.o: %.c $(DEPS)
    $(CC) $(CFLAGS) -c $< -o $@


    版本四:多文件夹管理编译
    将h文件放在include下,将.c文件放在src下,Makefile文件与两个文件同级,如下所示:

    |-- integrate
        -- include
            |-- integrate.h
        -- src
            |-- integrate.c
            |-- main.c
        Makefile
    

    #这时候再在InputSpeed目录下执行make就会报找不到文件的错误,解决的方法之一是通过VPATH = src include将源文件加入到Make的搜索路径中,但这样并不是最好的方法,因为不同的文件夹下可能有同名的文件,VPATH只会返回第一个找到的文件,并不一定是我们想要的文件,我们可以使用vpath pattern directory的形式来指定在哪个目录下搜索哪个文件,具体用法可以看下面给出的Makefile,其中%类似于通配符,告诉Make在src下找.c文件,在include下找.h文件。现在make已经可以找到所有的文件了,但还不行,因为gcc命令找不到函数的原型,我们通过-I命令把头文件的位置告诉GCC。修改后的Makefile文件如下所示

    #VAPTH src include
    vpath %.c src
    vpath %.h include
    CFLAGS = -I include
    
    main: main.o integrate.o
        gcc $^ -o $@
    
    main.o: main.c integrate.h
        gcc $(CFLAGS) -c $< -o $@
    
    integrate.o: integrate.c integrate.h
        gcc $(CFLAGS) -c $< -o $@
    
    .PHONY: clean all
    all:main
    clean:
    rm *.o *.exe
    

      

    版本五:隐含规则
    就是make自带的内置规则,不是模式规则就是后缀规则。在我们没有为规则编写命令时,make会自动去内置规则中找是否有对应的规则,上面模式规则中举的例子就是一个隐含规则,利用该隐含规则,我们可以进一步简化我们的Makefile,

    vpath %.c src
    vpath %.h include
    CFLAGS = -I include
    CC=gcc
    
    main: main.o integrate.o
    main.o: integrate.h
    integrate.o: integrate.h
    
    .PHONY: clean all
    all:main
    clean:
    rm *.o *.exe
    

    隐含规则的出现,使我们的Makefile一句命令都没有用就完成了编译,也简洁了很多,实在是十分强大。这个makefile格式真是比较厉害的。

    gcc -I include   -c -o main.o src/main.c
    gcc -I include   -c -o integrate.o src/integrate.c
    gcc   main.o integrate.o   -o main
    

      

  • 相关阅读:
    tyvj[1087]sumsets
    tyvj[1089]smrtfun
    [bzoj3289]Mato的文件管理
    luogu[2093]零件分组
    luogu[1135]奇怪的电梯
    codevs[1300]文件排版
    luogu[1140]相似基因
    动态规划练习题 胖男孩
    动态规划练习题 汇率
    vijos[1355]车队过桥问题
  • 原文地址:https://www.cnblogs.com/CodeWorkerLiMing/p/10890817.html
Copyright © 2020-2023  润新知