【Ovirt 笔记】ovirt-engine 的 Makefile 分析与整理

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

分析整理的版本为 Ovirt 3.4.5 版本。

1. 概述

  • 一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,通过 Makefile 可以定义一系列的规则来指定复杂的功能操作。
    • make 命令工具,它可以解释 Makefile 中的指令,这样 Makefile 可以像 shell 脚本一样,执行操作系统的命令。
    • Makefile 文件中描述了整个工程所有文件的编译顺序、编译规则。
    • Makefile 有自己的书写格式、关键字、函数。
    • Makefile 在绝大多数的 IDE 开发环境中都在使用,已经成为一种工程的编译方法。
  • Makefile 编写完成,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • make 命令工具最主要也是最基本的功能就是通过 Makefile 文件来描述源程序之间的相互关系并自动维护编译工作。

2. engine Makefile 原理分析

2.1 调试

warning 函数

  • $(warning string)函数可以放在 Makefile 中的任何地方,执行该函数时,会将 string 输出,方便定位 make 执行到哪个位置。

命令行选项

  • " -n "、" --just-print "、" --dry-run "、" --recon ",不管目标是否更新,把规则和连带规则下的命令打印出来,但不执行。
  • " -t "、" --touch ",把目标文件的时间更新,但不更改目标文件,make 假装编译目标,但不是真正的编译目标,只是把目标变成已编译过的状态。
  • " -q "、" --question ",如果目标存在,不输出,不执行编译,如果目标不存在,打印出一条出错信息。
  • " -W "、" --what-if= "、" --assume-new= "、" --new-file= ",参数需要指定一个文件。一般是是源文件(或依赖文件),make 会根据规则推导来运行依赖于这个文件的命令,一般来说,可以和 " -n " 参数一同使用,查看这个依赖文件所发生的规则命令。
  • 最适合用来调试的命令行选项有。
    • --just-print(-n),使 make 读进 Makefile 并且输出它更新工作目标时将会执行的命令,但是不会真的执行。
    • --print-database(-p),会运行 Makefile,显示 GNU 版权信息以及 make 所运行的命令,然后输出它的内部数据库。
    • --warn-undefined-variables,使得 make 在未定义的变量被扩展时显示警告信息。

--debug 选项

  • 当需要知道 make 如何分析依存图时,可以使用 --debug 选项。
    • 除了运行调试器,这个选项是获得最详细信息的另一个方法。
    • 有五个调试选项以及一个修饰符可用,分别是 basic、verbose、implicit、jobs、all 以及 makefile。
    • 调试选项被指定成 --debug,就是进行 basic 调试。
调试 说明
basic 信息最不详细的基本调试功能。启用时,make 会输出被发现尚未更新的工作目标并更新动作的状态。
verbose 会启用 basic 选项功能,以及提供关于 " 哪些文件被分析、哪些必要条件不需要重建等 " 的额外信息。
implicit 会启用 basic 选项功能,以及提供关于 " 为每个工作目标搜索隐含规则 " 的额外信息。
jobs 会输出被 make 调用的子进程的细节,不会启用 basic 选项的功能。
all 会启用所有选项,当使用 -d 选项时,默认会启用此功能。
makefile 不会启用调试信息,直到 Makefile 被更新。包括更新任何的引入文件。如果使用此修饰符,make 会在重编译 Makefile 以及引入文件的时候,输出被选择的信息。这个选项会启用 basic 选项,all 选项也会启用此选项。

2.2 原理

  • 通过 ovirt-engine 的 Makefile 文件可以编译整个 engine 的项目代码。

2.2.1 变量的自定义

