中山野鬼 linux 下 C 编程和make的方法 (七、补充,模块化项目组织的Makefil...

正题谈到模块化的设计方式。这里给出模块化Makefile模板的创建脚本的改良方案。先说说目标。然后贴上源码,最后给出一些简单的解释。如果有网友对特别是脚本的实现方法,有更好的方式,记得给个指正。我一向,“不怕被鄙视,就怕自认为一切OK。”
    谈目标前,得再谈一下程序开发,或者软件设计。编写程序,最终形成客户需要的软件,需要经过很多步骤。去掉后面包装的事情,仅谈开发,也包括问题细化,原型验证,平台验证,整体优化四个阶段。不过阶段与阶段之间,不是因果关系,有时甚至是递归。
    什么是问题细化。假设客户说,我要吃东西。于是乎,你随地捡起块石头放桌上。客户说,不行,第一,我要吃食物(靠不早说,只不过他以为你知道),第二刚拉过便便,我需要工具而不是用手。但至少现在明确了,需要个桌子,椅子,而且他已经就位了。
    于是乎,你拖来一头猪,外加一把菜刀。客户说,不行,第一,猪是生的,(死活暂不谈),第二,菜刀给我也没有用。
    于是乎,你切成块,该煮的还要煮,遇到色香味缺一的,还要回炉。
    软件开发,准确说是客户需求实现,和其他很多服务类似,例如“个人艺术照”,无论是定制,还是产品化。只不过后者是先将客户一棒子敲晕,后收钱。前者是不停的按客户需求实现,等到客户没时间了,算了解。
    因此,问题的细化,有时不单单是设计人员的问题,和客户本身也有关系。而原型验证,平台验证是由具体问题需求所产生的。而整体优化,这属于一个客户体验度 的问题。或者是问题本身。例如客户觉得原先的方案慢了。那么客户的基础目标已经全部确立,原先的方案就OK。只是体验度目标,客户要求调整。不过需要明 确,这两类的目标有很大差异。基础目标是客户的问题本身,体验度属于实现方案客户体验的问题。因此,后者是明确建立在前者基础之上的。
    说了这么多,是希望将整体优化,和其他工作区别开来。优化属于客户满意度的问题。而模块化项目组织,只是解决客户的基础问题而不是体验度。但是模块化的项目组织好坏,直接影响后期整体优化的项目开展进度。
    而对于开发者而言,还有一个和客户没有关系的问题,如何提高工作效率,降低重复性劳动。在面向对象问题上,采用类复用的技术,而在C语言开发中,模块化的方式,则更为有效。采用模块化开发至少有以下几个优势:
    1、问题分而治之。有效降低局部问题的扩散性的情况。
    2、复用技术,可以将设计工作重点集中在目标的特性上。
    3、对系统的理解更为容易,便于后期客户目标调整时的方案调整。
    针对上述好处,由此确定出模块化Makefile创建模板的目标。需要达到以下几个要求。
    1、每个目录组成一个模块。当然包括这个目录下的子模块。
    2、模块模板创建脚本能自动生成模块,包括目录,模块接口C文件,对应头文件,对应测试文件。对应当前默认Makefile。
    3、对应Makefile可以具备递归处理所依赖的子模块的make工作。

    由此我修正了前面的create_module.sh 的脚本。如下。

001 #!/bin/bash
002 MODULE_PATH=$1
003 MODULE_NAME=$1
004  
005 SRC_DIR_NAME=src
006 INC_DIR_NAME=inc
007 BIN_DIR_NAME=bin
008 OBJ_DIR_NAME=obj
009 C_FILE_SUFFIX=.c
010 H_FILE_SUFFIX=.h
011 TEST_FILE_SUFFIX=.t
012 MAKE_FILE_SUFFIX=.m
013 CREATE_FILE_FLAG=-f
014 CREATE_H_FILE_FLAG=-h
015 CREATE_TEST_FILE_FLAG=-t
016 CREATE_MAKEFILE_FILE=-m
017 CREATE_DEP_FILE=-d
018 OVERWRITE_FILE=0
019 NOT_OVERWRITE_FILE=1
020  
021 create_mkdir(){
022     mkdir $1 > /dev/null 2>&1
023     if [ $? = 0 ];then 
024         echo /$1 had created
025         return 1
026     else
027         if [ -d $1 ];then
028             echo /$1 had exist
029             return 0
030         else
031             echo "could not create directory "/$1
032             exit
033         fi
034     fi
035  
036 }
037 check_file_exist(){
038     if [ -e $1 ];then
039         while :;do
040             echo -n "the $1 had exist , do you want to overwrite?(y(Y) done:n(N) not:e(E) exit) : "
041             read check_file_exist_ans
042             case $check_file_exist_ans in
043             y|Y)
044                 echo you answer y
045                 return $OVERWRITE_FILE
046             ;;
047             n|N)
048                 echo you answer n
049                 return $NOT_OVERWRITE_FILE
050             ;;
051             e|E)
052                 exit
053             ;;
054             *)
055                 echo  "fuck ,i need you correct answer!"
056             esac
057         done
058     else
059         return $OVERWRITE_FILE
060     fi
061 }
062 CREATE_NEW_FLIE=0
063 CREATE_NEW_FILE_ERROR=1
064 EXIST_FILE=2
065 INSERT_FILE_CON=""
066  
067 get_c_init_context(){
068 #$1 path/filename.ext
069 #$2 filename
070     INSERT_FILE_CON="/***************\n$1\n by luckystar\n ***************/\n"
071     INSERT_FILE_CON+="#include \"$2.h\"\n"
072     INSERT_FILE_CON+="static int $2_flag =0;\n"
073     INSERT_FILE_CON+="\nvoid $2_init(void){\n"
074     INSERT_FILE_CON+="\tif ($2_flag) {\n\t\t//log(\"module inited..\",X);\n\t\treturn;\n\t}\n"
075     INSERT_FILE_CON+="\t$2_flag = 1;\n"
076     INSERT_FILE_CON+="\t//todo:module init...\n\n}\n"
077 #up is create module_init func 
078     INSERT_FILE_CON+="\nvoid $2_destory(void){\n"
079     INSERT_FILE_CON+="\tif (!$2_flag) {\n\t\t//log(\"module not inited..\",X);\n\t\treturn;\n\t}\n"
080     INSERT_FILE_CON+="\t$2_flag = 0;\n"
081     INSERT_FILE_CON+="\t//todo:module destory...\n\n}\n"
082 #up is create module_destory func
083 }
084  
085 get_h_init_context(){
086 #$1 path/filename.ext
087 #$2 filename
088     INSERT_FILE_CON="#ifndef _$2_H_\n#define _$2_H_\n"
089     INSERT_FILE_CON+="\n//ins_inc_file\n"
090     INSERT_FILE_CON+="\n//ins_typedef_def\n"
091     INSERT_FILE_CON+="\n//ins_def\n"
092     INSERT_FILE_CON+="\n//ins_func_declare\n"
093     INSERT_FILE_CON+="\n\n"
094     INSERT_FILE_CON+="#endif //_$2_H_\n"       
095 }
096 get_test_init_context(){
097 #$1 filename
098 #$2 libname
099     INSERT_FILE_CON="#include \"$2.h\"\n"
100     INSERT_FILE_CON+="#include <stdio.h>\n"
101     INSERT_FILE_CON+="\n\n"
102     INSERT_FILE_CON+="int main(int argc,char *argv[]){\n"
103     INSERT_FILE_CON+="\tprintf(\"hello test_$2_main now run...\\\n\");\n"  
104     INSERT_FILE_CON+="\t$2_init();\n"
105     INSERT_FILE_CON+="\t$2_destory();\n"
106     INSERT_FILE_CON+="\tprintf(\"hello test_$2_main now exit...\\\n\");\n"     
107     INSERT_FILE_CON+="\treturn 0;\n"
108     INSERT_FILE_CON+="}\n"     
109 }
110 get_make_init_context(){
111 #$1 module_name
112 INSERT_FILE_CON="SRC_PATH=src/\n"
113 INSERT_FILE_CON+="INC_PATH=inc/\n"
114 INSERT_FILE_CON+="OBJ_PATH=obj/\n"
115 INSERT_FILE_CON+="BIN_PATH=bin/\n"
116 INSERT_FILE_CON+="MODULE_NAME = $1\n"
117 INSERT_FILE_CON+="MODULE_FILE = \$(MODULE_NAME) \n"
118 INSERT_FILE_CON+="MODULE_INC =\n\n\n\n"
119 INSERT_FILE_CON+="MODULE_T = test_\$(MODULE_NAME)_main\n"
120 INSERT_FILE_CON+="MODULE_TS = \$(SRC_PATH)\$(MODULE_T).c\n"
121 INSERT_FILE_CON+="MODULE_TB = \$(BIN_PATH)\$(MODULE_T)\n"
122 INSERT_FILE_CON+="MODULE_SUB =\n\n\n"
123 INSERT_FILE_CON+="MODULE_SRC = \$(addsuffix .c,\$(addprefix \$(SRC_PATH),\$(MODULE_FILE)))\n"
124 INSERT_FILE_CON+="MODULE_OBJ = \$(addsuffix .o,\$(addprefix \$(OBJ_PATH),\$(MODULE_FILE)))\n"
125 INSERT_FILE_CON+="MODULE_INC += \$(addsuffix .h,\$(addprefix \$(INC_PATH),\$(MODULE_FILE)))\n"
126 INSERT_FILE_CON+="MODULE_LIB = lib\$(MODULE_NAME).a\n"
127 INSERT_FILE_CON+="MODULE_BIN = \$(BIN_PATH)\$(MODULE_LIB)\n"
128 INSERT_FILE_CON+="MODULE_SUB_LIB = \$(foreach var,\$(MODULE_SUB),\$(var)/\$(BIN_PATH)lib\$(var).a)\n"
129 INSERT_FILE_CON+="MODULE_SUB_INC =\n\n\n"
130 INSERT_FILE_CON+="test:\n\n\n\n"
131 INSERT_FILE_CON+="ifndef MODULE_DEP\n"
132 INSERT_FILE_CON+="\$(error No Dependence)\n"
133 INSERT_FILE_CON+="endif\n"
134 INSERT_FILE_CON+="\$(foreach var,\$(MODULE_FILE),\$(eval \$(OBJ_PATH)\$(var).o:\$(SRC_PATH)\$(var).c  \$(INC_PATH)\$(var).h))\n\n"
135 INSERT_FILE_CON+="RM = -rm -f\n\n"
136 INSERT_FILE_CON+="test:all \$(MODULE_TB)\n\n"
137 INSERT_FILE_CON+="\$(MODULE_TB):\$(MODULE_TS)\n"
138 INSERT_FILE_CON+="  gcc -O2 -I\$(MODULE_SUB_INC) -I\$(INC_PATH) \$^ -L\$(BIN_PATH) -l\$(MODULE_NAME)    -o \$@\n\n\n"
139 INSERT_FILE_CON+="\$(MODULE_OBJ):\n"
140 INSERT_FILE_CON+="  gcc  -I\$(MODULE_SUB_INC) -I\$(INC_PATH) -c \$< -o \$@\n\n\n"
141 INSERT_FILE_CON+="\$(MODULE_BIN):\$(MODULE_OBJ) \$(MODULE_SUB_LIB)\n"
142 INSERT_FILE_CON+="  <a href="http://my.oschina.net/yuning0502" target="_blank" rel="nofollow">@echo</a> module bin \$@\n"
143 INSERT_FILE_CON+="  ar -r \$@ \$(MODULE_OBJ)\n"
144 INSERT_FILE_CON+="  ar -q \$@ \$(MODULE_SUB_LIB)\n\n"
145 INSERT_FILE_CON+="all:\$(MODULE_BIN)\n\n"  
146 INSERT_FILE_CON+="\$(MODULE_SUB_LIB):   \$(MODULE_SUB)\n\n"
147 INSERT_FILE_CON+="clean: \$(MODULE_SUB) clean_self\n\n"
148 INSERT_FILE_CON+="clean_self:\n"
149 INSERT_FILE_CON+="  \$(RM) \$(MODULE_OBJ)\n"
150 INSERT_FILE_CON+="  \$(RM) \$(MODULE_BIN)\n"
151 INSERT_FILE_CON+="  \$(RM) \$(MODULE_TB)\n\n"
152 INSERT_FILE_CON+="rebuild:clean module_dep all\n\n"
153 INSERT_FILE_CON+="\$(MODULE_SUB):\n"
154 INSERT_FILE_CON+="  <a href="http://my.oschina.net/yuning0502" target="_blank" rel="nofollow">@echo</a> \"***************  todo Module SUB\" \$@  \"*****************\"\n"
155 INSERT_FILE_CON+="  - \$(MAKE) -C \$@ \$(MAKECMDGOALS)\n\n\n"
156 INSERT_FILE_CON+="#module_dep:\n"
157 INSERT_FILE_CON+="# gcc -I\$(MODULE_SUB_INC) -I\$(INC_PATH) -MM \$(MODULE_SRC)  > \$(MODULE_NAME).d\n"
158 INSERT_FILE_CON+="# sed -i '1 i\$(MODULE_NAME)_DEP = \$(MODULE_NAME)_DEP' \$(MODULE_NAME).d\n"
159 INSERT_FILE_CON+="# sed -i '/.o:/ s,^,\$(OBJ_PATH),' \$(MODULE_NAME).d\n\n"
160 INSERT_FILE_CON+=".PHONY: test all clean clean_self rebuild \$(MODULE_SUB) module_dep\n"
161 }
162 insert_file_tmp(){
163 #$1 path/filename.ext
164 #$2 filename
165 #$3 ext mode
166     case $3 in
167     $C_FILE_SUFFIX)
168     get_c_init_context $1 $2
169     ;;
170     $H_FILE_SUFFIX)
171     get_h_init_context $1 $2
172     ;;
173     $TEST_FILE_SUFFIX)
174     get_test_init_context $4 $2
175     ;;
176     $MAKE_FILE_SUFFIX)
177     get_make_init_context $2
178     ;;
179     esac
180     sed  -i "a\\$INSERT_FILE_CON" $1
181      
182 }
183 create_Makefile(){
184 #$1 makefile name
185     NEW_FILENAME="Makefile"
186     check_file_exist $NEW_FILENAME
187     echo > $NEW_FILENAME
188     if [ $? = $OVERWRITE_FILE ];then
189         echo > $NEW_FILENAME
190         insert_file_tmp $NEW_FILENAME $MODULE_NAME $MAKE_FILE_SUFFIX
191         echo create /$MODULE_PATH/$NEW_FILENAME files
192         return $CREATE_NEW_FILE
193     else
194         return $EXIST_FILE
195     fi 
196          
197 }
198 create_file_in_sub_dir(){
199      
200     if [ -d $1 ];then
201         if [ $3 = $TEST_FILE_SUFFIX ]; then
202         NEW_FILENAME=$1/test_$4_main.c
203         else
204         NEW_FILENAME=$1/$2$3
205         fi
206         check_file_exist $NEW_FILENAME
207         if [ $? = $OVERWRITE_FILE ];then
208             echo > $NEW_FILENAME
209             insert_file_tmp $NEW_FILENAME $2 $3 $4
210             echo create /$MODULE_PATH/$NEW_FILENAME files
211             return $CREATE_NEW_FILE
212         else
213             return $EXIST_FILE
214         fi
215     else
216         echo  /$MODULE_PATH/$1 is not directory, create_file not continue...
217         return $CREATE_NEW_FILE_ERROR
218         #not exit , continue done the other cmd
219     fi
220 }
221 MODULE_FILE=MODULE_FILE
222 MODULE_SRC=""
223 OBJ_PATH=OBJ_PATH
224 SRC_PATH=SRC_PATH
225 MODULE_NAME_DEP_CHECK="ifndef MODULE_DEP"
226 RETURN_VALUE=
227  
228 read_value_from_file(){
229 #$1 filename $s2 valuename $3 is not add
230 #get return ,need used RETURN_VALUE
231 var=$2
232 mode=
233  
234     unset RETURN_VALUE
235  
236     while read var;do
237          
238         case $var in
239         \#*)    ;;
240         \.*)    ;;
241         *)
242          
243         var=`echo $var | sed -n "/^$2[\ ]*=/p"`
244         #get name  += value
245         #name ?= value .....
246         if [ -z "$var" ]; then
247             continue;
248         fi
249         #echo step1 $var
250         mode=`echo $var | sed -n "/+=/p"`
251         var=`echo $var | sed -n "s/^.*=//p"`
252         if [ -z "$mode" ]; then
253             RETURN_VALUE=$var
254             continue;
255         else
256             if [ 3 -le $# ]; then
257             RETURN_VALUE=${RETURN_VALUE}${var}
258             fi
259         fi
260         #echo step2 $RETURN_VALUE
261  
262         esac
263     done < $1
264 #   echo get return_value $RETURN_VALUE
265     return
266 }
267 get_first_data(){
268     echo first data $1
269     return $1
270 }
271 get_last_data(){
272     while [ 1 -lt $# ];do
273         shift
274     done
275     echo last1 data $1
276     return $1
277 }
278 cut_lines_in_file(){
279 #cut from $2 line to $3 line in file $1
280 #not check $1 file exist ,static func only
281 first=
282 last1=
283     #echo $2 $3
284     unset first
285     unset last1
286     first=`sed -n "/$2/=" $1`
287     last1=`sed -n "/$3/=" $1`
288     if [ -n "$first" -a -n "$last1" ]; then
289         get_first_data $first
290         first=$?
291         get_last_data $last1
292         last1=`expr $? - 1`
293         echo $first ${last1} $1
294         sed -i "${first},${last1}d" $1
295     fi
296     return
297       
298 }
299 get_sub_module(){
300     #$1 Makefile file name
301     if [ -e $MAKEFILE ];then
302         echo "read info form $MAKEFILE ..."
303     else
304         echo "Makefile(${MAKEFILE}) not exist!"
305         unset RETURN_VALUE
306         return
307     fi
308     read_value_from_file $1 "MODULE_SUB"
309 #   echo $RETURN_VALUE
310     exit   
311 }
312 cut_value_from_const(){
313 #$1 if have $(XXX) ,will cut
314     RETURN_VALUE=`echo $RETURN_VALUE | sed -n "s/[\$][(][^)]*[)]/ /p"`
315      
316 }
317 MODULE_INC=
318 adjust_MODULE_INC(){
319     MODULE_INC=`echo $MODULE_INC|sed -n "s/[^ ]*/ -I&/gp"`
320 }
321 MODULE_SUB_ALL_PATH=
322 get_inc_path(){
323 path_tmp=
324     echo "all subdir is: " $@
325     while [ 1 -le $# ] ;do
326          
327         path_tmp=`echo $1 | sed -n "s/^.*$/ &\Makefile/p"`
328         echo "ready get file is :" $path_tmp
329         read_value_from_file $path_tmp "MODULE_SUB" "+"
330         MODULE_SUB1=$RETURN_VALUE
331          
332         if [ -z "$MODULE_SUB1" ]; then
333             MODULE_SUB_ALL_PATH+=${1}
334             echo "No MODULE_SUB more..." $1
335             shift
336             continue;
337         fi
338         MODULE_SUB1=`echo $MODULE_SUB1 | sed -e "/[^ ]*/s,,$1&\/,g"`
339         MODULE_SUB_ALL_PATH+=$1
340         get_inc_path $MODULE_SUB1
341         shift
342     done
343 }
344 get_all_INC_path(){
345     unset MODULE_SUB_ALL_PATH
346     get_inc_path "../$MODULE_NAME/"
347     MODULE_SUB_ALL_PATH=`echo $MODULE_SUB_ALL_PATH | sed -n "/[\.][\.][]\/]/s,, &,gp"`
348     MODULE_SUB_ALL_PATH=`echo $MODULE_SUB_ALL_PATH | sed -n "/[\.][\.][]\/][^\.^ ]*/s,, -I&inc,gp"`
349     echo "all path is : " $MODULE_SUB_ALL_PATH
350     #exit  
351 }
352 create_depend_file(){
353 #use gcc -MM create dependfile 
354 #$1 module_name $2 makefile name not support!!
355     #if [ 2 -le $# ];then
356     #   MAKEFILE=$2
357     #else
358         MAKEFILE=Makefile
359     #fi
360      
361  
362     #get_sub_module $MAKEFILE
363 #   echo $MAKEFILE set MAKEFILE default is Makefile
364     if [ -e $MAKEFILE ];then
365         echo "read info form $MAKEFILE ..."
366     else
367         echo "Makefile(${MAKEFILE}) not exist!"
368         exit
369     fi
370     read_value_from_file $MAKEFILE $SRC_PATH
371     SRC_PATH=$RETURN_VALUE
372     read_value_from_file $MAKEFILE $OBJ_PATH
373     OBJ_PATH=$RETURN_VALUE 
374     read_value_from_file $MAKEFILE $MODULE_FILE "+"
375     echo return_cut begin $RETURN_VALUE
376     cut_value_from_const $RETURN_VALUE
377     echo return_cut end $RETURN_VALUE
378     MODULE_FILE=${MODULE_NAME}${RETURN_VALUE}
379     MODULE_SRC=`echo $MODULE_FILE | sed -e "/[^ ]*/s,,$SRC_PATH&.c,g"`
380     echo "MODULE INFO:"
381     echo "SRC_PATH = "$SRC_PATH
382     echo "OBJ_PATH = "$SRC_PATH
383     echo "MODULE_FILE = "$MODULE_FILE
384     echo "MODULE_SRC = "$MODULE_SRC
385     get_all_INC_path
386     gcc $MODULE_SUB_ALL_PATH  -MM $MODULE_SRC > $MODULE_NAME.d
387     sed -i "1 iMODULE_DEP = ${MODULE_NAME}_DEP" $MODULE_NAME.d
388     sed -i "/.o:/ s,^,${OBJ_PATH}," $MODULE_NAME.d
389     cut_lines_in_file $MAKEFILE ${MODULE_NAME}_DEP  "$MODULE_NAME_DEP_CHECK"
390     echo "Dependinfo is :"
391     cat  $MODULE_NAME.d
392     echo "Dependinfo end"
393     sed -i "/ifndef[ ]*MODULE_DEP/i ifndef__TMP MODULE_DEP" $MAKEFILE
394     sed -i "/ifndef__TMP[ ]*MODULE_DEP/r $MODULE_NAME.d" $MAKEFILE
395     sed -i "/ifndef__TMP[ ]*MODULE_DEP/d"  $MAKEFILE
396     sed -i "/^MODULE_SUB_INC.*$/s,,MODULE_SUB_INC = $MODULE_SUB_ALL_PATH," $MAKEFILE
397     return
398  
399 }
400  
401 check_other_cmd(){
402 #MODULE_INC="a b/c/d e"
403 #   echo $MODULE_INC
404 #   adjust_MODULE_INC
405 #   echo $MODULE_INC
406 #   exit
407     #MODULE_SUB= read_value_from_file "Makefile" "MODULE_SUB" "+"
408  
409     #echo $MODULE_SUB1
410     #exit
411  
412      
413 while [ 2 -le $# ];do
414     case $2 in
415     $CREATE_FILE_FLAG)
416         shift
417         create_file_in_sub_dir $SRC_DIR_NAME $2 $C_FILE_SUFFIX #$C_FILE_TMP
418         create_file_in_sub_dir $INC_DIR_NAME $2 $H_FILE_SUFFIX #$H_FILE_TMP
419          
420         #create_file_in_sub_dir $LOG_DIR_NAME $2 $LOG_FILE_SUFFIX
421          
422     ;;
423     $CREATE_TEST_FILE_FLAG)
424         shift
425         create_file_in_sub_dir $SRC_DIR_NAME $2 $TEST_FILE_SUFFIX  $3
426         shift
427          
428         ;;
429     $CREATE_H_FILE_FLAG)
430         shift
431         create_file_in_sub_dir $INC_DIR_NAME $2 $H_FILE_SUFFIX #$H_FILE_TMP
432         ;; 
433     $CREATE_DEP_FILE)
434         #shift
435         create_depend_file $MODULE_NAME #$2
436         ;;
437     $CREATE_MAKEFILE_FILE)
438         #shift
439         create_Makefile $MODULE_NAME
440         ;;
441     *)
442         ;;
443        #    echo $2" test "
444     esac
445         shift
446 done
447     exit
448 }
449 echo $MODULE_PATH
450  
451 create_mkdir $MODULE_PATH
452 is_created=$?
453 echo $is_created
454  
455     MODULE_NAME=`echo $MODULE_PATH|sed -e "s/^.*[\/]//"`
456  
457 if [ -d $MODULE_PATH ];then
458     cd $MODULE_PATH
459     create_mkdir $SRC_DIR_NAME
460     create_mkdir $INC_DIR_NAME
461     create_mkdir $BIN_DIR_NAME
462     create_mkdir $OBJ_DIR_NAME
463      
464     if [ "$is_created" -eq "1" ];then
465     #create_Makefile $MODULE_NAME
466     check_other_cmd $@ -f $MODULE_NAME -t $MODULE_NAME $MODULE_NAME -m -d
467     else
468     check_other_cmd $@
469     fi
470 else
471     echo $MODULE_NAME is not directory ,could not continue...  
472     exit
473 fi

