make与Makefile

Linux Make 使用与 Makefile 编写指南 Make是 Linux 下常用的自动化构建工具,通过读取Makefile文件中的规则,自动判断哪些文件需要重新编译,从而高效管理项目构建流程。依赖管理:自动处理文件间的依赖关系。增量编译:仅重新编译修改过的文件,提升效率。任务自动化:支持编译、清理、测试、安装等自定义任务。 阅读详情

Makefile 包含了所有的规则和目标,而 make 则是为了完成目标而去解释 Makefile 规则的工具

make语法
make [ -f makefile ] [ options ] … [ targets ] …

前期准备

无论是c/c++都是由源文件编译为目标文件,Windows上.obj,UNIX上.o文件,即Object File文件。然后再把大量的Object File合成执行文件,此过程交链接。

makefile介绍

make命令执行时,需要一个makefile文件,用以告诉make命令需要如何去链接和编译

makefile规则

target ... : prerequisites ...
    command

target
可以是一个object file(目标文件),也可以是一个执行文件,还可以是一个标签(label)。

prerequisites
生成该target所依赖的文件和/或target

command
该target要执行的命令(任意的shell命令)

示例:
如果一个工程有3个头文件和8个c文件,为了完成前面所述的那三个规则,我们的makefile 应该是下面的这个样子的。

edit : main.o kbd.o command.o display.o \
        insert.o search.o files.o utils.o
    cc -o edit main.o kbd.o command.o display.o \
        insert.o search.o files.o utils.o

main.o : main.c defs.h
    cc -c main.c
kbd.o : kbd.c defs.h command.h
    cc -c kbd.c
command.o : command.c defs.h command.h
    cc -c command.c
display.o : display.c defs.h buffer.h
    cc -c display.c
insert.o : insert.c defs.h buffer.h
    cc -c insert.c
search.o : search.c defs.h buffer.h
    cc -c search.c
files.o : files.c defs.h buffer.h command.h
    cc -c files.c
utils.o : utils.c defs.h
    cc -c utils.c
clean :
    rm edit main.o kbd.o command.o display.o \
        insert.o search.o files.o utils.o

这样比较便于makefile的阅读。我们可以把这个内容保存在名字 为“makefile”或“Makefile”的文件中,然后在该目录下直接输入命令 make 就可以生成执行文件edit。如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下 make clean 就可以了。
make会比较targets文件 和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或 者target不存在的话,那么,make就会执行后续定义的命令。
这里要说明一点的是, clean 不是一个文件,它只不过是一个动作名字,有点像c语言中的label一 样,其冒号后什么也没有,那么,make就不会自动去找它的依赖性,也就不会自动执行其后所定义的命令。 要执行其后的命令,就要在make命令后明显得指出这个label的名字。这样的方法非常有用,我们可以在一 个makefile中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份,等等

make是如何工作

输入make命令
1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个 文件,并把这个文件作为最终的目标文件。
2. 如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比 edit 这个 文件新,那么,他就会执行后面所定义的命令来生成 edit 这个文件。
3. 如果 edit 所依赖的 .o 文件也不存在,那么make会在当前文件中找目标为 .o 文件 的依赖性,如果找到则再根据那一个规则生成 .o 文件。(这有点像一个堆栈的过程)
4. 当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生 成make的终极任务,也就是执行文件 edit 了。

在makefile中使用变量

在makefile中可以使用变量来简化makefile的编辑。
如上边的例子中可以将edit依赖的文件用变量表示,用来减轻工作量。

objects = main.o kbd.o command.o display.o \
     insert.o search.o files.o utils.o

经过使用变量改良后的例子:

objects = main.o kbd.o command.o display.o \
    insert.o search.o files.o utils.o

edit : $(objects)
    cc -o edit $(objects)
main.o : main.c defs.h
    cc -c main.c
kbd.o : kbd.c defs.h command.h
    cc -c kbd.c
command.o : command.c defs.h command.h
    cc -c command.c
display.o : display.c defs.h buffer.h
    cc -c display.c
insert.o : insert.c defs.h buffer.h
    cc -c insert.c
search.o : search.c defs.h buffer.h
    cc -c search.c
files.o : files.c defs.h buffer.h command.h
    cc -c files.c
utils.o : utils.c defs.h
    cc -c utils.c
clean :
    rm edit $(objects)

make自动推导

只要make看到一个 .o 文件,它就会自动的把 .c 文件加在依赖关系中,如果make找到一个 whatever.o ,那么 whatever.c 就会是 whatever.o 的依赖文件。并且 cc -c whatever.c 也会被推导出来,于是,我们的makefile再也不用写得这么复杂。我们的 新makefile又出炉了。