engine Makefile 中的自定义变量 说明
BUILD_GWT 是否启用编译前端 GWT,默认值为 1 启用。
BUILD_GWT_USERPORTAL 是否启用编译用户门户,默认值为 1 启用。
BUILD_GWT_WEBADMIN 是否启用编译管理门户,默认值为 1 启用。
BUILD_LOCALES 是否启用本地化处理,默认值为 0 不启用。
BUILD_DEV 是否为开发编译,默认值为 0 不是。
BUILD_UT 是否执行单元测试,默认值为 1 执行。
EXTRA_BUILD_FLAGS 编译额外参数。
BUILD_VALIDATION 是否编译验证,默认值 1 验证。
DEV_REBUILD 重新执行开发编译标记,默认值 1。
DEV_BUILD_GWT_DRAFT 开发编译阶段,是否启用 GWT 编译优化,默认值 0 不启用。
DEV_EXTRA_BUILD_FLAGS 开发编译额外参数。
DEV_EXTRA_BUILD_FLAGS_GWT_DEFAULTS 开发编译额外的 GWT 参数默认值,默认值 -D gwt.userAgent=gecko1_8,只编译火狐浏览器。
PACKAGE_NAME 包名,默认值 ovirt-engine。
ENGINE_NAME 引擎名称,与包名一致。
MVN mvn 命令,Makefile 文件中可用 $(MVN) 调用执行。
RPMBUILD rpmbuild 命令, Makefile 文件中可用 $(RPMBUILD) 调用执行。
PYTHON python 命令,Makefile 文件中可用 $(PYTHON) 调用执行。
PYFLAKES pyflakes 命令,Makefile 文件中可用 $(PYFLAKES) 调用执行,是用于测试 python 源码的工具。
PEP8 pep8 命令,Makefile 文件中可用 $(PEP8) 调用执行,是用于 python 规范格式检查。
PREFIX 编译至目录的前缀,默认值为 /usr/local,编译后的文件放置在 /usr/local 这个目录下。
LOCALSTATE_DIR 本地状态文件目录,默认值 $(PREFIX)/var。
BIN_DIR 执行目录,默认值 $(PREFIX)/bin。
PID_DIR PID 文件目录,默认值 $(LOCALSTATE_DIR)/run。
SYSCONF_DIR 系统配置目录,默认值 $(PREFIX)/etc。
DATAROOT_DIR 数据目录,默认值 $(PREFIX)/share。
MAN_DIR MAN 目录,默认值 $(DATAROOT_DIR)/man。
DOC_DIR 文档目录,默认值 $(DATAROOT_DIR)/doc。
DATA_DIR engine 数据目录,默认值 $(DATAROOT_DIR)/$(ENGINE_NAME)。
MAVENPOM_DIR maven pom 目录,默认值 $(DATAROOT_DIR)/maven-poms。
JAVA_DIR java 目录,默认值 $(DATAROOT_DIR)/java。
PKG_SYSCONF_DIR engine 配置目录,默认值 $(SYSCONF_DIR)/$(ENGINE_NAME)。
PKG_PKI_DIR engine PKI 配置目录,默认值 $(SYSCONF_DIR)/pki/$(ENGINE_NAME)。
PKG_DOC_DIR engine 文档目录,默认值 $(DOC_DIR)/$(ENGINE_NAME)。
PKG_EAR_DIR engine ear 目录,默认值 $(DATA_DIR)/engine.ear。
PKG_JBOSS_MODULES Jboss modules 目录,默认值 $(DATA_DIR)/modules。
PKG_CACHE_DIR 缓存文件目录,默认值 $(LOCALSTATE_DIR)/cache/$(ENGINE_NAME)。
PKG_LOG_DIR 日志目录,默认值 $(LOCALSTATE_DIR)/log/$(ENGINE_NAME)。
PKG_STATE_DIR 状态目录,默认值 $(LOCALSTATE_DIR)/lib/$(ENGINE_NAME)。
PKG_TMP_DIR 临时文件目录,默认值 $(LOCALSTATE_DIR)/tmp/$(ENGINE_NAME)。
JBOSS_HOME Jboss 目录,默认值 /usr/share/jboss-as。
JBOSS_RUNTIME Jboss 运行目录,默认值 $(PKG_STATE_DIR)/jboss_runtime。
PYTHON_DIR $(PYTHON_SYS_DIR) 变量定义的目录。
DEV_PYTHON_DIR 开发编译阶段 python 目录。
PKG_USER 执行用户,默认值 ovirt。
PKG_GROUP 执行组,默认值 ovirt。

2.2.2 版本的定义

  • 引入版本描述文件。
include version.mak

[test@localhost engine]$ cat version.mak 
# Version Information

# Major and minor are taken from pom.xml

# Fix release is manually specified,
# increment after releasing/branching
FIX_RELEASE=5

# Milestone is manually specified,
# example for ordering:
# - master
# - alpha
# - master
# - beta
# - master
# - beta2
# - master
# - rc
# - master
# - rc2
# - master
# - 
#
MILESTONE=

# RPM release is manually specified,
# For pre-release:
# RPM_RELEASE=0.N.$(MILESTONE).$(shell date -u +%Y%m%d%H%M%S)
# While N is incremented when milestone is changed.
#
# For release:
# RPM_RELEASE=N
# while N is incremented each re-release
#
RPM_RELEASE=0.0.$(MILESTONE).$(shell date -u +%Y%m%d%H%M%S)

#
# Downstream only release prefix
# Downstream (mead) does not use RPM_RELEASE but internal
# mead versioning.
# Increment the variable bellow after every milestone is
# released.
# Or leave empty to have only mead numbering.
#
DOWNSTREAM_RPM_RELEASE_PREFIX=0.

POM_VERSION

  • 获取 pom 文件的版本信息,值为 3.4.5。
# POM_VERSION:=$(shell cat pom.xml | grep '' | sed -e 's/.*>\(.*\)<.*/\1/' -e 's/-SNAPSHOT//')
[test@localhost engine]$ cat pom.xml | grep '' | sed -e 's/.*>\(.*\)<.*/\1/' -e 's/-SNAPSHOT//'
3.4.5
  • $(shell ) 可以执行 shell 命令。
赋值运算符 说明
= 最基本的赋值。
:= 覆盖之前的值。
?= 如果没有被赋值过就赋予等号后面的值。
+= 添加等号后面的值。
  • " = " 赋值,变量的值将会是整个 Makefile 中最后被指定的值。
x = foo
y = $(x) bar
x = xyz
# y 的值是 xyz bar。 
  • " := " 赋值,变量的值决定于它在 Makefile 中的位置。
x = foo
y := $(x) bar
x = xyz
# y 的值是 foo bar。

APP_VERSION

  • 获取软件版本信息,值为 3.4.5。
# APP_VERSION=$(shell echo $(POM_VERSION) | sed 's/\([^.]*\.[^.]\)\..*/\1/').$(FIX_RELEASE)
[test@localhost engine]$ echo 3.4.5 | sed 's/\([^.]*\.[^.]\)\..*/\1/'
3.4

RPM_VERSION

  • RPM 包版本与软件版本信息一致,值为 3.4.5。
RPM_VERSION=$(APP_VERSION)

