Makefile

Makefile 基本命令: 目标:依赖 命令 #makefile中的命令行必须以单个TAB字符进行缩进 make [ flags ] [ macro definitions ] [ targets ] -c 在读取makefile之前改变到制定目录dir -h help文档 -w 在处理makefile之前和之后都显示工作目录 makefile中的宏: $(宏名) ${宏名} $* 不包含扩展名的目标文件名称。 $+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。 $< 第一个依赖文件的名称。 $? 所有依赖文件,以空格分开,这些依赖文件的修改日期比目标文件的创建日期晚。 $@ 目标的完整名称。 $^ 所有的依赖文件,以空格分开,不包含重复的依赖文件。 $% 如果目标是归档成员,则该变量表示目标的归档成员名。 @ 命令如果以"@"起始,则@符号禁止打印输出它所在的命令行 包含其他makefile文件: include FILENAMES... #该行切不可以TAB缩进 -include FILENAMES... #“-”的意思是告诉make,忽略此操作的错误。make继续执行 目录搜索 一般搜索 变量VPATH VPATH = src:../headers 使用空格或者冒号(:)将多个需要搜索的目录分开。 选择性搜索 变量vpath 1、vpath PATTERN DIRECTORIES 为所有符合模式“PATTERN”的文件指定搜索目录“DIRECTORIES”。多个目录使用空格或者冒号(:)分开。类似上一小节的“VPATH”变量。 2、vpath PATTERN 清除之前为符合模式“PATTERN”的文件设置的搜索路径。 3、vpath 清除所有已被设置的文件搜索路径。 注:vapth使用方法中的“PATTERN”需要包含模式字符“%”。“%”意思是匹配一个或者多个字符,例如,“%.h”表示所有以“.h”结尾的文件。如果在“PATTERN”中没有包含模式字符“%”,那么它就是一个明确的文件名,这样就是给定了此文件的所在目录。 makefile特殊目标: .PHONY: 目标“.PHONY”的所有的依赖被作为伪目标。伪目标时这样一个目标:当使用make命令行指定此目标时,这个目标所在规则定义的命令、无论目标文件是否存在都会被无条件执行。 clean: rm *.o temp #当当前工作目录下有clean文件时,make clean由于规则没有任何依赖文件,所以rm不会被执行 故完整的书写格式应该为: .PHONY: clean clean: rm *.o temp .SUFFIXES: 特殊目标“SUFFIXES”的所有依赖指出了一系列在后缀规则中需要检查的后缀名(就是当前make需要处理的后缀)。 .DEFAULT Makefile中,目标“.DEFAULT”所在规则定义的命令,被用在重建那些没有具体规则的目标(明确规则和隐含规则)。就是说一个文件作为某个规则的依赖,但却不是另外一个规则的目标时。Make程序无法找到重建此文件的规则,此种情况时就执行“.DEFAULT”所指定的命令。 .PRECIOUS 目标“.PRECIOUS”的所有依赖文件在make过程中会被特殊处理:当命令在执行过程中被中断时,make不会删除它们。而且如果目标的依赖文件是中间过程文件,同样这些文件不会被删除。这一点目标“.PRECIOUS”和目标“.SECONDAY”实现的功能相同。 另外,目标“.PRECIOUS”的依赖文件也可以是一个模式,例如“%.o”。这样可以保留有规则创建的中间过程文件。 .INTERMEDIATE 目标“.INTERMEDIATE”的依赖文件在make时被作为中间过程文件对待。没有任何依赖文件的目标“.INTERMEDIATE”没有意义。 .SECONDARY 目标“.SECONDARY”的依赖文件被作为中间过程文件对待。但这些文件不会被自动删除。 没有任何依赖文件的目标“.SECONDARY”的含义是:将所有的文件作为中间过程文件(不会自动删除任何文件)。 .DELETE_ON_ERROR 如果在Makefile中存在特殊目标“.DELETE_ON_ERROR”,make在执行过程中,如果规则的命令执行错误,将删除已经被修改的目标文件。 .IGNORE 如果给目标“.IGNORE”指定依赖文件,则忽略创建这个文件所执行命令的错误。给此目标指定命令是没有意义的。当此目标没有依赖文件时,将忽略所有命令执行的错误。 .LOW_RESOLUTION_TIME 目标“.LOW_RESOLUTION_TIME”的依赖文件被make认为是低分辨率时间戳文件。给目标“.LOW_RESOLUTION_TIME”指定命令是没有意义的。 .SILENT 出现在目标“.SILENT”的依赖列表中的文件,make在创建这些文件时,不打印出重建此文件所执行的命令。同样,给目标“.SILENT”指定命令行是没有意义的。 没有任何依赖文件的目标“.SILENT”告诉make在执行过程中不打印任何执行的命令。现行版本make支持目标“.SILENT”的这种功能和用法是为了和旧版本的兼容。在当前版本中如果需要禁命令执行过程的打印,可以使用make的命令行参数“-s”或者“--silent”。 .EXPORT_ALL_VARIABLES 此目标应该作为一个简单的没有依赖的目标,它的功能含义是将之后所有的变量传递给子make进程。 .NOTPARALLEL Makefile中,如果出现目标“.NOPARALLEL”,则所有命令按照串行方式执行,即使存在make的命令行参数“-j”。但在递归调用的字make进程中,命令可以并行执行。此目标不应该有依赖文件,所有出现的依赖文件将被忽略。 makefile变量: 递归展开式 = 优点:这种类型变量在定义时,可以引用其它的之前没有定义的变量(可能在后续部分定义,或者是通过make的命令行选项传递的变量)。 缺点:可能会无限展开 直接展开式 := 不会引用其后定义的变量,故可以避免无限展开 ?=操作符 条件赋值,只有此变量在之前没有赋值的情况下才会对这个变量进行赋值。 +=追加变量值 如果之前没定义变量的话,+=变成= override指示符 如果不希望命令行指定的变量值替代在Makefile中的变量定义,那么我们需要在Makefile中使用指示符“override”来对这个变量进行声明 目标指定变量 目标指定的变量值只在指定它的目标的上下文中有效,对于其他的目标没有影响。 TARGET ... : VARIABLE-ASSIGNMENT TARGET ... : override VARIABLE-ASSIGNMENT 模式指定变量 模式指定变量定义是将一个变量值指定到所有符合此模式的目标上。 PATTERN ... : VARIABLE-ASSIGNMENT PATTERN ... : override VARIABLE-ASSIGNMENT makefile条件执行: 基本语法: CONDITIONAL-DIRECTIVE TEXT-IF-TRUE endif 或 CONDITIONAL-DIRECTIVE TEXT-IF-TRUE else TEXT-IF-FALSE endif 关键字: ifeq 判断参数是否相等 ifeq (ARG1, ARG2) ifeq 'ARG1' 'ARG2' ifeq "ARG1" "ARG2" ifeq "ARG1" 'ARG2' ifeq 'ARG1' "ARG2" ifneq 判断参数是否不相等 ifneq (ARG1, ARG2) ifneq 'ARG1' 'ARG2' ifneq "ARG1" "ARG2" ifneq "ARG1" 'ARG2' ifneq 'ARG1' "ARG2" ifdef 判断一个变量是否已经定义 ifdef VARIABLE-NAME ifndef makefile的内嵌函数: 语法: $(FUNCTION ARGUMENTS) ${FUNCTION ARGUMENTS} 文本处理函数: $(subst FROM,TO,TEXT) 函数名称:字符串替换函数—subst。 函数功能:把字串“TEXT”中的“FROM”字符替换为“TO”。 返回值:替换后的新字符串。 示例: $(subst ee,EE,feet on the street) 替换“feet on the street”中的“ee”为“EE”,结果得到字符串“fEEt on the strEEt”。 $(patsubst PATTERN,REPLACEMENT,TEXT) 函数名称:模式替换函数—patsubst。 函数功能:搜索“TEXT”中以空格分开的单词,将否符合模式“TATTERN”替换为“REPLACEMENT”。参数“PATTERN”中可以使用模式通配符“%”来代表一个单词中的若干字符。如果参数“REPLACEMENT”中也包含一个“%”,那么“REPLACEMENT”中的“%”将是“TATTERN”中的那个“%”所代表的字符串。在“TATTERN”和“REPLACEMENT”中,只有第一个“%”被作为模式字符来处理,之后出现的不再作模式字符(作为一个字符)。在参数中如果需要将第一个出现的“%”作为字符本身而不作为模式字符时,可使用反斜杠“/”进行转义处理。 返回值:替换后的新字符串。 函数说明:参数“TEXT”单词之间的多个空格在处理时被合并为一个空格,并忽略前导和结尾空格。 示例: $(patsubst %.c,%.o,x.c.c bar.c) 把字串“x.c.c bar.c”中以.c结尾的单词替换成以.o结尾的字符。函数的返回结果是“x.c.o bar.o” $(strip STRINT) 函数名称:去空格函数—strip。 函数功能:去掉字串(若干单词,使用若干空字符分割)“STRINT”开头和结尾的空字符,并将其中多个连续空字符合并为一个空字符。 返回值:无前导和结尾空字符、使用单一空格分割的多单词字符串。 函数说明:空字符包括空格、[Tab]等不可显示字符。 示例: STR = a b c LOSTR = $(strip $(STR)) 结果是“a b c”。 “strip”函数经常用在条件判断语句的表达式中,确保表达式比较的可靠和健壮! $(findstring FIND,IN) 函数名称:查找字符串函数—findstring。 函数功能:搜索字串“IN”,查找“FIND”字串。 返回值:如果在“IN”之中存在“FIND”,则返回“FIND”,否则返回空。 函数说明:字串“IN”之中可以包含空格、[Tab]。搜索需要是严格的文本匹配。 示例: $(findstring a,a b c) $(findstring a,b c) 第一个函数结果是字“a”;第二个值为空字符。 $(filter PATTERN…,TEXT) 函数名称:过滤函数—filter。 函数功能:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词。可以使用多个模式。模式中一般需要包含模式字符“%”。存在多个模式时,模式表达式之间使用空格分割。 返回值:空格分割的“TEXT”字串中所有符合模式“PATTERN”的字串。 函数说明:“filter”函数可以用来去除一个变量中的某些字符串,我们下边的例子中就是用到了此函数。 示例: sources := foo.c bar.c baz.s ugh.h foo: $(sources) cc $(filter %.c %.s,$(sources)) -o foo 使用“$(filter %.c %.s,$(sources))”的返回值给cc来编译生成目标“foo”,函数返回值为“foo.c bar.c baz.s”。 $(filter-out PATTERN...,TEXT) 函数名称:反过滤函数—filter-out。 函数功能:和“filter”函数实现的功能相反。过滤掉字串“TEXT”中所有符合模式“PATTERN”的单词,保留所有不符合此模式的单词。可以有多个模式。存在多个模式时,模式表达式之间使用空格分割。 返回值:空格分割的“TEXT”字串中所有不符合模式“PATTERN”的字串。 函数说明:“filter-out”函数也可以用来去除一个变量中的某些字符串,(实现和“filter”函数相反)。 示例: objects=main1.o foo.o main2.o bar.o mains=main1.o main2.o $(filter-out $(mains),$(objects)) 实现了去除变量“objects”中“mains”定义的字串(文件名)功能。它的返回值为“foo.o bar.o”。 $(sort LIST) 函数名称:排序函数—sort。 函数功能:给字串“LIST”中的单词以首字母为准进行排序(升序),并取掉重复的单词。 返回值:空格分割的没有重复单词的字串。 函数说明:两个功能,排序和去字串中的重复单词。可以单独使用其中一个功能。 示例: $(sort foo bar lose foo) 返回值为:“bar foo lose” 。 $(word N,TEXT) 函数名称:取单词函数—word。 函数功能:取字串“TEXT”中第“N”个单词(“N”的值从1开始)。 返回值:返回字串“TEXT”中第“N”个单词。 函数说明:如果“N”值大于字串“TEXT”中单词的数目,返回空字符串。如果“N”为0,出错! 示例: $(word 2, foo bar baz) 返回值为“bar”。 $(wordlist S,E,TEXT) 函数名称:取字串函数—wordlist。 函数功能:从字串“TEXT”中取出从“S”开始到“E”的单词串。“S”和“E”表示单词在字串中位置的数字。 返回值:字串“TEXT”中从第“S”到“E”(包括“E”)的单词字串。 函数说明:“S”和“E”都是从1开始的数字。 当“S”比“TEXT”中的字数大时,返回空。如果“E”大于“TEXT”字数,返回从“S”开始,到“TEXT”结束的单词串。如果“S”大于“E”,返回空。 示例: $(wordlist 2, 3, foo bar baz) 返回值为:“bar baz”。 $(words TEXT) 函数名称:统计单词数目函数—words。 函数功能:字算字串“TEXT”中单词的数目。 返回值:“TEXT”字串中的单词数。 示例: $(words, foo bar) 返回值是“2”。所以字串“TEXT”的最后一个单词就是:$(word $(words TEXT),TEXT)。 $(firstword NAMES…) 函数名称:取首单词函数—firstword。 函数功能:取字串“NAMES…”中的第一个单词。 返回值:字串“NAMES…”的第一个单词。 函数说明:“NAMES”被认为是使用空格分割的多个单词(名字)的序列。函数忽略“NAMES…”中除第一个单词以外的所有的单词。 示例: $(firstword foo bar) 返回值为“foo”。函数“firstword”实现的功能等效于“$(word 1, NAMES…)”。 文件名处理函数: $(dir NAMES…) 函数名称:取目录函数—dir。 函数功能:从文件名序列“NAMES…”中取出各个文件名的目录部分。文件名的目录部分就是包含在文件名中的最后一个斜线(“/”)(包括斜线)之前的部分。 返回值:空格分割的文件名序列“NAMES…”中每一个文件的目录部分。 函数说明:如果文件名中没有斜线,认为此文件为当前目录(“./”)下的文件。 示例: $(dir src/foo.c hacks) 返回值为“src/ ./”。 $(notdir NAMES…) 函数名称:取文件名函数——notdir。 函数功能:从文件名序列“NAMES…”中取出非目录部分。目录部分是指最后一个斜线(“/”)(包括斜线)之前的部分。删除所有文件名中的目录部分,只保留非目录部分。 返回值:文件名序列“NAMES…”中每一个文件的非目录部分。 函数说明:如果“NAMES…”中存在不包含斜线的文件名,则不改变这个文件名。以反斜线结尾的文件名,是用空串代替,因此当“NAMES…”中存在多个这样的文件名时,返回结果中分割各个文件名的空格数目将不确定!这是此函数的一个缺陷。 示例: $(notdir src/foo.c hacks) 返回值为:“foo.c hacks”。 $(suffix NAMES…) 函数名称:取后缀函数—suffix。 函数功能:从文件名序列“NAMES…”中取出各个文件名的后缀。后缀是文件名中最后一个以点“.”开始的(包含点号)部分,如果文件名中不包含一个点号,则为空。 返回值:以空格分割的文件名序列“NAMES…”中每一个文件的后缀序列。 函数说明:“NAMES…”是多个文件名时,返回值是多个以空格分割的单词序列。如果文件名没有后缀部分,则返回空。 示例: $(suffix src/foo.c src-1.0/bar.c hacks) 返回值为“.c .c”。 $(basename NAMES…) 函数名称:取前缀函数—basename。 函数功能:从文件名序列“NAMES…”中取出各个文件名的前缀部分(点号之后的部分)。前缀部分指的是文件名中最后一个点号之前的部分。 返回值:空格分割的文件名序列“NAMES…”中各个文件的前缀序列。如果文件没有前缀,则返回空字串。 函数说明:如果“NAMES…”中包含没有后缀的文件名,此文件名不改变。如果一个文件名中存在多个点号,则返回值为此文件名的最后一个点号之前的文件名部分。 示例: $(basename src/foo.c src-1.0/bar.c /home/jack/.font.cache-1 hacks) 返回值为:“src/foo src-1.0/bar /home/jack/.font hacks”。 $(addsuffix SUFFIX,NAMES…) 函数名称:加后缀函数—addsuffix。 函数功能:为“NAMES…”中的每一个文件名添加后缀“SUFFIX”。参数“NAMES…”为空格分割的文件名序列,将“SUFFIX”追加到此序列的每一个文件名的末尾。 返回值:以单空格分割的添加了后缀“SUFFIX”的文件名序列。 函数说明: 示例: $(addsuffix .c,foo bar) 返回值为“foo.c bar.c”。 $(addprefix PREFIX,NAMES…) 函数名称:加前缀函数—addprefix。 函数功能:为“NAMES…”中的每一个文件名添加前缀“PREFIX”。参数“NAMES…”是空格分割的文件名序列,将“SUFFIX”添加到此序列的每一个文件名之前。 返回值:以单空格分割的添加了前缀“PREFIX”的文件名序列。 函数说明: 示例: $(addprefix src/,foo bar) 返回值为“src/foo src/bar”。 $(join LIST1,LIST2) 函数名称:单词连接函数——join。 函数功能:将字串“LIST1”和字串“LIST2”各单词进行对应连接。就是将“LIST2”中的第一个单词追加“LIST1”第一个单词字后合并为一个单词;将“LIST2”中的第二个单词追加到“LIST1”的第二个单词之后并合并为一个单词,……依次列推。 返回值:单空格分割的合并后的字(文件名)序列。 函数说明:如果“LIST1”和“LIST2”中的字数目不一致时,两者中多余部分将被作为返回序列的一部分。 示例1: $(join a b , .c .o) 返回值为:“a.c b.o”。 示例2: $(join a b c , .c .o) 返回值为:“a.c b.o c”。 $(wildcard PATTERN) 函数名称:获取匹配模式文件名函数—wildcard 函数功能:列出当前目录下所有符合模式“PATTERN”格式的文件名。 返回值:空格分割的、存在当前目录下的所有符合模式“PATTERN”的文件名。 函数说明:“PATTERN”使用shell可识别的通配符,包括“?”(单字符)、“*”(多字符)等。 示例: $(wildcard *.c) 返回值为当前目录下所有.c源文件列表。 foreach函数 $(foreach VAR,LIST,TEXT) 函数功能:这个函数的工作过程是这样的:如果需要(存在变量或者函数的引用),首先展开变量“VAR”和“LIST”的引用;而表达式“TEXT”中的变量引用不展开。执行时把“LIST”中使用空格分割的单词依次取出赋值给变量“VAR”,然后执行“TEXT”表达式。重复直到“LIST”的最后一个单词(为空时结束)。“TEXT”中的变量或者函数引用在执行时才被展开,因此如果在“TEXT”中存在对“VAR”的引用,那么“VAR”的值在每一次展开式将会到的不同的值。 返回值:空格分割的多次表达式“TEXT”的计算的结果。 if函数 $(if CONDITION,THEN-PART,[ELSE-PART]) 函数功能:第一个参数“CONDITION”,在函数执行时忽略其前导和结尾空字符,如果包含对其他变量或者函数的引用则进行展开。如果“CONDITION”的展开结果非空,则条件为真,就将第二个参数“THEN_PATR”作为函数的计算表达式;“CONDITION”的展开结果为空,将第三个参数“ELSE-PART”作为函数的表达式,函数的返回结果为有效表达式的计算结果。 返回值:根据条件决定函数的返回值是第一个或者第二个参数表达式的计算结果。当不存在第三个参数“ELSE-PART”,并且“CONDITION”展开为空,函数返回空。 函数说明:函数的条件表达式“CONDITION”决定了函数的返回值只能是“THEN-PART”或者“ELSE-PART”两个之一的计算结果。 call函数 $(call VARIABLE,PARAM,PARAM,...) 函数功能:在执行时,将它的参数“PARAM”依次赋值给临时变量“$(1)”、“$(2)”(这些临时变量定义在“VARIABLE”的值中,参考下边的例子)…… call函数对参数的数目没有限制,也可以没有参数值,没有参数值的“call”没有任何实际存在的意义。执行时变量“VARIABLE”被展开为在函数上下文有效的临时变量,变量定义中的“$(1)”作为第一个参数,并将函数参数值中的第一个参数赋值给它;变量中的“$(2)”一样被赋值为函数的第二个参数值;依此类推(变量$(0)代表变量“VARIABLE”本身)。之后对变量“VARIABLE” 表达式的计算值。 返回值:参数值“PARAM”依次替换“$(1)”、“$(2)”…… 之后变量“VARIABLE”定义的表达式的计算值。 函数说明:1. 函数中“VARIBLE”是一个变量名,而不是变量引用。因此,通常“call”函数中的“VARIABLE”中不包含“$”(当然,除非此变量名是一个计算的变量名)。2. 当变量“VARIBLE”是一个make内嵌的函数名时(如“if”、“foreach”、“strip”等),对“PARAM”参数的使用需要注意,因为不合适或者不正确的参数将会导致函数的返回值难以预料。3. 函数中多个“PARAM”之间使用逗号分割。4. 变量“VARIABLE”在定义时不能定义为直接展开式!只能定义为递归展开式。 value函数 $(value VARIABLE) 函数功能:不对变量“VARIBLE”进行任何展开操作,直接返回变量“VARIBALE”的值。这里“VARIABLE”是一个变量名,一般不包含“$”(除非计算的变量名) 返回值:变量“VARIBALE”所定义文本值(如果变量定义为递归展开式,其中包含对其他变量或者函数的引用,那么函数不对这些引用进行展开。函数的返回值是包含有引用值)。 eval函数 函数功能:函数“eval”是一个比较特殊的函数。使用它可以在Makefile中构造一个可变的规则结构关系(依赖关系链),其中可以使用其它变量和函数。函数“eval”对它的参数进行展开,展开的结果作为Makefile的一部分,make可以对展开内容进行语法解析。展开的结果可以包含一个新变量、目标、隐含规则或者是明确规则等。也就是说此函数的功能主要是:根据其参数的关系、结构,对它们进行替换展开。 返回值:函数“eval”的返回值是空,也可以说没有返回值。 函数说明:“eval”函数执行时会对它的参数进行两次展开。第一次展开过程发是由函数本身完成的,第二次是函数展开后的结果被作为Makefile内容时由make解析时展开的。明确这一过程对于使用“eval”函数非常重要。理解了函数“eval”二次展开的过程后。实际使用时,如果在函数的展开结果中存在引用(格式为:$(x)),那么在函数的参数中应该使用“$$”来代替“$”。因为这一点,所以通常它的参数中会使用函数“value”来取一个变量的文本值。 origin函数 $(origin VARIABLE) 函数功能:函数“origin”查询参数“VARIABLE”(一个变量名)的出处。 函数说明:“VARIABLE”是一个变量名而不是一个变量的引用。因此通常它不包含“$”(当然,计算的变量名例外)。 返回值:返回“VARIABLE”的定义方式。用字符串表示。 函数的返回情况有以下几种: 1. undefined 变量“VARIABLE”没有被定义。 2. default 变量“VARIABLE”是一个默认定义(内嵌变量)。如“CC”、“MAKE”、“RM”等变量。如果在Makefile中重新定义这些变量,函数返回值将相应发生变化。 3. environment 变量“VARIABLE”是一个系统环境变量,并且make没有使用命令行选项“-e”(Makefile中不存在同名的变量定义,此变量没有被替代)。 4. environment override 变量“VARIABLE”是一个系统环境变量,并且make使用了命令行选项“-e”。Makefile中存在一个同名的变量定义,使用“make -e”时环境变量值替代了文件中的变量定义。 5. file 变量“VARIABLE”在某一个makefile文件中定义。 6. command line 变量“VARIABLE”在命令行中定义。 7. override 变量“VARIABLE”在makefile文件中定义并使用“override”指示符声明。 8. automatic 变量“VARIABLE”是自动化变量。 shell函数 函数功能:函数“shell”所实现的功能和shell中的引用(``)相同。实现对命令的扩展。这就意味着需要一个shell 命令作为此函数的参数,函数的返回结果是此命令在shell中的执行结果。make仅仅对它的回返结果进行处理;make将函数返回结果中的所有换行符(“/n”)或者一对“/n/r”替换为单空格;并去掉末尾的回车符号(“/n”)或者“/n/r”。进行函数展开式时,它所调用的命令(它的参数)得到执行。除对它的引用出现在规则的命令行和递归变量的定义中以外,其它决大多数情况下,make是在读取解析Makefile时完成对函数shell的展开。 返回值:函数“shell”的参数(一个shell命令)在shell环境中的执行结果。 函数说明:函数本身的返回值是其参数的执行结果,没有进行任何处理。对结果的处理是由make进行的。当对函数的引用出现在规则的命令行中,命令行在执行时函数才被展开。展开时函数参数(shell命令)的执行是在另外一个shell进程中完成的,因此需要对出现在规则命令行的多级“shell”函数引用需要谨慎处理,否则会影响效率(每一级的“shell”函数的参数都会有各自的shell进程)。 makefile控制函数 $(error TEXT…) $(warning TEXT…)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值