思春期ブログ

ディレクトリ分けてて、automakeでも使おうかと思ったんだけど、automakeがインストールされてなかったという。


futonマシンのよいところは、ネットワークに繋がらないことです。あと、冬場に強い(僕がふとんにこもりたがるので)。あと、最近Macfutonマシンにしました。僕も立派なApple信者です。OSはUbuntuだけど。


話が逸れた。んで、ディレクトリ分けたいけど、automakeもautoconfも無かったので、Makefile自動生成するのを作った。
もちろんautomake使ったほうがよい。

for i in `find -name module.sh | sed -e 's|^\./||g'`
do
    (mod_dir=`dirname $i`
     . $i
     srcs=`echo $SOURCES | sed -e 's|\([a-zA-Z./\-]\+\)|'${mod_dir}'/\1|g'`
     gen_files=`echo $GENERATED | sed -e 's|\([a-zA-Z./\-_]\+\)|'${mod_dir}'/\1|g'`
     redirect_err="2>&1 |sed -e 's|${mod_dir}/||g'"
     cat <<EOF
# Do not edit. This file is generated by readmodule.sh

${MODNAME}_SOURCES=${srcs}
${MODNAME}_LEX_SRCS=\$(filter %.l,\$(${MODNAME}_SOURCES))
${MODNAME}_LEX_GEN_SRCS=\$(patsubst %.l,%.c,\$(${MODNAME}_LEX_SRCS))
${MODNAME}_C_SRCS=\$(filter %.c,\$(${MODNAME}_SOURCES)) \$(${MODNAME}_LEX_GEN_SRCS) \$(patsubst %.l,%.flex.h,\$(${MODNAME}_LEX_SRCS))
${MODNAME}_CXX_SRCS=\$(filter %.cpp,\$(${MODNAME}_SOURCES))
${MODNAME}_OBJS=\$(patsubst %.c,%.o,\$(${MODNAME}_C_SRCS)) \$(patsubst %.cpp,%.o,\$(${MODNAME}_CXX_SRCS))


ifeq (\$(COMPILE_DIR),$mod_dir)
REDIRECT_ERR=${redirect_err}
endif
EOF

     if echo $SOURCES | grep '\.cpp'
     then
	 linker='$(CXX)'
	 
     else
	 linker='$(CC)'
     fi

     if test x"${NEED_MODULE}" != x""; then
	 depends="\$(${NEED_MODULE}_OUTPUT)"
     fi

     if test "$OUT_EXE" != ""; then
	 cat <<EOF
${mod_dir}/${OUT_EXE}: \$(${MODNAME}_OBJS) ${depends}
	${linker} -o \$@ \$^  \$(ALL_LIBPATH) \$(LDFLAGS) $LDFLAGS \$(REDIRECT_ERR)
${MODNAME}_OUTPUT=${mod_dir}/${OUT_EXE}
EOF
	 target="${mod_dir}/${OUT_EXE}"
     elif test "$OUT_LIB" != ""; then
	 cat <<EOF
${mod_dir}/${OUT_LIB}: \$(${MODNAME}_OBJS)  ${depends}
	ar rsu \$@ \$^
ALL_LIBPATH+=-L${mod_dir}
${MODNAME}_OUTPUT=${mod_dir}/${OUT_LIB}
EOF
	 target="${mod_dir}/${OUT_LIB}"
     fi

     if echo $SOURCES | grep '.l'>/dev/null ; then
	 LDFLAGS="$LDFLAGS -lfl"
     fi
     cat<<EOF

${mod_dir}/%.o: ${mod_dir}/%.c
	\$(CC) -o \$@ -c -I${mod_dir} \$(CFLAGS) \$(CPPFLAGS) $CFLAGS $CPPFLAGS \$< \$(REDIRECT_ERR)
${mod_dir}/%.o: ${mod_dir}/%.cpp
	\$(CXX) -o \$@ -c -I${mod_dir} \$(CXXFLAGS) \$(CPPFLAGS) $CXXFLAGS $CPPFLAGS \$< \$(REDIRECT_ERR)
${mod_dir}/%.c: ${mod_dir}/%.l
	flex --header-file=\$(patsubst %.l,%.flex.h,\$(${MODNAME}_LEX_SRCS)) --outfile=\$@ \$< \$(REDIRECT_ERR)

${MODNAME}_GEN_FILES=$target \$(${MODNAME}_LEX_GEN_SRCS) \$(${MODNAME}_OBJS)
${MODNAME}_GEN_SOURCES=\$(${MODNAME}_LEX_GEN_SRCS) ${gen_files}

ALL_GEN_FILES+=\$(${MODNAME}_GEN_FILES)
ALL_SOURCES+=\$(${MODNAME}_C_SRCS) \$(${MODNAME}_CXX_SRCS)
ALL_TARGETS+=$target
ALL_GEN_SOURCES+=\$(${MODNAME}_GEN_SOURCES)
DEPEND_INC+=-I${mod_dir}

${MODNAME}_clean:
	rm -f \$(${MODNAME}_GEN_FILES)

${POST_APPEND}

EOF
     cat >$mod_dir/Makefile <<EOF
all:
	make -C $PWD $target COMPILE_DIR="${mod_dir}"
clean:
	make -C $PWD ${MODNAME}_clean COMPILE_DIR="${mod_dir}"
redep:
	make -C $PWD redep COMPILE_DIR="${mod_dir}"
EOF

    )
