自动化编译原理

来自Ubuntu中文
Manbuzhe留言 | 贡献2013年1月18日 (五) 11:29的版本 (以内容'= 自动化编译工具设计 = <pre> 1 实现有效的对不同仓库有效管理,原子事务型的添加,删除,以及对项目生命周期结束后对整个项…'创建新页面)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航跳到搜索

自动化编译工具设计

1 实现有效的对不同仓库有效管理,原子事务型的添加,删除,以及对项目生命周期结束后对整个项目归档后,删除
2 采用XML作为后端数据库,减少资源占用
3 支持集中式和分布式编译,
4 依据RPM打包时定义的组别自动生成分组文件,rpm(comps.xml)
存储中心 : 采用软件包池的概念,文件快照只是指向软件包池的硬链接,最近的软件仓库只是指向硬链接的目录,仓库的变化不会直接影响软件包池中,只允许向软件包池进行提交操作,每次提交操作都会和触发仓库的更新

软件仓库自动创建:


客户端: 采用xml_rpc

编译任务分发
邮件通知 
版本自动发布

自动化测试

分布式编译:
集中样式编译:


仓库结构

/pools
/snap
/repo/arch
/DB

pbuilder

pbuilder --create

mock 的基本使用

创建配置文件 /etc/mock/RG6.0.cfg

config_opts['root'] = 'regulus-0.1'
config_opts['target_arch'] = 'mips64el'
config_opts['chroot_setup_cmd'] = 'groupinstall build'
config_opts['dist'] = 'RG6.0'  # only useful for --resultdir variable subst
# ccache not available on epel4
config_opts['plugin_conf']['ccache_enable'] = False

config_opts['yum.conf'] = """
[main]
cachedir=/var/cache/yum
debuglevel=1
logfile=/var/log/yum.log
reposdir=/dev/null
retries=20
obsoletes=1
gpgcheck=0
assumeyes=1

# repos
[local]
name=local
baseurl=http://110.76.44.83/mirrors
cost=2000
enabled=1
"""

创建编译任务

mock -r RG6.0 --init 
mock -r RG6.0 --rebuild mksh-39-4.RG6.0.src.rpm

mock的原理分析

在所有包管理系统中,能够在当前系统环境下制作出安装包,并不代表这个安装包的封装过程是严谨的,重复使用当前环境来打包多多少少都会带来缺少正确性验证的问题,于是主流的包管理系统都引入了可以解决这些问题的工具。

  1. deb包管理系统对应是: pbuilder
  2. rpm包管理系统对应是: mock

引用一段debian网站文档的原文

it is an automatic Debian Package Building system for personal development workstation environments. 
pbuilder aims to be an easy-to-setup system for auto-building Debian packages inside a clean-room environment

这两个工具的核心思想都是为一次build都创建一个干净的编译环境,然后以chroot方式在这个环境内来编译软件包,而这一切都依赖chroot。

chroot 概述

chroot 就是Change Root,也就是改变应用程序执行时所参考的根目录位置.chroot操作后运行的所有程序都是指定的根目录下的程序.在一些复杂的应用中,简单的chroot操作是不够,我们还需要更多的准备工作(假设制定的根目录为/mnt/taget_os):

在指定目录中创建必要的文件与目录

export rootdir=/mnt/taget_os
mkdir -pv ${rootdir}/{dev,proc,sys}            #建立 设备文件目录,程序信息与系统设置目录,系统分类信息目录
mkdir -pv ${rootdir}/dev/{pts,shm}              #建立 设备控制台目录和一个LINUX专门用来分享内存需要的目录

将制定目录中必要的文件系统挂载

mount -v --bind /dev ${rootdir}/dev            #由于硬件设备信息是系统系统后初始化的,我们只能将现有的设备信息映射过来 
mount -n -t proc proc ${rootdir}/proc          #挂载proc 文件系统
mount -n -t sysfs sysfs ${rootdir}/sys         #挂载sys  文件系统
mount -n -t devpts -o gid=5,mode=620,newinstance devpts ${rootdir}/dev/pts
mount -n -t tmpfs shmfs ${rootdir}/dev/shm
                                               #把设备控制台和内存共享相关的两个目录也挂在起来

mock编译一个软件包的过程简述

  • mock 在完成上述操作后(实际情况是更多的操作,mock开发者会有更周全的考虑,这里只是个对必要部分的演示),特别是第一次初始化最小系统的时候,会执行
yum groupinstall build --installroot=${rootdir},
  • 接下来就是每次编译重构系统环境使用包管理工具包要解决要编译的源码包的依赖关系,将全部的需要的软件包都安装到这个目录下
  • 最后 chroot进入该环境开始编译软件包...

使用净室编译虽然更加浪费时间,但是带来的好处是最大限度的减少外界环境的干扰,能有效保证源码包的编写的正确性,因为许多隐藏的潜在问题,可以轻易地在净室编译过程中显现,但是mock不是完美的,最近就遇到过宿主系统的 JAVA_HOME 变量干扰了mock的编译环境导致编译任务失败!

模拟系统安装程序从软件仓库安装出一个koji编译机器


export rootdir=/mnt/taget_os
mkdir -pv ${rootdir}/{dev,proc,sys}            
mkdir -pv ${rootdir}/dev/{pts,shm}              
mount -v --bind /dev ${rootdir}/dev            
mount -n -t proc proc ${rootdir}/proc          
mount -n -t sysfs sysfs ${rootdir}/sys         
mount -n -t devpts -o gid=5,mode=620,newinstance devpts ${rootdir}/dev/pts
mount -n -t tmpfs shmfs ${rootdir}/dev/shm

yum install koji-builder mock koji-utils rpm-build createrepo openssh-server openssh-clients --installroot=/mnt/taget_os

umount ${rootdir}/dev/pts
umount ${rootdir}/dev/shm
umount ${rootdir}/sys
umount ${rootdir}/proc
umount ${rootdir}/dev