fastDFS 简介 安装 配置及API使用

1. 分布式文件系统

1.1传统文件系统

  • 传统的文件系统格式:
    • ntfs / fat32 / ext3 / ext4
      在这里插入图片描述

1.2分布式文件系统

文件系统的全部,不在同一台主机上,而是在很多台主机上,多个分散的文件系统组合在一起,形成了一个完整的文件系统。

在这里插入图片描述

思考:如何将多台主机组合成为一个分布式文件系统???

  • 使用现有的框架实现该功能
    -必须有两个角色
    -存储文件角色
    -管理者角色 - 进程


2. FastDFS

2.1 fastDFS介绍

1.fastDFS概述

  • 是用c语言编写的一款开源的分布式文件系统框架。
    • 中国人
    • 余庆-淘宝架构师
  • 为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,注重高可用、高性能等指标
    • 冗余备份:- 纵向扩容
    • 线性扩容:- 横向扩容
  • 可以很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
    • 应用场景:高效的存储文件
      • 上传过程
      • 下载过程
    • 案例:
      • 图:-图片服务器
        • 电商网站-展示的图片

2.fastDFS框架中的三个角色

  • 追踪器-tracker
    • 管理者角色
  • 存储节点-storage
    • 存储文件
    • 负责实现文件上传/下载功能
  • 客户端-client
    • 负责进行文件上传/下载操作(发出请求、下达命令)

3.fastDFS三个角色之间的关系

在这里插入图片描述
在这里插入图片描述

  • 1.追踪器
    • 可以对存储节点进行管理
    • 存储节点和客户端都需要连接追踪器
    • 追踪器进程需要先启动,然后存储节点启动,最后客户端启动
  • 2.存储节点
    • 连接追踪器,上传当前节点的状态信息
      • 存储节点当前的使用容量和剩余容量
      • 文件的同步情况
      • 文件上传/下载的次数
  • 客户端
    • 先连接追踪器
    • 上传和下载,为什么先连接追踪器?
      • 譬如上传-1G
        • 向追踪器询问:哪个存储节点有足够的容量存储上传的文件?
          • 客户端会得到符合条件的存储节点的连接信息
            • IP+Port
          • 客户端通过得到的IP+port连接存储节点
          • 给存储节点发送数据
          • 得到存储节点返回的文件ID
      • 譬如下载-a.txt
        • 客户端连接追踪器,询问要下载的文件信息
        • 追踪器进行查找,将对应的存储节点的IP+port发送给客户端
        • 客户端根据得到的IP+port连接这个存储节点
        • 存储节点将请求的文件数据发送给客户端
        • 客户端接收存储节点发送的数据,并且将其写入磁盘

4.fastDFS集群-(了解即可)

在这里插入图片描述

1.追踪器集群

  • 为什么集群?

    • 避免单点故障
  • 多个Tracker如何工作?

    • 轮询
  • 如何实现集群?

    • 修改配置文件

2.存储节点集群

  • fastDFS管理存储节点的方式?
    • 以分组的形式管理的
      • 每个组中可以有1台也可以有多台主机(纵向扩容 / 线性扩容:相互备份)
      • 同一组的主机之间,一般是相互备份关系,需要相互通信。
    • 可以有1个组也可以有多个组
  • 集群方式(扩容方式)
    • 横向扩容
      • 目的:增加存储的容量
      • 需要有一台新主机,添加到一个新的不存在的分组中
      • 不同组的主机(存储节点),不需要通信
    • 纵向扩容
      • 目的:备份
      • 给一个已经存在的组中添加新的主机,同一组中的主机会相互备份数据,所以同一组中的主机需要通信
      • 一个组的容量,是以组内容量最小的主机的容量,作为整个存储节点的容量

2.2 fastDFS安装

fastDFS安装

  • 先安装libfastcommon-1.36.zip //它是fastDFS的基础库包
    • unzip libfastcommon-1.36.zip //解压
    • rm libfastcommon-1.36.zip -rf //(安装完毕删除安装包)
    • cd libfastcommon-master //进入到安装包内
    • ./make.sh //生成库文件
    • ./make.sh install //安装
  • 再安装fastdfs-5.10.tar.gz // 安装fastDFS
    • tar -zxvf fast.xxx.tar.gz //解压
    • ./make.sh //生成库文件
    • ./make.sh install // 安装

