zoukankan      html  css  js  c++  java
  • GNU Make / Makefile 学习

    在学习GNU Make / Makefile总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

    目录:
    一、GNU Make / Makefile 学习资料
    二、makefile入门基础
    1、make简介
    2、为什么要使用make
    3、makefile简介
    4、makefile的基本结构
    5、基础示例
    6、Makefile自动化变量
    7、make常用的内嵌函数

    一、GNU Make / Makefile 学习资料

    1)阮一峰-Make命令教程——http://www.ruanyifeng.com/blog/2015/02/make.html
    推荐理由:这篇写的很简单,不过其中提到了一点很重要:每一行"命令"是独立的Shell。第二篇《使用Make构建网站》不需要看,是针对node.js的。

    2)陈皓-跟我一起写Makefile——https://github.com/seisman/how-to-write-makefile
    推荐理由:这本读起来很轻松,同时也比较全面。

    3)徐海兵翻译-GNU make手册——http://hacker-yhj.github.io/resources/gun_make.pdf
    推荐理由:官方文档通常是深入浅出的,非常推荐。就是比较罗嗦,也很厚。

    二、makefile入门基础

    1、make简介

    make是一个指令工具,它解释makefile中的指令或者说规则。makefile文件描述了整个工程中所有文件的**编译顺序,编译规则**。Makefile也有自己的编写规则,通常,我们所使用的IDE都会生成相应的makefile,然后再根据makefile来进行编译,只是这些操作是由IDE来完成,我们只需要点击一个编译按钮。


    2、为什么要使用make

    现可以在GitHub上看到,很多的开源项目,在编译的时候,都是使用make来完成的,也就是说,都有其对应的makefile。他们都有个特点,那就是文件很多。
    考虑这样一种情况,我们的项目现在有三、四十个文件,你使用的不是IDE工具,而是命令行,那么不同的人,在编译你的项目的时候,都需要一个一个文件的
    gcc -o asample.c bsample.c ...... xxx.out
    这样慢慢的一个文件,一个文件的去找到以后再编译吗?

    答案肯定是否定的,当你工程的文件多了以后,时间一长,可能你自己都不能记住所有的文件。所以,这个时候我们就可以使用make来根据makefile对整个项目进行管理。除此之外,make还有一个优点,那就是当你修改你的文件以后,make只会编译更新的文件以及它相关依赖的文件。这里后边进行详细的解释,意思就是,当你只修改了几十个文件中的某一个文件时,make只会重新编译跟你修改的文件有关联的文件,而不是所有的文件。这就大大的减短了编译的时间。

    》总结:

    利用make工具可以自动完成编译工作。这些工作包括:
        如果仅仅修改了某几个源文件,则只重新编译这几个源文件;
        如果某个头文件被修改,则重新编译所有包含该头文件的源文件。
    利用这种自动编译可大大简化开发工作,避免不必要的重新编译。

    make工具通过一个称为Makefile的文件来完成并自动维护编译工作。Makefile文件描述了整个工程的编译、链接等规则。


    3、makefile简介

    在我们执行make之前,需要有一个名为makefile或Makefile的文件。这个文件用来告诉make需要完成什么样的操作。我们可以简单的把makefile认为是一份定义了源文件间依赖关系、如何编译各个源文件并生成可执行文件的说明书。


    4、makefile的基本结构

    TARGET... : PREREQUISITES...
        COMMAND
        ...
        ...
    TARGET:规则的目标,程序产生的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如clean,也称伪目标。
    PREREQUISITES:规则的依赖,是用来产生目标的输入文件列表,一个目标通常依赖于多个文件。
    COMMAND:规则的命令。是make执行的动作(命令是shell命令或者是可在shell下执行的程序)。

    》注意:

    1)这里需要注意的是,命令前面使用的是TAB键,而不是空格,使用空格会出现错误。

    2)如果DEPENDENCIES中有一个或多个文件更新的话,COMMAND就要执行,这就是Makefile最核心的内容。

    5、基础示例

    .PHONY:clean
    main:main.o sub.o add.o print.o
        gcc -Wall -g main.o add.o sub.o print.o -o main
    main.o:main.c 
        gcc -Wall -g -c main.c -o main.o
    add.o:add.c add.h
        gcc -Wall -g -c add.c -o add.o
    sub.o:sub.c sub.h
        gcc -Wall -g -c sub.c -o sub.o
    print.o:print.c print.h
        gcc -Wall -g -c print.c -o print.o
    clean:
        rm -f *.o mai

    我们可以看到,main是我们最终想要生成的目标文件,它依赖main.o sub.o add.o print.o这四个.o文件。因此要执行gcc -Wall -g main.o add.o sub.o print.o -o main命令来生成目标文件,但是当前没有这些.o文件,因此就要先生成这些.o文件。我们写了四条xxx.o:xxx.c然后执行gcc -Wall -g -c xxx.c -o xxx.o,这些语句就会生成目标文件的依赖项。

    clean是一个伪目标文件,因为它没有依赖项。我们只是想通过make clean来将.o文件删除,但是我们通常要指定.PHONY:clean这条语句,用来显式的指定clean是伪目标,来防止当前目录下有一个同名的clean文件。这样,一个简单呢的Makefile文件就写好了。

    6、Makefile自动化变量

    虽然像上述那样可以完成编译,但是明显非常麻烦,接下来介绍Makefile的自动化变量。
    选项名    作用
    $@     规则的目标文件名
    $<     规则的第一个依赖文件名
    $^     规则的所有依赖文件列表

    我们使用这些自动化变量来尝试从写刚才的Makefile

    .PHONY:clean
    OBJ=main.o sub.o add.o print.o
    main:$(OBJ)
        gcc -Wall -g $^ -o $@
    main.o:main.c 
        gcc -Wall -g -c $< -o $@ 
    add.o:add.c add.h
        gcc -Wall -g -c $< -o $@ 
    sub.o:sub.c sub.h
        gcc -Wall -g -c $< -o $@ 
    print.o:print.c print.h
        gcc -Wall -g -c $< -o $@
    clean:
        rm -f *.o main

    我们定义了一个变量叫OBJ,他是我们的依赖项列表。然后使用自动化变量来代替对应的文件,如上所示。

    但是,我们这些.c文件都要生成.o文件,这样写也非常麻烦,我们介绍另一些规则。
        模式规则
            %.o:%.c
        后缀规则
            .c:.o

    我们来使用这两种规则:

    .PHONY:clean
    
    CC = gcc
    CFLAGS = -Wall -g
    OBJ = main.o sub.o add.o print.o
    main:$(OBJ)
        $(CC) $(CFLAGS) $^ -o $@
    #%.o:%.c
    .c.o:
        $(CC) $(CFLAGS) -c $< -o $@
    
    clean:
        rm -f *.o main

    使用这两个规则,就会将所有.c文件生成同名的.o文件,这样,Makefile就更加简洁。

    7、make常用的内嵌函数

        函数调用
            $(function arguments)
        $(wildcard PATTERN)
            当前目录写的匹配模式的文件
            例如:src=$(wildcard *.c)
        $(patsubst PATTERN,REPLACEMENT,TEXT)
            模式替换函数
            例如:$(patsubst %.c, %.o, $src)
            等价于$(src:.c=.o)
        shell函数
            执行shell命令
            例如:$(shell ls -d */)

    在学习GNU Make / Makefile总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

  • 相关阅读:
    4 Apr 18 软件开发目录 logging模块的使用 序列化(Json, Pickle) os模块
    3 Apr 18 内置函数 列表生成式与生成器表达式 模块的使用之import 模块的使用之from…import…
    2 Apr 18 三元表达式 函数递归 匿名函数 内置函数
    30 Mar 18 迭代器 生成器 面向过程的编程
    29 Mar 18 函数 有参、无参装饰器
    28 Mar 18 函数
    27 Mar 18 函数的参数
    26 Mar 18 函数介绍
    23 Mar 18 文件处理
    22 Mar 18 补充数据类型+字符编码+文件处理
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/GNUMakeOrMakefile_notes.html
Copyright © 2011-2022 走看看