objects = main.o kbd.o command.o display.o \
    insert.o search.o files.o utils.o

edit : $(objects)
    cc -o edit $(objects)

main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h

.PHONY : clean
clean :
    rm edit $(objects)

清空目标文件规则

例子中

clean:
    rm edit $(objects)

更稳健的方法

.PHONY : clean
clean :
    -rm edit $(objects)

前面说过, .PHONY 表示 clean 是一个“伪目标”。而在 rm 命令前面加了一个小减号的 意思就是,也许某些文件出现问题,但不要管,继续做后面的事。当然, clean 的规则不要放在文件 的开头,不然,这就会变成make的默认目标,相信谁也不愿意这样。不成文的规矩是——“clean从来都是放 在文件的最后”。

makefile可以有什么

  1. 显式规则。显式规则说明了如何生成一个或多个目标文件。这是由Makefile的书写者明显指出要生成的 文件、文件的依赖文件和生成的命令。
  2. 隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较简略地书写 Makefile,这是由make所支持的。
  3. 变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点像你C语言中的 宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
  4. 文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中 的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一 样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。
  5. 注释。#

引用其他的makefile

使用 include 关键字可以把别的Makefile包含进来
在 include 前面可以有一些空字符,但是绝不能是 Tab 键开始。
make命令开始时,会找寻 include 所指出的其它Makefile,并把其内容安置在当前的位置。就好 像C/C++的 #include 指令一样。如果文件都没有指定绝对路径或是相对路径的话,make会在当前目 录下首先寻找,如果当前目录下没有找到,那么,make还会在下面的几个目录下找:

  1. 如果make执行时,有 -I 或 –include-dir 参数,那么make就会在这个参数所指定的目 录下去寻找。
  2. 如果目录 \/include (一般是: /usr/local/bin 或 /usr/include )存在的话,make也会去找。
    如果有文件没有找到的话,make会生成一条警告信息,但不会马上出现致命错误。它会继续载入其它的 文件,一旦完成makefile的读取,make会再重试这些没有找到,或是不能读取的文件,如果还是 不行,make才会出现一条致命信息。如果你想让make不理那些无法读取的文件,而继续执行,你可以 在include前加一个减号“-”。如:
-include <filename>

其表示,无论include过程中出现什么错误,都不要报错继续执行。和其它版本make兼容的相关命令 是sinclude,其作用和这一个是一样的。

make的工作方式

GNU的make工作时的执行步骤如下:(想来其它的make也是类似)
1. 读入所有的Makefile。
2. 读入被include的其它Makefile。
3. 初始化文件中的变量。
4. 推导隐晦规则,并分析所有规则。
5. 为所有的目标文件创建依赖关系链。
6. 根据依赖关系,决定哪些目标要重新生成。
7. 执行生成命令。

书写规则

语法

targets是文件名,以空格分开,可以使用通配符。一般来说,我们的目标基本上是一个文件,但也有可能 是多个文件。

command是命令行,如果其不与“target:prerequisites”在一行,那么,必须以 Tab 键开头,如 果和prerequisites在一行,那么可以用分号做为分隔。(见上)

prerequisites也就是目标所依赖的文件(或依赖目标)。如果其中的某个文件要比目标文件要新,那么, 目标就被认为是“过时的”,被认为是需要重生成的。这个在前面已经讲过了。

在规则中使用通配符

如果我们想定义一系列比较类似的文件,我们很自然地就想起使用通配符。make支持三个通配符: * , ? 和 ~ 。
波浪号( ~ )字符在文件名中也有比较特殊的用途。如果是 ~/test ,这就表示当前用户 的 $HOME 目录下的test目录。而 ~hchen/test 则表示用户hchen的宿主目录下的test 目录。(这些都是Unix下的小知识了,make也支持)而在Windows或是 MS-DOS下,用户没有宿主目录, 那么波浪号所指的目录则根据环境变量“HOME”而定。

objects = *.o

上面这个例子,表示了通配符同样可以用在变量中。并不是说 *.o 会展开,不!objects的值就是 *.o 。Makefile中的变量其实就是C/C++中的宏。如果你要让通配符在变量中展开,也就是 让objects的值是所有 .o 的文件名的集合,那么,你可以这样:

objects := $(wildcard *.o)

文件搜索

在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的源文件分类,并存放在不同的目录中。 所以,当make需要去找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是把一个路径告 诉make,让make在自动去找。