需要解释一下修正的几个部分。
    1、./create_module name 时,如果 name这个目录不存在时,处理以下工作。
     1、创建 name  name/inc name/src name/obj name/bin 5个目录。
    2、创建 name/src/name.c name/inc/name.h name/src/test_name_main.c 3个C语言文件。
    3、创建 name/Makefile 这个Makefile。同时将上述3个C语言文件的对应信息加载进去。
    4、修正Makefile的文件依赖规则,通过读取3步骤中的Makefile文件里的MODULE_FILE(这里仅针对 C文件),使用gcc -MM。(哈有人要骂我了。因为我前面才说不要依赖gcc -MM,我的理由是此处是为了给予方便)形成依赖规则,保存在 name/name.d内。同时将name.d内的内容,扩充到 name/Makefile的内容中去。
    当你执行
    ./create_moudle learn_make 这里用learn_make作为一个典型模块举例。
    你可以
    cd learn_make
    make
    此时make 执行 make test的工作。完成所有的库的编译,并完成 test_learn_make_main.c的对应编译。
    执行
    bin/test_learn_make_main
    此时会出现对应打印信息。你可以通过观察 test_learn_make_main.c的源码理解。
    以上是针对一个模块。你可以继续,如下
    ./create_module learn_make/data_struct
    此时会和 create_module learn_make一样,完成上述动作。同时你进入
    cd learn_make/data_struct
    make
    bin/test_data_struct_main
    也可以。
    不过这个只解决了如何在模块下面创建子模块的问题。
    有另外个问题。此时learn_make和 data_struct并没有关联起来。你需要在
    learn_make/Makefile的文件中,找到
    MODULE_SUB= 的位置,此处添加data_struct,该行的处理结果如下
    MODULE_SUB= data_struct 这个作用下面会说到。如果不这么关联,Makefile只能递归执行所有模块的独自编译和.a 的依次合并。
    此时,保存退出。你进入learn_make目录下,
    此时
    make
    实际执行make test。
    此时,make会将learn_make 和data_struct均make一遍,同时Makefile文件保持一个递归模式,将data_struct/bin/libdata_struct.a 并入到当前bin/liblearn_make.a中。
    由此完成每个子模块内的.a文件,如何被最上层模块使用的问题。但问题只完成了一半。当你在learn_make/src/learn_make.c 或者learn_make/src/test_learn_make_main.c中,尝试 #include "data_struct.h"时,gcc会出错。因此你需要使用create_module的另一个自动检测。
    ./create_module.sh learn_make -d
    但这样并不会立刻有效果。是因为,这个工作我实现的方法是,依赖于对/learn_make/Makefile里,MODULE_SUB的变量进行检查。以递归的寻找所有的inc目录。
    如上方法,你需要将learn_make/Makefile的文件,在 MODULE_SUB=这行进行修改,最终效果如下
    MODULE_SUB= data_struct
    此时,你执行
    ./create_module.sh learn_make -d
    则对应的文件依赖性的关系,会自动创建在 /learn_make/Makefile 中,同时,对应也修改了Makefile 里 MODULE_SUB_INC的变量内容。
    当然你会发现,这里多了一个-I../learn_make/inc 这么变态的内容,而我的Makefile的内部模板在gcc -c 中本身包行了 -Iinc。这是为了简单的递归查找 Makefile的文件时的遗留问题,我暂时不做此修正了。
    现在你会发现,以上的工作,已经可以使得模块调用子模块存在自动化的操作。
    当你进入每个目录时,均是针对当前这个目录对应的模块处理。同时你可以通过COPY其他模块到本模块下,进行操作。但是有个很致命的问题。假设你现在有如下的模块
    A/B/C
    也即A 模块下有B ,B 模块下有C 。此时,你将 C的整体目录COPY到A目录下,由此,A目录下存在两个C模块。则会导致一个非常头疼的事情。即库函数冲突。
