shell脚本自动生成makefile

33 篇文章 0 订阅
5 篇文章 0 订阅

效果展示

生成的makefile是这样的效果:

# automake version 1.0
CC  = gcc
BIN = pkg
OBJ = pkg.o
LIB = 
INC = 
FLAGS = $(INC) -Wall

pkg: $(OBJ)
	$(CC) $(OBJ) -o $(BIN) $(LIB)
pkg.o: pkg.c err.h color.h
	$(CC) -c pkg.c -o pkg.o $(FLAGS)

.PHONY: clean
clean:
	rm $(OBJ) $(BIN)

使用方法

  • 会在当前路径下生成名为makefile的文件。
  • 会编译当前目录下所有.c文件,自动处理依赖关系(额外库(LIB)和头文件路径(INC)要手动添加)。
  • 额外库(LIB)和头文件路径(INC)会留空,不需要请手动移除对应代码(FLAGS变量中的$(INC)、链接命令中的的$(LIB))。
$automake
Usage: automake <target.c>
$automake pkg.c
Succeed!

target.c是你的main()函数所在.c文件,生成的可执行程序名为main()所在.c文件的文件名去掉后缀名。

源代码

#!/bin/bash

RED="\033[0;31m"
GREEN="\033[0;32m"
NONE="\033[0m"