PACKAGE_VERSION

  • 软件包版本。(如果包含里程碑信息,可以追加)
PACKAGE_VERSION=$(APP_VERSION)$(if $(MILESTONE),_$(MILESTONE))

DISPLAY_VERSION

  • 显示版本。
DISPLAY_VERSION=$(PACKAGE_VERSION)

2.2.3 编译参数的组装

条件判断

  • 条件判断语句只能用于 控制 make 实际执行的语言,但是 不能控制规则中命令的执行过程
关键字 说明
ifeq 判断参数是否相等,相等返回 true,否则 false。
ifneq 判断参数是否不相等,不相等返回 true,否则 false。
ifdef 判断变量是否有值,有值为 true,否则 false。
ifndef 判断变量是否没有值,没有值为 true,否则 false。
  • 条件判断语句之间可以有空格,但不能有 Tab 字符(\t)。
  • 条件语句中不能使用自动变量($@,@^,$<)。
  • 一条完整的条件语句必须位于同一个 Makefile 中。
  • 条件判断类似C语言中的宏,预处理阶段有效,执行阶段无效
  • make 在加载 Makefile 时,首先计算表达式的值(赋值方式不同,计算方式不同),然后根据 判断语句的表达式 决定执行的内容。

开发编译参数的组装

DEV_BUILD_FLAGS:=
ifneq ($(DEV_BUILD_GWT_DRAFT),0)
DEV_BUILD_FLAGS:=$(DEV_BUILD_FLAGS) -P gwtdraft
endif
DEV_BUILD_FLAGS:=$(DEV_BUILD_FLAGS) $(DEV_EXTRA_BUILD_FLAGS_GWT_DEFAULTS)
DEV_BUILD_FLAGS:=$(DEV_BUILD_FLAGS) $(DEV_EXTRA_BUILD_FLAGS)
  • 如果开发编译阶段 GWT 优化启用,添加参数 -P gwtdraft
  • 添加开发编译额外的 GWT 默认参数和开发编译额外参数。

编译参数的组装

BUILD_FLAGS:=
ifneq ($(BUILD_GWT),0)
ifneq ($(BUILD_GWT_USERPORTAL),0)
BUILD_FLAGS:=$(BUILD_FLAGS) -P gwt-user
endif
ifneq ($(BUILD_GWT_WEBADMIN),0)
BUILD_FLAGS:=$(BUILD_FLAGS) -P gwt-admin
endif
endif
ifneq ($(BUILD_LOCALES),0)
BUILD_FLAGS:=$(BUILD_FLAGS) -D gwt.locale=en_US,zh_CN
endif
ifeq ($(BUILD_UT),0)
BUILD_FLAGS:=$(BUILD_FLAGS) -D skipTests
endif
ifneq ($(BUILD_DEV),0)
BUILD_FLAGS:=$(BUILD_FLAGS) $(DEV_BUILD_FLAGS)
endif
BUILD_FLAGS:=$(BUILD_FLAGS) $(EXTRA_BUILD_FLAGS)
  • 如果开启了 GWT 编译,再判断是否开启用户门户和管理门户的编译,根据开关不同,组装 -P gwt-user-P gwt-admin 的参数。
  • 如果开启了本地化编译,组装 -D gwt.locale=en_US,zh_CN,编译中文和英文。
  • 如果开启了单元测试,组装 -D skipTests 参数。
  • 如果开启了开发编译,组装开发编译的一些参数。
  • 最后组装编译的额外参数。

其他组装

PYTHON_SYS_DIR:=$(shell $(PYTHON) -c "from distutils.sysconfig import get_python_lib as f;print(f())")
OUTPUT_RPMBUILD=$(shell pwd -P)/tmp.rpmbuild
OUTPUT_DIR=output
TARBALL=$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz
ARCH=noarch
BUILD_FILE=tmp.built
MAVEN_OUTPUT_DIR=.
BUILD_TARGET=install
  • 获取 python 系统命令目录。
[test@localhost engine]$ python -c "from distutils.sysconfig import get_python_lib as f;print(f())"
/usr/lib/python2.7/site-packages
  • rpmbuild 输出。
OUTPUT_RPMBUILD=$(shell pwd -P)/tmp.rpmbuild
# /root/rpmbuild/BUILD/ovirt-engine/tmp.rpmbuild
  • 输出目录。
OUTPUT_DIR=output
  • 打包 Tar 包名称。
TARBALL=$(PACKAGE_NAME)-$(PACKAGE_VERSION).tar.gz
# ovirt-engine-3.4.5.tar.gz
  • 软件架构。
ARCH=noarch
  • 编译文件。
BUILD_FILE=tmp.built
  • maven 输出目录。
MAVEN_OUTPUT_DIR=.
  • 编译 Tar 命令。(install 是一个函数)
BUILD_TARGET=install

2.2.4 后缀自定义规则

.SUFFIXES:
.SUFFIXES: .in

