diff options
author | Chris Johns <chrisj@rtems.org> | 2022-09-23 16:46:46 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2022-09-26 13:58:16 +1000 |
commit | b72413ca19c719458e31af461028a55079532139 (patch) | |
tree | 3ba7e3b4ed49570c526d1b0162d6a85391c3dbdd | |
parent | 2f84e3d78334193befd5d78f4d193ee910a6a2e4 (diff) |
pkg: Add packaging and support for RPM on Linux
-rw-r--r-- | pkg/__init__.py (renamed from builds.py) | 82 | ||||
-rw-r--r-- | pkg/configs.py | 156 | ||||
-rw-r--r-- | pkg/linux.py | 119 | ||||
-rw-r--r-- | pkg/rpm.spec.in | 98 | ||||
-rw-r--r-- | wscript | 105 |
5 files changed, 479 insertions, 81 deletions
diff --git a/builds.py b/pkg/__init__.py index 385d204..0b53f6d 100644 --- a/builds.py +++ b/pkg/__init__.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-2-Clause -""" -RSB Deployment Builds -""" +''' + Packaging Support +''' # # Copyright 2022 Chris Johns (chris@contemporary.software) @@ -28,30 +28,52 @@ RSB Deployment Builds # POSSIBILITY OF SUCH DAMAGE. # -configs = [ - { - 'buildset': 'test/arm-bsps-bad-opts', - 'good': False, - 'dry-run': True - }, - { - 'buildset': 'test/sparc-bsps', - 'good': True, - 'dry-run': True - }, - { - 'buildset': 'test/arm-bsps-opts', - 'good': True, - 'dry-run': True - }, - { - 'buildset': 'test/aarch64-config', - 'good': True, - 'dry-run': True - }, - { - 'buildset': 'test/aarch64-powerpc-config', - 'good': True, - 'dry-run': True - }, -] +import os + +import pkg.configs + +packager = None +if os.name == 'posix': + system = os.uname()[0] + if system == 'FreeBSD': + import pkg.freebsd as packager + elif system == 'Linux': + import pkg.linux as packager + + +def init(ctx): + pkg.configs.init(ctx) + packager.init(ctx) + + +def options(opt): + if packager is not None: + opt.add_option('--package', + action='store_true', + default=False, + dest='package', + help='Package build if supported and set up') + pkg.configs.options(opt) + packager.options(opt) + + +def configure(conf): + pkg.configs.configure(conf) + conf.env.PACKAGER = False + if packager is not None: + packager.configure(conf) + package_build = 'no' + if conf.options.package: + if not conf.env.PACKAGER: + conf.fatal( + 'Platform packager not supported or installed,' + \ + ' please fix to package build' + ) + package_build = 'yes' + conf.env.PACKAGE = True + conf.msg('Package build', package_build) + + +def build(bld, build, bset, dry_run): + if packager is not None: + packager.build(bld, build, bset, dry_run) diff --git a/pkg/configs.py b/pkg/configs.py new file mode 100644 index 0000000..1d39088 --- /dev/null +++ b/pkg/configs.py @@ -0,0 +1,156 @@ +# SPDX-License-Identifier: BSD-2-Clause +""" +RSB Deployment Configurations +""" + +# +# Copyright 2022 Chris Johns (chris@contemporary.software) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +import re +import os +import sys + +from waflib import Context + +path = 'config' + +configs = [ + { + 'buildset': 'test/arm-bsps-bad-opts', + 'good': False, + 'dry-run': True + }, + { + 'buildset': 'test/sparc-bsps', + 'good': True, + 'dry-run': True + }, + { + 'buildset': 'test/arm-bsps-opts', + 'good': True, + 'dry-run': True + }, + { + 'buildset': 'test/aarch64-config', + 'good': True, + 'dry-run': True + }, + { + 'buildset': 'test/aarch64-powerpc-config', + 'good': True, + 'dry-run': True + }, +] + + +def init(ctx): + pass + + +def options(opt): + opt.add_option('--builds', + default=None, + dest='builds', + help='Regex filter of buildset to build') + + +def configure(conf): + if conf.options.builds is not None: + try: + bf = re.compile(conf.options.builds) + build_filter = conf.options.builds + bf = 'yes' + except: + conf.fatal('Builds filter regex invalid') + else: + build_filter = None + bf = 'no' + conf.env.BUILD_FILTER = build_filter + conf.msg('Buildset filter', bf, color='GREEN') + + +def add_wscript_fun(ctx, fun_name, fun_func): + node = ctx.path.find_node(Context.WSCRIPT_FILE) + if node: + wscript_module = Context.load_module(node.abspath()) + setattr(wscript_module, fun_name, fun_func) + + +def find_buildsets(bld): + discovered = [] + for root, dirs, files in os.walk(path): + base = root[len('config') + 1:] + for f in files: + r, e = os.path.splitext(f) + if e == '.bset': + discovered += [os.path.join(base, r)] + bs_default = [bs['buildset'] for bs in configs] + bs = configs + [{ + 'buildset': b, + 'good': True, + 'dry-run': False + } for b in discovered if b not in bs_default] + if bld.env.BUILD_FILTER is not None: + bf = re.compile(bld.env.BUILD_FILTER) + bs = [b for b in bs if bf.match(b['buildset'])] + return sorted(bs, key=lambda bs: bs['buildset']) + + +def buildset(bld, build, dry_run): + name = os.path.basename(build['buildset']) + logs = bld.path.get_bld() + log = logs.make_node(name) + config = 'config/' + build['buildset'] + '.bset' + bset = bld.path.find_resource(config) + if buildset is None: + bld.fatal('buildset not found: ' + build['buildset']) + tardir = bld.path.make_node('tar') + tar = tardir.make_node(os.path.basename(build['buildset']) + '.tar.bz2') + cmd = bld.env.RSB_SET_BUILDER + opts = [ + '--prefix=' + bld.env.PREFIX, '--bset-tar-file', '--trace', + '--log=' + str(log.path_from(bld.path)) + '.txt' + ] + opts_extra = [] + if bld.env.NO_INSTALL: + opts_extra += ['--no-install'] + if build['dry-run'] or dry_run: + opts_extra += ['--dry-run'] + run_opts = opts + opts_extra + [build['buildset']] + pkg_opts = opts + ['--no-install', build['buildset']] + return { + 'name': name, + 'config': config, + 'buildset': bset, + 'log': log, + 'tardir': tardir, + 'tar': tar, + 'dry-run': build['dry-run'] or dry_run, + 'cmd': cmd, + 'opts': opts, + 'opts-extra': opts_extra, + 'run-opts': run_opts, + 'pkg-opts': pkg_opts + } diff --git a/pkg/linux.py b/pkg/linux.py new file mode 100644 index 0000000..3d59a1e --- /dev/null +++ b/pkg/linux.py @@ -0,0 +1,119 @@ +# SPDX-License-Identifier: BSD-2-Clause +""" +Linux Packaging Support + +Currently only RPM is supported. Happy to have more added +""" + +# +# Copyright 2022 Chris Johns (chris@contemporary.software) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +import os.path + +import pkg.configs + +from waflib import Build, TaskGen + + +@TaskGen.feature('rpmspec') +class rpmspecer(Build.BuildContext): + '''generate RPM spec files''' + cmd = 'rpmspec' + fun = 'rpmspec' + + +def _esc_name(s): + return s.replace('_', '-') + + +def _esc_label(s): + return s.replace('-', '_') + + +def _esc_path(s): + if type(s) != str: + s = str(s) + return s.replace('/', '\/') + + +def rpm_configure(conf): + try: + conf.find_program('rpmbuild', var='RPMBUILD', manditory=False) + conf.env.PACKAGER = True + except: + pass + conf.find_program('sed', var='SED') + + +def rpm_build(bld, build): + bset = pkg.configs.buildset(bld, build, dry_run=False) + spec_file = _esc_name(build['buildset']) + spec = bld.path.get_bld().find_or_declare(spec_file + '.spec') + buildroot = bld.path.get_bld().find_or_declare('buildroot') + sed = bld.env.SED[0] + ' ' + sed += "-e 's/@RSB_BUILDROOT@/%s/' " % (_esc_path(buildroot)) + sed += "-e 's/@RSB_PKG_NAME@/%s/' " % (_esc_path(bset['name'])) + sed += "-e 's/@PREFIX@/%s/' " % (_esc_path(bld.env.PREFIX)) + sed += "-e 's/@RSB_VERSION@/%s/' " % (bld.env.RSB_VERSION) + sed += "-e 's/@RSB_REVISION@/%s/' " % (_esc_label(bld.env.RSB_REVISION)) + if bld.env.RSB_RELEASED: + rel = 'released' + else: + rel = 'not-released' + sed += "-e 's/@RSB_RELEASED@/%s/' " % (rel) + sed += "-e 's/@TARFILE@/%s/' " % (_esc_path(bset['tar'])) + sed += "-e 's/@RSB_SET_BUILDER@/%s/' " % (_esc_path(bset['cmd'])) + sed += "-e 's/@RSB_SET_BUILDER_ARGS@/%s/' " % (_esc_path(' '.join( + bset['pkg-opts']))) + sed += "-e 's/@RSB_WORK_PATH@/%s/' " % (_esc_path(bld.path)) + sed += "-e 's/@RSB_WORK_PATH@/%s/' " % (_esc_path(bld.path)) + rpm_name = 'rpmspec/' + bset['name'] + bld(name=rpm_name, + features='rpmspec', + description='Generate RPM spec file', + target=spec, + source=['pkg/rpm.spec.in', bset['config']], + rule=sed + ' < ${SRC[0]} > ${TGT}') + + +def rpmspec(bld): + for build in pkg.configs.find_buildsets(bld): + rpm_build(bld, build) + + +def init(ctx): + pkg.configs.add_wscript_fun(ctx, 'rpmspec', rpmspec) + + +def options(opt): + pass + + +def configure(conf): + rpm_configure(conf) + + +def build(bld, build, bset, dry_run): + pass diff --git a/pkg/rpm.spec.in b/pkg/rpm.spec.in new file mode 100644 index 0000000..46dbba4 --- /dev/null +++ b/pkg/rpm.spec.in @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: BSD-2-Clause + +# +# RTEMS Deloyment RPM spec file template +# + +# +# Copyright 2022 Chris Johns (chris@contemporary.software) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +%global _enable_debug_package 0 +%global debug_package %{nil} +%global __os_install_post /usr/lib/rpm/brp-ldconfig %{nil} +%global __os_install_post /usr/lib/rpm/brp-compress %{nil} + + +# Build subst, collect here +%define rsb_buildroot @RSB_BUILDROOT@ +%define rsb_version @RSB_VERSION@ +%define rsb_revision @RSB_REVISION@ +%define rsb_pkg_name @RSB_PKG_NAME@ +%define rsb_prefix @PREFIX@ +%define rsb_tarfile @TARFILE@ +%define rsb_set_builder @RSB_SET_BUILDER@ +%define rsb_set_builder_args @RSB_SET_BUILDER_ARGS@ +%define rsb_work_path @RSB_WORK_PATH@ + + +# Use a buildroot under this repo build path +%define _topdir %{rsb_buildroot} + + +# Package +%define name rtems-%{rsb_pkg_name} +%define arch noarch + + +# Package details +Name: %{name} +Version: %{rsb_version} +Release: %{rsb_revision}%{?dist} +Summary: RTEMS tools and board support package +License: GPLv2, GPLv3, BSD-2 + + +%description +This RPM is development tools and BSP for RTEMS + + +%prep +# We have no source because configure options supplied the path + + +%build +# The RSB deployment build command +cd %{rsb_work_path} +%{rsb_set_builder} %{rsb_set_builder_args} + +%install +if test -d %{buildroot}; then + rm -rf %{buildroot} +fi +mkdir -p %{buildroot} +tar jxf %{rsb_tarfile} -C %{buildroot} + + +%clean +rm -rf %{buildroot} + + +%files +%defattr(-,root,root) +%dir %{rsb_prefix} +%{rsb_prefix}/* + + +%changelog @@ -36,12 +36,14 @@ import errno import itertools import os import os.path +import re import shutil +import sys # # Provide a set of builds with special settings # -import builds +import pkg from waflib import Context, Build, Errors, Logs, Scripting, Task, TaskGen, Utils @@ -84,6 +86,7 @@ class set_builder_task(Task.Task): class set_builder_task_run(set_builder_task): '''run the build, run after dry-run tasks so they checked first''' ext_in = ['dry-run'] + ext_out = ['tarfile'] class set_builder_task_dry_run(set_builder_task): @@ -92,7 +95,7 @@ class set_builder_task_dry_run(set_builder_task): @TaskGen.taskgen_method -@TaskGen.feature('*') +@TaskGen.feature('setbuilder') def set_builder_generator(self): if getattr(self, 'dry_run', None): task_type = 'set_builder_task_dry_run' @@ -106,12 +109,14 @@ def set_builder_generator(self): tsk.rsb_cmd = getattr(self, 'rsb_cmd', None) +@TaskGen.feature('setbuilder') class shower(Build.BuildContext): '''show the builds for a version of RTEMS''' cmd = 'show' fun = 'show' +@TaskGen.feature('setbuilder') class dry_runner(Build.BuildContext): '''runs the build sets with --dry-run''' cmd = 'dry-run' @@ -119,50 +124,24 @@ class dry_runner(Build.BuildContext): def set_builder_build(bld, build, dry_run=False, show=False): - name = os.path.basename(build['buildset']) - logs = bld.path.get_bld() - log = logs.make_node(name) - cmd = [bld.env.RSB_SET_BUILDER, '--prefix=' + bld.env.PREFIX] - if bld.env.NO_INSTALL: - cmd += ['--no-install'] - cmd += ['--bset-tar-file'] - if build['dry-run'] or dry_run: - cmd += ['--dry-run'] - cmd += [ - '--trace', '--log=' + str(log.path_from(bld.path)) + '.txt', - build['buildset'] - ] + bset = pkg.configs.buildset(bld, build, dry_run) + run_cmd = [bset['cmd']] + bset['run-opts'] if show: - print(build['buildset'] + ':', ' '.join(cmd)) + print(build['buildset'] + ':', ' '.join(bset['run_cmd'])) else: - config = 'config/' + build['buildset'] + '.bset' - buildset = bld.path.find_resource(config) - if buildset is None: - bld.fatal('buildset not found: ' + build['buildset']) bld(name=build['buildset'], + description='Build tar file', + features='setbuilder', + target=bset['tar'], base=bld.path, good=build['good'], - dry_run=build['dry-run'] or dry_run, - rsb_cmd=' '.join(cmd), + dry_run=bset['dry-run'], + rsb_cmd=' '.join(run_cmd), always=True) -def find_buildsets(version): - path = 'config' - discovered = [] - for root, dirs, files in os.walk(path): - base = root[len('config') + 1:] - for f in files: - r, e = os.path.splitext(f) - if e == '.bset': - discovered += [os.path.join(base, r)] - bs_default = [bs['buildset'] for bs in builds.configs] - bs = builds.configs + [{ - 'buildset': b, - 'good': True, - 'dry-run': False - } for b in discovered if b not in bs_default] - return sorted(bs, key=lambda bs: bs['buildset']) +def init(ctx): + pkg.init(ctx) def options(opt): @@ -179,6 +158,8 @@ def options(opt): default=False, dest='install', help='RSB Install mode') + pkg.options(opt) + pkg.configs.options(opt) def configure(conf): @@ -191,28 +172,50 @@ def configure(conf): 'sb-set-builder') if not os.path.exists(rsb_set_builder): conf.fatal('RSB path not the valid: ' + rsb_path) - conf.msg('RSB', rsb_path, 'GREEN') - conf.msg('RSB Prefix', conf.options.prefix, 'GREEN') + conf.msg('RSB', rsb_path, color='GREEN') + # Get the version details from the RSB + sys_path = sys.path + try: + sys.path = [os.path.join(rsb_path, 'source-builder', 'sb')] + sys.path + import version as rsb + rsb_version = rsb.version() + rsb_revision = rsb.revision() + rsb_released = rsb.released() + except: + raise + conf.fatal('cannot get the RSB version information') + finally: + sys.path = sys_path + conf.msg('RSB Version', rsb_version, color='GREEN') + if 'modified' in rsb_revision: + col = 'YELLOW' + else: + col = 'GREEN' + conf.msg('RSB Revision', rsb_revision, color=col) + if rsb_released: + conf.msg('RSB Released', 'yes', color='GREEN') + else: + conf.msg('RSB Released', 'no', color='YELLOW') + conf.msg('RSB Prefix', conf.options.prefix, color='GREEN') if conf.options.install: install = 'install' else: install = 'no-install' - conf.msg('RSB Install mode', install, 'GREEN') + conf.msg('RSB Install mode', install, color='GREEN') conf.env.RSB_PATH = rsb_path conf.env.RSB_SET_BUILDER = rsb_set_builder + conf.env.RSB_VERSION = rsb_version + conf.env.RSB_REVISION = rsb_revision + conf.env.RSB_RELEASED = rsb_released conf.env.PREFIX = conf.options.prefix conf.env.NO_INSTALL = not conf.options.install + pkg.configure(conf) def build(bld): - dry_runs = [ - build for build in find_buildsets(bld.env.RTEMS_VERSION) - if build['dry-run'] - ] - tars = [ - build for build in find_buildsets(bld.env.RTEMS_VERSION) - if not build['dry-run'] - ] + builds = pkg.configs.find_buildsets(bld) + dry_runs = [build for build in builds if build['dry-run']] + tars = [build for build in builds if not build['dry-run']] for build in dry_runs: set_builder_build(bld, build) for build in tars: @@ -244,10 +247,10 @@ def distclean(ctx): def show(bld): - for build in find_buildsets(bld.env.RTEMS_VERSION): + for build in pkg.configs.find_buildsets(bld): set_builder_build(bld, build, show=True) def dry_run(bld): - for build in find_buildsets(bld.env.RTEMS_VERSION): + for build in pkg.configs.find_buildsets(bld): set_builder_build(bld, build, dry_run=True) |