zoukankan      html  css  js  c++  java
  • linux下make以及makefile(一)

    0x00 前言

    文章中的文字可能存在语法错误以及标点错误,请谅解;

    如果在文章中发现代码错误或其它问题请告知,感谢!
    0x01make工具简介

    make工具是一个根据makefile文件内容,针对目标(可执行文件)进行依赖性检测(要生成该可执行文件之前要有哪些中间文件)并执行相关动作(编译等)的工具 。而这个makefile文件类似一个脚本,其中内容包含make所要进行的处理动作以及依赖关系。

    另外make的一个好处就是当你对某个源文件进行了修改,你再次执行 make 命令,它将只编译与该源文件相关的目标文件而不是整个代码工程,因此,为编译完最终的目标(可执行文件)节省了大量的时间提高工作连贯性。比如一个工程下面有A.c 、B.c、 B.c三个文件,在make生成可执行目标文件之后,改动了A.c,则再次make时,只会执行有关A.c处理动作,其它的不处理。

    学习make工具,需要明白三个概念:目标、依赖、处理动作。
    makefile所要进行的主要内容是明确目标、明确目标所依赖的内容、明确依赖条件满足时应该执行对应的处理动作。例如我们最终要实现a这个目标,但是需要依赖b,而b依赖于c的存在,则可以描述为:

    a:b
        cmdbtoa
    b:c
        cmdctob

        1
        2
        3
        4

    “:”代表依赖,另外每个处理动作之前都要用tab键分隔。
    上述四行的意思是:a依赖于b,而处理cmdbtoa;b依赖于c,而处理cmdctob。
    0x02实例

    首先准备三个文件,test1.c、test2.c、test2.h。

    test1.c:

    #include<stdio.h>
    #include "test2.h"
     
    int main()
    {
        printf("This is test1! ");
        PrintTest2();
        return 0;
    }

        1
        2
        3
        4
        5
        6
        7
        8
        9

    test2.c

        #include<stdio.h>
        #include "test2.h"
     
        void PrintTest2t()
        {
            printf("This is test2! ");
        }

        1
        2
        3
        4
        5
        6
        7

    test2.h

     #ifndef TEST2_H_
     #define TEST2_H_
     
    void PrintTest2();

     #endif

        1
        2
        3
        4
        5
        6

    使用ls指令查看目录内容:
    在这里插入图片描述
    有了上述三个代码文件后,下面介绍使用三种makefie文件编写方式
    1.基础版
    新建一个文件,命名为makefile,文件内容如下(注意要用tab来分隔处理动作指令):

    test: test1.o test2.o
        gcc -Wall test1.o test2.o -o test
        
    test1.o: test1.c test2.h
        gcc -c -Wall test1.c -o test1.o

    test2.o: test2.c test2.h
        gcc -c -Wall test2.c -o test2.o

    clean:
        rm -rf *.o test

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11

    在这里插入图片描述
    然后在终端内输入make指令编译工程:
    在这里插入图片描述

    再次使用ls查看目录多了.o和可执行文件:
    在这里插入图片描述
    对makefile里的指令进行解释:
    test: test1.o test2.o :test依赖于test1.o、test2.o两个目标文件

    gcc -Wall test1.o test2.o -o test:编译出可执行文件test。-o表示指定的可执行文件名称

    test1.o: test1.c test2.h:test1.o依赖于test1.c、test2.h两个文件

    gcc -c -Wall test1.c -o test1.o:编译出test1.o文件,-c表示只把给它的文件编译成目标文件,用源码文件的文件名命名,但把其后缀由“.c”变成“.o”。

    make clean:删除掉所有.o以及可执行文件,当修改了某一个源文件使用该指令清除旧的文件。在终端输入“make clean”实现:
    在这里插入图片描述

    此时修改了test2.c中内容,在printf()下一行增加一个无意义的回车,然后使用make编译会发现只有跟test2.c有关的部分进行了处理,这种自动化的进行依赖性检测和选择性执行必要的处理动作的工作,体现了make的特色:
    在这里插入图片描述
    2.使用变量版
    makefile内容如下:

    OBJS = test1.o test2.o
    G = gcc
    CFLAGS = -Wall -O -g
     
    test:$(OBJS)
        $(G) $(OBJS) -o test
     
    test1.o:test1.c test2.h
        $(G) $(CFLAGS) -c test1.c
    test2.o:test2.c test2.h
        $(G) $(CFLAGS) -c test2.c
     
    clean:
        rm -rf *.o test

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15

    在这个makefile中使用了变量,变量的格式是“varName = content”;若要引用这个变量,只需要用$ 即可,$(varName)。

    CFLAGS = -Wall -O -g 配置编译器设置,并把它赋值给CFLAGS变量

    -Wall:输出所有警告信息

    -O:在编译时进行优化

    -g:表示编译debug版本

    使用make后生成文件同上:
    在这里插入图片描述
    这样写的Makefile比较简单,但是缺点显著,每添加一个.c文件,就需要修改Makefile文件。

    3使用函数
    makefile内容如下

    C = gcc
    G = g++
    CFLAGS = -Wall -O -g
    TARGET = ./test
     
    %.o:%.c
        $(C) $(CFLAGS) -c $< -o $@
     
    %.o:%.cpp
        $(G) $(CFLAGS) -c $< -o $@
     
    SOURCES = $(wildcard *.c *.cpp)
     
    OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
     
    $(TARGET):$(OBJS)
        $(G) $(OBJS) -o $(TARGET)
        chmod a+x $(TARGET)
     
    clean:
        rm -rf *.o test

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22

    %.o:%.c
    $© $(CFLAGS) -c $< -o $@

    %.o:%.cpp
    $(G) $(CFLAGS) -c $< -o $@

    表示把所有的.c、.cpp文件编译成.o文件。

    SOURCES = $(wildcard *.c *.cpp) 表示产生一个所有以.c、.cpp结尾的文件列表,然后存入变量SOURCES里。

    OBJS = $ (patsubst %.c,%.o,$ (patsubst %.cpp,%.o,$(SOURCES)))
    把SOURCES文件列表中所有.cpp变成.o、.c变成.o,然后形成一个新的列表,存入OBJS变量。

    $ @扩展成当前规则的目的文件名,$ <扩展成依靠列表中的第一个依靠文件,$^扩展成整个依靠的列表(除掉里面所有重复的文件名)。

    chmod a+x $(TARGET) 表示把firstTest强制变成可执行文件。

    使用make后生成文件同上:
    在这里插入图片描述

    以上。
    ————————————————
    版权声明:本文为CSDN博主「wangqingchuan92」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/wangqingchuan92/java/article/details/92832544

  • 相关阅读:
    LeetCoded第21题题解--合并两个有序链表
    入门数据结构与算法,看这一个就够了,知识点+LeetCode实战演练
    LeetCoded第242题题解--java--数组
    映射Map、队列Queue、优先级队列PriorityQueue
    链表LinkedList、堆栈Stack、集合Set
    bzoj1588: [HNOI2002]营业额统计
    bzoj3223: Tyvj 1729 文艺平衡树
    bzoj1503: [NOI2004]郁闷的出纳员
    hdu1700 Points on Cycle
    poj1981 Circle and Points
  • 原文地址:https://www.cnblogs.com/wanghuaijun/p/12812579.html
Copyright © 2011-2022 走看看