if	[ $# != 1 ]
then
	printf "${RED}Usage: automake <target.c>\n${NONE}"
	exit 0
fi

makefile="makefile"
target=$(echo $1|sed 's/.c$//g')
allCFiles=$(ls *.c)

#needCFiles="$(gcc -MM ${target}.c | grep -o '\S*\.c')"
needCFiles=${allCFiles}

OBJ=$(echo ${needCFiles} | sed 's/\.c/\.o/g')
INC=""
CC="gcc"
LIB=""
BIN=${target}
FLAGS="-Wall"

echo 	"# automake version 1.0"	> 	${makefile}
echo 	"CC  = ${CC}"				>> 	${makefile}
echo 	"BIN = ${BIN}" 				>> 	${makefile}
echo 	"OBJ = ${OBJ}"				>>	${makefile}
echo 	"LIB = ${LIB}" 				>> 	${makefile}
echo 	"INC = ${INC}" 				>> 	${makefile}
echo 	"FLAGS = \$(INC) ${FLAGS}" 	>> 	${makefile}
echo 	"" 							>>	${makefile}

echo "${target}: \$(OBJ)" >> ${makefile}
echo -e "\t\$(CC) \$(OBJ) -o \$(BIN) \$(LIB)" >> ${makefile}
for file in ${needCFiles}
do
	echo $(gcc -MM ${file}) >> ${makefile}
	file=$(echo ${file} | sed 's/.c//g')
	echo -e "\t\$(CC) -c ${file}.c -o ${file}.o \$(FLAGS)" >> ${makefile}
done

echo ""							>> ${makefile}
echo ".PHONY: clean"			>> ${makefile}
echo "clean:"					>> ${makefile}
echo -e "\trm \$(OBJ) \$(BIN)"	>> ${makefile}

printf "${GREEN}Succeed!\n${NONE}"

改进版

$automake
Usgae: automake <main C file> [options] [file]...
Options:
  -e <excluded files>
		Exclude the files from makefile.
  -o <outfile>
		Specify the outfile.
  -n
		Do not add @ before cmd, which forbid echo of makefile.

增加了三个参数:

  • -e可以在生成makefile时添加排除选项。
  • -o指定makefile文件名。
  • -n开启makefile命令回显。
#!/bin/bash
version='1.0'

RED="\033[0;31m"
GREEN="\033[0;32m"
YELLOW="\033[0;33m"
LYELLOW="\033[1;33m"
NONE="\033[0m"
usage="${YELLOW}\
Usgae: automake <main C file> [options] [file]...
Options:
  -e <excluded files>
		Exclude the files from makefile.
  -o <outfile>
		Specify the outfile.
  -n
		Do not add @ before cmd, which forbid echo of makefile.\n${NONE}"

#print C source file names n current path and return 0.
# 	args:	none
#	return:	0
#	example:	find_source_files
find_source_files()	
{
	filename_end_with_point_c=$(ls | grep ".*\.c")
	sourceFiles=""
	for file in ${filename_end_with_point_c}
	do
		if [ -f ${file} ]
		then
			index=${#sourceFiles[*]}
			sourceFiles[$index]=${file}
		fi
	done
	printf "${sourceFiles[*]}"
	return 0
}
#	print	exchange suffix and print
#	args:	filenames,	old suffix,	new suffix
#	return:	0
#	example:	exchange_suffix	"1.c 2.c 3.c"	.c	.o
#				exchange_suffix	"1.c 2.c 3.c"	".c" '.o'
exchange_suffix()
{
	if	[ $# -ne 3 ]
	then
		return -1
	fi
	file_names=$1
	old_suffix=$(echo $2|sed 's/\./\\\./g')
	new_suffix=$(echo $3|sed 's/\./\\\./g')
	exchaned=""
	for name in ${file_names}
	do
		name=$(echo ${name} | sed "s/${old_suffix}/${new_suffix}/g")
		index=${#exchanged[*]}
		exchanged[$index]="${name}"
	done
	printf	"${exchanged[*]}"
	return 0
}
main()
{
	if	[ $# -eq 0 ]
	then
		printf "${usage}"
		exit 0
	fi
	
	if	[ ! -f $1 ]
	then
		printf "${YELLOW}Invalid main C file.${NONE}\n"
		exit 0
	fi
	main_c_file="/tmp/main_c_file"
	echo -n "$1" > ${main_c_file}
	shift
	excluded_files="/tmp/excluded_files"
	outfile="/tmp/outfile"
	cmd_echo="true"
	is_finding_excluded_files="false"
	echo -n "" > ${excluded_files}
	echo -n "" > ${outfile}
	while [ $# -ne 0 ]
	do		
		OPTIND=1
		if getopts "e:o:nv" option
		then
			case "$option"
			in
				e)	echo ${OPTARG} >> ${excluded_files}
					shift 2
					is_finding_excluded_files="true";;
				o)	echo ${OPTARG} >> ${outfile}
					shift 2
					is_finding_excluded_files="false";;
				n)	cmd_echo="false"
					shift
					is_finding_excluded_files="false";;
				?)	printf	"${usage}"
					exit 0;;
			esac
		fi
		
		if [ $# -eq 0 ]
		then
			break
		fi
			
		if	[ "$(echo "N$1"|grep -o 'N-')" != "N-" ]
		then
			if [ $is_finding_excluded_files == "true" ]
			then
				echo $1 >> ${excluded_files}
				shift
			else
				printf	"${usage}"
				exit 0
			fi
		fi
		done
	
	makefile="makefile"
	if [ "$(cat $outfile)" != "" ]
	then
		makefile="$(cat $outfile)"
	fi
	all_source_files="/tmp/all_source_files"
	echo -n "" > "$all_source_files"
	for file in $(find_source_files)
	do
		echo "$file" >> "$all_source_files"
	done
	same_files="/tmp/same_files"
	tmp_file="/tmp/tmp_file"
	echo -n "" > ${same_files}
	for file in $(cat ${all_source_files} ${excluded_files}|sort|uniq -d)
	do
		echo ${file} >> ${same_files}
	done
	for file in $(cat ${same_files})
	do
		grep "${file}" -v ${all_source_files} > ${tmp_file}
		mv ${tmp_file} ${all_source_files}
	done
	sourceFiles="$(cat ${all_source_files})"
	
	if [ $cmd_echo == "true" ]
	then
		cmd_echo="@"
	else
		cmd_echo=""
	fi

	OBJ=$(exchange_suffix "${sourceFiles}" .c .o)
	CC="gcc"
	INC=""
	LIB=""
	BIN="$(exchange_suffix "$(cat ${main_c_file})" '.c' '')"
	FLAGS="-Wall"

	echo 	"CC  = ${CC}"				> 	${makefile}
	echo 	"BIN = ${BIN}" 				>> 	${makefile}
	echo 	"OBJ = ${OBJ}"				>>	${makefile}
	echo 	"LIB = ${LIB}" 				>> 	${makefile}
	echo 	"INC = ${INC}" 				>> 	${makefile}
	echo 	"FLAGS = \$(INC) ${FLAGS}" 	>> 	${makefile}
	echo 	"" 							>>	${makefile}

	echo "${BIN}: \$(OBJ)" >> ${makefile}
	echo -e "\t${cmd_echo}\$(CC) \$(OBJ) -o \$(BIN) \$(LIB)" >> ${makefile}
	for file in ${sourceFiles}
	do
		rule=$(gcc -MM ${file})
		echo "${rule}" >> ${makefile}
		file=$(exchange_suffix "${file}" '.c' '')
		cmd="\t${cmd_echo}\$(CC) -c ${file}.c -o ${file}.o \$(FLAGS)"
		echo -e ${cmd} >> ${makefile}
	done

	echo ""							>> ${makefile}
	echo ".PHONY: clean"			>> ${makefile}
	echo "clean:"					>> ${makefile}
	printf  "\t${cmd_echo}rm \$(OBJ) \$(BIN)"	>> ${makefile}

	printf "${LYELLOW}Succeed!\n${NONE}"
}

main $*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

barbyQAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值