Makefile文件中的特殊变量 VPATH 就是完成这个功能的,如果没有指明这个变量,make只会在当前 的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make就会在当当前目录找不到的情况下 ,到所指定的目录中去找寻文件了。

VPATH = src:../headers

上面的的定义指定两个目录,“src”和“../headers”,make会按照这个顺序进行搜索。目录由“冒号”分隔 。(当然,当前目录永远是最高优先搜索的地方)

伪目标

可以使用一个特殊的标记“.PHONY”来显式地指明一个目标是“ 伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”。

条件判断

libs_for_gcc = -lgnu
normal_libs =

foo: $(objects)
ifeq ($(CC),gcc)
    $(CC) -o foo $(objects) $(libs_for_gcc)
else
    $(CC) -o foo $(objects) $(normal_libs)
endif

我们可以从上面的示例中看到三个关键字: ifeq 、 else 和 endif 。 ifeq 的 意思表示条件语句的开始,并指定一个条件表达式,表达式包含两个参数,以逗号分隔,表达式以圆括号括 起。 else 表示条件表达式为假的情况。 endif 表示一个条件语句的结束,任何一个条件表达 式都应该以 endif 结束。

当我们的变量 (CC)值是gcc时,目标foo的规则是:foo:(CC)值是gcc时,目标foo的规则是:foo:(objects)
(CC)−ofoo(CC)−ofoo(objects) $(libs_for_gcc)

而当我们的变量 (CC)值不是gcc时(比如cc),目标foo的规则是:foo:(CC)值不是gcc时(比如cc),目标foo的规则是:foo:(objects)
(CC)−ofoo(CC)−ofoo(objects) $(normal_libs)

语法

<conditional-directive>
<text-if-true>
endif

and

<conditional-directive>
<text-if-true>
else
<text-if-false>
endif

其中 表示条件关键字,如 ifeq 。这个关键字有四个。
1. ifeq 比较参数 arg1 和 arg2 的值是否相同。
2. ifneq 其比较参数 arg1 和 arg2 的值是否相同,如果不同,则为真。
3. ifdef 如果变量 的值非空,那到表达式为真。否则,表达式为假。 同样可以是一个函数的返回值。
4. ifndef 在 这一行上,多余的空格是被允许的,但是不能以 Tab 键 作为开始(不然就被认为是命令)。

使用VIVADO 2019.1 搭建以太网接口 以太网 MAC+SGMII->GMII接口转换 以FPGA V7为例,搭建一个千兆以太网接口。运行环境为Vivado2019.1。板卡的FPGA V7与千兆网口芯片采用SGMII互联,最终实现FPGA与上位机之间的千兆网卡通信,实际实现时,V7采用MAC + GMII ->SGMII的结构。SGMII接口使用1G/2.5G Ethernet PCS/PMA or SGMII ip核,MAC层使用Tri Mode Ethernet MAC ip核。 由于MAC层IP不支持SGMII接口,因此需要G 阅读详情

相关推荐

GD32官方资料学习体系(主要包括MCU选型、原理图PCB设计、软件开发入门及用户手册等)

大部分还未更新,先占个坑,日后更新…… 目前国外芯片涨价涨的离谱(就是在说ST),国内最好的替代就是兆易创新出的系列芯片了。但是官方资料繁杂,小白上手不易,因此边入门边记录,也给后来者根据官方资料可以有一个较为完整的学习体系。

Eddie的博客 1万+

Makefile文件中的MAKEFILE_LIST变量

                                                                                          Makefile文件中的MAKEFILE_LIST变量        

Andy的博客 6530

中文顶刊《会计研究》文本分析技术最新进展总结盘点

会计研究》是由中华人民共和国财政部主管、中国会计学会主办的国家一级学术期刊,为会计领域中文顶级期刊。随着大数据技术的日益成熟, 社交网络类文本 、上市公司披露类文本、媒体报道类文本、 其他类文本 、网络搜索数据、P2P 网络借贷文 本与分析师报告等文本数据逐渐成为财务会计的研究素材。

qq_52891550的博客 2893

分享一个支持多目录层级的通用型Makefile配置文件

一、介绍 结合自己工程实践中的经验及参考网上资料,制作了一个通用型的Makefile配置文件,以求快速适配各种项目。 该Makefile支持自动头文件依赖处理、进度显示、根据终端开启/关闭多颜色区分显示。 整体划分为以下几个部分;配置区 完成工程基本配置,如工程根目录、目标文件、目标目录、缓存目录、代码、头文件、库文件等目录以及链接项编译配置处理区 设定DEFINES、CPPFLAGS、CXX等配置编译目标准备(勿动) 获取...