.in:
    sed \
    -e "s|@ENGINE_DEFAULTS@|$(DATA_DIR)/services/ovirt-engine/ovirt-engine.conf|g" \
    -e "s|@ENGINE_VARS@|$(PKG_SYSCONF_DIR)/engine.conf|g" \
    -e "s|@ENGINE_SETUP_VARS@|$(SYSCONF_DIR)/ovirt-engine-setup.conf|g" \
    -e "s|@ENGINE_NOTIFIER_VARS@|$(PKG_SYSCONF_DIR)/notifier/notifier.conf|g" \
    -e "s|@ENGINE_WSPROXY_VARS@|$(PKG_SYSCONF_DIR)/ovirt-websocket-proxy.conf|g" \
    -e "s|@ENGINE_USER@|$(PKG_USER)|g" \
    -e "s|@ENGINE_GROUP@|$(PKG_GROUP)|g" \
    -e "s|@ENGINE_ETC@|$(PKG_SYSCONF_DIR)|g" \
    -e "s|@ENGINE_PKI@|$(PKG_PKI_DIR)|g" \
    -e "s|@ENGINE_LOG@|$(PKG_LOG_DIR)|g" \
    -e "s|@ENGINE_TMP@|$(PKG_TMP_DIR)|g" \
    -e "s|@ENGINE_USR@|$(DATA_DIR)|g" \
    -e "s|@ENGINE_DOC@|$(PKG_DOC_DIR)|g" \
    -e "s|@ENGINE_VAR@|$(PKG_STATE_DIR)|g" \
    -e "s|@ENGINE_CACHE@|$(PKG_CACHE_DIR)|g" \
    -e "s|@ENGINE_PID@|$(PID_DIR)/$(ENGINE_NAME).pid|g" \
    -e "s|@DEV_PYTHON_DIR@|$(DEV_PYTHON_DIR)|g" \
    -e "s|@RPM_VERSION@|$(RPM_VERSION)|g" \
    -e "s|@RPM_RELEASE@|$(RPM_RELEASE)|g" \
    -e "s|@PACKAGE_NAME@|$(PACKAGE_NAME)|g" \
    -e "s|@PACKAGE_VERSION@|$(PACKAGE_VERSION)|g" \
    -e "s|@DISPLAY_VERSION@|$(DISPLAY_VERSION)|g" \
    -e "s|@JBOSS_HOME@|$(JBOSS_HOME)|g" \
    -e "s|@JBOSS_RUNTIME@|$(JBOSS_RUNTIME)|g" \
    -e "s|@PEP8@|$(PEP8)|g" \
    -e "s|@PYFLAKES@|$(PYFLAKES)|g" \
    -e "s|@DEVMODE@|$(BUILD_DEV)|g" \
    $< > $@
符号 说明
$@ 目标文件。
$< 第一个依赖文件。
$^ 所有的依赖文件。
$? 比目标还要新的依赖文件列表。
$% 仅当目标是函数库文件中,表示规则中的目标成员名。
$+ 所有依赖目标的集合,与 $^ 类似,包含重复。
$* 不包含扩展名的目标文件名称。
  • 结合上述用例,将变量替换后,根据 .in 文件生成没有 .in 的文件,即 config.py.in 经过变量替换后生成 config.py 文件。
  • 通过模板 后缀自定义规则 生成的文件列表。
GENERATED = \
    ovirt-engine.spec \
    build/python-check.sh \
    packaging/bin/engine-prolog.sh \
    packaging/bin/ovirt-engine-log-setup-event.sh \
    packaging/bin/pki-common.sh \
    packaging/etc/engine-manage-domains/engine-manage-domains.conf \
    packaging/etc/engine.conf.d/README \
    packaging/etc/notifier/log4j.xml \
    packaging/etc/notifier/notifier.conf.d/README \
    packaging/etc/ovirt-websocket-proxy.conf.d/README \
    packaging/pythonlib/ovirt_engine/config.py \
    packaging/services/ovirt-engine-notifier/config.py \
    packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf \
    packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.systemd \
    packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.sysv \
    packaging/services/ovirt-engine/config.py \
    packaging/services/ovirt-engine/ovirt-engine.conf \
    packaging/services/ovirt-engine/ovirt-engine.systemd \
    packaging/services/ovirt-engine/ovirt-engine.sysv \
    packaging/services/ovirt-websocket-proxy/config.py \
    packaging/services/ovirt-websocket-proxy/ovirt-websocket-proxy.conf \
    packaging/services/ovirt-websocket-proxy/ovirt-websocket-proxy.systemd \
    packaging/services/ovirt-websocket-proxy/ovirt-websocket-proxy.sysv \
    packaging/setup/bin/ovirt-engine-setup.env \
    packaging/setup/ovirt_engine_setup/config.py \
    packaging/sys-etc/logrotate.d/ovirt-engine \
    packaging/sys-etc/logrotate.d/ovirt-engine-notifier \
    packaging/sys-etc/logrotate.d/ovirt-engine-setup \
    $(NULL)

2.2.5 执行动作

  • make 的基本规则。
target ... : prerequisites ...
    command
    ....
    ....
  • target 是目标文件, 可以是 Object File,可以是 可执行文件,还可是 标签
  • prerequisites 生成 target 所需的文件或目标。
  • command make 需要执行的命令,可以是任何 shell 命令。

generated-files 标签

  • 修改部分文件权限。
generated-files:    $(GENERATED)
    chmod a+x build/python-check.sh
    chmod a+x packaging/services/ovirt-engine/ovirt-engine.sysv
    chmod a+x packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.sysv
    chmod a+x packaging/services/ovirt-websocket-proxy/ovirt-websocket-proxy.sysv
    chmod a+x packaging/bin/ovirt-engine-log-setup-event.sh

validations 标签

  • 执行了文件的检查和验证。
validations:    generated-files
    if [ "$(BUILD_VALIDATION)" != 0 ]; then \
        build/shell-check.sh && \
        build/python-check.sh && \
        build/dbscripts/check_for_duplicate_upgrade_scripts.sh; \
    fi