因为目前的操作,是将 C的.a,合并到B的.a,B的.a合并到A的.a中。而当A下还有个C。则出现同样C模块的函数,在最终A的库中存在重名问题。

    解决这个问题,有两个操作方式。
    1、库化。将C的.a不是依次继承到最上层的.a中,而是独立放在一个A,B都能看到的lib 目录里,同时 .h放置在一个include的目录里,用于给A调用。和传统的库一样。但是这是基于C已经没有问题下。此时C模块已经不属于开发态。
    2、强制A模块禁止直接挂载C这个目录,如果C的目录被A的子模块使用时。但这个当B模块被拿走时,A又郁闷了。此时,则当C模块处于开发态时,B拿走,需要将B下的所有子模块,强制挂载到A下,如果C模块不属于开发态时,则按照1的方案实施。
    需要注意,上述这个问题,在目前的create_module脚本中,并没有处理。
    目前只是解决,假设存在,A,AA两个模块。当A模块下的B子模块被AA也需要使用。则可以采用COPY B目录下所有内容。到AA下,并修改AA/Makefile,MODULE_SUB 加上 B。随后执行 ./create_module AA -d 则,B模块会自动作为AA的依赖,并入到AA的Makefile里。

    同样需要注意的Makefile内的细节问题。
    Makefile 目前存在依赖冗余,就是一个相同依赖被几个不同地方描述。这个暂时不考虑。提一下一些变量的内容含义。
    SRC_PATH=src/
    INC_PATH=inc/
    OBJ_PATH=obj/
    BIN_PATH=bin/
    MODULE_NAME = learn_make
    以上5个,原则上,禁止修改,此是和

   $./create_module learn_make

   创建模块形成目录有关
