一个自动生成 makefile 依赖的 bash 脚本 - 哆啦比猫的技术瞎扯 - Arch Linux · ドラえもん · 实时绘制
一个自动生成 makefile 依赖的 bash 脚本
哆啦比猫
posted @ 2011年8月10日 16:42
in Shell
with tags
make makefile bash shell dependence generate auto
, 4379 阅读
很多初学 Linux 编程的人抱怨 makefile 怎么那么麻烦,干嘛不能自动生成依赖关系;我有时也觉得写 makefile 比较麻烦,每次代码里增加文件都要去改 makefile,注意力无法集中于代码上,后来干脆尽量不增加文件,把代码都尽可能的塞进已有的文件。
Makefile 的这种设计自有它的优点,但这确实给人们带来太多麻烦。我也见过一些可以解决此麻烦的方法,但是得另外装软件。于是乎,一个念头闪过,何不用 bash 写一个自动生成 makefile 依赖的脚本呢?顺便还能练一下 bash 呢。
经过 2 天间断性的努力,终于完成了。
#!/bin/bash # Automatic Dependencies Solving Makefile Generating Configure Script # Written by eXerigumo Clanjor # CUSTOMIZE MAIN="main" LIBS="-lglut -lGL -lGLU" # GLOBAL VARS CXXFLAGS="-s" CXXOPTIMIZE="-O2" DEPS=() OBJS=() # -- void main(argv) main() { # parse arguments while ! [ -z "$1" ]; do case $1 in "--help" | "-h") show_help ;; "--enable-debug") CXXFLAGS="-g -DDEBUG" CXXOPTIMIZE="" # No optimization shift ;; "-Ofast") CXXOPTIMIZE="-Ofast" shift ;; "--clean") make cleanall rm -f makefile exit 0 ;; *) error "unknown argument: $1" ;; esac done generate_makefile } # -- void generate_makefile(void) generate_makefile() { echo -e "# Generated by ADSMGCS." > makefile echo >> makefile echo -e "CXXFLAGS = -Wall $CXXFLAGS $CXXOPTIMIZE $LIBS" >> makefile echo >> makefile echo -e "all: $MAIN" >> makefile echo -e "clean:" >> makefile echo -e "\trm -f *.o" >> makefile echo -e "cleanall: clean" >> makefile echo -e "\trm -f $MAIN" >> makefile echo -e "rebuild: clean all" >> makefile echo -e "debug: all" >> makefile echo -e "\t./$MAIN" >> makefile echo >> makefile generate_dep "${MAIN}.cc" echo -e "$MAIN:" ${OBJS[*]} >> makefile echo -e '\t$(CXX) $(CXXFLAGS) -o $@ $^' >> makefile cat .makefile >> makefile echo >> makefile rm -f .makefile } # -- void show_help(void) show_help() { echo echo -e "OPTIONS:" echo -e "\t--help, -h" echo -e "\t\tShow this help" echo -e "\t--enable-debug" echo -e "\t\tEnable debug mode" echo -e "\t-Ofast" echo -e "\t\tUse -Ofast instead of -O2" echo exit 0 } # -- void error(string err) error() { echo -e "\e[1;31merror:\e[m $1" exit 1 } # -- void generate_dep(string file) generate_dep() { echo -e "Solving dependencies of $1..." if ! g++ -MM "$1" > .dep; then error "unexpected failure of g++." fi cat .dep >> .makefile echo -e '\t$(CXX) $(CXXFLAGS) -c -o $@ $<' >> .makefile local dep="`cat .dep|awk '{sub(/\\\\/, ""); printf $0}' \ |sed 's/[^ ]\+: [^ ]\+ \?//g'`" local obj="`cat .dep|head -n 1|awk -F: '{printf $1}'`" rm -f .dep OBJS[${#OBJS[*]}]="$obj" local d for d in $dep; do if need_recursive_dep "$d"; then [[ "$d" =~ (.*)\.h$ ]] && d="${BASH_REMATCH[1]}.cc" [ -f "$d" ] && generate_dep "$d" fi done } # -- bool need_recursive_dep(string file) need_recursive_dep() { local d for d in ${DEPS[*]}; do [[ "$d" == "$1" ]] && return 1 done DEPS[${#DEPS[*]}]="$1" return 0 } main $*
将此脚本命名为 configure(以假乱真,哈哈),然后就可以两部曲了——./configure && make
目前仅支持 C++,但理论上只要是 GCC 支持的语言都可以用,只不过要改里面关于后缀名替换的部分。
主文件名由全局变量 MAIN 指定(MAIN="main" 代表主文件名为 main.cc,生成的可执行文件名为 main)
凡未特殊声明(转载/翻译),所有文章均为原创。
by Giumo Xavier Clanjor (哆啦比猫/兰威举), 2010-2019.
本作品采用知识共享署名·非商业性使用·相同方式共享 3.0 中国大陆许可协议进行许可。
文中凡未特殊声明且未声明为引用的代码均以 MIT 协议授权。
blog comments powered by Disqus