源码分析
核心MakeFile
这个 Makefile
是一个复杂的构建脚本,用于管理和构建一个大型项目。它包括多个目标、条件判断和递归调用 make
命令来处理多个子项目和子目录。让我们逐部分进行详细解析。
伪目标和变量定义
.PHONY: all clean install build test init
-
.PHONY
目标声明了all
、clean
、install
、build
、test
和init
是伪目标,不对应实际文件。
PLATDIRS = newbuild so fantom share party www update var SIP-INSTALLROOT linux
CLEANDIRS = $(PLATDIRS) apps
-
PLATDIRS
和CLEANDIRS
是目录列表变量,用于后续的构建和清理操作。
模式规则
%.all :
cd $* && $(MAKE)
%.clean :
cd $* && $(MAKE) clean
%.build :
cd $* && $(MAKE) build
- 这三条规则定义了通用目标规则,对于目录列表中的每个目录,会进入该目录并执行相应的
make
目标(all
、clean
、build
)。
clean
目标
clean:
rm -rf $(BUILD)/fantom
make $(patsubst %, %.clean, $(CLEANDIRS))
-
clean
目标删除$(BUILD)/fantom
目录,并调用make
命令清理CLEANDIRS
列表中的每个目录。
平台预构建目标
build_plat_pre:
@chmod +x $(ROOT)/update/setbaseversion
@if [ ! -d $(BUILDROOT) ]; then mkdir -p $(BUILDROOT) ; fi
@if [ ! -d $(BUILDROOT)/newbuild ]; then mkdir -p $(BUILDROOT)/newbuild ; fi
@if [ ! -d $(BUILDROOT)/apps ]; then mkdir -p $(BUILDROOT)/apps ; fi
@if [ ! -d $(BUILDROOT)/bin ]; then mkdir -p $(BUILDROOT)/bin ; fi
@if [ ! -d $(BUILDROOT)/party ]; then mkdir -p $(BUILDROOT)/party ; fi
@if [ ! -d $(BUILDROOT)/share/lib ]; then mkdir -p $(BUILDROOT)/share/lib ; fi
@if [ ! -d $(BUILDROOT)/share/Python-2.7/lib ]; then mkdir -p $(BUILDROOT)/share/Python-2.7/lib ; fi
-
build_plat_pre
目标进行了一些预构建任务,包括设置文件权限和创建所需目录。
应用列表和目标
sis_apps_list = accessskeleton coengine dnsdetect ngfw saas secvisual server_anomaly super \
wskiller update secdetect dgadetect httpdetector scandetect beforehanddetect \
cloud_report webshelldetect wxscandetect brutedetect dosdetect netflow_forensic smbdetect \
mailector secevent sec_dnsdetect sec_httpdetect sec_maildetect sec_netdetect sec_secdetect \
sec_smbdetect sec_tidnsdetect sec_tihttpdetect sec_tiipdetect sec_thirdparty infoshare monitor \
sec_filedetect sec_threatdetect documents agent
ifndef NO_SECLIB
sis_apps_list += seclib
endif
SISAPPS = $(patsubst %, apps/%, $(sis_apps_list))
-
sis_apps_list
定义了一个应用列表,包含多个应用名。 - 如果未定义
NO_SECLIB
,则将seclib
添加到应用列表中。 -
SISAPPS
将sis_apps_list
转换为带有apps/
前缀的格式。
平台打包前置任务
plat_sis_pre:
@python $(ROOT)/apps/super/plat/plat.py $(ROOT)/apps/super/plat/sis/plugins.conf
-
plat_sis_pre
目标运行一个 Python 脚本,用于配置或预处理。
平台打包
plat_sis: plat_sis_pre plat_fantom $(SISAPPS:=.build)
-
plat_sis
目标依赖于plat_sis_pre
、plat_fantom
和所有SISAPPS
的.build
目标。
云平台应用列表和目标
cloud_apps_list = super cloud_report
CLOUDAPPS = $(patsubst %, apps/%, $(cloud_apps_list))
-
cloud_apps_list
定义了云平台的应用列表。 -
CLOUDAPPS
将cloud_apps_list
转换为带有apps/
前缀的格式。
plat_cloud_pre:
@python $(ROOT)/apps/super/plat/plat.py $(ROOT)/apps/super/plat/cloud/plugins.conf
-
plat_cloud_pre
目标运行一个 Python 脚本,用于云平台的预处理。
plat_cloud: plat_cloud_pre plat_fantom $(CLOUDAPPS:=.build)
-
plat_cloud
目标依赖于plat_cloud_pre
、plat_fantom
和所有CLOUDAPPS
的.build
目标。
平台基础内容打包
plat_fantom: build_plat_pre $(PLATDIRS:=.build)
@cd $(BUILD) && tar -czf fantom.tar.gz fantom
-
plat_fantom
目标依赖于build_plat_pre
和所有PLATDIRS
的.build
目标。 - 它会进入
$(BUILD)
目录并将fantom
目录打包成fantom.tar.gz
。
应用打包预处理
build_apps_pre:
@if [ ! -d "$(BUILDROOT)/apps" ]; then mkdir -p "$(BUILDROOT)/apps" ; fi
-
build_apps_pre
目标确保$(BUILDROOT)/apps
目录存在。
应用打包
plat_apps: build_apps_pre
ifdef NAME
@if [ -d $(ROOT)/apps/$(NAME) ]; then \
cd "$(ROOT)/apps/$(NAME)" && make build; \
cd "$(ROOT)/update" && make build; \
cd $(BUILD)/fantom/apps/ && tar -czf $(NAME).tar.gz $(NAME); \
mv $(NAME).tar.gz $(BUILD);\
else \
echo "App $(NAME) not exists"; \
fi
else
endif
-
plat_apps
目标依赖于build_apps_pre
。 -
如果定义了
NAME
变量并且$(ROOT)/apps/$(NAME)
目录存在,则- 进入
$(ROOT)/apps/$(NAME)
并执行make build
。 - 进入
$(ROOT)/update
并执行make build
。 - 将
$(BUILD)/fantom/apps/$(NAME)
目录打包成$(NAME).tar.gz
,并移动到$(BUILD)
目录。
- 进入
-
如果
$(ROOT)/apps/$(NAME)
目录不存在,则输出错误信息。
总结
这个 Makefile
用于构建和打包一个复杂的项目,包含多个应用和平台组件。它通过定义变量和模式规则来管理不同的构建任务,并使用条件判断和递归调用 make
命令来处理各个子目录和应用的构建过程。
php
TYPE = dir
ifdef NO_SECLIB
dirs := $(shell find . -maxdepth 1 -path ./seclib -prune -o -type d -print)
else
dirs := $(shell find . -maxdepth 1 -type d)
endif
dirs := $(basename $(patsubst ./%,%,$(dirs)))
SUBDIRS = $(dirs)
include $(MAKEFILEDIR)/Makefile.$(TYPE)
这个 Makefile
代码片段通过使用条件和 shell 命令来动态生成子目录列表,并根据一个特定的类型包含相应的 Makefile
。让我们逐行解析这个 Makefile
片段
代码解析
TYPE = dir
- 这行定义了一个变量
TYPE
,其值为dir
。这个变量在后续的include
语句中被使用。
ifdef NO_SECLIB
dirs := $(shell find . -maxdepth 1 -path ./seclib -prune -o -type d -print)
else
dirs := $(shell find . -maxdepth 1 -type d)
endif
-
这里使用了条件判断
ifdef
来检测是否定义了NO_SECLIB
变量。 -
如果定义了
NO_SECLIB
,则执行第一条命令dirs := $(shell find . -maxdepth 1 -path ./seclib -prune -o -type d -print)
- 这条命令使用
find
命令查找当前目录(不包括子目录)的所有目录,但排除了./seclib
目录。 -
-maxdepth 1
限制查找深度为当前目录。 -
-path ./seclib -prune
用于排除./seclib
目录。 -
-o -type d -print
查找类型为目录并打印路径。
- 这条命令使用
-
否则(如果未定义
NO_SECLIB
),则执行第二条命令dirs := $(shell find . -maxdepth 1 -type d)
- 这条命令使用
find
命令查找当前目录(不包括子目录)的所有目录。
- 这条命令使用
dirs := $(basename $(patsubst ./%,%,$(dirs)))
-
这行代码使用了
patsubst
和basename
函数对dirs
变量进行处理-
$(patsubst ./%,%,$(dirs))
移除每个目录路径前面的./
前缀。 -
$(basename $(patsubst ./%,%,$(dirs)))
进一步处理每个目录路径,只保留目录名称。
-
SUBDIRS = $(dirs)
- 将处理后的目录列表赋值给变量
SUBDIRS
。
include $(MAKEFILEDIR)/Makefile.$(TYPE)
- 包含另一个
Makefile
文件。文件的路径和名称由$(MAKEFILEDIR)/Makefile.$(TYPE)
决定。-
$(MAKEFILEDIR)
是另一个变量,通常在其他地方定义,用于指定Makefile
文件所在的目录。 -
$(TYPE)
变量的值为dir
,所以这行等价于include $(MAKEFILEDIR)/Makefile.dir
。
-
总结
这个 Makefile
片段的目的是
- 动态生成当前目录下的子目录列表,并处理排除某些特定目录(如
seclib
)。 - 处理目录路径,将它们标准化为不带
./
前缀的格式。 - 将处理后的目录列表赋值给
SUBDIRS
变量。 - 根据
TYPE
变量的值,包含另一个Makefile
文件,便于分层和模块化管理构建过程。
通过这种方式,可以根据不同的条件动态调整构建过程,灵活应对各种需求和依赖关系。
python
TYPE = app
SUBDIRS =
.PHONY: build clean
appversion=`date "+%Y%m%d/%H:%M:%S"`
build:
@find ./appserver -name .svn | xargs rm -rf
@find ./bin -name .svn | xargs rm -rf
@find ./default -name .svn | xargs rm -rf
@find ./lib -name .svn | xargs rm -rf
@find ./local -name .svn | xargs rm -rf
@find ./var -name .svn | xargs rm -rf
@find ./meta-info -name .svn | xargs rm -rf
@rwini -w -s info -k version -f libinfo -v $(appversion)
@mkdir -p ./patch0/$(notdir $(CURDIR))
@mv -f ./appserver ./patch0/$(notdir $(CURDIR))/appserver
@mv -f ./bin ./patch0/$(notdir $(CURDIR))/bin
@mv -f ./default ./patch0/$(notdir $(CURDIR))/default
@mv -f ./lib ./patch0/$(notdir $(CURDIR))/lib
@mv -f ./local ./patch0/$(notdir $(CURDIR))/local
@mv -f ./var ./patch0/$(notdir $(CURDIR))/var
@cp -rf ./libinfo ./patch0/$(notdir $(CURDIR))/libinfo
@cp -rf ./meta-info/update ./patch0
@cp -rf ./meta-info ./patch0/$(notdir $(CURDIR))/meta-info
@zip -r -q $(notdir $(CURDIR)).zip patch0 libinfo meta-info
@rm -rf ./libinfo
@rm -rf ./meta-info
@rm -rf ./patch0
@if [ ! -d "$(BUILDROOT)/apps/$(notdir $(CURDIR))" ]; then mkdir -p "$(BUILDROOT)/apps/$(notdir $(CURDIR))" ; fi
@rsync -r . "$(BUILDROOT)/apps/$(notdir $(CURDIR))" --exclude="Makefile" --exclude='.svn/'
clean:
@rm -f $(notdir $(CURDIR)).zip
这个 Makefile
定义了两个主要目标build
和 clean
。它主要用于清理项目目录中的 .svn
文件夹、更新版本信息、组织项目文件,并将其打包成压缩文件。下面是对每一部分的详细解析
变量和伪目标
TYPE = app
SUBDIRS =
.PHONY: build clean
-
TYPE = app
定义了一个变量TYPE
,其值为app
。虽然在这个Makefile
中没有进一步使用,但它可以用来在包含的其他Makefile
中使用。 -
SUBDIRS =
定义了一个空的SUBDIRS
变量。在这个Makefile
中没有实际使用。 -
.PHONY: build clean
声明了两个伪目标build
和clean
,这表示这些目标不是实际的文件名,而是任务名称。
版本信息
appversion=`date "+%Y%m%d/%H:%M:%S"`
-
appversion
变量用来保存当前的日期和时间,格式为YYYYMMDD/HH:MM:SS
。这个变量会用于更新版本信息。
build 目标
build:
@find ./appserver -name .svn | xargs rm -rf
@find ./bin -name .svn | xargs rm -rf
@find ./default -name .svn | xargs rm -rf
@find ./lib -name .svn | xargs rm -rf
@find ./local -name .svn | xargs rm -rf
@find ./var -name .svn | xargs rm -rf
@find ./meta-info -name .svn | xargs rm -rf
@rwini -w -s info -k version -f libinfo -v $(appversion)
@mkdir -p ./patch0/$(notdir $(CURDIR))
@mv -f ./appserver ./patch0/$(notdir $(CURDIR))/appserver
@mv -f ./bin ./patch0/$(notdir $(CURDIR))/bin
@mv -f ./default ./patch0/$(notdir $(CURDIR))/default
@mv -f ./lib ./patch0/$(notdir $(CURDIR))/lib
@mv -f ./local ./patch0/$(notdir $(CURDIR))/local
@mv -f ./var ./patch0/$(notdir $(CURDIR))/var
@cp -rf ./libinfo ./patch0/$(notdir $(CURDIR))/libinfo
@cp -rf ./meta-info/update ./patch0
@cp -rf ./meta-info ./patch0/$(notdir $(CURDIR))/meta-info
@zip -r -q $(notdir $(CURDIR)).zip patch0 libinfo meta-info
@rm -rf ./libinfo
@rm -rf ./meta-info
@rm -rf ./patch0
@if [ ! -d "$(BUILDROOT)/apps/$(notdir $(CURDIR))" ]; then mkdir -p "$(BUILDROOT)/apps/$(notdir $(CURDIR))" ; fi
@rsync -r . "$(BUILDROOT)/apps/$(notdir $(CURDIR))" --exclude="Makefile" --exclude='.svn/'
清理 .svn
文件夹
- 使用
find
命令查找并删除各个目录下的.svn
文件夹,这些文件夹是 Subversion (SVN) 版本控制系统的目录,不需要打包到最终的发布版本中。
更新版本信息
- 使用
rwini
命令更新libinfo
文件中的版本信息,rwini
是一个假设的工具,用于写入 INI 文件格式中的值。具体操作是设置[info]
节点中的version
键为当前时间。
组织项目文件
- 创建一个名为
patch0
的目录,并将各个子目录(如appserver
、bin
、default
、lib
、local
、var
)移动到patch0/$(notdir $(CURDIR))
中。-
$(notdir $(CURDIR))
获取当前目录的名称(不包括路径),例如,如果当前目录是/home/user/project
,则$(notdir $(CURDIR))
会得到project
。
-
复制和压缩文件
- 将
libinfo
和meta-info
目录复制到patch0
下的相应位置。 - 使用
zip
命令将patch0
、libinfo
和meta-info
压缩成一个 zip 文件,名称为当前目录名称加.zip
(例如project.zip
)。 - 删除
libinfo
、meta-info
和patch0
目录。
同步文件
- 如果
$(BUILDROOT)/apps/$(notdir $(CURDIR))
目录不存在,则创建它。 - 使用
rsync
命令将当前目录的内容(除了Makefile
和.svn
文件夹)同步到$(BUILDROOT)/apps/$(notdir $(CURDIR))
目录。
clean 目标
clean:
@rm -f $(notdir $(CURDIR)).zip
- 删除以当前目录名称命名的 zip 文件(例如
project.zip
)。
总结
- 这个
Makefile
主要用于清理项目目录中的.svn
文件夹,更新版本信息,组织和打包项目文件,并将其同步到一个特定的构建目录。 -
build
目标执行了所有这些步骤,而clean
目标仅删除生成的 zip 文件。 - 使用了 shell 命令和
rwini
工具来处理文件和目录,动态生成版本信息,并打包和同步项目文件。