MODULE_FILE = $(MODULE_NAME)
    这里可以后续增加当前模块下,新的C文件的文件名,但别加后缀以及路径。对应在MODULE_SRC MODULE_INC中,会自动增加同名的.c和同名的.h
MODULE_INC =
    这里只增加只有头文件,没有实际C文件的独立头文件名。但是此时需要注意,例如你要增加个type.h则需要写为 $(INC_PATH)type.h。
MODULE_T = test_$(MODULE_NAME)_main
    这个是定义该模块的唯一测试主程序。模块本身并不可直接编译运行。模块内部不存在main函数。这个唯一测试文件名,是由./create_module 创建,当然你可以自己任意修改成自己的名字。但是对应的 src/下的C文件名也需要修改。当然此处一样,不需要加.c后缀。
MODULE_TS = $(SRC_PATH)$(MODULE_T).c
MODULE_TB = $(BIN_PATH)$(MODULE_T)
    这两个不许要修改,是根据测试文件本身,获取测试文件C源文件全名,和输出执行程序名。在bin/下。
MODULE_SUB =
    这里是用于添加子模块名称。不需要路径。同时只需要当前目录下直接关联的子模块,对于孙子等等模块,Makefile描述中包含了递归自动处理的部分。这 样处理也希望开发人员,只关注当前模块和当前直接调用的模块的关系,而不要关注子模块内部。当然前面说的父子同调用一个孙子的情况另谈。

