linux 下 C 编程和make的方法 ( 六:补充 关于搭窝)
2012-11-11 23:13
591 查看
前面堆了一堆代码,说件让刚码过的朋友吐血的事,就上面这些代码我没有写一行,除了一些修改,整体就是COPY。从哪COPY来的,后面会说。先谈搭窝。
这事得从资源利用说起。我说了。大家的智商都差不多,你想做的更好,就得利用好你的脑袋的资源聚焦在一点上。有经验的老鸟能处理大项目,没经验的菜鸟,一 碰到复杂点点的,就完了。差异除了老鸟有知识技术方面的积累外,还有工作方法的经验。复杂的东西,抽丝剥茧,分成模块,集中注意力,盯住当前的目标。系统 明确,模块明确,目标明确。老鸟,一天搞一点,但是每天都有积累,汇总起来就OK。
因此,对于菜鸟而言,在你没学到广泛的知识前(这得花时间,毕竟你耳朵根子没有个USB口),集中你当前要解决的问题,这最重要的。尽可能把要面对的问 题,切得足够小。这还不够。还要最短时间内,能验证问题是否解决了。你可以把有些事情切出去,拖后处理,但当前的行为,要尽快验证。
所以,搭窝对于新手,是必须要。10个函数,2个C文件,洋洋洒洒的写完,才编译,好嘛,错误填满整个屏幕都不够,这也太打击你积极性了。
不过,我也不能每次介绍新模块时,都贴上 cd .. mkdir ..等等东西。怎么办呢?这里给了一个弱智版的脚本文件。用于自动生成模块目录,和生成对应模块文件。包括.h包括.c。包括测试文件。弱智版的我觉得好 啊,至少你们能看得懂。而且,没有必要搞那么复杂,我当然希望各位能理解configure文件的内部每个操作。但是这得解释太多东西。不如一步步来。
先说下,弱智版的自动生成模块的脚本怎么用。
有几个参数。
第一个参数必须要有,是表示模块名的。由这个模块,会自动创建目录。如果目录已经存在则会提示已经存在。或无法创建,比如有同名的文件在当前目录下。
第二个参数可以选择,目前有 -f -t两个。后面要对应跟上文件名。
-f 是你需要给模块module目录下自动生成src/a.c 和inc/a.h。并添加些基本代码。如下操作
-t 是自动生成测试文件,但是测试文件总要至少针对一个文件进行测试(别吐,目前也只能添加对一个文件进行测试的基本代码)。因此 -t有两个参数
此时会在src/下自动生成一个test_b_main.c,而且会自动加上 #include "a.h"这类的代码。
需要注意,如果已经有对应文件存在,会提示,是否覆盖。这里没有追加的代码,毕竟弱智版的,我不想一下把脚本写的太多。目前已经够弱智的了。
对于前面那些搭窝的工作。你可以如下操作。
这和
你也可以尝试如下命令,换个测试名字
当然你也可以
上面两个命令没有顺序。都会检测目录是否存在,是否需要创建。
此时生成的是test_ds_main.c文件,在src/下。
清单如下。
这里需要有几个声明的:
1、这个离理解configure的距离还差的很远。我尽可能的用函数调用,和简单的方式实现。当然有更精炼的操作方式。不过脚本语言一直有个悖论。高效 的看不懂,看得懂的不高效。而我本身主业是搞算法优化的,包括从系统架构上做调整。所以我对脚本的设计,追求一点:但求好看,不求高效。
估计又要被喷了,你做优化的还不要高效?我现在开始狡辩,如下:
1、优化讲究目标。而不存在没有任何边界或者没有任何约束的优化。
2、脚本的最大作用在于自动化的完成任务。但它是通过其他功能模块实现核心处理,脚本要什么都能做就不是脚本了。如果仅凭脚本自身就能做C都不能做的事情,那和汇编有什么区别,且不谈其他高级语言。
3、用脚本的,不会只RUN一次。不会是个小事情,步骤单一的操作。一定是比较复杂的,或步骤繁琐的目标组合。
4、现实中有两种脚本,一个是自己写的,一个是产品化发布中存在的。
总结一下,轮到但凡自己写的,优化目标不是脚本自身运行的高效。同时,自己写的,不是给自己看的,就是给同事看的,而且会随项目的推进而做调整,因此,脚本本身优化的目标就是在于易读易改,而不是脚本自身的速度(不谈脚本所调用的其他模块的运行效率问题 )。
我可没说我只做运行速度的优化。开发速度的优化也是优化。我自己写的代码足够快,也不可能是天下第一。我就是做了天下第一的一个软件,也不可能各个软件都 天下第一。我更希望的去优化一个团队的组织行为,而不是工作目标本身。如同,美女值得调戏,但是你能调戏尽天下所有美女吗?因此,告诉新手组织化调戏的手 段,比调戏本身更重要。
对于那些非产品级发布的脚本,写的高效的,准确说,我连用都不用,更别提看了。因为有理解你脚本的功夫,不如我自己写了。不理解清楚脚本的目标和工作原理 对我毫无价值。也希望新手保持个习惯,不要拿脚本设计来当作智力的体现,爱因斯坦成名那会也没有脚本这玩意啊。设计脚本的评价目标就是“易读,易改”。
最后,建议新手:
毕竟是linux下的C编程,基本的脚本命令和格式还是要会的。希望上述脚本作为模版,有利于你理解脚本的一些常用操作方式。同时记得ctrl+c ctrl+v保存为文件后,除了爱其什么名字就起什么名字,你得如下操作(如果你和我一样起名为create_moudule.sh)
为什么这么做,记得gcc main.c 输出为什么是a.out吗?我们在linux下面,不是微软的win下。
同时建议高手:
能有空对我的脚本进行改动修正,前提是更易读,更易改。
关于Makefile:
C代码可不是弱智版的(后面会展开讨论),我自动生成没关系。Makefile现在是弱智版的,我自动生成,脑袋进水了。大家和外我一样慢慢码吧。
转自http://my.oschina.net/luckystar/blog/67083
这事得从资源利用说起。我说了。大家的智商都差不多,你想做的更好,就得利用好你的脑袋的资源聚焦在一点上。有经验的老鸟能处理大项目,没经验的菜鸟,一 碰到复杂点点的,就完了。差异除了老鸟有知识技术方面的积累外,还有工作方法的经验。复杂的东西,抽丝剥茧,分成模块,集中注意力,盯住当前的目标。系统 明确,模块明确,目标明确。老鸟,一天搞一点,但是每天都有积累,汇总起来就OK。
因此,对于菜鸟而言,在你没学到广泛的知识前(这得花时间,毕竟你耳朵根子没有个USB口),集中你当前要解决的问题,这最重要的。尽可能把要面对的问 题,切得足够小。这还不够。还要最短时间内,能验证问题是否解决了。你可以把有些事情切出去,拖后处理,但当前的行为,要尽快验证。
所以,搭窝对于新手,是必须要。10个函数,2个C文件,洋洋洒洒的写完,才编译,好嘛,错误填满整个屏幕都不够,这也太打击你积极性了。
不过,我也不能每次介绍新模块时,都贴上 cd .. mkdir ..等等东西。怎么办呢?这里给了一个弱智版的脚本文件。用于自动生成模块目录,和生成对应模块文件。包括.h包括.c。包括测试文件。弱智版的我觉得好 啊,至少你们能看得懂。而且,没有必要搞那么复杂,我当然希望各位能理解configure文件的内部每个操作。但是这得解释太多东西。不如一步步来。
先说下,弱智版的自动生成模块的脚本怎么用。
有几个参数。
第一个参数必须要有,是表示模块名的。由这个模块,会自动创建目录。如果目录已经存在则会提示已经存在。或无法创建,比如有同名的文件在当前目录下。
第二个参数可以选择,目前有 -f -t两个。后面要对应跟上文件名。
-f 是你需要给模块module目录下自动生成src/a.c 和inc/a.h。并添加些基本代码。如下操作
1 | $./create_module.sh module -f a |
1 | $./create_module.sh module -t b a |
需要注意,如果已经有对应文件存在,会提示,是否覆盖。这里没有追加的代码,毕竟弱智版的,我不想一下把脚本写的太多。目前已经够弱智的了。
对于前面那些搭窝的工作。你可以如下操作。
1 | $./create_module.sh data_struct -f ds_tree -t ds_tree ds_tree |
1 | $./create_module.sh data_struct -t ds_tree ds_tree -f ds_tree |
1 | $./create_module.sh data_struct -f ds_tree -t ds_tree ds |
1 | $./create_module.sh data_struct -t ds_tree ds |
2 | $./create_module.sh data_struct -f ds_tree |
此时生成的是test_ds_main.c文件,在src/下。
清单如下。
001 | #!/bin/bash |
002 | MODULE_NAME=$1 |
003 |
004 | SRC_DIR_NAME=src |
005 | INC_DIR_NAME=inc |
006 | BIN_DIR_NAME=bin |
007 | OBJ_DIR_NAME=obj |
008 | C_FILE_SUFFIX=.c |
009 | H_FILE_SUFFIX=.h |
010 | TEST_FILE_SUFFIX=.t |
011 | CREATE_FILE_FLAG=-f |
012 | CREATE_TEST_FILE_FLAG=-t |
013 | OVERWRITE_FILE=0 |
014 | NOT_OVERWRITE_FILE=1 |
015 |
016 | create_mkdir(){ |
017 | mkdir $1 > /dev/null 2>&1 |
018 | if [ $? = 0 ]; then |
019 | echo /$1 had created |
020 | else |
021 | echo /$1 had exist |
022 | fi |
023 |
024 | } |
025 | check_file_exist(){ |
026 | if [ -e $1 ]; then |
027 | while :; do |
028 | echo -n "the $1 had exist , do you want to overwrite?(y(Y) done:n(N) not:e(E) exit) : " |
029 | read check_file_exist_ans |
030 | case $check_file_exist_ans in |
031 | y|Y) |
032 | echo you answer y |
033 | return $OVERWRITE_FILE |
034 | ;; |
035 | n|N) |
036 | echo you answer n |
037 | return $NOT_OVERWRITE_FILE |
038 | ;; |
039 | e|E) |
040 | exit |
041 | ;; |
042 | *) |
043 | echo "fuck ,i need you correct answer!" |
044 | esac |
045 | done |
046 | else |
047 | return $OVERWRITE_FILE |
048 | fi |
049 | } |
050 | CREATE_NEW_FLIE=0 |
051 | CREATE_NEW_FILE_ERROR=1 |
052 | EXIST_FILE=2 |
053 | INSERT_FILE_CON= "" |
054 |
055 | get_c_init_context(){ |
056 | #$1 path/filename.ext |
057 | #$2 filename |
058 | INSERT_FILE_CON= "/***************\n$1\n by luckystar\n ***************/\n" |
059 | INSERT_FILE_CON+= "static int $2_flag =0;\n" |
060 | INSERT_FILE_CON+= "\nvoid $2_init(void){\n" |
061 | INSERT_FILE_CON+= "\tif ($2_flag) {\n\t\t//log(\"module inited..\",X);\n\t\treturn;\n\t}\n" |
062 | INSERT_FILE_CON+= "\t$2_flag = 1;\n" |
063 | INSERT_FILE_CON+= "\t//todo:module init...\n\n}\n" |
064 | #up is create module_init func |
065 | INSERT_FILE_CON+= "\nvoid $2_destory(void){\n" |
066 | INSERT_FILE_CON+= "\tif (!$2_flag) {\n\t\t//log(\"module not inited..\",X);\n\t\treturn;\n\t}\n" |
067 | INSERT_FILE_CON+= "\t$2_flag = 0;\n" |
068 | INSERT_FILE_CON+= "\t//todo:module destory...\n\n}\n" |
069 | #up is create module_destory func |
070 | } |
071 |
072 | get_h_init_context(){ |
073 | #$1 path/filename.ext |
074 | #$2 filename |
075 | INSERT_FILE_CON= "#ifndef _$2_H_\n#define _$2_H_\n" |
076 | INSERT_FILE_CON+= "\n//ins_inc_file\n" |
077 | INSERT_FILE_CON+= "\n//ins_typedef_def\n" |
078 | INSERT_FILE_CON+= "\n//ins_def\n" |
079 | INSERT_FILE_CON+= "\n//ins_func_declare\n" |
080 | INSERT_FILE_CON+= "\n\n" |
081 | INSERT_FILE_CON+= "#endif //_$2_H_\n" |
082 | } |
083 | get_test_init_context(){ |
084 | #$1 filename |
085 | #$2 libname |
086 | INSERT_FILE_CON= "#include \"$2.h\"\n" |
087 | INSERT_FILE_CON+= "\n\n" |
088 | INSERT_FILE_CON+= "int main(int argc,char *argv[])\n" |
089 | INSERT_FILE_CON+= "\t$2_init();\n" |
090 | INSERT_FILE_CON+= "\t$2_destrory();\n" |
091 | INSERT_FILE_CON+= "\treturn 0;\n" |
092 | INSERT_FILE_CON+= "}\n" |
093 | } |
094 | insert_file_tmp(){ |
095 | #$1 path/filename.ext |
096 | #$2 filename |
097 | #$3 ext mode |
098 | case $3 in |
099 | $C_FILE_SUFFIX) |
100 | get_c_init_context $1 $2 |
101 | ;; |
102 | $H_FILE_SUFFIX) |
103 | get_h_init_context $1 $2 |
104 | ;; |
105 | $TEST_FILE_SUFFIX) |
106 | get_test_init_context $4 $2 |
107 | esac |
108 | sed -i "a\\$INSERT_FILE_CON" $1 |
109 |
110 | } |
111 |
112 | create_file_in_sub_dir(){ |
113 |
114 | if [ -d $1 ]; then |
115 | if [ then |
116 | NEW_FILENAME=$1/test_$4_main.c |
117 | else |
118 | NEW_FILENAME=$1/$2$3 |
119 | fi |
120 | check_file_exist $NEW_FILENAME |
121 | if [ $? = $OVERWRITE_FILE ]; then |
122 | echo > $NEW_FILENAME |
123 | insert_file_tmp |
124 | echo create /$MODULE_NAME/$NEW_FILENAME file |
125 | return $CREATE_NEW_FILE |
126 | else |
127 | return $EXIST_FILE |
128 | fi |
129 | else |
130 | echo /$MODULE_NAME/$1 is not directory, create_file not continue ... |
131 | return $CREATE_NEW_FILE_ERROR |
132 | #not exit , continue done the other cmd |
133 | fi |
134 | } |
135 |
136 |
137 | check_other_cmd(){ |
138 | while [ 2 - le $ # ];do |
139 | case $2 in |
140 | $CREATE_FILE_FLAG) |
141 | shift |
142 | create_file_in_sub_dir #$C_FILE_TMP |
143 | create_file_in_sub_dir #$H_FILE_TMP |
144 |
145 | #create_file_in_sub_dir |
146 |
147 | ;; |
148 | $CREATE_TEST_FILE_FLAG) |
149 | shift |
150 | create_file_in_sub_dir |
151 | shift |
152 |
153 | ;; |
154 | *) |
155 | # echo $2" test " |
156 | esac |
157 | shift |
158 | done |
159 | exit |
160 | } |
161 | create_mkdir $MODULE_NAME |
162 | if [ -d $MODULE_NAME ]; then |
163 | cd $MODULE_NAME |
164 | create_mkdir $SRC_DIR_NAME |
165 | create_mkdir $INC_DIR_NAME |
166 | create_mkdir $BIN_DIR_NAME |
167 | create_mkdir $OBJ_DIR_NAME |
168 | check_other_cmd $@ |
169 | else |
170 | echo $MODULE_NAME is not directory ,could not continue ... |
171 | exit |
172 | fi |
1、这个离理解configure的距离还差的很远。我尽可能的用函数调用,和简单的方式实现。当然有更精炼的操作方式。不过脚本语言一直有个悖论。高效 的看不懂,看得懂的不高效。而我本身主业是搞算法优化的,包括从系统架构上做调整。所以我对脚本的设计,追求一点:但求好看,不求高效。
估计又要被喷了,你做优化的还不要高效?我现在开始狡辩,如下:
1、优化讲究目标。而不存在没有任何边界或者没有任何约束的优化。
2、脚本的最大作用在于自动化的完成任务。但它是通过其他功能模块实现核心处理,脚本要什么都能做就不是脚本了。如果仅凭脚本自身就能做C都不能做的事情,那和汇编有什么区别,且不谈其他高级语言。
3、用脚本的,不会只RUN一次。不会是个小事情,步骤单一的操作。一定是比较复杂的,或步骤繁琐的目标组合。
4、现实中有两种脚本,一个是自己写的,一个是产品化发布中存在的。
总结一下,轮到但凡自己写的,优化目标不是脚本自身运行的高效。同时,自己写的,不是给自己看的,就是给同事看的,而且会随项目的推进而做调整,因此,脚本本身优化的目标就是在于易读易改,而不是脚本自身的速度(不谈脚本所调用的其他模块的运行效率问题 )。
我可没说我只做运行速度的优化。开发速度的优化也是优化。我自己写的代码足够快,也不可能是天下第一。我就是做了天下第一的一个软件,也不可能各个软件都 天下第一。我更希望的去优化一个团队的组织行为,而不是工作目标本身。如同,美女值得调戏,但是你能调戏尽天下所有美女吗?因此,告诉新手组织化调戏的手 段,比调戏本身更重要。
对于那些非产品级发布的脚本,写的高效的,准确说,我连用都不用,更别提看了。因为有理解你脚本的功夫,不如我自己写了。不理解清楚脚本的目标和工作原理 对我毫无价值。也希望新手保持个习惯,不要拿脚本设计来当作智力的体现,爱因斯坦成名那会也没有脚本这玩意啊。设计脚本的评价目标就是“易读,易改”。
最后,建议新手:
毕竟是linux下的C编程,基本的脚本命令和格式还是要会的。希望上述脚本作为模版,有利于你理解脚本的一些常用操作方式。同时记得ctrl+c ctrl+v保存为文件后,除了爱其什么名字就起什么名字,你得如下操作(如果你和我一样起名为create_moudule.sh)
1 | $ chmod +x create_module.sh |
同时建议高手:
能有空对我的脚本进行改动修正,前提是更易读,更易改。
关于Makefile:
C代码可不是弱智版的(后面会展开讨论),我自动生成没关系。Makefile现在是弱智版的,我自动生成,脑袋进水了。大家和外我一样慢慢码吧。
转自http://my.oschina.net/luckystar/blog/67083
相关文章推荐
- linux 下 C 编程和make的方法 ( 六:补充 关于搭窝)
- linux 下 C 编程和make的方法 (五:补充 怎么抓BUG)
- linux 下 C 编程和make的方法 (七、补充,模块化项目组织的Makefile设计和自动生成脚本)
- linux 下 C 编程和make的方法 (五:补充 怎么抓BUG)
- linux 下 C 编程和make的方法 (七、从项目组织化开发谈make操作模块)
- linux 下 C 编程和make的方法 (四、开始make)
- linux 下 C 编程和make的方法 (五、准备写C代码)
- linux 下 C 编程和make的方法 (一、综述:为什么学这些)
- linux 下 C 编程和make的方法 (六:一个C模块的实现)
- linux 下 C 编程和make的方法
- linux 下 C 编程和make的方法 ( 九、malloc 和free的使用 上)
- linux 下 C 编程和make的方法 (十、C版的try catch 捕捉段错误和异常处理)
- linux 下 C 编程和make的方法 (三、工程文档的组织)
- 嵌入式开发基础--关于Linux与windows的共享问题解决方法二的补充
- linux 下 C 编程和make的方法 (四、开始make)
- linux 下 C 编程和make的方法 (五、准备写C代码)
- linux 下 C 编程和make的方法 (六:一个C模块的实现)
- linux 下 C 编程和make的方法 (三、工程文档的组织)
- 关于Linux下M9 SDK模拟器太大,无法全部显示的解决方法
- 关于VMWare安装centOs得到的IP地址与xshell连接的方法(慕课网linux课程)