在fastdfs安装包里,有一个INSTALL文件,里面有全部的安装和配置步骤

  • 安装完成后测试一把,在shell里直接执行

    • fdfs_test
  • ls /usr/bin/fdfs* //查看安装完成后都拷贝进去了哪些可执行文件

    /usr/bin/fdfs_appender_test /usr/bin/fdfs_download_file /usr/bin/fdfs_test1
    /usr/bin/fdfs_appender_test1 /usr/bin/fdfs_file_info /usr/bin/fdfs_trackerd
    /usr/bin/fdfs_append_file /usr/bin/fdfs_monitor /usr/bin/fdfs_upload_appender
    /usr/bin/fdfs_crc32 /usr/bin/fdfs_storaged /usr/bin/fdfs_upload_file
    /usr/bin/fdfs_delete_file /usr/bin/fdfs_test

    • 在shell中,可以直接执行这些可执行程序
  • cd /etc/fdfs //安装成功之后会在/etc下创建这个目录,并拷贝进去一系列的配置文件
    ls

    client.conf.sample — 客户端使用的配置文件

    storage.conf.sample — 存储节点使用的配置文件

    tracker.conf.sample — 追踪器使用的配置文件

    storage_ids.conf.sample – 用不着


3.3 fastFDS配置文件修改(部署fastDFS)

cp tracker.conf.sample tracker.conf // 依次去掉 .sample 后缀,保留原来的配置文件不动

cp tracker.conf.sample tracker.conf

cp client.conf.sample client.conf

cp storage.conf.sample storage.conf

cp storage_ids.conf.sample storage_ids.conf


1.tracker.conf

# 追踪器对应的主机的IP地址, 可以不写
bind_addr=

# 追踪器绑定的端口, 只要保证其是一个没有被占用的端口就可以
port=22122

# 追踪器进程写log日志的目录, 一些简单的数据文件也会放到该目录, xxx.pid
base_path=/home/yuqing/fastdfs
	# 这个路径必须存在
	# 我的改为了:
base_path=/home/lwh/Desktop/study/fastDFSLogFile/tracker # 只需更改这一处
	mkdir fastDFSLogFile
	mkdir client tracker storage

2.storage.conf

# 存储节点所属的组(横向扩容还是纵向扩容)
group_name=group1

# 当前存储节点对应的主机的IP地址, 也可不写
bind_addr=

# 存储节点绑定的端口
port=23000

# 存储log日志的目录, 也存储少量的数据文件
base_path=/home/lwh/Desktop/study/fastDFSLogFile/storage
	# 这个路径必须存在

# 当前存储节点的存储路径个数
store_path_count=1
# 指定具体的存储路径
store_path0=/home/lwh/Desktop/study/fastDFSLogFile/storage

# 如果 当前存储节点的存储路径个数为N个
store_path_count=N
# 依次 指定具体的存储路径
store_path0=/home/lwh/Desktop/study/fastDFSLogFile/storage/1
store_path1=/home/lwh/Desktop/study/fastDFSLogFile/storage/2
...
store_pathN=/home/lwh/Desktop/study/fastDFSLogFile/storage/n

# 要连接的追踪器的IP和端口(很重要)
tracker_server=192.168.184.131:22122

3.client.conf

# 客户端写log日志的目录
base_path=/home/lwh/Desktop/study/fastDFSLogFile/client
# 客户端要连接的追踪器的ip+port信息
tracker_server=192.168.0.197:22122

4.fastDFS集群配置

在这里插入图片描述


4.1如何集群tracker

  • 修改storage.conf,告诉存储节点,追踪器有集群
  • 修改client.conf,告诉客户端,追踪器有集群
  • 各个tracker,修改自己的tracker.conf
#storage.conf #配置追踪器集群的IP和Port
tracker_server=192.168.184.131:22122
tracker_server=192.168.185.131:22123
tracker_server=192.168.186.131:22124
tracker_server=192.168.187.131:22125
...	
#client.conf #配置追踪器集群的IP和Port
tracker_server=192.168.184.131:22122
tracker_server=192.168.185.131:22123
tracker_server=192.168.186.131:22124
tracker_server=192.168.187.131:22125
...

在这里插入图片描述


4.2 如何集群存储节点

  • (有足够多的主机)(自己实验时,要有足够多的虚拟机)
  • 在各个主机上安装fastDFS,然后分别修改storage.conf

