make是什么?
    make:一种控制编译或者重复编译软件的工具make 可以自动完成软件的编译内容,方式和时机,从而使程序员把更多的精力集中在编写代码上。make命令不仅仅用于编译程序,无论何时,当需要通过输入多个输入文件来生成输出文件的时候都可以利用它来完成任务,它的其他用法还包括文档处理。

make命令和makfile文件:
    make命令本身内置了很多智能机制,但光凭其自身是无法了解应该如何建立应用程序的。必须为make提供一个配置文件这个配置文件就是makefile。make命令默认读当前目录下的makefile文件,也可以通过-f来指定makefile文件。

make命令的选项和参数:

    -k 让make在发生错误的时候继续执行。
    -n 输出要执行的步骤而不是执行
    -f <filename> 指定makefile文件


makefile文件的构成:
    1.依赖关系
        依赖关系定义了最终应用程序里的每个文件与源文件之间的关系.
        例如:main.o 依赖于 main.c和a.h
        依赖关系的语法:
            目标名称:空格/tab 各个文件列表(用空格或tab分割)
        那么就可以写成:
            main.o:    main.c a.h
        下面是一个完整的依赖关系:

        myapp:    main.o 2.o 3.o
        main.o: main.c a.h
        2.o: 2.c a.h b.h
        3.o: 3.c b.h c.h

        显示了源文件之间的依赖关系。要想创建myapp就要先创建main.o 2.o 3.o,main.o有依赖main.c a.h等等
        通过解决这些依赖关系最终创建目标文件myapp。如果想在一个makefile文件中创建多个文件就需要使用all伪目标
        示列如下:

        firstapp: main.o
        main.o: main.c main.h
        secondapp: second.o
        second.o: second.c second.h
        all: firstapp secondapp

        如果没有指定all 那么make默认只创建makefile中找到的第一个目标

    2.规则
        定义了目标的创建方式,上面只是定义目标,但是目标该如何创建就需要规则。makefile中的规则是有语法限制的,要以tab制表符开头。
        下面是一个简单的makefile文件示列:

        myapp:    main.o 2.o 3.o
            gcc myapp main.o 2.o 3.o
        main.o: main.c a.h
            gcc -c main.c
        2.o: 2.c a.h b.h
            gcc -c 2.c
        3.o: 3.c b.h c.h
            gcc -c 3.c

        上面的执行过程如下:

        gcc -c main.c
        gcc -c 2.c
        gcc -c 3.c
        gcc -o myapp main.o 2.o 3.o


    3.注释
        makefile文件的注释是以#号开头

    4.makefile文件中的宏
     一个问题,如果目标文件不是main.c 2.c 3.c这些,换成其他的名字,那么整个makfile文件都要修改,如果gcc换成g++那么makefile文件又要重新修改很是麻烦,makefile文件中提供了宏的功能。
     示列如下:

    CC=gcc
    CFLAGS=-g -Wall -ansi
    hello: hello.o
            ${CC} -o hello hello.o
    hello.o:
            ${CC} -o hello.o ${CFLAGS} -c hello.c

    输出:

    gcc -o hello.o -g -Wall -ansi -c hello.c
    hello.c: In function ‘main’:
    hello.c:6: warning: control reaches end of non-void function
    gcc -o hello hello.o
    makefile中内置宏:
    $?    当前目标所依赖的文件列表中比当前目标文件还要新的文件
    $@    当前目标的名字
    $<    当前依赖文件的名字
    $*  不包括后缀名的当前依赖文件的名字

    更加充分的利用宏:

    CC=gcc
    SRCS=hello.c test.c
    OBJS=$(SRCS:.c=.o)
    EXEC=hello
    start: $(OBJS)
            $(CC) -o $(EXEC) $(OBJS)
    .c.o:
            $(CC) -o $@ -c $<


       OBJS=$(SRCS:.c=.o) 将.c源文件的后缀替换成.o就是其目标文件
       这样来定义宏有一个好处就是假如有多个源文件,就不需要写多个对应的目标文件了,
       .c.o: 这个标号代表.c和.o文件有依赖关系,要想生成.o文件需要编译.c文件
        $(CC) -o $@ -c $< 这句话就是要执行的规则,$@当前.o文件的名字$<当前.o依赖的文件名字
        上面的这个makefile执行过程如下:

    gcc -o hello.o -c hello.c
    gcc -o test.o -c test.c
    gcc -o hello hello.o test.o

    5.makfile中的clean,和install
        通常在makefile编译中需要清楚上一次的编译结果需要清楚.o文件,可以加入一个clean目标来清除.o文件编译好的二进制文件通过也会通过make install拷贝到相应目录中。
    下面是完整的makefile的带有clean和install目标示列:

    CC=gcc
    SRCS=hello.c test.c
    OBJS=$(SRCS:.c=.o)
    EXEC=hello
    start: $(OBJS)
            $(CC) -o $(EXEC) $(OBJS)
    .c.o:
            $(CC) -o $@ -c $<
    clean:
            rm -rf ${OBJS}
    install:
            cp ${EXEC} /tmp/
      执行makr clean结果如下:
          rm -rf hello.o test.o
      执行make install结果如下:
          rm -rf hello.o test.o