MakeFile:
(感觉用在编译go程序简直就是大材小用, 编译生成的是一个静态可执行文件,除了glibc外没有其他外部依赖,机器上只需要一个基础的系统和必要的管理、监控工具,完全不需要操心应用所需的各种包、库的依赖关系,大大减轻了维护的负担。)
简单案例展示:
//.PHONY是一个伪目标,可以防止在Makefile中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,
//另一种是提交执行makefile时的效率。
.PHONY:all build install clean uninstall bin test upgrade upload testcase
//定义需要用到的全局变量
PROJECT_PATH=$(PWD) //将当前目录作为项目的目录
NAME=sdns-agent //软件的名字
FULL_NAME=$(PROJECT_PATH)/$(NAME) //编译出软件二进制可执行文件名字放置的绝对路径
SRC_PATH=$(PROJECT_PATH)/agent //源码目录
FTP=127.0.0.1 //编译完之后上传ftp保存
X86=x86_64 //rpm包放置的路径
AAA=$(shell git pull)
VERSION=$(shell git describe --tags |awk -F '-' '{printf $$1 }') //软件的版本号
RELEASE_NUM=$(shell git describe --tags |awk -F '-' '{printf $$2 }')//发布号
if eq ($(RELEASE_NUM), )
RELEASE_NUM=0
endif
//定义make的标签,分标签执行相关的操作,使用方式make + 标签名 就可以执行标签下的命令
//直接使用make命令时会执行的默认标签
all: clean uninstall build install
testcase:
cd $(SRC_PATH); go test
cd $(PROJECT_PATH)
bin:
//先进入源码目录,使用godep进行编译
cd $(SRC_PATH); godep go build -o $(FULL_NAME)
-ldflags "-X main.gitVersion=$(VERSION)_$(RELEASE_NUM)"
//出源码目录,进入项目目录
cd $(PROJECT_PATH)
test: bin
$(FULL_NAME) -loglevel=Debug -setlogger=console
build: clean bin
//_name 软件的名字 _sourcedir 项目的目录 _rpmdir rpm打包的目录 _version 软件的版本号
//使用rpmbuild工具进行打包,方便存储使用安装。
rpmbuild -bb --define '_name $(NAME)' --define '_sourcedir $(PROJECT_PATH)'
--define '_rpmdir $(PROJECT_PATH)' --define '_version $(VERSION)'
--define '_release_num $(RELEASE_NUM)' -bs rpm.spec
install: build
yum install $(X86)/$(NAME)*.rpm -y
upgrade: build
yum upgrade $(X86)/$(NAME)*.rpm -y
clean://打包之前先清理
rm -rf $(X86) //rpm包放置的路径
rm -rf $(NAME) //软件编译之后的名字
uninstall:
yum remove $(NAME) -y
upload: build
lftp $(FTP) -uharbor,123456 -e "ls;cd $(NAME)/;mrm *;mput $(X86)/*.rpm;exit"
spec文件中内置的变量
查阅rpm常用路径 rpm --showrc>/usr/rpmShowrc.txt
Macros mimicking autoconf variables(RPM中内部宏变量,可以直接使用)
%{_sysconfdir} /etc
%{_prefix} /usr
%{_exec_prefix} %{_prefix}
%{_bindir} %{_exec_prefix}/bin
%{_lib} lib (lib64 on 64bit systems)
%{_libdir} %{_exec_prefix}/%{_lib}
%{_libexecdir} %{_exec_prefix}/libexec
%{_sbindir} %{_exec_prefix}/sbin
%{_sharedstatedir} /var/lib
%{_datadir} %{_prefix}/share
%{_includedir} %{_prefix}/include
%{_oldincludedir} /usr/include
%{_infodir} /usr/share/info
%{_mandir} /usr/share/man
%{_localstatedir} /var
%{_initddir} %{_sysconfdir}/rc.d/init.d
RPM directory macros
%{_topdir} %{getenv:HOME}/rpmbuild
%{_builddir} %{_topdir}/BUILD
%{_rpmdir} %{_topdir}/RPMS
%{_sourcedir} %{_topdir}/SOURCES
%{_specdir} %{_topdir}/SPECS
%{_srcrpmdir} %{_topdir}/SRPMS
%{_buildrootdir} %{_topdir}/BUILDROOT
简单spec文件案例
为了方便观看,使用了虚线将各个部分分割开来。
//设置变量
%global _summary summary
%global _source sdns-agent
%global _source_upgrade sdns-agent-upgrade
%global _description "sdns-agent"
------------------------------------------
//设置变量
Name: %_name //通过rpmbuild命令传递过来的数据
Version: %_version //通过rpmbuild命令传递过来的数据
Release: %_release_num%{?dist}
Summary: %_summary
Group: GPL
License: 1
URL: http://www.letv.com
//源码包的目录
Source0: %_source
//在rpmbuild中的路径, _tmppath====tmp
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
--------------------------------------------
BuildRequires: rpm-build //打rpm包需要rpmbuild命令
Requires: rpm-build //依赖的软件包
------------------------------------------
//rpm打包从上往下依次执行相关的标签
%description //项目描述
%_description
------------------------------------------
//全局变量,build时的目录
%global _build_dir %{name}-%{version}-%{release}.letv
-----------------------------------------
%prep
//与准备阶段 先进入rpm的根目录,这个可以在rpm的配置文件中设置,
// /letv/rpmbuild/作为根目录,则下面会有这些目录,BUILD/ BUILDROOT/ RPMS/ SOURCES/ SPECS/ SRPMS/
rm -rf %{_build_dir}
//(sdns-agent-%_version-0.el7.centos.letv 作为我们项目的build目录)
mkdir %{_build_dir}
-----------------------------------------
/**
其实在Makefile中已经进行了编译,这里只是将文件从源码位置拷贝到/rpmbuild/BUILD相关位置然后进行打包,
install阶段将会从这个BUILD目录拷贝需要安装的文件到BUILDROOT中
**/
%build
pushd %{_build_dir}
mkdir -p {script,conf,sysconfig}
cp %{_sourcedir}/%{_source} .
cp %{_sourcedir}/script/%{_source_upgrade} .
cp %{_sourcedir}/script/%{_source} script/
cp %{_sourcedir}/conf/%{_source}.conf conf/
cp %{_sourcedir}/sysconfig/%{_source} sysconfig/
popd
-----------------------------------------------------------------------------------
//此时的目录还是上次的目录,/letv//rpmbuild/BUILD
buildroot: 是用于测试安装的目录./letv/rpmbuild/BUILDROOT
rpmbuild会在buildroot目录下执行spec文件的install段,模拟将来rpm包在客户机上的安装过程.
这样,通过观察buildroot目录下的文件即目录结构,你就可以看到将来rpm包将会在客户机上安装哪些文件.
*/
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/%{_sbindir} %{buildroot}/%{_initrddir}
mkdir -p %{buildroot}/%{_sysconfdir}/%{_source}/conf
mkdir -p %{buildroot}/%{_sysconfdir}/sysconfig
cp %{_build_dir}/%{_source} %{buildroot}/%{_sbindir}
cp %{_build_dir}/%{_source_upgrade} %{buildroot}/%{_sbindir}
cp %{_build_dir}/script/%{_source} %{buildroot}/%{_initrddir}
cp %{_build_dir}/conf/%{_source}.conf %{buildroot}/%{_sysconfdir}/%{_source}/conf
cp %{_build_dir}/sysconfig/%{_source} %{buildroot}/%{_sysconfdir}/sysconfig
chmod a+x %{buildroot}/%{_sbindir}/*
chmod a+x %{buildroot}/%{_initrddir}/*
---------------------------------------------------------------------------------------
//这一节所描述的内容表示在完成包建立的工作之后,自动执行此节下的脚本进行附加的清除工作
%clean
rm -rf %{buildroot}
---------------------------------------------------------------------------------------
%files
%defattr(-,root,root,-) //设置权限
%{_sbindir}/%{_source} // /usr/sbin/sdns-agent
%{_sbindir}/%{_source_upgrade}
%{_initrddir}/%{_source}
%config(noreplace) %{_sysconfdir}/%{_source}/conf/*
%config(noreplace) %{_sysconfdir}/sysconfig/%{_source}
----------------------------------------------------------------------------------------
%changelog
* Tue May 19 2015 Letv Engineering <GCP@letv.com> - 0.1
- Hello World!
----------------------------------------------------------------------------------------
一个文件被%config(noreplace)指令配置。
此时包含如下情况:
该文件在新的rpm包里相对之前的rpm有变化,且在本地没有被修改过。
此时执行rpm -Uvh xxxx时,新rpm包里的该文件会替换旧的文件。(旧文件被删除)
该文件在新的rpm包里相对之前的rpm有变化,且在本地被修改过。
此时执行rpm -Uvh xxxx时,旧文件保持不变,新rpm包里的该文件并重命名为xx.rpmnew,例如/etc/redis/redis.conf.rpmnew
该文件在新的rpm包里相对之前的rpm没有变化,且在本地没有被修改过。
此时执行rpm -Uvh xxxx时,新rpm包里的该文件会替换旧的文件。(旧文件被删除)
该文件在新的rpm包里相对之前的rpm没有变化,且在本地被修改过。
此时执行rpm -Uvh xxxx时,新rpm包里的该文件不会覆盖旧的文件,旧文件保持不变。
总结如下:
如果一个文件在%files段没有被%config或%config(noreplace)指令配置;则执行rpm -Uvh时,该文件会无条件被新文件替换。
无论一个文件有没有被%config或%config(noreplace)指令配置,只要改文件在本地没有被编辑过,则执行rpm -Uvh时,该文件会被新文件替换。
一个被%config或%config(noreplace)指令配置的文件,如果被编辑过,那么在rpm更新时,如果新的rpm包中该文件没有修改,则该文件不会被新rpm包中的文件替换,之前做的编辑依然有效。
一个被%config指令配置的文件,如果被编辑过,且新的rpm包中该文件有修改,则该文件会被重命名为xx.rpmsave, 新文件会替代原文件。
一个被%config(noreplace)指令配置的文件,如果被编辑过,且新的rpm包中该文件有修改,则该文件不会被新的rpm包中的文件替换,之前做的编辑依然有效;但新rpm包中的同名文件会被重命名为xx.rpmnew.