EMACS & 程序 编程点滴...
天下难事必作于易,天下大事必作于细
MakeFile经验
TOP符号说明
| 符号 | 说明 |
|---|---|
| $* | 工作目标的主文件名 |
| $@ | 工作目标的名称 |
| $? | 时间戳在工作目标之后的所有必要文件 |
| $% | 档案文件成员结构中的文件名元素 |
| $< | 第一个必要条件 |
| $^ | 所有必要条件 |
| $+ | 同$^, 不过包含所有重复的条件(解决链接依存的问题) |
TOP文件关联
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# 利用以下的缩写关联各类文件 c.s: $(CC) $(CFLAGS) -S -o $*.s $< s.o: $(AS) -c -o $*.o $< c.o: $(CC) $(CFLAGS) -c -o $*.o $< # SOURCE (将目录下所有的.c文件作为对象文件) SRCS = $(shell ls *.c) OBJS = $(notdir $(SRCS:.c=.o)) # 生成目标对象 TARGET = xxx.o .PHONY: all all: $(TARGET) $(TARGET): .depend $(OBJS) $(LD) $(LFLAGS) -o $@ $(OBJS) $(OBJS): %.o: %.c $(CC) $(CFLAGS) $(COPTION) -c $< ########################################### ## 没有规则的依赖关系 $(OBJS): Makefile xxx.h ## Makefile更新时,需重新编译目标文件 ## 头文件更新时,需重新编译目标文件 ## 源代码间的依赖关系(包括头文件),用 gcc -M 或 mkdep 生成 |
TOP函数大全1
TOP字符串函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# 返回字符串链表中条件相符的值 $(filter pattern ...,text) # eg. $(filter %.c, $(all_source)) # 返回字符串链表中条件不相符的值 $(filter-out pattern ...,text) # eg. $(filter-out %.h, $(all_source)) # 搜索字符串 $(findstring string...,text) #eg. $(findstring /root/work/emma2th, $(PWD)) # 搜索和替换 $(subst search-string,replace-string,text) # objects = $(subst .c,.o, $(sources)) # 具通配符能力的搜索与替换 $(patsubst search-pattern,replace-pattern,text) #eg. $(patsubst %/,%, $(directory-path)) # 统计单词的数量 $(words text) # 返回第n个单词 $(words n,text) # 返回第一个单词 $(firstword text) # 返回指定范围内的单词 $(wordlist start,end,text) |
TOP杂项函数
1 2 3 4 5 6 7 8 9 10 11 |
# 排序并移除重复的项目 $(sort list) # 运行shell $(shell command) # eg. 创建一组目录 #REQUIRED_DIRS = ... #_MKDIRS := $(shell for d in $(REQUIRED_DIRS); \ # do \ # [[ -d $$d ]] || mkdir -p $$d; \ # done) |
TOP文件名函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# 匹配指定文件 $(wildcard pattern ...) # eg. sources := $(wildcard *.c *.h) 所有源文件 # dot-emacs-exists := $(wildcard ~/.emacs) 该文件有无? # 返回每个单词的目录部分 $(dir list . . . ) # 返回文件路径的文件名部分 $(notdir name . . . ) # 返回单词的后缀 $(suffix name . . . ) # 返回文件名部分,不含后缀 $(basename name . . . ) # 添加后缀 $(addsuffix suffix,name . . . ) # 添加前缀 $(addprefix prefix,name . . . ) # 衔接前缀与后缀(链表中各元素对应) $(join prefix-list,suffix-list) # 移除前导和接在后面的空格 $(strip text) |
TOP流程控制函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$(if condition,then-part,else-part) # eg. PATH_SEP := $(if $(COMSPEC),;,:) # 输出错误信息, 程序退出 $(error text) # 输出警告,程序不退出 $(warning text) # 循环控制 $(foreach variable,list,body) # eg. 测试一组变量是否定义过 #VARIABLE_LIST := SOURCES OBJECTS HOME #$(foreach i,$(VARIABLE_LIST), \ # $(if $($i),, \ # $(shell echo $i has no value > /dev/stderr))) # 查找变量来自何处 $(origin variable) # 环境变量,makefile,命令行等等 |
TOP自定义函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# $(call has-duplicates, word-list) 是否包含重复内容 has-duplicates = $(filter \ $(words $1) \ $(words $(sort $1)))) # $(call source-dirs, dir-list) 搜索源文件的路径 source-dirs = $(sort \ $(dir \ $(shell find $1 -name '*.c')))) # $(call get-java-class-name, file-name) 返回java类名 get-java-class-name = $(notdir $(subst .java,,$1)) # $(call same-suffix, file-list) 所有单词是否有相同后缀 same-suffix = $(filter 1 $(words $(sort $(suffix $1)))) # $(call find-program,wildcard-pattern) 查找可执行程序 find-program = $(wildcard \ $(addsuffix /$1, \ $(sort \ $(subst :, , \ $(subst ::,:.:, \ $(patsubst :%,.:%, \ $(patsubst %:,%:.,$(PATH)))))))) find: @echo $(words $(call find-program,*)) # $(call assert,condition,message) 普通assert define assert $(if $1,,$(error Assertion failed: $2)) endef # $(call assert-file-exists,wildcard-pattern) 文件是否存在 define assert-file-exists $(call assert,$(wildcard $1),$1 does not exist) endef # $(call assert-not-null,make-variable) 检查make变量是否为空 define assert-not-null $(call assert,$($1),The variable "$1" is null) endef # $(call assert-defined,variable-name) 检查变量是否未定义 define assert-defined $(call assert, \ $(filter-out undefined,$(origin $1)), \ '$1' is undefined) endef # $(call grep-string, search-string, word-list) 单词中搜索子字符串 define grep-string $(strip \ $(foreach w, $2, \ $(if $(findstring $1, $w), \ $w))) endef words := count_words.c counter.c lexer.l lexer.h counter.h find-words: @echo $(call grep-string,un,$(words)) # $(call make-dir, directory) 创建目录 make-dir = $(if $(wildcard $1),,$(MKDIR) -p $1) $(config): $(config_template) $(call make-dir, $(dir $@)) $(M4) $^ > $@ # $(call collect-names, root-dir, dir-list, suffix1-opt, suffix2-opt) 建立文件列表 define collect-names echo Making $@ from directory list... cd $1; \ shopt -s nullglob; \ for f in $(foreach file,$2,'$(file)'); do \ files=( $$f$(if $3,/*.{$3$(if $4,$(comma)$4)}) ); \ if (( $${#files[@]} > 0 )); \ then \ printf '"%s"\n' $${files[@]}; \ else :; fi; \ done endef #eg. 创建图像文件列表 #%.images: # @$(call collect-names,$(SOURCE_DIR),$^,gif,jpeg) > $@ # $(call program-variables,variable-prefix,file-list) 利用eval解析程序变量--版本1 define program-variables $(eval $1_sources = $(filter %.c,$2)) $(eval $1_headers = $(filter %.h,$2)) $(eval $1_objects = $(subst .c,.o,$(filter %.c,$2))) $($1_objects): $($1_headers) endef ls: $(ls_objects) $(eval $(call program-variables,ls,ls.c ls.h glob.c glob.h)) #$(call program-variables,variable-prefix,file-list) 利用eval解析程序变量--版本2 define program-variables $(eval $1_sources = $(filter %.c,$2)) $(eval $1_headers = $(filter %.h,$2)) $(eval $1_objects = $(subst .c,.o,$(filter %.c,$2))) programs += $1 $1: $($1_objects) $($1_objects): $($1_headers) endef # Place all target here, so it is the default goal. all: $(eval $(call program-variables,ls,ls.c ls.h glob.c glob.h)) $(eval $(call program-variables,cp,...)) $(eval $(call program-variables,mv,...)) $(eval $(call program-variables,ln,...)) $(eval $(call program-variables,rm,...)) # Place the programs prerequisite here where it is defined. all: $(programs) # $(call source-to-object, source-file-list) source-to-object = $(subst .c,.o,$(filter %.c,$1)) \ $(subst .y,.o,$(filter %.y,$1)) \ $(subst .l,.o,$(filter %.l,$1)) # $(call make-library, library-name, source-file-list) define make-library libraries += $1 sources += $2 $1: $(call source-to-object,$2) $(AR) $(ARFLAGS) $$@ $$^ endef #eg. # local_src := $(wildcard $(subdirectory)/*.c) # $(eval $(call make-library, $(subdirectory)/libcodec.a, $(local_src))) # $(call make-depend,source-file,object-file,depend-file) 产生依存文件 define make-depend $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -M $1 | \ $(SED) 's,\($$(notdir $2)\) *:,$$(dir $2) $3: ,' > $3.tmp $(MV) $3.tmp $3 endef %.o: %.c $(call make-depend,$<,$@,$(subst .o,.d,$@)) $(COMPILE.c) -o $@ $< # $(call get-file, variable-name) define get-file $(strip \ $($1) \ $(if $(call file-exists-eval,$1),, \ $(warning The file referenced by variable \ '$1' ($($1)) cannot be found))) endef # $(call file-exists-eval, variable-name) define file-exists-eval $(strip \ $(if $($1),,$(warning '$1' has no value)) \ $(wildcard $($1))) # $(call file-exists, wildcard-pattern) file-exists = $(wildcard $1) # $(call check-file, file-list) define check-file $(foreach f, $1, \ $(if $(call file-exists, $($f)),, \ $(warning $f ($($f)) is missing))) endef |