开发者可使用gbs build在本地编译源代码然后生成RPM包.使用这个命令:gbs build --help可以获取关于子命令build的帮助指南.
本地仓库支持二种类型:
注意:在输出仓库(默认是~/GBS-ROOT/local/repos/<VERSION>/)的所有的RPM包在编译软件包时都用到.也就是说,在输出仓库的所有软件包都会被用在创建编译环境,所以如果你不想要这种行为, 保证输出仓库里没有其他内容.
如果改变了提交或者指定选项--include-all,总是会重新编译,这时--overwrite就没必要了.
例如:
这种模式主要用来单个包的开发和验证,不能替代标准 的编译方式.这种模式下一次只能编译一个包.
这种模式分成多步来设置编译环境,把本地的Git目录绑定到chroot的编译目录后就完成了.
注意:因为gbs会把git目录绑定到buid root,所以当要删除build root时要十分的小心.要确定删除前已经手动的把源码解绑定.
这种模式有以下优点:
这种方法也有一些局限性,都是关于打包和代码的管理.尤其是依赖于RPM的spec文件:
从编译的日志看出只有log.c重新编译了.这就是增量编译的做法.也是目前增量编译的一个局限.
可以像这样与--incremental选项一起使用--noinit来加速编译:
具体的一些限制:
选项--binary-list指定一个以逗号分隔包名的列表.
当包的数量很小,特别是包的名字能够清楚的在命令中写出时,出于简洁的目的推荐用选项--binary-list:
选项--exclude-from-file可以用于指定一个含有要忽略的包的名字的文件.
具体的包可以用--binary-from-file或--binary-list选项来包含, 也可以用选项--exclude或--exclude-from-file来排除.
二个选项是兼容的.如果同时指定,除了特定的包,GBS不但编译它们所依赖的包,还会编译依赖于这些包的相关包.
gbs build -h
gbs build工作流程
gbs build所需输入
下面所列的是gbs build的输入:
- 包含RPM打包文件的一个(或多个)git项目
- 二进制RPM软件包仓库(远程或本地)
- 项目编译的配置选项(宏,开关等)
本地仓库支持二种类型:
- 带有仓库元信息的标准仓库
- 含有RPM软件包的普通目录.GBS在这个目录下能够找到所有的软件包
编译的流程
gbs编译的输入和输出都是仓库.注意:在输出仓库(默认是~/GBS-ROOT/local/repos/<VERSION>/)的所有的RPM包在编译软件包时都用到.也就是说,在输出仓库的所有软件包都会被用在创建编译环境,所以如果你不想要这种行为, 保证输出仓库里没有其他内容.
这是gbs build的基本流程:
____________________ | | ___________ | Source Code (GIT) |---->| | _________________________ |____________________| | | | | | | | Local repository of | ____________________ | GBS Build |---->| build RPM packages | | | | | |(~/GBS-ROOT/local/repos/)| |Binary repositories | | | |_________________________| |in GBS conf |---->|___________| | |(Remote or Local) | ^ | |____________________| |________________________|
从上面的图可能看出输入和输出都在仓库之中并且输出仓库默认是在"~/GBS-ROOT/local/repos".可以用--buildroot选项指定不同的build root来改变仓库的路径.
- GBS build默认会把所有的输出文件都放在~/GBS-ROOT里
- 如果存在环境变量TIZEN_BUILD_ROOT,其值$(TIZEN_BUILD_ROOT)用来做build root
- 如果使用-B选项,那么就用-B选项的参数作为build root,即使环境变量$(TIZEN_BUILD_ROOT)有值
gbs build的输出
gbs build root的目录结构:gbs output top dir |-- local | |-- cache # repodata and RPMs from remote repositories | |-- repos # generated local repo top directory | | |-- tizen # distro one: tizen | | | |-- armv7l # store armv7l RPM packages | | | |-- i586 # store x86 RPM packages | | `-- tizen2.0 # build for distro two: tizen2.0 | | `-- i586 # the same as above | |-- scratch.armv7l.0 # first build root for arm build | |-- scratch.i586.0 # second build root for x86 build | |-- scratch.i586.1 # third build root for x86 build | |-- scratch.i586.2 # fourth build root for x86 build | |-- scratch.i586.3 # fifth build root for x86 build | | # The above build root dir can be used by gbs chroot <build root dir> | `-- sources # sources generated for build, including tarball, spec, patches, etc. | |-- tizen | `-- tizen2.0 `-- meta # meta data used by gbs
GBS Build 例子(基础用法)
1. 编译单个包
$ cd package1
$ gbs build -A i586
2. 为不同的架构平台编译包
$ gbs build -A armv7l #build package for armv7l
$ gbs build -A i586 #build package for i586
3. 删除旧的build root完全重新编译.如果软件包仓库已经改变时这个选项必须使用,比如当改变成发行版的软件仓库时.
$ gbs build -A armv7l --clean
4. 使用某一次特定的提交编译
$ gbs build -A armv7l --commit=<COMMIT_ID>
5. 用--overwrite触发一次重新编译
如果以前已经编译过然后想重新编译, 应该使用--overwrite,否则包可以会被跳过.$ gbs build -A i586 --overwrite
如果改变了提交或者指定选项--include-all,总是会重新编译,这时--overwrite就没必要了.
6. 输出调试信息
$ gbs build -A i586 --debug
7.指定某个本地仓库来编译.可以在.gbs.conf或者通过命令行来配置本地仓库
$ gbs build -R /path/to/repo/dir/ -A i586
8.用选项--noinit来离线编译
当build root是就绪的就可以使用选项--noinit.使用--noinit选项时,gbs不会连接远程仓库并且会跳过解析检查仓库和初始化编译环境.直接使用rpmbuild编译包.例如:
$ gbs build -A i586 # build first and create build environment
$ gbs build -A i586 --noinit # use --noinit to start building directly
9.用--include-all来编译所有的未提交的改动
例如,git目录中包含一个改动的文件和二个新加的文件$ git status -s
M ail.pc.in
?? base.repo
?? main.repo
- 不用--include-all编译
仅编译已提交的文件.所有未提交或未添加到版本控制的文件都不会被编译:
$ gbs build -A i586 warning: the following untracked files would NOT be included: base.repo main.repo warning: the following uncommitted changes would NOT be included: ail.pc.in warning: you can specify '--include-all' option to include these uncommitted and untracked files. .... info: Binaries RPM packages can be found here: /home/test/GBS-ROOT/local/scratch.i586.0/home/abuild/rpmbuild/RPMS/ info: Done
- 使用--include-all来编译所有的文件:
$ gbs build -A i586 --include-all info: the following untracked files would be included: base.repo main.repo info: the following un-committed changes would be included: ail.pc.in info: export tar ball and packaging files ... ... [build finished]
- 当使用--incldue-all时可以用.gitignore来忽略特定的文件.如果要想忽略某类型文件可以修改.gitignore,例如:
$ cat .gitignore .* */.* *.pyc *.patch*
增量编译
增量的概念
从gbs 0.10,gbs子命令build就支持增量式的编译,通过指定--incremental选项来启用.这种模式主要用来单个包的开发和验证,不能替代标准 的编译方式.这种模式下一次只能编译一个包.
这种模式分成多步来设置编译环境,把本地的Git目录绑定到chroot的编译目录后就完成了.
注意:因为gbs会把git目录绑定到buid root,所以当要删除build root时要十分的小心.要确定删除前已经手动的把源码解绑定.
这种模式有以下优点:
- 编译环境总能够使用最新的源代码且代码的改动不会触发一个新的编译环境(也就是对编译环境的修改).
- git目录变成了编译的目录.任何git中的改动,只要运行编译脚本所做的修改就能够得到编译
- 如果 由于某种原因导致编译失败,一旦导致编译失败的错误被修正,编译脚本会从先前失败的地方接着编译.
这种方法也有一些局限性,都是关于打包和代码的管理.尤其是依赖于RPM的spec文件:
- 不支持spec文件中的patches.所有的源码必须是git目录的一部分
- 需要一个整洁的打包流程.spec文件中的极特殊的流程可能不会有效,因为这种模式预期以下模型:
- 代码准备(%prep)
- 代码编译(%build)
- 代码安装(%install)
- 因为每次都运行编译部分,如果%build脚本有自动配置脚本,二进制文件会被重新生成,导致每次都完整编译.为了避免这样,推荐使用下面的宏,这些宏能够用--no-configure选项来覆盖:
- %configure: 运行带有预定义的路径和选项的配置脚本
- %reconfigure:重新生成脚本然后运行%configure
- %autogen:运行自动创建脚本
实例
在这个例子里,使用dlog的源代码.首先,需要 用--incremental选项来编译,然后直接修改一个源文件,然后再增量编译.可以看到在增量编译时仅仅是被修改的源码才被编译:$ cd dlog
# first build:
$ gbs build -A i586 --incremental
$ vim log.c # change code
# second build:
$ gbs build -A i586 --incremental
info: generate repositories ...
info: build conf has been downloaded at:
/var/tmp/test-gbs/tizen.conf
info: Start building packages from: /home/test/packages/dlog (git)
info: Prepare sources...
info: Retrieving repo metadata...
info: Parsing package data...
info: *** overwriting dlog-0.4.1-5.1 i586 ***
info: Next pass:
dlog
info: *** building dlog-0.4.1-5.1 i586 tizen (worker: 0) ***
info: Doing incremental build
[ 0s] Memory limit set to 10854336KB
[ 0s] Using BUILD_ROOT=/home/test/GBS-ROOT/local/scratch.i586.0
[ 0s] Using BUILD_ARCH=i686:i586:i486:i386:noarch
[ 0s] test-desktop started "build dlog.spec" at Thu Sep 13 07:36:14 UTC 2012.
[ 0s] -----------------------------------------------------------------
[ 0s] ----- building dlog.spec (user abuild)
[ 0s] -----------------------------------------------------------------
[ 0s] -----------------------------------------------------------------
[ 0s] + rpmbuild --short-circuit -bc /home/abuild/rpmbuild/SOURCES/dlog.spec
[ 0s] Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.XLz8je
[ 0s] + umask 022
[ 0s] + export LD_AS_NEEDED
[ 4s] + make -j4
[ 4s] make all-am
[ 4s] make[1]: Entering directory /home/abuild/rpmbuild/BUILD/dlog-0.4.1
[ 4s] /bin/sh ./libtool --tag=CC --mode=compile gcc -c -o log.lo log.c
[ 4s] mv -f .deps/log.Tpo .deps/log.Plo
[ 4s] /bin/sh ./libtool --tag=CC --mode=link gcc -o libdlog.la /usr/lib log.lo
[ 4s] libtool: link: gcc -shared .libs/log.o -o .libs/libdlog.so.0.0.0
[ 4s] libtool: link: ar cru .libs/libdlog.a log.o
[ 4s] libtool: link: ranlib .libs/libdlog.a
[ 4s] make[1]: Leaving directory /home/abuild/rpmbuild/BUILD/dlog-0.4.1
[ 4s] + exit 0
[ 4s] finished "build dlog.spec" at Thu Sep 13 07:36:18 UTC 2012.
[ 4s]
info: finished incremental building dlog
info: Local repo can be found here:
/home/test/GBS-ROOT/local/repos/tizen/
info: Done
从编译的日志看出只有log.c重新编译了.这就是增量编译的做法.也是目前增量编译的一个局限.
可以像这样与--incremental选项一起使用--noinit来加速编译:
$ gbs build --incremental --noinit
增量编译的局限
增量编译不支持多个包.具体的一些限制:
- 目前增量编译方式仅支持一个包.不支持并行的编译多个包.
- spec文件中的压缩包名字必须是%{name}-%{version}.{tar.gz|tar.bz2|zip|...},否则GBS无法正确把源码绑定到build root中.
- %prep部分应该仅包含用于解圧压缩包的%setup宏,而不应该含有对源代码的其他操作,比如解压其他源码或打patch等都不允许.
多个包的编译
从gbs0.10开始就支持多个包的编译.如果包有相互的依赖,gbs会计算出它们之间的关系然后按正确的顺序来编译.作为依赖编译,先前编译出的RPM包会用来编译后面的有依赖需求的包.实例:
1.编译某一包目录下的所有的包
$ mkdir tizen-packages
$ cp package1 package2 package3 ... tizen-packages/
$ gbs build -A i586 tizen-packages # build all packages under tizen-packages
2.使用--threads选项来并行的编译多个包
# current directory have multiple packages, --threads can be used to set the max build worker at the same time $ gbs build -A armv7l --threads=4
3.选择性的编译一组包
选项--binary-from-file指定一个含有要编译的RPM包名字的列表的文本文件.文本文件的格式是一个包名占一行.选项--binary-list指定一个以逗号分隔包名的列表.
当包的数量很小,特别是包的名字能够清楚的在命令中写出时,出于简洁的目的推荐用选项--binary-list:
$ gbs build -A i586 --binary-from-file=/path/to/packages.list
$ gbs build -A i586 --binary-list=<pkg1>,<pkg2>
4.排除某些包
选项--exclude可以用于指定一个以逗号分隔的要忽略的包的名字的列表.选项--exclude-from-file可以用于指定一个含有要忽略的包的名字的文件.
$ gbs build -A i586 tizen-packages --exclude=<pkg1>
$ gbs build -A i586 tizen-packages --exclude=<pkg1>,<pkg2>
$ gbs build -A i586 tizen-packages --exclude-from-file=/path/to/packages.list
5.基于依赖来编译包
选项--deps可以让GBS编译某个包,同时编译这些包所依赖的所有相关包.选项--rdep可以让GBS编译某个包,同时编译所有依赖于这些包的相关包.具体的包可以用--binary-from-file或--binary-list选项来包含, 也可以用选项--exclude或--exclude-from-file来排除.
二个选项是兼容的.如果同时指定,除了特定的包,GBS不但编译它们所依赖的包,还会编译依赖于这些包的相关包.
$ gbs build -A i586 --binary-list=<pkg1,pkg2> --deps #编译pkg1和pkg2,以及pkg1和pkg2所依赖的相关包
$ gbs build -A i586 --binary-list=<pkg1,pkg2> --rdeps #编译pkg1和pkg2,以及依赖pkg1和pkg2的相关包
$ gbs build -A i586 --binary-list=<pkg1,pkg2> --deps --rdeps #编译pkg1和pkg2,以及pkg1和pkg2所依赖的相关包,还有依赖于pkg1的pkg2相关包.
其他有用的选项
在build root中安装额外的包:
$ gbs build --extra-packs=vim,zypper,gcc,gdb ...
保留build root中的现有包:
通常情况下,gbs build会把build root中的不需要的包删除掉.当要编译另外的包时可以使用--keep-packs选项来保留不再需要的包而只安装缺失的依赖包.这个选项可以加速多个包的编译.
$ gbs build --keep-packs
--keep-packs选项可以用来为多个包创建一个build root.一旦build root就绪,就可以用--noinit选项来快速的编译这些包.
$ gbs build pkg1/ --keep-packs -A i586
$ gbs build pkg2/ --keep-packs -A i586
$ gbs build pkg3/ --keep-packs -A i586
现在,build root(~/GBS-ROOT/local/scratch.i586.0)主准备好编译pkg1,pkg2和pkg3.可以用--noinit离线的编译它们,不必浪费时间去检查repo的更新和检查build root了.
$ gbs build pkg1 --noinit
$ gbs build pkg2 --noinit
$ gbs build pkg3 --noinit
(对于高级用户)获取项目的编译配置和定制build root
项目编译配置描述针对项目的配置信息,包括编译环境里的预定义的宏,包和开关.在Tizen的发布版本里,编译配置也在发布的仓库里一同发布了.可以在http://download.tizen.org/releases/daily/trunk/ivi/latest/builddata/xxx-build.conf找到例子.- gbs build会自动的获取编译配置
默认地,从0.71起, 如果指定了远程仓库, gbs会从远程仓库中取编译配置然后存储到临时的环境中.
这是编译日志:
$ gbs build -A i586 info: generate repositories ... info: build conf has been downloaded at: /var/tmp/<user>-gbs/tizen2.0.conf info: generate tar ball: packaging/acpid-2.0.14.tar.bz2 [sudo] password for <user>:
- 用-D选项来指定,如果想要使用自己的项目编译配置来编译包.
可以保存并修改然后用于自己的目的:
如果需要定制编译配置,可以参考http://en.opensuse.org/openSUSE:Build_Service_prjconf
原文:gbs build