maven 标签

  • 执行 mvn 命令,生成 ${BUILD_FILE} 文件。
maven:
    export MAVEN_OPTS="${MAVEN_OPTS} -XX:MaxPermSize=512m"
    $(MVN) \
        $(BUILD_FLAGS) \
        $(BUILD_TARGET)
    touch "$(BUILD_FILE)"

clean 标签

  • 清除 mvn 命令生成的文件。
  • 删除临时文件和通过模板后缀自定义规则生成的文件。
clean:
    # Clean maven generated stuff:
    $(MVN) clean $(EXTRA_BUILD_FLAGS)
    rm -rf $(OUTPUT_RPMBUILD) $(OUTPUT_DIR) $(BUILD_FILE) tmp.dev.flist

    # Clean files generated from templates:
    rm -rf $(GENERATED)

test 标签

  • 执行 mvn install 命令(mvn 命令可以查看 Maven 相关整理)。
test:
    $(MVN) install $(BUILD_FLAGS) $(EXTRA_BUILD_FLAGS)

$(BUILD_FILE) 标签

# BUILD_FILE=tmp.built
$(BUILD_FILE):
    $(MAKE) maven

install 标签

  • 执行动作标签 all、install-layout、install_artifacts 和 install_poms。
install: \
    all \
    install-layout \
    install_artifacts \
    install_poms \
    $(NULL)

all 标签

  • 执行动作标签 generated-files、validations 和 $(BUILD_FILE)。
all: \
    generated-files \
    validations \
    $(BUILD_FILE) \
    $(NULL)

install-layout 标签

  • install 命令的作用是安装或升级软件或备份数据,它的使用权限是所有用户。
  • install 允许控制目标文件的属性。
  • install 通常用于程序的 makefile,使用它来将程序拷贝到目标(安装)目录。
  • 命令格式:install [OPTION]… [-T] SOURCE DEST
    install [OPTION]… -d DIRECTORY…
参数 说明
-backup[=CONTROL] 为每个已存在 的目的地文件进行备份。
-b 类似 -backup,但不接受任何参数。
-D, -compare 比较每对源文件和目标文件,如果目的地具有相同的内容和任何指定的所有者,组,权限以及可能的 SELinux 上下文,那么不要修改目的地。
-d, -directory 所有参数都作为目录处理,而且会创建指定目录的所有主目录。
-D 创建 <目的地> 前的所有主目录,然后将 <来源> 复制至 <目的地>。在第一种格式中有用。
-g, -group=组 自行设定所属组,而不是进程目前的所属组。
-m, -mode=模式 自行设定权限模式,(像 chmod)。
-o, -owner 自行设定权限所有者(只适用于超级用户)。
-p, -preserve-timestamp 以 <来源> 文件的访问/修改时间作为相应的目的地文件的时间属性。
-s, -strip 用 strip 命令删除 symbol table。
-S, -suffix=后缀 自定指定备份文件的后缀。
-v, -verbose 处理每个文件/目录时印出名称。
-Z CONTEXT, -context=CONTEXT 设置要用于任何创建的文件和目录的默认。SELinux 安全上下文,如果 SELinux 被禁用,则打印警告并忽略该选项。
-help 显示此帮助信息并离开。
-version 显示版本信息并离开。
install-layout: \
        install-packaging-files \
        $(NULL)

    install -d -m 755 "$(DESTDIR)$(BIN_DIR)"
    ln -sf "$(DATA_DIR)/setup/bin/ovirt-engine-setup" "$(DESTDIR)$(BIN_DIR)/engine-setup"
    ln -sf "$(DATA_DIR)/setup/bin/ovirt-engine-remove" "$(DESTDIR)$(BIN_DIR)/engine-cleanup"
    ln -sf "$(DATA_DIR)/setup/bin/ovirt-engine-upgrade-check" "$(DESTDIR)$(BIN_DIR)/engine-upgrade-check"
    ln -sf "$(DATA_DIR)/bin/engine-config.sh" "$(DESTDIR)$(BIN_DIR)/engine-config"
    ln -sf "$(DATA_DIR)/bin/engine-manage-domains.sh" "$(DESTDIR)$(BIN_DIR)/engine-manage-domains"
    ln -sf "$(DATA_DIR)/bin/engine-backup.sh" "$(DESTDIR)$(BIN_DIR)/engine-backup"

    install -d -m 755 "$(DESTDIR)$(PKG_PKI_DIR)/certs"
    install -d -m 755 "$(DESTDIR)$(PKG_PKI_DIR)/keys"
    install -d -m 750 "$(DESTDIR)$(PKG_PKI_DIR)/private"
    install -d -m 755 "$(DESTDIR)$(PKG_PKI_DIR)/requests"
    install -d -m 755 "$(DESTDIR)$(DATA_DIR)/ui-plugins"
    install -d -m 755 "$(DESTDIR)$(PKG_SYSCONF_DIR)/branding"
    install -d -m 750 "$(DESTDIR)$(PKG_STATE_DIR)/backups"

    install -d -m 0755 "$(DESTDIR)$(DATA_DIR)/uploads"
    install -d -m 0755 "$(DESTDIR)$(DATA_DIR)/files"
    -rm -f "$(DESTDIR)$(DATA_DIR)/files/usbfilter.txt"
    ln -s "$(PKG_SYSCONF_DIR)/usbfilter.txt" "$(DESTDIR)$(DATA_DIR)/files/usbfilter.txt"
    -rm -f "$(DESTDIR)$(DATA_DIR)/files/novnc"
    ln -s "/usr/share/novnc" "$(DESTDIR)$(DATA_DIR)/files/novnc"
    -rm -f "$(DESTDIR)$(DATA_DIR)/files/spice-html5"
    ln -s "/usr/share/spice-html5" "$(DESTDIR)$(DATA_DIR)/files/spice-html5"

    install -d -m 755 "$(DESTDIR)$(PKG_SYSCONF_DIR)/branding"
    -rm -f "$(DESTDIR)$(PKG_SYSCONF_DIR)/branding/00-ovirt.brand"
    ln -s "$(DATA_DIR)/branding/ovirt.brand" "$(DESTDIR)$(PKG_SYSCONF_DIR)/branding/00-ovirt.brand"
    ln -sf "$(DATA_DIR)/conf/osinfo-defaults.properties" "$(DESTDIR)$(PKG_SYSCONF_DIR)/osinfo.conf.d/00-defaults.properties"
    ln -sf "$(DATA_DIR)/conf/osinfo-sdcos.properties" "$(DESTDIR)$(PKG_SYSCONF_DIR)/osinfo.conf.d/01-sdcos.properties"
  • 创建目录、建立软链接、删除部分文件等等。