在这里插入图片描述


4.3 客户端

  • 在各个主机上安装fastDFS,然后分别修改client.conf

在这里插入图片描述


3.4 fastDFS的启动

[root@lwh study]# ls /usr/bin/fdfs* # 查看fastDFS的可执行程序
/usr/bin/fdfs_appender_test   /usr/bin/fdfs_crc32          /usr/bin/fdfs_file_info  /usr/bin/fdfs_test      /usr/bin/fdfs_upload_appender
/usr/bin/fdfs_appender_test1  /usr/bin/fdfs_delete_file    /usr/bin/fdfs_monitor    /usr/bin/fdfs_test1     /usr/bin/fdfs_upload_file
/usr/bin/fdfs_append_file     /usr/bin/fdfs_download_file  /usr/bin/fdfs_storaged   /usr/bin/fdfs_trackerd

第一个:启动追踪器 - 守护进程

# 启动 tracker的可执行文件+配置文件
fdfs_trackerd /etc/fdfs/tracker.conf # 参数是需要加载的配置文件
# 关闭/终止
fdfs_trackerd /etc/fdfs/tracker.conf stop
# 重新加载/重启
fdfs_trackerd /etc/fdfs/tracker.conf restart


[root@lwh study]# ps aux | grep fdfs*
root      28546  0.0  0.1  80044  1664 ?        Sl   18:03   0:00 fdfs_trackerd /etc/fdfs/tracker.conf
root      28591  0.0  0.0 112712   968 pts/1    S+   18:03   0:00 grep --color=auto fdfs*

第二个:启动存储节点 - 守护进程

#启动
fdfs_storaged /etc/fdfs/storage.conf
# 终止
fdfs_storaged /etc/fdfs/storage.conf stop
# 重启
fdfs_storaged /etc/fdfs/storage.conf restart

[root@lwh study]# ps aux | grep fdfs*
root      28546  0.0  0.1  80044  1656 ?        Sl   18:03   0:00 fdfs_trackerd /etc/fdfs/tracker.conf
root      28626 64.4  0.0  12256   828 ?        R    18:05   0:04 fdfs_storaged /etc/fdfs/storage.conf
root      28629  0.0  0.0 112712   968 pts/1    R+   18:05   0:00 grep --color=auto fdfs*

最后:启动客户端 - 普通进程

# 上传
[root@lwh study]# fdfs_upload_file /etc/fdfs/client.conf ./a.txt 
group1/M00/00/00/wKi4g16z3j-AIFviAAAAGUtZyi8845.txt # 得到返回的file_id(文件ID)
[root@lwh study]# 
- 第一个参数: 客户端加载的配置文件
- 第二个参数: 上传的文件
	- 执行成功之后得到一个字符串
    group1/M00/00/00/wKi4g16z3j-AIFviAAAAGUtZyi8845.txt  #file_id 文件ID
    	- 组/文件夹名/文件夹名/文件名
        - 下载的时候需要使用这个字符串	

测试

# 上传test.cpp
fdfs_upload_file /etc/fdfs/client.conf /home/lwh/Desktop/study/test/test.cpp
# 得到的file_id为  group1/M00/00/00/wKi4hV7rfYyAd95HAAAGErTwkiY696.cpp
# 下载文件
[root@lwh download]# fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/wKi4hV7rfYyAd95HAAAGErTwkiY696.cpp
[root@lwh download]# ls
wKi4hV7rfYyAd95HAAAGErTwkiY696.cpp
# 把文件的名字改为原来的文件名
[root@lwh download]# mv wKi4hV7rfYyAd95HAAAGErTwkiY696.cpp test.cpp
[root@lwh download]# ls
test.cpp
# 下载
[root@lwh study]# fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/wKi4g16z3j-AIFviAAAAGUtZyi8845.txt
[root@lwh study]# ll | grep *.txt
-rw-r--r--. 1 root root 25 May  7 19:52 wKi4g16z3j-AIFviAAAAGUtZyi8845.txt
    - 参数1: 客户端使用的配置文件
    - 参数2: 上传文件成功之后得到的file_ID


# 分析
1. 文件上传之后得到fileID, 我们需要保存这个FileID, 也需要保存原来的文件名
	- 真实的开发环境中如何保存?
		写入数据库表中