MODULE_SRC = $(addsuffix .c,$(addprefix $(SRC_PATH),$(MODULE_FILE)))
MODULE_OBJ = $(addsuffix .o,$(addprefix $(OBJ_PATH),$(MODULE_FILE)))
MODULE_INC += $(addsuffix .h,$(addprefix $(INC_PATH),$(MODULE_FILE)))
MODULE_LIB = lib$(MODULE_NAME).a
MODULE_BIN = $(BIN_PATH)$(MODULE_LIB)
MODULE_SUB_LIB = $(foreach var,$(MODULE_SUB),$(var)/$(BIN_PATH)lib$(var).a)
MODULE_SUB_INC = 
    以上均不要改动,除非你要改动下面Makefile的依赖规则或目标

MODULE_DEP = learn_make_DEP
..
ifndef MODULE_DEP
$(error No Dependence)
endif
以上需要注意,均是自动生成的。
ifndef MODULE_DEP
$(error No Dependence)
endif
是通过创建Makefile的模板自动添加的,目的是防止没有O文件,C文件依赖描述时,make的依赖出现遗漏。
而MODULE_DEP = learn_make_DEP 是通过 ./create_module learn_make -d 这个操作实现的。这个操作前面说过。根据MODULE_SUB,获取头文件信息,并针对当前模块的源进行 gcc -MM。随后将依赖填写到这里,并自动加上 MODULE_DEP = learn_make_DEP
但需要非常注意的一点。gcc -MM 并没有递归实现每个子模块的依赖。因为我的逻辑是,当前模块的依赖自动生成,只是针对当前模块的情况,而子模块,假设 learn_make/data_struct ,你需要 ./create_module learn_make/data_struct -d来手动完成。因为你尝试在learn_make/data_struct内增加一个C文件,或#include的动作,此属于data_struct 本身,而不属于learn_make本身。各个模块做各个模块的事情嘛。呵呵。
以下给出create_module脚本的参数和举例
./create_module module_name
会自动创建目录,某块接口C,头文件, MAKEFILE和依赖
此处会自动调用 -d -m -f module_name -t module_name module_name
./create_module module_name -d
-d 自动刷新依赖
./create_module module_name -m
-m 重建MAKEFILE 但不会处理依赖
-f name 生成name.c 的C文件,对应有name.h的头文件。
-h name 生成name.h的头文件
-t name1 name2 生成 test_name2_main.c的 C文件,不会生成头文件,但会在 test_name2_main.c 自动增加 #include "name1.h"

  • 中山野鬼:SORRY,Makefile有个依赖缺失的错误,在137行。原先的INSERT_FILE_CON+="\$(MODULE_TB):\$(MODULE_TS)\n"需要修改为: INSERT_FILE_CON+="\$(MODULE_TB):\$(MODULE_TS) \$(MODULE_TB)\n" 否则,模块文件更新后,make test并不会重新链接模块。 删除 3个月前
  • 中山野鬼:sorry ,又错了。笔误,笔误,哈哈。 对应的修改应该为 INSERT_FILE_CON+="\$(MODULE_TB):\$(MODULE_TS) \$(MODULE_BIN)\n" 删除 3个月前

后续实际使用,又发现错误, 已经做了些小操作的增补,当然代码越来越不成样子了。(2010年7月)以下给出目前代码

 #!/bin/bash