install-packaging-files 标签

install-packaging-files: \
        $(GENERATED) \
        $(NULL)
    $(MAKE) copy-recursive SOURCEDIR=packaging/sys-etc TARGETDIR="$(DESTDIR)$(SYSCONF_DIR)" EXCLUDE_GEN="$(GENERATED)"
    $(MAKE) copy-recursive SOURCEDIR=packaging/etc TARGETDIR="$(DESTDIR)$(PKG_SYSCONF_DIR)" EXCLUDE_GEN="$(GENERATED)"
    $(MAKE) copy-recursive SOURCEDIR=packaging/pki TARGETDIR="$(DESTDIR)$(PKG_PKI_DIR)" EXCLUDE_GEN="$(GENERATED)"
    for d in bin branding conf files firewalld services setup; do \
        $(MAKE) copy-recursive SOURCEDIR="packaging/$${d}" TARGETDIR="$(DESTDIR)$(DATA_DIR)/$${d}" EXCLUDE_GEN="$(GENERATED)"; \
    done
    $(MAKE) copy-recursive SOURCEDIR=packaging/man TARGETDIR="$(DESTDIR)$(MAN_DIR)" EXCLUDE_GEN="$(GENERATED)"
    $(MAKE) copy-recursive SOURCEDIR=packaging/pythonlib TARGETDIR="$(DESTDIR)$(PYTHON_DIR)" EXCLUDE_GEN="$(GENERATED)"

    # we should avoid make these directories dirty
    $(MAKE) copy-recursive SOURCEDIR=packaging/dbscripts TARGETDIR="$(DESTDIR)$(DATA_DIR)/dbscripts" \
        EXCLUDE_GEN="$(GENERATED)" \
        EXCLUDE="$$(echo $$(find packaging/dbscripts \( -name '*.scripts.md5' -or -name '*.schema' -or -name '*.log' \)))"

copy-recursive 标签

copy-recursive:
    ( cd "$(SOURCEDIR)" && find . -type d -printf '%P\n' ) | while read d; do \
        install -d -m 755 "$(TARGETDIR)/$${d}"; \
    done
    ( \
        cd "$(SOURCEDIR)" && find . -type f -printf '%P\n' | \
        while read f; do \
            exclude=false; \
            for x in $(EXCLUDE_GEN); do \
                if [ "$(SOURCEDIR)/$${f}" = "$${x}.in" ]; then \
                    exclude=true; \
                    break; \
                fi; \
            done; \
            for x in $(EXCLUDE); do \
                if [ "$(SOURCEDIR)/$${f}" = "$${x}" ]; then \
                    exclude=true; \
                    break; \
                fi; \
            done; \
            $${exclude} || echo "$${f}"; \
        done \
    ) | while read f; do \
        src="$(SOURCEDIR)/$${f}"; \
        dst="$(TARGETDIR)/$${f}"; \
        [ -x "$${src}" ] && MASK=0755 || MASK=0644; \
        [ -n "$(DEV_FLIST)" ] && echo "$${dst}" | sed 's#^$(PREFIX)/##' >> "$(DEV_FLIST)"; \
        install -T -m "$${MASK}" "$${src}" "$${dst}"; \
    done

install_artifacts 标签

  • 命令格式:unzip [-Z] [-cflptTuvz[abjnoqsCDKLMUVWX$/:^]] file[.zip] [file(s) ...] [-x xfile(s) ...] [-d exdir]
