Makefile 学习笔记(三)实例



1 迷宫问题的工程实例

        该工程包含三个头文件main.hstack.hmaze.h,和三个源文件main.cstack.cmaze.c

/*头文件main.h*/
#ifndef MAIN_H
#define MAIN_H

typedef struct point {int row, col;}item_t;

#define MAX_ROW 5
#define MAX_COL 5

#endif
/*源文件main.c*/
#include <stdio.h>
#include "main.h"
#include "stack.h"
#include "maze.h"

struct point predecessor[MAX_ROW][MAX_COL] = {
    {{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1}},
    {{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1}},
    {{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1}},
    {{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1}},
    {{-1, -1},{-1, -1},{-1, -1},{-1, -1},{-1, -1}},
};

void visit(int row, int col, struct point pre)
{
    struct point visit_point = {row, col};
    maze[row][col] = 2;
    predecessor[row][col] = pre;
    push(visit_point);
}

int main(void)
{
    struct point p = {0, 0};

    maze[p.row][p.col] = 2;
    push(p);

    while (!is_empty())
    {
        p = pop();
        if (p.row == MAX_ROW - 1 && p.col == MAX_COL - 1)
            break;
        if (p.col + 1 < MAX_COL && maze[p.row][p.col + 1] == 0)
        {
            visit(p.row, p.col + 1, p);
        }

        if (p.row + 1 < MAX_ROW && maze[p.row+1][p.col] == 0)
        {
            visit(p.row +1, p.col, p);
        }
        
        if (p.col -1 >= 0 && maze[p.row][p.col - 1] == 0)
        {
            visit(p.row, p.col - 1, p);
        }

        if (p.row -1 >= 0 && maze[p.row - 1][p.col] == 0)
        {
            visit(p.row - 1, p.col, p);
        }

        print_maze();
        
    }

    if (p.row == MAX_ROW - 1 && p.col == MAX_COL - 1)
    {
        printf("(%d, %d)\n", p.row, p.col);
        while (predecessor[p.row][p.col].row != -1)
        {
            p = predecessor[p.row][p.col];
            printf("(%d, %d)\n", p.row, p.col);
        }
    }
    else
    {
        printf("No path!\n");
    }

    return 0;
}
/*头文件stack.h*/
#ifndef STACK_H
#define STACK_H

#include "main.h"
extern void push(item_t);
extern item_t pop(void);
extern int is_empty(void);

#endif
/*源文件stack.c*/
#include "stack.h"

static item_t stack[512];
static int top = 0;

void push(item_t p)
{
    stack[top++] = p;
}

item_t pop(void)
{
    return stack[--top];
}

int is_empty(void)
{
    return top == 0;
}
/*头文件maze.h*/
#ifndef MAZE_H
#define MAZE_H

#include "main.h"

extern int maze[MAX_ROW][MAX_COL];
void print_maze(void);

#endif
/*源文件maze.c*/
#include <stdio.h>
#include "maze.h"

int maze[MAX_ROW][MAX_COL] = {
    0, 1, 0, 0, 0,
    0, 1, 0, 1, 0,
    0, 0, 0, 0, 0,
    0, 1, 1, 1, 0,
    0, 0, 0, 1, 0,
};

void print_maze(void)
{
    int i, j;
    for (i = 0; i < MAX_ROW; i++)
    {
        for (j = 0; j < MAX_COL; j++)
            printf("%d ", maze[i][j]);
        putchar('\n');
    }
    printf("*******************\n");
}
一般,将这些源文件编译链接在一起的命令如下:
gcc main.c stack.c maze.c -o main

但这不是好方法,因为如果其中的maze.c文件做了修改,则需要把所有源文件编译一遍,即使其他的源文件和头文件都没有修改也需要跟着重新编译。

2 Makefile文件

    这个时候就需要编写一个Makefile文件和源代码放在同一个目录下,用Makefile文件来管理这些源文件的编译过程。
#Makefile文件
main : main.o stack.o maze.o
	gcc main.o stack.o maze.o -o main

main.o : main.c main.h stack.h maze.h
	gcc -c main.c

stack.o : stack.c stack.h main.h
	gcc -c stack.c

maze.o : maze.c maze.h main.h
	gcc -c maze.c

clean:
	@echo "cleanning project"
	-rm main *.o
	@echo "clean completed"

.PHONY : clean
   用make命令编译:
[root]# make
make: Warning: File `makefile' has modification time 4.5e+03 s in the future
gcc -c main.c
gcc -c stack.c
gcc -c maze.c
gcc main.o stack.o maze.o -o main
make: 警告:检测到时钟错误。您的创建可能是不完整的。
[root]# make clean
make: Warning: File `makefile' has modification time 3.5e+03 s in the future
cleanning project
rm main *.o
clean completed
make: 警告:检测到时钟错误。您的创建可能是不完整的。
[root]# 

2.1 make处理Makefile文件的过程分为两个阶段:

1)从前到后读取所有规则,建立起完整的依赖关系图。


2)从缺省目标或者命令执行指定的目标开始,根据依赖关系图选择适当的规则执行。


2.2Makefile文件中一些约定的目标名字:

all:执行主要的编译工作,通常用作缺省目标。

install:执行编译后的安装工作,把可执行文件、配置文件、文档等分别拷贝到不同的安装目录。

cean:删除编译生成的二进制文件

distclean:不仅删除编译生成的二进制文件,也删除其他的生成文件。


2.3 Makefile中的变量

Makefile中的变量包括自己定义的变量和一些特殊变量。

1)自定义变量

Makefile中的变量就像C语言中的宏定义一样,代表一串字符(或者空字符串)。变量名加上括号和$符号,则表示将变量的值展开。

自定义变量的格式1:

#格式1:  变量名 =  值
all:
	@echo $(foo)
foo = Ah $(bar)
bar = Huh?

    通过=号定义一个变量,如果=号右边有需要展开的形式,如$(bar),并不会在定义这个变量时立即展开,而是直到这个变量取值时才进一步展开,也叫做递归展开。

自定义变量的格式2

#格式2:  变量名 :=  值
all:
	@echo $(foo)
bar := Huh?
foo := Ah $(bar)

    通过:=号定义的变量在定义时就立即展开=右边,而不是等到变量取值时再展开。

2)特殊变量

$@,表示规则中的目标

$*,表示模式中规则中的stem

$<,表示规则中的第一个条件

$?,表示规则中所有比目标新的条件,组成一个列表,以空格分隔

$^,表示规则中的所有条件,组成一个列表,以空分隔,如果这个列表中有重复的项,则消除重复的项。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值