qq_25145163的博客 785

Docker:安装Apache Pulsar 消息队列的详细指南

本文详细介绍了Apache Pulsar的Docker化安装部署方法,包括单节点Pulsar服务和管理界面Pulsar Manager的安装配置。通过Docker命令快速搭建Pulsar环境,并演示了租户和命名空间的基础管理操作。同时提供了Spring Boot项目与Pulsar集成的完整方案,从依赖配置到客户端初始化,为开发人员构建实时消息系统提供实用参考。

木头 2209

Python爬虫实战:高效爬取法律法规数据库的完整指南

本文将详细介绍如何使用Python最新技术栈构建一个高效、稳定的法律法规数据库爬虫。我们将从爬虫的基本原理讲起,逐步深入到反爬机制应对、数据解析与存储、性能优化等高级话题。文章包含完整的代码实现,使用requests-html、aiohttp等现代库,以及应对法律数据库特殊结构的处理技巧。通过本文,您将掌握构建专业级法律数据采集系统的全套技能。关键词:Python爬虫、法律法规、数据采集、异步爬虫、反反爬本文详细介绍了使用Python爬取法律法规数据库的完整技术方案。

2201_76125261的博客 1275

makefile学习(五):预定义变量的使用

5.预定义变量的使用 学自<狄泰软件学院> 在makefile中存在一些预定义的变量 自动变量 $@, $^, $< 特殊变量 (MAKE) , (MAKECMDFOALS) , (MAKEFILE_LIST) (MAKE_VERSION), (CURDIR) , (.VARIABLES) …. 自动变量 $@: 当前规则中触发命令被执行的目标 ...

食梦者 931

ArcGIS Pro SDK (二十五)工作流管理器

【代码】ArcGIS Pro SDK (二十五)工作流管理器。

Winemonk 494

Makefile 变量MAKEFILE_LIST

make程序在读取多个makefile文件时,包括由环境变量“MAKEFILES”指定、命令行指定、当前工作下的默认的以及使用指示符“include”指定包含的,在这些文件进行解析执行之前make读取的文件名将会被自动依次追加到变量“MAKEFILE_LIST”的定义域中。 这样我们就可以通过测试此变量的最后一个字来获取当前make程序正在处理的makefile文件名。具体的说就是在一个makefile文件中如果使用指示符“include”包含另一个文件之后,变量“MAKEFILE_LIST”的最后一个字只

肥叔菌的博客 8573

【ACP】2025-最新-疑难题解析- 练习二汇总

全球加速是优化公网访问的,负载均衡是分发流量的,公网 NAT 网关是处理公网 IP 的,高速通道是建私网连接但不直接提供固定私网地址功能。C 是客户端加密方式,D 是 ECS 云盘加密,都不属于 OSS 服务器端加密。某企业想使用云服务器 ECS + 负载均衡 SLB + 弹性伸缩 (Auto Scaling) 的架构搭建一个企业级门户网站,技术负责人对于负载均衡和弹性伸缩配合使用没有经验,于是将他理解的两种产品配合使用的一些技术细节列成了一个表单,并请作为架构师的您帮他做一下鉴别,以下哪些项是正确的?

jundao1997的专栏 297

【大模型】百度千帆大模型对接LangChain使用详解

百度千帆大模型对接LangChain使用详解

congge 5065

Linux 下的make命令与Makefile

概述 博客内容包含linux下make命令的使用与makefile的书写规则等,希望通过本文档使读者对make命令makefile文件有进一步了解,由于鄙人经验学识有限文档中会有描述不准确以及理解偏差,欢迎读者指正。fythons@sina.com 从一只猫说起hello kitty linux系统中的make命令与makefile文件 make与makefile 在linux系统...

Fythons的博客 11万+

智能水下机器人设计: 基于MATLAB的水下机器人动力学建模和控制系统设计,包括水下环境感知、路径规划和任务执行等

智能水下机器人是指能够在水下自主完成各种任务的机器人,例如探测、勘察、救援等。它具有广阔的应用前景,可用于海洋环境监测、水下考古、海上作业等领域。基于MATLAB的水下机器人设计可以为科研人员和工程师提供强大的建模和仿真工具,帮助他们设计更智能、更高效的水下机器人。智能水下机器人是未来海洋科技发展的重要方向,它将为海洋科学研究、水下考古和海上作业等领域带来新的机遇。MATLAB是一种功能强大的数学和科学计算软件,它可以为智能水下机器人设计提供强大的工具和支持。

走向CTO的路上... 963

Make与Makefile

