构建工程化:多种不同的工程体系如何编写MakeFile

源码分析

核心MakeFile

这个 Makefile 是一个复杂的构建脚本,用于管理和构建一个大型项目。它包括多个目标、条件判断和递归调用 make 命令来处理多个子项目和子目录。让我们逐部分进行详细解析。

伪目标和变量定义

.PHONY: all clean install build test init
  • .PHONY 目标声明了 allcleaninstallbuildtestinit 是伪目标,不对应实际文件。
PLATDIRS = newbuild so fantom share party www update var SIP-INSTALLROOT linux
CLEANDIRS = $(PLATDIRS) apps
  • PLATDIRSCLEANDIRS 是目录列表变量,用于后续的构建和清理操作。

模式规则

%.all :cd $* && $(MAKE)
%.clean :cd $* && $(MAKE) clean
%.build :cd $* && $(MAKE) build
  • 这三条规则定义了通用目标规则,对于目录列表中的每个目录,会进入该目录并执行相应的 make 目标(allcleanbuild)。

clean 目标

clean:rm -rf $(BUILD)/fantommake $(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 添加到应用列表中。
  • SISAPPSsis_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_preplat_fantom 和所有 SISAPPS.build 目标。

云平台应用列表和目标

cloud_apps_list = super cloud_report
CLOUDAPPS = $(patsubst %, apps/%, $(cloud_apps_list))
  • cloud_apps_list 定义了云平台的应用列表。
  • CLOUDAPPScloud_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_preplat_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 = dirifdef NO_SECLIB
dirs := $(shell find . -maxdepth 1 -path ./seclib -prune -o -type d -print)
else
dirs := $(shell find . -maxdepth 1 -type d)
endifdirs := $(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)))
  • 这行代码使用了 patsubstbasename 函数对 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 = appSUBDIRS =.PHONY: build cleanappversion=`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 定义了两个主要目标
buildclean。它主要用于清理项目目录中的 .svn 文件夹、更新版本信息、组织项目文件,并将其打包成压缩文件。下面是对每一部分的详细解析

变量和伪目标

TYPE = app
SUBDIRS =
.PHONY: build clean
  • TYPE = app
    定义了一个变量 TYPE,其值为 app。虽然在这个 Makefile 中没有进一步使用,但它可以用来在包含的其他 Makefile 中使用。
  • SUBDIRS =
    定义了一个空的 SUBDIRS 变量。在这个 Makefile 中没有实际使用。
  • .PHONY: build clean
    声明了两个伪目标 buildclean,这表示这些目标不是实际的文件名,而是任务名称。

版本信息

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 的目录,并将各个子目录(如 appserverbindefaultliblocalvar)移动到 patch0/$(notdir $(CURDIR)) 中。
    • $(notdir $(CURDIR)) 获取当前目录的名称(不包括路径),例如,如果当前目录是 /home/user/project,则 $(notdir $(CURDIR)) 会得到 project
复制和压缩文件
  • libinfometa-info 目录复制到 patch0 下的相应位置。
  • 使用 zip 命令将 patch0libinfometa-info 压缩成一个 zip 文件,名称为当前目录名称加 .zip(例如 project.zip)。
  • 删除 libinfometa-infopatch0 目录。
同步文件
  • 如果 $(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 工具来处理文件和目录,动态生成版本信息,并打包和同步项目文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/41755.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

依赖注入的优点、解决的问题以及其底层原理和逻辑

依赖注入(Dependency Injection, DI)是一种设计模式,用于实现控制反转(Inversion of Control, IoC)。它通过将对象的依赖关系从类内部转移到外部配置或注入,从而提高代码的可维护性、可测试性和可扩展性。以…

使用Spring Boot和Apache Camel集成第三方服务

使用Spring Boot和Apache Camel集成第三方服务 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨如何利用Spring Boot和Apache Camel来集成第三方服…

pycharm如何使用jupyter

目录 配置jupyter新建jupyter文件别人写的方法(在pycharm种安装,在网页中使用) pycharm专业版 配置jupyter 在pycharm终端启动一个conda虚拟环境,输入 conda install jupyter会有很多前置包需要安装: 新建jupyter…

一文理清LK光流

举出几种光流方法,说明LK光流的建模方式? 光流方法是用于估计图像序列中像素点运动的技术,广泛应用于计算机视觉和视频处理领域。以下是几种常见的光流方法: Lucas-Kanade (LK) 方法: 一种基于局部窗口的光流估计方法…

代理IP在未来将面临哪些挑战?

今天我们来聊聊代理IP在未来可能会面临的挑战。虽然代理IP技术目前应用广泛,但随着科技的发展和网络环境的变化,代理IP也将面临一些新的挑战。让我们一起来看看这些挑战是什么吧! 1. 更严格的网络封锁和检测 现代社会各行各业都在飞速发展&…

可变参数 Collections 不可变集合 Stream流

目录 1.可变参数: 2.Collections: 3.不可变集合: 4.Stream流: 1、什么是流 2、如何生成流 1.单列集合获取Stream流 2.双列集合获取Stream流 3.数组获取Stream流: 4.一堆零散数据: Stream接口中的静态方法 3.Stream流的…

解决分布式环境下session共享问题

在分布式环境下,session会存在两个问题 第一个问题:不同域名下,浏览器存储的jsessionid是没有存储的。比如登录时认证服务auth.gulimall.com存储了session,但是搜索服务search.gulimall.com是没有这个session的; 第二个问题&…

基于SpringBoot的校园台球厅人员与设备管理系统

本系统是要设计一个校园台球厅人员与设备管理系统,这个系统能够满足校园台球厅人员与设备的管理及用户的校园台球厅人员与设备管理功能。系统的主要功能包括首页、个人中心、用户管理、会员账号管理、会员充值管理、球桌信息管理、会员预约管理、普通预约管理、留言…

【SSRF】

SSRF (Server-Side Request Forgery 服务端请求伪造) 文章目录 0x01 是什么?0x02 怎么判断是否存在SSRF漏洞?0x03 防御0x04 绕过手段 0x01 是什么? 是什么?   答:攻击者构造请求,…

w3wp.exe 中发生未处理的 Microsoft ,NETFramework 异常。

🏆本文收录于「Bug调优」专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&…

Spring 6.1.10版本源码编译

每篇一句 我们对时间的感知其实非常主观,我们越习惯于我们的生活方式,生活里面的新鲜感就越少,我们对时间 的感知就越快,生命就越短。 1.源码下载 进入Spring官网 https://spring.io/ 按照上图步骤进入如下Spring Framework链…

罗剑锋的C++实战笔记学习(二):容器、算法库、多线程

4、容器 1)、容器的通用特性 所有容器都具有的一个基本特性:它保存元素采用的是值(value)语义,也就是说,容器里存储的是元素的拷贝、副本,而不是引用 容器操作元素的很大一块成本就是值的拷贝…

RAG 工业落地方案框架(Qanything、RAGFlow、FastGPT、智谱RAG)细节比对!CVPR自动驾驶最in挑战赛赛道,全球冠军被算力选手夺走了

RAG 工业落地方案框架(Qanything、RAGFlow、FastGPT、智谱RAG)细节比对!CVPR自动驾驶最in挑战赛赛道,全球冠军被算力选手夺走了。 本文详细比较了四种 RAG 工业落地方案 ——Qanything、RAGFlow、FastGPT 和智谱 RAG,重…

git push之后回滚到某个版本

背景 因为粗心在主分支上修改了代码,push了上去,污染了主分支,希望将主分支之后的修改回滚,包括提交记录,就是远程的记录中回到希望回到的版本,保持干净。 git push -f 可以做到,会冲掉所有的…

SwiftUI 6.0(iOS 18.0)滚动视图新增的滚动阶段(Scroll Phase)监听功能趣谈

何曾几时,在 SwiftUI 开发中的秃头小码农们迫切需要一种能够读取当前滚动状态的方法。 在过去,他们往往需要借助于 UIKit 的神秘力量。不过这一切在 SwiftUI 6.0 中已成“沧海桑田”。 在本篇博文中,您将学到如下内容: 1. Scroll…

一份适合新手的软件测试练习项目

最近,不少读者托我找一个能实际练手的测试项目。开始,我觉得这是很简单的一件事,但当我付诸行动时,却发现,要找到一个对新手友好的练手项目,着实困难。 我翻了不下一百个web网页,包括之前推荐练…

nginx的知识面试易考点

Nginx概念 Nginx 是一个高性能的 HTTP 和反向代理服务。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好。 Nginx 专为性能优化而开发,性能是其最重要的考量指标,实现上非常注重效率&#…

C#用链表和数组分别实现堆栈

1.链表 实现栈的四个基本功能 入栈 出栈 长度 栈顶值 public class 基础 : MonoBehaviour {public class MyStack{//定义每一个元素的数据结构 //下一个元素 和 该元素的值public class StackData{public StackData next;public object data;public StackData(StackData next,…

linux驱动编程 - kfifo先进先出队列

简介: kfifo是Linux Kernel里面的一个 FIFO(先进先出)数据结构,它采用环形循环队列的数据结构来实现,提供一个无边界的字节流服务,并且使用并行无锁编程技术,即当它用于只有一个入队线程和一个出…

nginx修改网站默认根目录及发布(linux、centos、ubuntu)openEuler软件源repo站点

目录 安装nginx配置nginx其它权限配置 安装nginx dnf install -y nginx配置nginx whereis nginxcd /etc/nginx llcd conf.d touch vhost.conf vim vhost.conf 命令模式下输入:set nu或:set number可以显示行号 复制如下内容: server {listen 80;server_name…