2. 下载的时候通过这个ID下载
3. 下载完成需要将文件名改为原来的名字

上传文件完成之后,把file_id和原来的文件名,作为一条记录,插入到数据库中
下载下来文件之后,根据file_id进行查询,找到原来的文件名,进行名字的还原,此时完成下载

fastDFS状态检测

  • 命令
# fdfs_monitor /etc/fdfs/client.conf   # 显示整个分布式文件系统及各个存储节点的状态信息
	# 着重看 ip_addr 后的状态是不是 ACTIVE # 证明这个节点能正常工作


# 删除指定组中的某一个存储节点
fdfs_monitor /etc/fdfs/client.conf delete group1 10.120.151.114
	# 删除group1中的 IP为10.120.151.114存储节点

[Storage Server的7种状态]
https://blog.csdn.net/u014723529/article/details/46048411

# FDFS_STORAGE_STATUS:INIT :初始化,尚未得到同步已有数据的源服务器
# FDFS_STORAGE_STATUS:WAIT_SYNC :等待同步,已得到同步已有数据的源服务器
# FDFS_STORAGE_STATUS:SYNCING :同步中
# FDFS_STORAGE_STATUS:DELETED :已删除,该服务器从本组中摘除
# FDFS_STORAGE_STATUS:OFFLINE :离线
# FDFS_STORAGE_STATUS:ONLINE :在线,尚不能提供服务

某一个存储节点状态不正常,以上状态都不能正常工作
	原因:频繁的修改配置文件,导致多次读取,有一些数据混乱,导致不能正常工作
	解决:
		删除指定组中的某一个存储节点,
		把配置文件修改正确之后,然后再添加上去,
		重新启动fastDFS,让它能够正确的加载


# FDFS_STORAGE_STATUS:ACTIVE :在线,可以提供服务
#正常状态必须是ACTIVE,如果运行以下命令:
fdfs_monitor /etc/fdfs/client.conf

#发现有以下状态的服务器:
Storage 4:
        ip_addr = 10.120.151.114  WAIT_SYNC
        
#经过各种重启都不解决问题,只好先删除,再加入
#从集群中删除
fdfs_monitor /etc/fdfs/client.conf delete group1 10.120.151.114
#在114服务器中,删除数据文件夹
rm -rf /home/lwh/Desktop/study/fastDFSLogFile/storage/data
#重启114节点
fdfs_storaged /etc/fdfs/storage.conf

#重新检测状态信息
fdfs_monitor /etc/fdfs/client.conf

3.5 对file_id的解释

  • group1/M00/00/00/wKi4g16z3j-AIFviAAAAGUtZyi8845.txt
  • group1
    • 组名, 文件上传到了存储节点上, 这个存储节点所属的组
  • M00
    • M00是虚拟磁盘目录, M00这个目录是不存在的
    • 它实际上是映射到了一个真实存在的目录
      • 需要参考存储节点设置的存储目录
      • 先找store_path0=/home/lwh/Desktop/study/fastDFSLogFile/storage
      • 然后在进入其data目录
        • M00等价于/home/lwh/Desktop/study/fastDFSLogFile/storage/data/
    • 这个值有可能是M00、M01、M02…
      • store_path_count=1
      • 每一个真实的存储目录都对应的M0x(x=0,1,2,3…)
  • 00/00
    • 实际的存储目录
    • /home/lwh/Desktop/study/fastDFSLogFile/storage/data/00/00/
  • wKi4g16z3j-AIFviAAAAGUtZyi8845.txt
    • 文件名包含的信息
    • 采用Base64编码
      • 包含的字段包括
        • 源storage server Ip 地址
        • 文件创建时间
        • 文件大小
        • 文件CRC32效验码
          • 循环冗余校验
        • 随机数


4. 上传下载代码实现

  1. 使用多进程方式实现
    在这里插入图片描述
  2. 使用fastDFS API实现

源码安装包里面的 ./client 下有作者的源码例程

看明白之后,自己修改成函数,就可以直接使用这个函数完成某项功能了



5. Linux下源码安装 - 回顾

安装流程:

  1. 以下文件, 里边有安装步骤

    readme

    readme.md

    INSTALL

  2. 找 可执行文件 configure

  • 执行这个可执行文件
    • 检测安装环境
    • 生成 makefile
  1. 执行make命令
  • 编译源代码
    • 生成了动态库
    • 静态库
    • 可执行程序
  1. 安装 make install (需要管理员权限)
  • 将第三步生成的动态库/动态库/可执行程序拷贝到对应的系统目录


