# SPDX-License-Identifier: BSD-2-Clause """ Deployment regression tests This can be a template for using waf to run the RSB. """ # # 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. # from __future__ import print_function import errno import itertools import os import os.path import re import shutil import sys # # Provide a set of builds with special settings # import pkg from waflib import Context, Build, Errors, Logs, Scripting, Task, TaskGen, Utils out = 'out' class set_builder_task(Task.Task): always_run = True semaphore = Task.TaskSemaphore(1) def __str__(self): return self.name def uid(self): return Utils.h_list(self.name) def run(self): r = 0 out = None err = None try: self.generator.bld.cmd_and_log(self.rsb_cmd, cwd=self.base, quiet=Context.BOTH) except Errors.WafError as e: out = e.stdout err = e.stderr r = 1 if not self.good: if r == 0: r = 1 else: r = 0 if r != 0: self.generator.bld.to_log(err) self.generator.bld.to_log('rsb cmd: ' + self.rsb_cmd + os.linesep) return r 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): '''build is a dry run''' ext_out = ['dry-run'] @TaskGen.taskgen_method @TaskGen.feature('setbuilder') def set_builder_generator(self): if getattr(self, 'dry_run', None): task_type = 'set_builder_task_dry_run' else: task_type = 'set_builder_task_run' tsk = self.create_task(task_type) tsk.name = getattr(self, 'name', None) tsk.base = getattr(self, 'base', None) tsk.config = getattr(self, 'config', None) tsk.good = getattr(self, 'good', None) 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' fun = 'dry_run' @TaskGen.feature('html') class docs_builder(Build.BuildContext): '''build the documentation as html''' cmd = 'docs' fun = 'docs' def set_builder_build(bld, build, dry_run=False, show=False): bset = pkg.configs.buildset(bld, build, dry_run) run_cmd = [bset['cmd']] + bset['run-opts'] if show: print(build['buildset'] + ':', ' '.join(run_cmd)) else: bld(name=build['buildset'], description='Build tar file', features='setbuilder', target=bset['tar'], base=bld.path, good=build['good'], dry_run=bset['dry-run'], rsb_cmd=' '.join(run_cmd), always=True) def init(ctx): pkg.init(ctx) def options(opt): opt.add_option('--rsb', default=None, dest='rsb_path', help='Path to the RTEMS Source Builder (RSB)') opt.add_option('--prefix', default='/opt/rtems/deploy', dest='prefix', help='RSB prefix path to install the packages too') opt.add_option('--install', action='store_true', default=False, dest='install', help='RSB Install mode') pkg.options(opt) pkg.configs.options(opt) def configure(conf): if conf.options.rsb_path is None: conf.fatal('RSB path not provided as configure option') if not os.path.exists(conf.options.rsb_path): conf.fatal('RSB path not found: ' + conf.options.rsb_path) rsb_path = os.path.abspath(conf.options.rsb_path) rsb_set_builder = os.path.join(rsb_path, 'source-builder', '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, color='GREEN') # Get the version details from the RSB sys_path = sys.path try: rsb = None try: sys.path = [os.path.join(rsb_path, 'source-builder')] + sys.path import sb.version as rsb except: sys.path = [os.path.join(rsb_path, 'source-builder', 'sb')] + sys.path import version as rsb if rsb is None: conf.fatal('cannot import RSB version') rsb.set_top(rsb_path) 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, color='GREEN') conf.find_program('pandoc', var='PANDOC', manditory=False) 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): if bld.cmd == 'install': print('Nothing to install') return 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: set_builder_build(bld, build) bld.clean_files = \ itertools.chain(bld.bldnode.ant_glob('**', excl='.lock* config.log c4che/* config.h', quiet=True, generator=True), bld.path.ant_glob('tar/**', quiet=True, generator=True)) def distclean(ctx): '''removes build folders and data''' def remove_and_log(k, fun): try: fun(k) except EnvironmentError as e: if e.errno != errno.ENOENT: Logs.warn('Could not remove %r', k) Scripting.distclean(ctx) for d in ['build', 'tar']: remove_and_log(d, shutil.rmtree) for f in os.listdir('.'): r, e = os.path.splitext(f) if e == '.txt': remove_and_log(f, os.remove) def show(bld): for build in pkg.configs.find_buildsets(bld): set_builder_build(bld, build, show=True) def dry_run(bld): for build in pkg.configs.find_buildsets(bld): set_builder_build(bld, build, dry_run=True) def docs(bld): if not bld.env.PANDOC: bld.fatal('no pandoc found during configure') bld(name='css', features='subst', source='doc/rtems.css', target='rtems.css', is_copy=True) title = 'RTEMS Deployment' pandoc_std_opts = [ '-f markdown_phpextra+grid_tables+multiline_tables+simple_tables+auto_identifiers', '--section-divs', '--toc', '-M title="%s"' % (title), '-t html', '--include-in-header=rtems.css' ] bld(name='html', source='README.md', target='README.html', rule=bld.env.PANDOC[0] + ' ${SRC} ' + ' '.join(pandoc_std_opts) + ' > ${TGT}', use='css')