选项 说明
-f 更新现有的文件。
-l 显示压缩文件内所包含的文件。
-p 与 -c 参数类似,会将解压缩的结果显示到屏幕上,但不会执行任何的转换。
-t 检查压缩文件是否正确。
-u 与 -f 参数类似,但是除了更新现有的文件外,也会将压缩文件中的其他文件解压缩到目录中。
-v 执行时显示详细的信息。
-z 仅显示压缩文件的备注文字。
-a 对文本文件进行必要的字符转换。
-b 不要对文本文件进行字符转换。
-C 压缩文件中的文件名称区分大小写。
-j 不处理压缩文件中原有的目录路径。
-L 将压缩文件中的全部文件名改为小写。
-M 将输出结果送到 more 命令处理。
-n 解压缩时不要覆盖原有的文件。
-o 不必先询问用户,unzip 执行后覆盖原有的文件。
-P<密码> 使用 zip 的密码选项。
-q 执行时不显示任何信息。
-s 将文件名中的空白字符转换为底线字符。
-V 保留 VMS 的文件版本信息。
-X 解压缩时同时回存文件原来的 UID/GID。
-d<目录> 指定文件解压缩后所要存储的目录。
-x<文件> 指定不要处理 .zip 压缩文件中的哪些文件。
-Z unzip-Z 等于执行 zipinfo 指令。
install_artifacts:
    # we must exclude tmp.repos directory so we
    # won't get artifacts of older branches
    # we should use search MAVEN_OUTPUT_DIR as it may contain
    # pre-compiled artifacts at different hierarchy.
    install -dm 0755 "$(DESTDIR)$(PKG_JBOSS_MODULES)"
    find "$(MAVEN_OUTPUT_DIR)" -name '*-modules.zip' | grep -v tmp.repos | xargs -n 1 unzip -q -o -d "$(DESTDIR)$(PKG_JBOSS_MODULES)"
    install -dm 0755 "$(DESTDIR)$(PKG_EAR_DIR)"
    find "$(MAVEN_OUTPUT_DIR)" -name '*.ear' -type f | grep -v tmp.repos | xargs -n 1 unzip -q -o -d "$(DESTDIR)$(PKG_EAR_DIR)"

    # extract embedded artifacts as doc
    # no need to relay on source tree for these
    install -d -m 755 "$(DESTDIR)$(PKG_DOC_DIR)"
    unzip -q -c "$(DESTDIR)$(PKG_JBOSS_MODULES)/org/ovirt/engine/core/dal/main/dal.jar" bundles/AuditLogMessages.properties > \
        "$(DESTDIR)$(PKG_DOC_DIR)/AuditLogMessages.properties"
    chmod 0644 "$(DESTDIR)$(PKG_DOC_DIR)/AuditLogMessages.properties"

install_poms 标签

  • 对个模块的 pom 文件进行处理。
install_poms:
    install -dm 755 "$(DESTDIR)$(MAVENPOM_DIR)"
    install -m 644 backend/manager/modules/bll/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-bll.pom"
    install -m 644 backend/manager/modules/common/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-common.pom"
    install -m 644 backend/manager/modules/compat/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-compat.pom"
    install -m 644 backend/manager/modules/dal/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-dal.pom"
    install -m 644 backend/manager/modules/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-manager-modules.pom"
    install -m 644 backend/manager/modules/restapi/interface/common/jaxrs/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-interface-common-jaxrs.pom"
    install -m 644 backend/manager/modules/restapi/interface/definition/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-restapi-definition.pom"
    install -m 644 backend/manager/modules/restapi/jaxrs/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-restapi-jaxrs.pom"
    install -m 644 backend/manager/modules/restapi/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-restapi-parent.pom"
    install -m 644 backend/manager/modules/restapi/types/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-restapi-types.pom"
    install -m 644 backend/manager/modules/scheduler/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-scheduler.pom"
    install -m 644 backend/manager/modules/searchbackend/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-searchbackend.pom"
    install -m 644 backend/manager/modules/utils/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-utils.pom"
    install -m 644 backend/manager/modules/vdsbroker/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-vdsbroker.pom"
    install -m 644 backend/manager/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-manager.pom"
    install -m 644 backend/manager/tools/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-tools.pom"
    install -m 644 backend/pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-backend.pom"
    install -m 644 pom.xml "$(DESTDIR)$(MAVENPOM_DIR)/$(PACKAGE_NAME)-root.pom"

gwt-debug 标签

  • 前端 GWT debug 模式。
gwt-debug:
    [ -n "$(DEBUG_MODULE)" ] || ( echo "Please specify DEBUG_MODULE" && false )
    cd "frontend/webadmin/modules/$(DEBUG_MODULE)" && \
        $(MVN) \
            $(DEV_EXTRA_BUILD_FLAGS_GWT_DEFAULTS) \
            $(DEV_EXTRA_BUILD_FLAGS) \
            -Dgwt.noserver=true \
            -Pgwtdev,gwt-admin,gwt-user \
            gwt:debug

install-dev 标签

  • 开发编译模式。