6. fastDFS复习

  • fastDFS是什么?
    • 分布式文件系统的框架
  • 能干什么?
    • 实现文件的上传、下载
  • 怎么用?
    • 三个角色:
      • 追踪器 - tracker
      • 存储节点 - storage
      • 客户端 - client
    • 修改配置文件
    • 启动
      • 追踪器:

        • fdfs_trackerd /etc/fdfs/tracker.conf (stop/restart)
      • 存储节点

        • fdfs_storaged /etc/fdfs/storage.conf (stop/restart)
      • 客户端

        • 代码根据用户需求由程序员实现


7. 客户端编写

7.1 多线程方式

在这里插入图片描述

  • 直接执行fdfs_upload_file命令, 得到的文件ID会写到当前终端
    • 需要对输出做重定向 - dup2(old, new)
// 调用execlp()这个进程有没有能力读数据?
// 没有!灵魂替换!此时这个进程已经不受控制了
// 所以,在调用execlp()之前,进行重定向
// 把file_id交父进程去读(子进程生成的数据,由父进程去读,其实就是进程间通信)
int dup2(int oldfd, int newfd);
dup2(xxx, stdout_fileno)
execlp(fdfs_upload_file, xxx, xxx, NULL);

// 父进程需要读子进程得到的文件ID
// 通过匿名管道的方式, 实现进程间通信(有血缘关系时,匿名管道最简单)
// dup2重定向的时候,把标准输出重定向到写端,父进程通过管道读端,就把子进程中的数据读出来了

7.2 fastDFS API

1. 多线程方式实现文件上传

// myUpload_file_execlp.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

void myUpload_file_execlp(const char *conf_filename, const char *local_filename, char *file_id, int len)
{
    
    
	// 1.创建管道
	int fd[2];
	int ret = pipe(fd);
	if (-1 == ret)
	{
    
    
		perror("pipe error");
		exit(0);
	}

	// 2.创建子进程
	pid_t pid = fork();
	if (pid == 0)
	{
    
    
		//子进程
		close(fd[0]);
		dup2(fd[1], STDOUT_FILENO);
		execlp("fdfs_upload_file", "fdfs_upload_file", conf_filename, local_filename, NULL);
		perror("execlp() error");
		exit(-1);
	}
	else if (pid > 0)
	{
    
    
		//父进程
		close(fd[1]);
		read(fd[0], file_id, len);
		close(fd[0]);
		wait();
	}
}

int main()
{
    
    
	char file_id[1024] = {
    
    0};
	int len = sizeof(file_id);
	myUpload_file_execlp("/etc/fdfs/client.conf", "myUpload_file_execlp.c", file_id, len);
	printf("file_id: %s", file_id);
	return 0;
}
# Makefile

#---------------------------------------------------------
# 生成可执行文件 execute
PROJECT     = execute
#---------------------------------------------------------
# .o文件
SrcSuf      = c
SrcSuf2     = cpp
ObjSuf      = o
LibSuf      = so

OBJFILES    = ./myUpload_file_execlp.$(ObjSuf)

#---------------------------------------------------------
CC          = g++

# 编译选项
CFlag       = -w -g -ggdb -fshort-wchar -std=c++11  
#---------------------------------------------------------
.SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(LibSuf) .$(SrcSuf2)

all:  $(PROJECT) clean

$(PROJECT):$(OBJFILES)
	@echo "creating $(PROJECT) start..."
	$(CC) $(OBJFILES) -o $(PROJECT)
	@echo "creating $(PROJECT) end"
#---------------------------------------------------------
.$(SrcSuf).$(ObjSuf):
	@echo "Compiling $(PROJECT) $<"
	$(CC) -MM $^ 
	$(CC) -c $< -o $@ $(CFlag) 
#---------------------------------------------------------
.$(SrcSuf2).$(ObjSuf):
	@echo "Compiling $(PROJECT) $<"
	$(CC) -MM $^ 
	$(CXX) -c $< -o $@
#---------------------------------------------------------
clean:
	@echo "Cleaning $(PROJECT) project files"
	@rm -f $(OBJFILES) core
	
