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,转载请注明出处。

  • 相关阅读:
    Ubuntu安装Cassandra
    Ubuntu安装中文输入法
    CoreOS, Kubernetes, etcd
    CountDownLatch, CyclicBarrier and Semaphore
    Java Primitives and Bits
    vue 和 webstorm(01) 之 基本入门 _fei
    ubuntu 命令窗口背景颜色 #300a24 _fei
    2345 看图王ad介绍----关闭广告 _fei
    PHP 使用 pdo 操作oracle数据库 报错 _fei
    PHP 使用 pdo 操作oracle数据库 报错 _fei
  • 原文地址:https://www.cnblogs.com/Alliswell-WP/p/GNUMakeOrMakefile_notes.html
Copyright © 2011-2022 走看看