done

module.shという名前で、

MODNAME=nanika
SOURCES='a.c b.c d.c'
OUT_EXE='a.out'

こういう感じのファイルを転がしておけば、(←ここらへんがautomakeより偉い。automakeはconfigure.inにMakefileの位置を書かないといけない)

# Do not edit. This file is generated by readmodule.sh

nanika_SOURCES=sub/a.c sub/b.c sub/d.c
nanika_LEX_SRCS=$(filter %.l,$(nanika_SOURCES))
nanika_LEX_GEN_SRCS=$(patsubst %.l,%.c,$(nanika_LEX_SRCS))
nanika_C_SRCS=$(filter %.c,$(nanika_SOURCES)) $(nanika_LEX_GEN_SRCS) $(patsubst %.l,%.flex.h,$(nanika_LEX_SRCS))
nanika_CXX_SRCS=$(filter %.cpp,$(nanika_SOURCES))
nanika_OBJS=$(patsubst %.c,%.o,$(nanika_C_SRCS)) $(patsubst %.cpp,%.o,$(nanika_CXX_SRCS))


ifeq ($(COMPILE_DIR),sub)
REDIRECT_ERR=2>&1 |sed -e 's|sub/||g'
endif
sub/a.out: $(nanika_OBJS) 
	$(CC) -o $@ $^  $(ALL_LIBPATH) $(LDFLAGS)  $(REDIRECT_ERR)
nanika_OUTPUT=sub/a.out

sub/%.o: sub/%.c
	$(CC) -o $@ -c -Isub $(CFLAGS) $(CPPFLAGS)   $< $(REDIRECT_ERR)
sub/%.o: sub/%.cpp
	$(CXX) -o $@ -c -Isub $(CXXFLAGS) $(CPPFLAGS)   $< $(REDIRECT_ERR)
sub/%.c: sub/%.l
	flex --header-file=$(patsubst %.l,%.flex.h,$(nanika_LEX_SRCS)) --outfile=$@ $< $(REDIRECT_ERR)

nanika_GEN_FILES=sub/a.out $(nanika_LEX_GEN_SRCS) $(nanika_OBJS)
nanika_GEN_SOURCES=$(nanika_LEX_GEN_SRCS) 

ALL_GEN_FILES+=$(nanika_GEN_FILES)
ALL_SOURCES+=$(nanika_C_SRCS) $(nanika_CXX_SRCS)
ALL_TARGETS+=sub/a.out
ALL_GEN_SOURCES+=$(nanika_GEN_SOURCES)
DEPEND_INC+=-Isub

nanika_clean:
	rm -f $(nanika_GEN_FILES)

こんな感じのを出力してくれます。
あと、automakeよりも良い点として、ディレクトリ深くなっても「入ります」「出ます」が一回ぐらいしか出ない。