.PHONY:cleanobj
cleanobj:
	-rm -f $(OBJFILES) 
.PHONY:cleanexe
cleanexe:
	-rm -f $(PROJECT) 
.PHONY:cleanall
cleanall:cleanobj cleanexe

2. 使用fastDFS API实现文件上传

// myUpload_file_fdfsAPI.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "fdfs_client.h"

int myUpload_file_fdfsAPI(const char *conf_filename, const char *local_filename, char *file_id)
{
    
    
	char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
	ConnectionInfo *pTrackerServer;
	int result;
	int store_path_index;
	ConnectionInfo storageServer;

	if ((result = fdfs_client_init(conf_filename)) != 0)
	{
    
    
		return result;
	}

	pTrackerServer = tracker_get_connection();
	if (pTrackerServer == NULL)
	{
    
    
		fdfs_client_destroy();
		return errno != 0 ? errno : ECONNREFUSED;
	}

	*group_name = '\0';

	if ((result = tracker_query_storage_store(pTrackerServer,
											  &storageServer,
											  group_name,
											  &store_path_index)) != 0)
	{
    
    
		fdfs_client_destroy();
		fprintf(stderr, "tracker_query_storage fail, "
						"error no: %d, error info: %s\n",
				result, STRERROR(result));
		return result;
	}

	result = storage_upload_by_filename1(pTrackerServer,
										 &storageServer, store_path_index,
										 local_filename, NULL,
										 NULL, 0, group_name, file_id);
	if (result == 0)
	{
    
    
		printf("%s\n", file_id);
	}
	else
	{
    
    
		fprintf(stderr, "upload file fail, "
						"error no: %d, error info: %s\n",
				result, STRERROR(result));
	}

	tracker_disconnect_server_ex(pTrackerServer, true);
	fdfs_client_destroy();

	return result;
}

int main()
{
    
    
	char file_id[1024] ;
	memset(file_id,0,sizeof(file_id));
	myUpload_file_fdfsAPI("/etc/fdfs/client.conf", "myUpload_file_fdfsAPI.c", file_id);
	printf("file_id: %s", file_id);
	return 0;
}
#---------------------------------------------------------
# 生成可执行文件 execute
PROJECT     = execute
#---------------------------------------------------------
# .o文件
SrcSuf      = c
SrcSuf2     = cpp
ObjSuf      = o
LibSuf      = so

OBJFILES    = ./myUpload_file_fdfsAPI.$(ObjSuf)

# 头文件目录
INCLUDEPATH =  -I /usr/include/fastdfs/ 
INCLUDEPATH += -I /usr/include/fastcommon/ 

# 库目录
LIBPATH    +=  -L /usr/lib/
#---------------------------------------------------------
CC         =   g++

# 编译选项
CFlag      =   -w -g -ggdb -fshort-wchar -std=c++11  $(INCLUDEPATH)

# 链接选项
LDFLAGS    +=  -l fdfsclient $(LIBPATH) 
#---------------------------------------------------------
.SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(LibSuf) .$(SrcSuf2)

all:  $(PROJECT) clean
# 生成可执行文件
$(PROJECT):$(OBJFILES)
	@echo "creating $(PROJECT) start..."
	$(CC) $(LDFLAGS) $(OBJFILES) -o $(PROJECT) 
	@echo "creating $(PROJECT) end"
#---------------------------------------------------------
# .c 生成 .o 文件
.$(SrcSuf).$(ObjSuf):
	@echo "Compiling $(PROJECT) $<"
	$(CC) -c $(CFlag) $< -o $@ 
#---------------------------------------------------------
# .cpp 生成 .o 文件
.$(SrcSuf2).$(ObjSuf):
	@echo "Compiling $(PROJECT) $<"
	$(CXX) -c $(CFlag) $< -o $@
#---------------------------------------------------------
# 删除 .o 文件
clean:
	@echo "Cleaning $(PROJECT) project files"
	@rm -f $(OBJFILES) core

# make cleanall 删除 .o 文件 execute文件
.PHONY:cleanobj
cleanobj:
	-rm -f $(OBJFILES) 
.PHONY:cleanexe
cleanexe:
	-rm -f $(PROJECT) 
.PHONY:cleanall
cleanall:cleanobj cleanexe


猜你喜欢

转载自blog.csdn.net/liangwenhao1108/article/details/109143414