Make是一个经典的构建自动化工具,最初由Stuart Feldman于1977年在贝尔实验室开发。它通过读取Makefile文件来自动化编译过程,特别适用于C/C++项目,但也可用于其他语言的构建过程或任何需要文件转换的任务。

Made In SQL 1141

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Make与Makefile概述

**Make**是一个自动化构建工具,它通过读取名为**Makefile**的配置文件,确定项目中文件之间的依赖关系,并基于这些关系决定哪些部分需要重新构建,以及以何种顺序构建。

ScilogyHunter的博客 1930

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

make与makefile详解

在linux系统上编译大一点的项目时,会用到make/makefile文件 1.make与makefile 利用make工具,我们可以将大型的开发项目分解成为多个更易于管理的模块,对于一个包括几百个源文件的应用程序,使用make和makefile工具就可以简洁明快地理顺各个源文件之间纷繁复杂的相互关系。 而且如此多的源文件,如果每次都要键入gcc命令进行编译的话,那对程序员来说简直就是一场灾难。 而make工具则可自动完成编译工作,并且可以只对程序员在上次编译后修改过的部分进行编译。 因此,有效的利用mak

weixin_43966547的博客 3193

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

make、makefile、cmake之间的区别与联系

make、makefile、cmake之间的区别与联系 首先说明一下make、makefile、cmake存在的原因 在进行编译时,如果程序只有一个源文件,那么我们可以直接利用gcc命令对其进行编译; 但是,如果程序包含多个源文件的话,用gcc命令对源文件进行逐个编译显然会比较繁琐。尤其是在有大量源文件时,这样繁琐的编译工作很容易会导致混乱; 为了使多个源文件的编译工作更加便捷,就出现了make...

Aiyanghong的博客 6681

Linux工具之make与makefile

递归赋值 (:(即前面的变量可以通过后面的变量定义)a2 = 0a1 = $(a2) # a1的值在使用时动态确定,即a1的值在运行时取决于a2的当前值直接赋值 (:=:(前面的不可通过后面的定义,后面直接赋值给前面)a1 := $(a2) # a2此时未定义,a1为空a2 = 0 # 不影响a1的值这里对递归以及直接做一个对比,加深印象递归赋值:延迟展开,值在调用时动态确定,允许前后变量依赖直接赋值:立即展开,值在定义时固定避免后续依赖追加赋值 (+=

W_32600的博客 1120

make与makefile

我们在Linux操作时,需要大量的指令对文件进行编译工作,在此过程中需要反复敲出重复的代码,这大大降低了我们的编程效率。而make与makefile则可帮助我们减少了指定命令的编写,通过提前编译好命令,在需要时只需要调用特定命令,即可调用一系列已经设置好的命令,达到节省时间的效果。

2401_84360682的博客 948

Linux中的make与Makefile详解

makefile# 定义变量CC = gcc# 使用变量$@:当前目标$<:第一个依赖项$^:所有依赖项$*:不包含扩展名的目标名称make和Makefile是Linux系统中强大的自动化构建工具,通过定义规则和依赖关系,可以大大简化复杂项目的编译过程。进度条的实现可以直观地了解编译进度。

m0_74319933的博客 2277

【Linux】从入门到精通:Make与Makefile完全指南

Make是一个自动化构建工具,主要用于管理源代码的编译和构建过程。它通过读取Makefile文件来执行构建任务,能够自动检测文件变化并仅编译必要内容,显著提升开发效率。

cilmy23的note 2109

make命令与makefile文件

一、多个源文件带来的问题在编写c/c++测试程序时,我们习惯每次修改一处代码,然后就马上编译运行来查看运行的结果。这种编译方式对于小程序来说是没有多大问题的,可对于大型程序来说,由于包含了大量的源文件,如果每次改动一个地方都需要编译所有的源文件,这个简单的直接编译所有源文件方式对程序员来说简直是噩耗。 我们看一个例子:// main.c #include "a.h"// 2.c #include

Leo的博客 3161

【Linux】Linux开发利器:make与Makefile自动化构建详解

在现代软件开发中,自动化构建工具显得尤为重要,make和Makefile是Linux环境下的常用选择。它们通过定义规则和依赖关系,帮助开发者高效管理项目的构建过程。本文将简要介绍make与Makefile的基本原理和用法,帮助提升构建效率。

专注于 C/C++ 后端开发,涵盖基础语法、Linux系统与网络、MySQL数据库、常见算法及项目经验。 3599
上一篇: pip-pop源码分析
下一篇: python实现word文档中有序内容变乱序
cslqm
博客等级 码龄11年 32粉丝 92原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值