#!/usr/bin/env python # Copyright Rene Rivera 2016 # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) import os.path import shutil import sys from common import toolset_info, main, utils, script_common, ci_cli, set_arg __dirname__ = os.path.dirname(os.path.realpath(__file__)) class script(script_common): ''' Main script to test a Boost C++ Library. ''' def __init__(self, ci_klass, **kargs): script_common.__init__(self, ci_klass, **kargs) def init(self, opt, kargs): opt.add_option( '--toolset', help="single toolset to test with" ) opt.add_option( '--target', help="test target to build for testing, defaults to TARGET or 'minimal'") opt.add_option( '--address-model', help="address model to test, ie 64 or 32" ) opt.add_option( '--variant', help="variant to test, ie debug, release" ) set_arg(kargs, 'toolset', os.getenv("TOOLSET")) set_arg(kargs, 'target', os.getenv('TARGET', 'minimal')) set_arg(kargs, 'address_model', os.getenv("ADDRESS_MODEL",None)) set_arg(kargs, 'variant', os.getenv("VARIANT","debug")) set_arg(kargs, 'cxxflags', os.getenv("CXXFLAGS",None)) return kargs def start(self): script_common.start(self) # Some setup we need to redo for each invocation. self.boost_root = os.path.join(self.ci.work_dir,'boostorg','boost') @property def repo_path(self): if not hasattr(self,'_repo_path'): # Find the path for the submodule of the repo we are testing. if self.repo != 'boost': self._repo_path = None with open(os.path.join(self.boost_root,'.gitmodules'),"rU") as f: path = None url = None for line in f: line = line.strip() if line.startswith("[submodule"): path = None url = None else: name = line.split("=")[0].strip() value = line.split("=")[1].strip() if name == "path": path = value elif name == "url": url = value if name and url and url.endswith("/%s.git"%(self.repo)): self._repo_path = path if not self._repo_path: self._repo_path = "libs/%s"%(self.repo) return self._repo_path def command_install(self): script_common.command_install(self) # Fetch & install toolset.. utils.log( "Install toolset: %s"%(self.toolset) ) if self.toolset: self.command_install_toolset(self.toolset) def command_before_build(self): script_common.command_before_build(self) # Clone boost super-project. if self.repo != 'boost': utils.git_clone('boost',self.branch,cwd=self.ci.work_dir,no_submodules=True) utils.check_call("git","submodule","update","--quiet","--init","tools/build") utils.check_call("git","submodule","update","--quiet","--init","tools/boostdep") # The global jamfiles require config as they trigger build config checks. utils.check_call("git","submodule","update","--quiet","--init","libs/config") # Find the path for the submodule of the repo we are testing. if self.repo != 'boost': self.repo_dir = os.path.join(self.boost_root,self.repo_path) if self.repo != 'boost': # Copy in the existing library tree checkout. shutil.rmtree(self.repo_path) shutil.copytree(self.root_dir, self.repo_path) # Fetch the dependencies for the library we are testing. if self.repo != 'boost': os.chdir(self.boost_root) utils.check_call( sys.executable, 'tools/boostdep/depinst/depinst.py', self.repo) # Create config file for toolset. if not isinstance(self.ci, ci_cli): cxxflags = None if self.cxxflags: cxxflags = self.cxxflags.split() cxxflags = " ".join(cxxflags) utils.make_file(os.path.join(self.boost_root, 'project-config.jam'), """ using %(toolset)s : %(version)s : %(command)s : %(cxxflags)s ; using python : %(pyversion)s : "%(python)s" ; """%{ 'toolset':toolset_info[self.toolset]['toolset'], 'version':toolset_info[self.toolset]['version'], 'command':toolset_info[self.toolset]['command'], 'cxxflags':""+cxxflags if cxxflags else "", 'pyversion':"%s.%s"%(sys.version_info[0],sys.version_info[1]), 'python':sys.executable.replace("\\","\\\\") }) def command_build(self): script_common.command_build(self) # Set up tools. utils.makedirs(os.path.join(self.build_dir,'dist','bin')) if not isinstance(self.ci, ci_cli) and toolset_info[self.toolset]['command']: os.environ['PATH'] = os.pathsep.join([ os.path.dirname(toolset_info[self.toolset]['command']), os.path.join(self.build_dir,'dist','bin'), os.environ['PATH']]) else: os.environ['PATH'] = os.pathsep.join([ os.path.join(self.build_dir,'dist','bin'), os.environ['PATH']]) os.environ['BOOST_BUILD_PATH'] = self.build_dir # Bootstrap Boost Build engine. os.chdir(os.path.join(self.boost_root,"tools","build")) if sys.platform == 'win32': utils.check_call(".\\bootstrap.bat") shutil.copy2("b2.exe", os.path.join(self.build_dir,"dist","bin","b2.exe")) else: utils.check_call("./bootstrap.sh") shutil.copy2("b2", os.path.join(self.build_dir,"dist","bin","b2")) utils.check_call("git","clean","-dfqx") # Run the limited tests. if self.repo != 'boost': print("--- Testing %s ---"%(self.repo_path)) os.chdir(os.path.join(self.boost_root,'status')) to_test = self.repo_path.split("/") del to_test[0] toolset_to_test = "" if self.toolset: if not isinstance(self.ci, ci_cli): toolset_to_test = toolset_info[self.toolset]['toolset'] else: toolset_to_test = self.toolset self.b2( '-d1', '-p0', '--include-tests=%s'%("/".join(to_test)), 'preserve-test-targets=off', '--dump-tests', '--build-dir=%s'%(self.build_dir), '--out-xml=%s'%(os.path.join(self.build_dir,'regression.xml')), '' if not toolset_to_test else 'toolset=%s'%(toolset_to_test), '' if not self.address_model else 'address-model=%s'%(self.address_model), 'variant=%s'%(self.variant), '--test-type=%s'%(self.target), '--verbose-test' ) # Generate a readable test report. import build_log log_main = build_log.Main([ '--output=console', os.path.join(self.build_dir,'regression.xml')]) # And exit with an error if the report contains failures. # This lets the CI notice the error and report a failed build. # And hence trigger the failure machinery, like sending emails. if log_main.failed: self.ci.finish(-1) def command_before_cache(self): script_common.command_before_cache(self) os.chdir(self.boost_root) utils.check_call("git","clean","-dfqx") utils.check_call("git","submodule","--quiet","foreach","git","clean","-dfqx") utils.check_call("git","status","-bs") utils.check_call("git","submodule","foreach","git","status","-bs") main(script)