Make以及Makefile的编写

1概述:

能读懂, 编写makefile应该是每一个Linux程序猿都必须拥有的基本素质,因为makefile是大型的工程中绕不过去的,你能不能写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。

因为,makefile关系到了整个工程的编译规则:

  1. 如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
  2. 如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程。
  3. 如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。

从上面的例子可以看出 , makefile是一个"自动化编译器",你只需要写好一个makefile, 然后执行一个make命令 , 整个工程就会自动按照规则编译了,极大提高了我们程序猿的效率。


2编写Makefile:

2.1 单文件Makefile:


//Makefile

test: test.o    #(test)是目标文件 (:)是依赖的文件或者命令   (test.o) 是test依赖的文件
    gcc -o test test.c 

.PHONY: clean   #(.PHONY)是伪目标标记, 伪目标标记后的命令,不会和目录下文件重复,\
                        也就是说clean如果没有伪目标标记的话,目录下有一个clean的文件\ 
                        make clean将不会正确执行! 
clean:
    rm -fr *.o test

引用一段百度百科结合我上面的例子,说明一下吧

1 冒号(:)左边的test是目标文件 , 目标文件依赖于冒号(:)右边, 

2 冒号右边即可以是文件test.o,也可以是目标,后面多文件多目录编译会讲到实例

3 第二行的gcc很明显是一个命令, 命令必须要以tab开头隔开 , Makefile里的命令可以是任何的shell命令


//test.c

#include <stdio.h>

int main(void) {

    printf("once_file_makefile ...\n");
    return 0;
}

运行结果:


2.2 多目录下Makefile编写

首先我建立一个Makefile的根目录如下图(1):


根目录下的Makefile如下:

CC := gcc
SUBDIR :=   d1\
            d2\
            test\
            obj#子目录文件夹
OBJS := d1.o d2.o test.o#生成目标文件所需的依赖
OBJS_DIR := obj#所有目标文件依赖的.o文件存放的目录
BIN := myapp#最终的目标文件
BIN_DIR := app#存放目标文件的目录
export CC OBJS OBJS_DIR BIN BIN_DIR#export关键字,导出CC等变量到子目录,让次级目录下的Makefile可以识别
all: CHECK_DIR $(SUBDIR) #分别执行CKECK_DIR和$(SUBDIR)两个依赖,这里的依赖是目标而不是文件
CHECK_DIR:
    @mkdir -p $(BIN_DIR) #创建存放目标文件的目录
$(SUBDIR): ECHO
    @make -C $@ #在所有的子目录下执行make 
ECHO:
    @echo start compile ...

.PHONY:clean
clean:
    @rm -fr $(OBJ)/*.o $(BIN_DIR)

d1/Makefile

../$(OBJS_DIR)/d1.o:d1.c #OBJS_DIR是从根目录通过export关键字传过来的变量\
                          也就等同于../obj/d1.o依赖于当前目录下d1.c
    $(CC) -c $^ -o $@ #gcc -c 依赖(d1.c) -o 目标(d1.o) $^表示所有依赖, $@表示目标

d2/Makefile

../$(OBJS_DIR)/d2.o: d2.c
    $(CC) -c $^ -o $@

test/Makefile

../$(OBJS_DIR)/test.o: test.c
    $(CC) -c $^ -o $@

obj/Makefile

../$(BIN_DIR)/$(BIN):$(OBJS)
    $(CC) -o $@ $^

include/include.h

// include/include.h
#ifndef __INCLUDE_H__
#define __INCLUDE_H__

#include <stdio.h>

#define DEBUG(f, arg...)    printf("file:[%s] " " line:[%d] :"f"\n",\
                            __FILE__, __LINE__, ##arg)
#endif //__INCLUDE_H__

d1/d1.c d2/d2.c test/test.c

// d1/d1.c
#include "../include/include.h"

void d2(void) {
    DEBUG("Massage from d2");

}
// d2/d2.c
#include "../include/include.h"

void d1(void) {
    DEBUG("Massage from d1");

}
// test/test.c
#include "../include/include.h"

int main(void) {

    d1();
    d2();
    return 0;
}



运行结果:


猜你喜欢

转载自blog.csdn.net/weixin_38176039/article/details/80246141
今日推荐