install-dev:    \
        all-dev \
        $(NULL)

    # remove dbscripts to avoid dups
    rm -fr "$(DESTDIR)$(DATA_DIR)/dbscripts"

    if [ -f "$(DESTDIR)$(PREFIX)/dev.$(PACKAGE_NAME).flist" ]; then \
        cat "$(DESTDIR)$(PREFIX)/dev.$(PACKAGE_NAME).flist" | while read f; do \
            rm -f "$(DESTDIR)$(PREFIX)/$${f}"; \
        done; \
        rm -f "$(DESTDIR)$(PREFIX)/dev.$(PACKAGE_NAME).flist"; \
    fi

    rm -f tmp.dev.flist
    $(MAKE) \
        install \
        BUILD_DEV=1 \
        BUILD_VALIDATION=0 \
        PYTHON_DIR="$(PREFIX)$(PYTHON_SYS_DIR)" \
        DEV_FLIST=tmp.dev.flist \
        $(NULL)
    cp tmp.dev.flist "$(DESTDIR)$(PREFIX)/dev.$(PACKAGE_NAME).flist"

    install -d "$(DESTDIR)$(PKG_TMP_DIR)"
    install -d "$(DESTDIR)$(PKG_CACHE_DIR)"
    install -d "$(DESTDIR)$(PKG_STATE_DIR)/content"
    install -d "$(DESTDIR)$(PKG_STATE_DIR)/setup/answers"
    install -d "$(DESTDIR)$(PKG_LOG_DIR)/host-deploy"
    install -d "$(DESTDIR)$(PKG_LOG_DIR)/setup"
    install -d "$(DESTDIR)$(PKG_LOG_DIR)/notifier"
    install -d "$(DESTDIR)$(PKG_LOG_DIR)/engine-manage-domains"
    install -d "$(DESTDIR)$(PKG_LOG_DIR)/dump"

    if [ -e "$(DESTDIR)$(PKG_TMP_DIR)/deployments" ]; then \
        touch "$(DESTDIR)$(PKG_TMP_DIR)/deployments/engine.ear.deployed"; \
    fi

all-dev 标签

  • 全编译模式。
all-dev:
    [ "$(DEV_REBUILD)" != 0 ] && rm -f "$(BUILD_FILE)" || :
    rm -f $(GENERATED)
    $(MAKE) \
        all \
        BUILD_DEV=1 \
        DEV_PYTHON_DIR="$(PREFIX)$(PYTHON_SYS_DIR)" \
        $(NULL)

  • engine spec 文件中的编译步骤,实际执行的就是 make 命令(spec 相关可以查看 【Ovirt 笔记】ovirt-engine.spec 配置分析与整理)。
%global make_common_opts \\\
        -j1 \\\
        BUILD_GWT=%{ovirt_build_gwt} \\\
        BUILD_LOCALES=%{ovirt_build_locales} \\\
        BUILD_UT=%{ovirt_build_ut} \\\
        BUILD_VALIDATION=0 \\\
        PACKAGE_NAME=%{name} \\\
        RPM_VERSION=%{version} \\\
        RPM_RELEASE=%{release} \\\
        DISPLAY_VERSION=%{version}-%{release} \\\
        ENGINE_NAME=%{engine_name} \\\
        LOCALSTATE_DIR=%{_localstatedir} \\\
        PREFIX=%{_prefix} \\\
        SYSCONF_DIR=%{_sysconfdir} \\\
        BIN_DIR=%{_bindir} \\\
        PID_DIR=%{_localstatedir}/run \\\
        DATAROOT_DIR=%{_datadir} \\\
        MAN_DIR=%{_mandir} \\\
        DOC_DIR=%{_docdir} \\\
        PYTHON=%{__python} \\\
        PYTHON_DIR=%{python_sitelib} \\\
        JAVA_DIR=%{_javadir} \\\
        MAVENPOM_DIR=%{_mavenpomdir} \\\
        PKG_SYSCONF_DIR=%{engine_etc} \\\
        PKG_DOC_DIR=%{engine_doc} \\\
        PKG_EAR_DIR=%{engine_ear} \\\
        PKG_PKI_DIR=%{engine_pki} \\\
        PKG_JBOSS_MODULES=%{engine_jboss_modules} \\\
        PKG_CACHE_DIR=%{engine_cache} \\\
        PKG_LOG_DIR=%{engine_log} \\\
        PKG_TMP_DIR=%{engine_tmp} \\\
        PKG_STATE_DIR=%{engine_state} \\\
        PKG_USER=%{engine_user} \\\
        PKG_GROUP=%{engine_group} \\\
        JBOSS_HOME=/usr/share/jbossas \\\
        MAVEN_OUTPUT_DIR=. \\\
        %{?BUILD_FLAGS:BUILD_FLAGS="%{BUILD_FLAGS}"} \\\
        %{?EXTRA_BUILD_FLAGS:EXTRA_BUILD_FLAGS="%{EXTRA_BUILD_FLAGS}"}
......
make %{make_common_opts} install DESTDIR="%{buildroot}"
  • 开发过程中的本地编译,可以执行。
make clean install-dev PREFIX=<编译至所在路径> DEV_EXTRA_BUILD_FLAGS_GWT_DEFAULTS="-Dgwt.userAgent=gecko1_8 -Dgwt.locale=en_US,zh_CN" BUILD_GWT_WEBADMIN="1" BUILD_GWT_USERPORTAL="0" BUILD_UT="0"
参数 说明
PREFIX 编译路径地址。
-Dgwt.userAgent 编译浏览器种类火狐。
-Dgwt.locale 编译语言中文、英文。
BUILD_GWT_WEBADMIN 是否编译前端 GWT 管理门户。
BUILD_GWT_USERPORTAL 是否编译前端 GWT 用户门户。
BUILD_UT 是否运行单元测试。
  • 前端 GWT 调试可以执行。
make gwt-debug DEBUG_MODULE="webadmin" DEV_EXTRA_BUILD_FLAGS_GWT_DEFAULTS="-Dgwt.userAgent=gecko1_8"
  • 调试前端 GWT 管理门户。
make gwt-debug DEBUG_MODULE="userportal-gwtp" DEV_EXTRA_BUILD_FLAGS_GWT_DEFAULTS="-Dgwt.userAgent=gecko1_8"
  • 调试前端 GWT 用户门户。

你可能感兴趣的:(【Ovirt 笔记】ovirt-engine 的 Makefile 分析与整理)