一种基于Makefile的编译系统架构实现及自动化
2017-05-27 09:08
543 查看
一. 我分享的是一个简化版的编译架构,我要实现的目标是:对遵循以下组织结构的文件夹进行编译:
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 > Makefilemak.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;
}
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 > Makefilemak.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;
}
相关文章推荐
- [转]一种基于智能卡登录Windows系统的实现方式
- 跨国际链路的数据服务系统架构设计的一种实现思路
- 在linux上搭建基于ant的android自动化编译系统
- python文件编译成so介绍 - 2.使用makefile将py文件编译成so文件并制作成rpm包,实现自动化
- 基于IMS架构的IPTV系统实现分析
- 基于Struts2,Spring4,Hibernate4框架的系统架构设计与示例系统实现
- 基于Java设计和实现系统的自动化巡检
- 一种基于EF+MVC的小型系统快速开发架构
- Postfix-2.11+Dovecot-2.0.9+MySQL+Cyrus-sasl+Extmail-1.2实现基于虚拟用户的邮件系统架构 推荐
- 基于Ado.net Entity Framework 通过系统运行时动态编译实现数据表字段的增删
- 一种基于WiFi的室内定位系统设计与实现 _RFID世界网
- 实现基于虚拟用户的邮件系统架构
- Postfix-2.11+Dovecot-2.0.9+MySQL+Nginx+Cyrus-sasl+Extmail-1.2实现基于虚拟用户的邮件系统架构
- 一种完全基于开源实现的SOA架构
- Postfix+Dovecot+MySQL+Cyrus-sasl+Extmail实现基于虚拟用户的邮件系统架构
- 基于整合了struts 和hibernate 的j2ee 架构的用户权限管理系统的设计与实现
- 基于B/S模式的公安办公自动化系统权限管理设计与实现
- 基于PXE实现自动化安装系统
- 基于SOA的设备智能维护系统架构设计及实现
- Linux基于PXE实现系统自动化部署