1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# Copyright (C) 2013 Intel Corporation 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# SPDX-License-Identifier: MIT 5*4882a593Smuzhiyun# 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun# Provides a class for automating build tests for projects 8*4882a593Smuzhiyun 9*4882a593Smuzhiyunimport os 10*4882a593Smuzhiyunimport re 11*4882a593Smuzhiyunimport bb.utils 12*4882a593Smuzhiyunimport subprocess 13*4882a593Smuzhiyunimport tempfile 14*4882a593Smuzhiyunfrom abc import ABCMeta, abstractmethod 15*4882a593Smuzhiyun 16*4882a593Smuzhiyunclass BuildProject(metaclass=ABCMeta): 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun def __init__(self, d, uri, foldername=None, tmpdir=None): 19*4882a593Smuzhiyun self.d = d 20*4882a593Smuzhiyun self.uri = uri 21*4882a593Smuzhiyun self.archive = os.path.basename(uri) 22*4882a593Smuzhiyun self.tempdirobj = None 23*4882a593Smuzhiyun if not tmpdir: 24*4882a593Smuzhiyun tmpdir = self.d.getVar('WORKDIR') 25*4882a593Smuzhiyun if not tmpdir: 26*4882a593Smuzhiyun self.tempdirobj = tempfile.TemporaryDirectory(prefix='buildproject-') 27*4882a593Smuzhiyun tmpdir = self.tempdirobj.name 28*4882a593Smuzhiyun self.localarchive = os.path.join(tmpdir, self.archive) 29*4882a593Smuzhiyun if foldername: 30*4882a593Smuzhiyun self.fname = foldername 31*4882a593Smuzhiyun else: 32*4882a593Smuzhiyun self.fname = re.sub(r'\.tar\.bz2$|\.tar\.gz$|\.tar\.xz$', '', self.archive) 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun # Download self.archive to self.localarchive 35*4882a593Smuzhiyun def _download_archive(self): 36*4882a593Smuzhiyun dl_dir = self.d.getVar("DL_DIR") 37*4882a593Smuzhiyun if dl_dir and os.path.exists(os.path.join(dl_dir, self.archive)): 38*4882a593Smuzhiyun bb.utils.copyfile(os.path.join(dl_dir, self.archive), self.localarchive) 39*4882a593Smuzhiyun return 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun exportvars = ['HTTP_PROXY', 'http_proxy', 42*4882a593Smuzhiyun 'HTTPS_PROXY', 'https_proxy', 43*4882a593Smuzhiyun 'FTP_PROXY', 'ftp_proxy', 44*4882a593Smuzhiyun 'FTPS_PROXY', 'ftps_proxy', 45*4882a593Smuzhiyun 'NO_PROXY', 'no_proxy', 46*4882a593Smuzhiyun 'ALL_PROXY', 'all_proxy', 47*4882a593Smuzhiyun 'SOCKS5_USER', 'SOCKS5_PASSWD'] 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun cmd = '' 50*4882a593Smuzhiyun for var in exportvars: 51*4882a593Smuzhiyun val = self.d.getVar(var) 52*4882a593Smuzhiyun if val: 53*4882a593Smuzhiyun cmd = 'export ' + var + '=\"%s\"; %s' % (val, cmd) 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun cmd = cmd + "wget -O %s %s" % (self.localarchive, self.uri) 56*4882a593Smuzhiyun subprocess.check_output(cmd, shell=True) 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun # This method should provide a way to run a command in the desired environment. 59*4882a593Smuzhiyun @abstractmethod 60*4882a593Smuzhiyun def _run(self, cmd): 61*4882a593Smuzhiyun pass 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun # The timeout parameter of target.run is set to 0 to make the ssh command 64*4882a593Smuzhiyun # run with no timeout. 65*4882a593Smuzhiyun def run_configure(self, configure_args='', extra_cmds=''): 66*4882a593Smuzhiyun return self._run('cd %s; %s ./configure %s' % (self.targetdir, extra_cmds, configure_args)) 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun def run_make(self, make_args=''): 69*4882a593Smuzhiyun return self._run('cd %s; make %s' % (self.targetdir, make_args)) 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun def run_install(self, install_args=''): 72*4882a593Smuzhiyun return self._run('cd %s; make install %s' % (self.targetdir, install_args)) 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun def clean(self): 75*4882a593Smuzhiyun if self.tempdirobj: 76*4882a593Smuzhiyun self.tempdirobj.cleanup() 77*4882a593Smuzhiyun self._run('rm -rf %s' % self.targetdir) 78*4882a593Smuzhiyun subprocess.check_call('rm -f %s' % self.localarchive, shell=True) 79*4882a593Smuzhiyun 80*4882a593Smuzhiyunclass TargetBuildProject(BuildProject): 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun def __init__(self, target, d, uri, foldername=None): 83*4882a593Smuzhiyun self.target = target 84*4882a593Smuzhiyun self.targetdir = "~/" 85*4882a593Smuzhiyun BuildProject.__init__(self, d, uri, foldername) 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun def download_archive(self): 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun self._download_archive() 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun (status, output) = self.target.copy_to(self.localarchive, self.targetdir) 92*4882a593Smuzhiyun if status != 0: 93*4882a593Smuzhiyun raise Exception("Failed to copy archive to target, output: %s" % output) 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun (status, output) = self.target.run('tar xf %s%s -C %s' % (self.targetdir, self.archive, self.targetdir)) 96*4882a593Smuzhiyun if status != 0: 97*4882a593Smuzhiyun raise Exception("Failed to extract archive, output: %s" % output) 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun #Change targetdir to project folder 100*4882a593Smuzhiyun self.targetdir = self.targetdir + self.fname 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun # The timeout parameter of target.run is set to 0 to make the ssh command 103*4882a593Smuzhiyun # run with no timeout. 104*4882a593Smuzhiyun def _run(self, cmd): 105*4882a593Smuzhiyun return self.target.run(cmd, 0)[0] 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun 108*4882a593Smuzhiyunclass SDKBuildProject(BuildProject): 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun def __init__(self, testpath, sdkenv, d, uri, foldername=None): 111*4882a593Smuzhiyun self.sdkenv = sdkenv 112*4882a593Smuzhiyun self.testdir = testpath 113*4882a593Smuzhiyun self.targetdir = testpath 114*4882a593Smuzhiyun bb.utils.mkdirhier(testpath) 115*4882a593Smuzhiyun self.datetime = d.getVar('DATETIME') 116*4882a593Smuzhiyun self.testlogdir = d.getVar("TEST_LOG_DIR") 117*4882a593Smuzhiyun bb.utils.mkdirhier(self.testlogdir) 118*4882a593Smuzhiyun self.logfile = os.path.join(self.testlogdir, "sdk_target_log.%s" % self.datetime) 119*4882a593Smuzhiyun BuildProject.__init__(self, d, uri, foldername, tmpdir=testpath) 120*4882a593Smuzhiyun 121*4882a593Smuzhiyun def download_archive(self): 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun self._download_archive() 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun cmd = 'tar xf %s%s -C %s' % (self.targetdir, self.archive, self.targetdir) 126*4882a593Smuzhiyun subprocess.check_output(cmd, shell=True) 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun #Change targetdir to project folder 129*4882a593Smuzhiyun self.targetdir = os.path.join(self.targetdir, self.fname) 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun def run_configure(self, configure_args='', extra_cmds=' gnu-configize; '): 132*4882a593Smuzhiyun return super(SDKBuildProject, self).run_configure(configure_args=(configure_args or '$CONFIGURE_FLAGS'), extra_cmds=extra_cmds) 133*4882a593Smuzhiyun 134*4882a593Smuzhiyun def run_install(self, install_args=''): 135*4882a593Smuzhiyun return super(SDKBuildProject, self).run_install(install_args=(install_args or "DESTDIR=%s/../install" % self.targetdir)) 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun def log(self, msg): 138*4882a593Smuzhiyun if self.logfile: 139*4882a593Smuzhiyun with open(self.logfile, "a") as f: 140*4882a593Smuzhiyun f.write("%s\n" % msg) 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun def _run(self, cmd): 143*4882a593Smuzhiyun self.log("Running . %s; " % self.sdkenv + cmd) 144*4882a593Smuzhiyun return subprocess.check_call(". %s; " % self.sdkenv + cmd, shell=True) 145