一种基于Makefile的编译系统架构实现及自动化

一.     我分享的是一个简化版的编译架构,我要实现的目标是:对遵循以下组织结构的文件夹进行编译:

     bb_xxx

          _inc

          _src

               entry

                     ………

               modules

                     module1

                          ………

                     module2

                          ………

                     ………

_src目录下可以允许有递归目录或者文件,最大深度不超过5,Makefile定义规则会去自动搜索所有的c源文件,编译出的所有.o文件会生成在out/obj目录,可执行文件会生成在out/bin目录

通常Makefile可能需要这样写:

rm=/bin/rm -f

CC= gcc

DEFS=

PROGNAME= out/bin/test

INCLUDES=  -I./_inc

LIBS=

 

DEFINES= $(INCLUDES) $(DEFS)-DSYS_UNIX=1

CFLAGS= -g $(DEFINES)

 

 

SRCS = src/entry/entry.csrc/modules/ module1/Mytest.c src/modules/module2/test.c

OBJS = out/obj/entry.oout/obj/Mytest.o out/obj/test.o

 

all: $(PROGNAME)

 

$(PROGNAME) : $(OBJS)

       $(CC) $(CFLAGS) -o $(PROGNAME) $(OBJS) $(LIBS)

 

out/obj/%.o:src/entry/%.c

       $(CC) $(CFLAGS) -c $< -o $@

out/obj/%.o:src/modules/module1/%.c

       $(CC) $(CFLAGS) -c $< -o $@

out/obj/%.o:src/modules/module2/%.c

       $(CC) $(CFLAGS) -c $< -o $@

 

clean:

       $(rm)$(OBJS) $(PROGNAME) core *~

 

虽然以上Makefile也可以工作,但是扩展性不佳,如果_src目录下将来需要加入更多module或者其他代码,就需要修改Makefile里面的SRCS以及依赖关系,假如_src目录很深,底下的文件众多,这个工作量可能比较繁琐

二、

              再看看下面的Makefile:

     # Created with mak.pl v0.1 on FriMay 26 19:43:38 2017

rm=/bin/rm -f

CC= gcc

DEFS=

PROGNAME= out/bin/test

INCLUDES=  -I./_inc

LIBS=

 

DEFINES= $(INCLUDES) $(DEFS)-DSYS_UNIX=1

CFLAGS= -g $(DEFINES)

 

SRCS_DIR = $(shell find _src -maxdepth 5 -type d)

OBJS_DIR = out/obj

 

SRCS = $(foreach d,$(SRCS_DIR),$(wildcard $(d)/*.c))

OBJS = $(addprefix$(OBJS_DIR)/,$(patsubst%.c,%.o,$(notdir $(SRCS))))

 

all: $(PROGNAME)

 

$(PROGNAME) : $(OBJS)

       $(CC) $(CFLAGS) -o $(PROGNAME) $(OBJS) $(LIBS)

 

define make-object

$1:$2

       $(CC) $(CFLAGS) -c $$< -o $$@

endef

 

$(foreach d,$(SRCS_DIR),$(eval $(callmake-object,$(OBJS_DIR)/%.o,$(d)/%.c)))

 

clean:

       $(rm) $(OBJS) $(PROGNAME) core *~

 

通过定义自己的规则,即使源码目录发生改变,Makefile也不需要做修改,达到增强扩展性的目的.大家有兴趣可以看看BASA编译体系里面的project.mk,它定义的规则更加复杂和庞大

三、

实现Makefile自动生成,以上Makefile可以通过一个perl脚本自动生成,执行run.sh即可(请参考附件),以下是run.sh脚本的内容:

#!/bin/sh

if [ ! -d "out"];then

mkdir -p out/bin

mkdir -p out/obj

fi

PROGNAME=hsm_test

./mak.pl --app=$PROGNAME _src >Makefile

 

其中--app选项定义生成的可执行文件名,_src指定存放源码的目录(其实源码目录也可以是其他名称而不局限于”_src”)

run.sh

#!/bin/sh
if [ ! -d "out" ];then
mkdir -p out/bin
mkdir -p out/obj
fi
PROGNAME=hsm_test
./mak.pl --app=$PROGNAME _src > Makefile
mak.pl

#!/usr/bin/perl

use strict;
use Getopt::Long;
$|=1;

my ($g_app,$g_help)='';

my %g_op=();

## Unix application template follows
my $g_unix_app_template=<<EOF;
# -=VERSION=-
rm=/bin/rm -f
CC= gcc 
DEFS=  
PROGNAME= -=PROG=-
INCLUDES=  -I./_inc
LIBS=

DEFINES= \$(INCLUDES) \$(DEFS) -DSYS_UNIX=1
CFLAGS= -g \$(DEFINES)

SRCS_DIR = \$(shell find -=SRCS=- -maxdepth 5 -type d)
OBJS_DIR = out/obj

SRCS = \$(foreach d,\$(SRCS_DIR),\$(wildcard \$(d)/*.c))
OBJS = \$(addprefix \$(OBJS_DIR)/,\$(patsubst %.c,%.o,\$(notdir \$(SRCS))))

all: \$(PROGNAME)

\$(PROGNAME) : \$(OBJS)
	\$(CC) \$(CFLAGS) -o \$(PROGNAME) \$(OBJS) \$(LIBS)

define make-object
\$1:\$2
	\$(CC) \$(CFLAGS) -c \$\$< -o \$\$@
endef

\$(foreach d,\$(SRCS_DIR),\$(eval \$(call make-object,\$(OBJS_DIR)/%.o,\$(d)/%.c)))

clean:
	\$(rm) \$(OBJS) \$(PROGNAME) core *~
EOF
;

my $argc=$#ARGV+1;

my %g_options=(
    "app=s"     =>\$g_op{app},
    "help"      =>\$g_help,
);
&do_it();
# show usage and exit
sub usage
{
    print<<EOF;
    gm.pl v0.1
    A program to generate simple Makefiles for Linux/Unix

    $0 [options]
    Where the options include:
    --app=name  generate Makefile for an application

Example:
    $0 --app=myapp  > Makefile

EOF
;
    exit(1);
}

##-----
# do everything and exit
##-----
sub do_it
{

    my $result=GetOptions(%g_options);

    $g_app=$g_op{app};

    if ($g_app)
    {
        $argc--;
    	&gen_unix_makefile();
    	exit(0);
    }

    &usage();
}

# generate Makefile for Linux/Unix
sub gen_unix_makefile
{
        my $date=localtime(time());
        my $created="Created with mak.pl v0.1 on $date";
        my $i;
    	my $srcs='';
        for ($i=0; $i < $argc; $i++)
        {
            $srcs .= "$ARGV[$i] ";
        }

        $g_unix_app_template =~ s/-=PROG=-/out\/bin\/$g_app/g;
        $g_unix_app_template =~ s/-=VERSION=-/$created/g;
        $g_unix_app_template =~ s/-=SRCS=-/$srcs/g;
        $g_unix_app_template =~ s/-=CC=-/cc/g;
        print $g_unix_app_template;
}




猜你喜欢

转载自blog.csdn.net/melody157398/article/details/72778183