002 MODULE_PATH=$1
003 MODULE_NAME=$1
004  
005 SRC_DIR_NAME=src
006 INC_DIR_NAME=inc
007 BIN_DIR_NAME=bin
008 OBJ_DIR_NAME=obj
009 INCLUDE_DIR_NAME=include
010 LIB_DIR_NAME=lib
011 C_FILE_SUFFIX=.c
012 H_FILE_SUFFIX=.h
013 TEST_FILE_SUFFIX=.t
014 MAKE_FILE_SUFFIX=.m
015 CREATE_FILE_FLAG=-f
016 CREATE_H_FILE_FLAG=-h
017 CREATE_TEST_FILE_FLAG=-t
018 CREATE_MAKEFILE_FILE=-m
019 CREATE_DEP_FILE=-d
020 OVERWRITE_FILE=0
021 NOT_OVERWRITE_FILE=1
022  
023 create_mkdir(){
024     mkdir $1 > /dev/null 2>&1
025     if [ $? = 0 ];then 
026         echo /$1 had created
027         return 1
028     else
029         if [ -d $1 ];then
030             echo /$1 had exist
031             return 0
032         else
033             echo "could not create directory "/$1
034             exit
035         fi
036     fi
037  
038 }
039 check_file_exist(){
040     if [ -e $1 ];then
041         while :;do
042             echo -n "the $1 had exist , do you want to overwrite?(y(Y) done:n(N) not:e(E) exit) : "
043             read check_file_exist_ans
044             case $check_file_exist_ans in
045             y|Y)
046                 echo you answer y
047                 return $OVERWRITE_FILE
048             ;;
049             n|N)
050                 echo you answer n
051                 return $NOT_OVERWRITE_FILE
052             ;;
053             e|E)
054                 exit
055             ;;
056             *)
057                 echo  "fuck ,i need you correct answer!"
058             esac
059         done
060     else
061         return $OVERWRITE_FILE
062     fi
063 }
064 CREATE_NEW_FLIE=0
065 CREATE_NEW_FILE_ERROR=1
066 EXIST_FILE=2
067 INSERT_FILE_CON=""
068  
069 get_c_init_context(){
070 #$1 path/filename.ext
071 #$2 filename
072     INSERT_FILE_CON="/***************\n$1\n by luckystar\n ***************/\n"
073     INSERT_FILE_CON+="#include \"$2.h\"\n"
074     INSERT_FILE_CON+="static int $2_flag =0;\n"
075     INSERT_FILE_CON+="\nvoid $2_init(void*pv){\n"
076     INSERT_FILE_CON+="\tif ($2_flag) {\n\t\t//log(\"module inited..\",X);\n\t\treturn;\n\t}\n"
077     INSERT_FILE_CON+="\t$2_flag = 1;\n"
078     INSERT_FILE_CON+="\t//todo:module init...\n\n}\n"
079 #up is create module_init func 
080     INSERT_FILE_CON+="\nvoid $2_destory(void){\n"
081     INSERT_FILE_CON+="\tif (!$2_flag) {\n\t\t//log(\"module not inited..\",X);\n\t\treturn;\n\t}\n"
082     INSERT_FILE_CON+="\t$2_flag = 0;\n"
083     INSERT_FILE_CON+="\t//todo:module destory...\n\n}\n"
084 #up is create module_destory func
085 }
086  
087 get_h_init_context(){
088 #$1 path/filename.ext
089 #$2 filename
090     INSERT_FILE_CON="#ifndef _$2_H_\n#define _$2_H_\n"
091     INSERT_FILE_CON+="\n//ins_inc_file\n"
092     INSERT_FILE_CON+="\n//ins_typedef_def\n"
093     INSERT_FILE_CON+="\n//ins_def\n"
094     INSERT_FILE_CON+="\n//ins_func_declare\n"
095     INSERT_FILE_CON+="void $2_init(void*);\n"
096     INSERT_FILE_CON+="void $2_destory(void);\n"
097     INSERT_FILE_CON+="\n\n"
098     INSERT_FILE_CON+="#endif //_$2_H_\n"       
099 }
100 get_test_init_context(){
101 #$1 filename
102 #$2 libname
103     INSERT_FILE_CON="#include \"$2.h\"\n"
104     INSERT_FILE_CON+="#include <stdio.h>\n"
105     INSERT_FILE_CON+="\n\n"
106     INSERT_FILE_CON+="int main(int argc,char *argv[]){\n"
107     INSERT_FILE_CON+="\tprintf(\"hello test_$2_main now run...\\\n\");\n"  
108     INSERT_FILE_CON+="\t$2_init(0);\n"
109     INSERT_FILE_CON+="\t$2_destory();\n"
110     INSERT_FILE_CON+="\tprintf(\"hello test_$2_main now exit...\\\n\");\n"     
111     INSERT_FILE_CON+="\treturn 0;\n"
112     INSERT_FILE_CON+="}\n"     
113 }
114 get_make_init_context(){
115 #$1 module_name
116 INSERT_FILE_CON="SRC_PATH=src/\n"
117 INSERT_FILE_CON+="INC_PATH=inc/\n"
118 INSERT_FILE_CON+="OBJ_PATH=obj/\n"
119 INSERT_FILE_CON+="BIN_PATH=bin/\n"
120 INSERT_FILE_CON+="INCLUDE_PATH=include/\n"
121 INSERT_FILE_CON+="LIB_PATH=lib/\n"
122 INSERT_FILE_CON+="MODULE_NAME = $1\n"
123 INSERT_FILE_CON+="MODULE_FILE = \$(MODULE_NAME) \n"
124 INSERT_FILE_CON+="MODULE_INC =\n\n\n\n"
125 INSERT_FILE_CON+="MODULE_T = test_\$(MODULE_NAME)_main\n"
126 INSERT_FILE_CON+="MODULE_TS = \$(SRC_PATH)\$(MODULE_T).c\n"
127 INSERT_FILE_CON+="MODULE_TB = \$(BIN_PATH)\$(MODULE_T)\n"
128 INSERT_FILE_CON+="MODULE_SUB =\n\n\n"
129 INSERT_FILE_CON+="MODULE_SRC = \$(addsuffix .c,\$(addprefix \$(SRC_PATH),\$(MODULE_FILE)))\n"
130 INSERT_FILE_CON+="MODULE_OBJ = \$(addsuffix .o,\$(addprefix \$(OBJ_PATH),\$(MODULE_FILE)))\n"
131 INSERT_FILE_CON+="MODULE_INC += \$(addsuffix .h,\$(addprefix \$(INC_PATH),\$(MODULE_FILE)))\n"
132 INSERT_FILE_CON+="MODULE_LIB = lib\$(MODULE_NAME).a\n"
133 INSERT_FILE_CON+="MODULE_BIN = \$(BIN_PATH)\$(MODULE_LIB)\n"
134 INSERT_FILE_CON+="MODULE_SUB_LIB = \$(foreach var,\$(MODULE_SUB),\$(var)/\$(BIN_PATH)lib\$(var).a)\n"
135 INSERT_FILE_CON+="MODULE_SUB_INC =\n\n\n"
136 INSERT_FILE_CON+="LIB_NAME =\n\n"
137 INSERT_FILE_CON+="test:\n\n\n\n"
138 INSERT_FILE_CON+="ifndef MODULE_DEP\n"
139 INSERT_FILE_CON+="\$(error No Dependence)\n"
140 INSERT_FILE_CON+="endif\n"
141 INSERT_FILE_CON+="\$(foreach var,\$(MODULE_FILE),\$(eval \$(OBJ_PATH)\$(var).o:\$(SRC_PATH)\$(var).c  \$(INC_PATH)\$(var).h))\n\n"
142 INSERT_FILE_CON+="RM = -rm -f\n\n"
143 INSERT_FILE_CON+="test:all \$(MODULE_TB)\n\n"
144 INSERT_FILE_CON+="\$(MODULE_TB):\$(MODULE_TS) \$(MODULE_BIN)\n"
145 INSERT_FILE_CON+="ifeq (\$(strip \$(LIB_NAME)),)\n"
146 INSERT_FILE_CON+="  gcc -O2 \$(MODULE_SUB_INC) -I\$(INCLUDE_PATH) -I\$(INC_PATH) \$^ -L\$(BIN_PATH) -L\$(LIB_PATH) -l\$(MODULE_NAME) -o \$@\n"
147 INSERT_FILE_CON+="else\n"
148 INSERT_FILE_CON+="  gcc -O2 \$(MODULE_SUB_INC) -I\$(INCLUDE_PATH) -I\$(INC_PATH) \$^ -L\$(BIN_PATH) -L\$(LIB_PATH) -l\$(MODULE_NAME) -l\$(LIB_NAME) -o \$@\n"
149 INSERT_FILE_CON+="endif\n\n"
150 INSERT_FILE_CON+="\$(MODULE_OBJ):\n"
151 INSERT_FILE_CON+="  gcc  \$(MODULE_SUB_INC) -I\$(INCLUDE_PATH) -I\$(INC_PATH) -c \$<  -o \$@\n\n\n"
152 INSERT_FILE_CON+="\$(MODULE_BIN):\$(MODULE_OBJ) \$(MODULE_SUB_LIB)\n"
153 INSERT_FILE_CON+="  <a href="http://my.oschina.net/u/578052" class="referer" target="_blank">@echo</a>  module bin \$@\n"
154 INSERT_FILE_CON+="  -ar -r \$@ \$(MODULE_OBJ)\n"
155 INSERT_FILE_CON+="  -ar -x \$(MODULE_SUB_LIB)\n"
156 INSERT_FILE_CON+="  -ar -q \$@ *.o\n"
157 INSERT_FILE_CON+="  \$(RM) *.o\n"
158 INSERT_FILE_CON+="  ranlib \$@\n\n"
159  
160      
161      
162      
163 INSERT_FILE_CON+="all:\$(MODULE_BIN)\n\n"  
164 INSERT_FILE_CON+="\$(MODULE_SUB_LIB):   \$(MODULE_SUB)\n\n"
165 INSERT_FILE_CON+="clean: \$(MODULE_SUB) clean_self\n\n"
166 INSERT_FILE_CON+="clean_self:\n"
167 INSERT_FILE_CON+="  \$(RM) \$(MODULE_OBJ)\n"
168 INSERT_FILE_CON+="  \$(RM) \$(MODULE_BIN)\n"
169 INSERT_FILE_CON+="  \$(RM) \$(MODULE_TB)\n\n"
170 INSERT_FILE_CON+="rebuild:clean module_dep all\n\n"
171 INSERT_FILE_CON+="\$(MODULE_SUB):\n"
172 INSERT_FILE_CON+="  <a href="http://my.oschina.net/u/578052" class="referer" target="_blank">@echo</a>  \"***************  todo Module SUB\" \$@  \"*****************\"\n"
173 INSERT_FILE_CON+="  - \$(MAKE) -C \$@ \$(MAKECMDGOALS)\n\n\n"
174 INSERT_FILE_CON+="#module_dep:\n"
175 INSERT_FILE_CON+="# gcc \$(MODULE_SUB_INC) -I\$(INC_PATH) -MM \$(MODULE_SRC)    > \$(MODULE_NAME).d\n"
176 INSERT_FILE_CON+="# sed -i '1 i\$(MODULE_NAME)_DEP = \$(MODULE_NAME)_DEP' \$(MODULE_NAME).d\n"
177 INSERT_FILE_CON+="# sed -i '/.o:/ s,^,\$(OBJ_PATH),' \$(MODULE_NAME).d\n\n"
178 INSERT_FILE_CON+=".PHONY: test all clean clean_self rebuild \$(MODULE_SUB) module_dep\n"
179 }
180 insert_file_tmp(){
181 #$1 path/filename.ext
182 #$2 filename
183 #$3 ext mode
184     case $3 in
185     $C_FILE_SUFFIX)
186     get_c_init_context $1 $2
187     ;;
188     $H_FILE_SUFFIX)
189     get_h_init_context $1 $2
190     ;;
191     $TEST_FILE_SUFFIX)
192     get_test_init_context $4 $2
193     ;;
194     $MAKE_FILE_SUFFIX)
195     get_make_init_context $2
196     ;;
197     esac
198     sed  -i "a\\$INSERT_FILE_CON" $1
199      
200 }
201 create_Makefile(){
202 #$1 makefile name
203     NEW_FILENAME="Makefile"
204     check_file_exist $NEW_FILENAME
205     echo > $NEW_FILENAME
206     if [ $? = $OVERWRITE_FILE ];then
207         echo > $NEW_FILENAME
208         insert_file_tmp $NEW_FILENAME $MODULE_NAME $MAKE_FILE_SUFFIX
209         echo create /$MODULE_PATH/$NEW_FILENAME files
210         return $CREATE_NEW_FILE
211     else
212         return $EXIST_FILE
213     fi 
214          
215 }
216 create_file_in_sub_dir(){
217      
218     if [ -d $1 ];then
219         if [ $3 = $TEST_FILE_SUFFIX ]; then
220         NEW_FILENAME=$1/test_$4_main.c
221         else
222         NEW_FILENAME=$1/$2$3
223         fi
224         check_file_exist $NEW_FILENAME
225         if [ $? = $OVERWRITE_FILE ];then
226             echo > $NEW_FILENAME
227             insert_file_tmp $NEW_FILENAME $2 $3 $4
228             echo create /$MODULE_PATH/$NEW_FILENAME files
229             return $CREATE_NEW_FILE
230         else
231             return $EXIST_FILE
232         fi
233     else
234         echo  /$MODULE_PATH/$1 is not directory, create_file not continue...
235         return $CREATE_NEW_FILE_ERROR
236         #not exit , continue done the other cmd
237     fi
238 }
239 MODULE_FILE=MODULE_FILE
240 MODULE_SRC=""
241 OBJ_PATH=OBJ_PATH
242 SRC_PATH=SRC_PATH
243 MODULE_NAME_DEP_CHECK="ifndef MODULE_DEP"
244 RETURN_VALUE=
245  
246 read_value_from_file(){
247 #$1 filename $s2 valuename $3 is not add
248 #get return ,need used RETURN_VALUE
249 var=$2
250 mode=
251  
252     unset RETURN_VALUE
253  
254     while read var;do
255          
256         case $var in
257         \#*)    ;;
258         \.*)    ;;
259         *)
260          
261         var=`echo $var | sed -n "/^$2[\ ]*=/p"`
262         #get name  += value
263         #name ?= value .....
264         if [ -z "$var" ]; then
265             continue;
266         fi
267         #echo step1 $var
268         mode=`echo $var | sed -n "/+=/p"`
269         var=`echo $var | sed -n "s/^.*=//p"`
270         if [ -z "$mode" ]; then
271             RETURN_VALUE=$var
272             continue;
273         else
274             if [ 3 -le $# ]; then
275             RETURN_VALUE=${RETURN_VALUE}${var}
276             fi
277         fi
278         #echo step2 $RETURN_VALUE
279  
280         esac
281     done < $1
282 #   echo get return_value $RETURN_VALUE
283     return
284 }
285 get_first_data(){
286     echo first data $1
287     return $1
288 }
289 get_last_data(){
290     while [ 1 -lt $# ];do
291         shift
292     done
293     echo last1 data $1
294     return $1
295 }
296 cut_lines_in_file(){
297 #cut from $2 line to $3 line in file $1
298 #not check $1 file exist ,static func only
299 first=
300 last1=
301     #echo $2 $3
302     unset first
303     unset last1
304     first=`sed -n "/$2/=" $1`
305     last1=`sed -n "/$3/=" $1`
306     if [ -n "$first" -a -n "$last1" ]; then
307         get_first_data $first
308         first=$?
309         get_last_data $last1
310         last1=`expr $? - 1`
311         echo $first ${last1} $1
312         sed -i "${first},${last1}d" $1
313     fi
314     return
315       
316 }
317 get_sub_module(){
318     #$1 Makefile file name
319     if [ -e $MAKEFILE ];then
320         echo "read info form $MAKEFILE ..."
321     else
322         echo "Makefile(${MAKEFILE}) not exist!"
323         unset RETURN_VALUE
324         return
325     fi
326     read_value_from_file $1 "MODULE_SUB"
327 #   echo $RETURN_VALUE
328     exit   
329 }
330 cut_value_from_const(){
331 #$1 if have $(XXX) ,will cut
332     RETURN_VALUE=`echo $RETURN_VALUE | sed -n " s/[\$][(][^)]*[)]/ /p"`
333      
334 }
335 MODULE_INC=
336 adjust_MODULE_INC(){
337     MODULE_INC=`echo $MODULE_INC|sed -n "s/[^ ]*/ -I&/gp"`
338 }
339 MODULE_SUB_ALL_PATH=
340 get_inc_path(){
341 path_tmp=
342     echo "all subdir is: " $@
343     while [ 1 -le $# ] ;do
344          
345         path_tmp=`echo $1 | sed -n "s/^.*$/ &\Makefile/p"`
346         echo "ready get file is :" $path_tmp
347         read_value_from_file $path_tmp "MODULE_SUB" "+"
348         MODULE_SUB1=$RETURN_VALUE
349          
350         if [ -z "$MODULE_SUB1" ]; then
351             MODULE_SUB_ALL_PATH+=${1}
352             echo "No MODULE_SUB more..." $1
353             shift
354             continue;
355         fi
356         MODULE_SUB1=`echo $MODULE_SUB1 | sed -e "/[^ ]*/s,,$1&\/,g"`
357         MODULE_SUB_ALL_PATH+=$1
358         get_inc_path $MODULE_SUB1
359         shift
360     done
361 }
362 get_all_INC_path(){
363     unset MODULE_SUB_ALL_PATH
364     get_inc_path "../$MODULE_NAME/"
365  
366     MODULE_SUB_ALL_PATH=`echo $MODULE_SUB_ALL_PATH | sed -n "/[\.][\.][]\/]/s,, &,gp"`
367     MODULE_SUB_ALL_PATH=`echo $MODULE_SUB_ALL_PATH | sed -n "/[\.][\.][]\/][^\.^ ]*/s,, -I&inc -I&include,gp"`
368     echo "all path is : " $MODULE_SUB_ALL_PATH
369     #exit  
370 }
371 create_depend_file(){
372 #use gcc -MM create dependfile 
373 #$1 module_name $2 makefile name not support!!
374     #if [ 2 -le $# ];then
375     #   MAKEFILE=$2
376     #else
377         MAKEFILE=Makefile
378     #fi
379      
380  
381     #get_sub_module $MAKEFILE
382 #   echo $MAKEFILE set MAKEFILE default is Makefile
383     if [ -e $MAKEFILE ];then
384         echo "read info form $MAKEFILE ..."
385     else
386         echo "Makefile(${MAKEFILE}) not exist!"
387         exit
388     fi
389     read_value_from_file $MAKEFILE $SRC_PATH
390     SRC_PATH=$RETURN_VALUE
391     read_value_from_file $MAKEFILE $OBJ_PATH
392     OBJ_PATH=$RETURN_VALUE 
393     read_value_from_file $MAKEFILE $MODULE_FILE "+"
394     echo return_cut begin $RETURN_VALUE
395     cut_value_from_const $RETURN_VALUE
396     echo return_cut end $RETURN_VALUE
397     MODULE_FILE=${MODULE_NAME}" "${RETURN_VALUE} #insert space
398     MODULE_SRC=`echo $MODULE_FILE | sed -e "/[^ ]*/s,,$SRC_PATH&.c,g"`
399     echo "MODULE INFO:"
400     echo "SRC_PATH = "$SRC_PATH
401     echo "OBJ_PATH = "$SRC_PATH
402     echo "MODULE_FILE = "$MODULE_FILE
403     echo "MODULE_SRC = "$MODULE_SRC
404     get_all_INC_path
405     gcc $MODULE_SUB_ALL_PATH  -MM $MODULE_SRC > $MODULE_NAME.d
406     sed -i "1 iMODULE_DEP = ${MODULE_NAME}_DEP" $MODULE_NAME.d
407     sed -i "/.o:/ s,^,${OBJ_PATH}," $MODULE_NAME.d
408     cut_lines_in_file $MAKEFILE ${MODULE_NAME}_DEP  "$MODULE_NAME_DEP_CHECK"
409     echo "Dependinfo is :"
410     cat  $MODULE_NAME.d
411     echo "Dependinfo end"
412     sed -i "/ifndef[ ]*MODULE_DEP/i ifndef__TMP MODULE_DEP" $MAKEFILE
413  
414     sed -i "/ifndef__TMP[ ]*MODULE_DEP/r $MODULE_NAME.d" $MAKEFILE
415     sed -i "/ifndef__TMP[ ]*MODULE_DEP/d"  $MAKEFILE
416     sed -i "/^MODULE_SUB_INC.*$/s,,MODULE_SUB_INC = $MODULE_SUB_ALL_PATH," $MAKEFILE
417 #check LIB_NAME
418          
419      
420     return
421  
422 }
423  
424 check_other_cmd(){
425 #MODULE_INC="a b/c/d e"
426 #   echo $MODULE_INC
427 #   adjust_MODULE_INC
428 #   echo $MODULE_INC
429 #   exit
430     #MODULE_SUB= read_value_from_file "Makefile" "MODULE_SUB" "+"
431  
432     #echo $MODULE_SUB1
433     #exit
434  
435      
436 while [ 2 -le $# ];do
437     case $2 in
438     $CREATE_FILE_FLAG)
439         shift
440         create_file_in_sub_dir $SRC_DIR_NAME $2 $C_FILE_SUFFIX #$C_FILE_TMP
441         create_file_in_sub_dir $INC_DIR_NAME $2 $H_FILE_SUFFIX #$H_FILE_TMP
442          
443         #create_file_in_sub_dir $LOG_DIR_NAME $2 $LOG_FILE_SUFFIX
444          
445     ;;
446     $CREATE_TEST_FILE_FLAG)
447         shift
448         create_file_in_sub_dir $SRC_DIR_NAME $2 $TEST_FILE_SUFFIX  $3
449         shift
450          
451         ;;
452     $CREATE_H_FILE_FLAG)
453         shift
454         create_file_in_sub_dir $INC_DIR_NAME $2 $H_FILE_SUFFIX #$H_FILE_TMP
455         ;; 
456     $CREATE_DEP_FILE)
457         #shift
458         create_depend_file $MODULE_NAME #$2
459         ;;
460     $CREATE_MAKEFILE_FILE)
461         #shift
462         create_Makefile $MODULE_NAME
463         ;;
464     *)
465         ;;
466        #    echo $2" test "
467     esac
468         shift
469 done
470     exit
471 }
472 echo $MODULE_PATH
473  
474 create_mkdir $MODULE_PATH
475 is_created=$?
476 echo $is_created
477  
478     MODULE_NAME=`echo $MODULE_PATH|sed -e "s/^.*[\/]//"`
479  
480 if [ -d $MODULE_PATH ];then
481     cd $MODULE_PATH
482     create_mkdir $SRC_DIR_NAME
483     create_mkdir $INC_DIR_NAME
484     create_mkdir $BIN_DIR_NAME
485     create_mkdir $OBJ_DIR_NAME
486     create_mkdir $LIB_DIR_NAME
487     create_mkdir $INCLUDE_DIR_NAME     
488     if [ "$is_created" -eq "1" ];then
489     #create_Makefile $MODULE_NAME
490     check_other_cmd $@ -f $MODULE_NAME -t $MODULE_NAME $MODULE_NAME -m -d
491     else
492     check_other_cmd $@
493     fi
494 else
495     echo $MODULE_NAME is not directory ,could not continue...  
496     exit
497 fi

 

 

 

你可能感兴趣的:(中山野鬼 linux 下 C 编程和make的方法 (七、补充,模块化项目组织的Makefil...)