def put_files_cache(self): if getattr(self, "cached", None): return None sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) dname = os.path.join(self.generator.bld.cache_global, ssig) tmpdir = tempfile.mkdtemp(prefix=self.generator.bld.cache_global + os.sep + "waf") try: shutil.rmtree(dname) except: pass try: for node in self.outputs: dest = os.path.join(tmpdir, node.name) shutil.copy2(node.abspath(), dest) except (OSError, IOError): try: shutil.rmtree(tmpdir) except: pass else: try: os.rename(tmpdir, dname) except OSError: try: shutil.rmtree(tmpdir) except: pass else: try: os.chmod(dname, Utils.O755) except: pass
def can_retrieve_cache(self): if not getattr(self, "outputs", None): return None sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) dname = os.path.join(self.generator.bld.cache_global, ssig) try: t1 = os.stat(dname).st_mtime except OSError: return None for node in self.outputs: orig = os.path.join(dname, node.name) try: shutil.copy2(orig, node.abspath()) os.utime(orig, None) except (OSError, IOError): Logs.debug("task: failed retrieving file") return None try: t2 = os.stat(dname).st_mtime except OSError: return None if t1 != t2: return None for node in self.outputs: node.sig = sig if self.generator.bld.progress_bar < 1: self.generator.bld.to_log("restoring from cache %r\n" % node.abspath()) self.cached = True return True
def can_retrieve_cache(self): if not getattr(self, 'outputs', None): return None sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) dname = os.path.join(self.generator.bld.cache_global, ssig) try: t1 = os.stat(dname).st_mtime except OSError: return None for node in self.outputs: orig = os.path.join(dname, node.name) try: shutil.copy2(orig, node.abspath()) os.utime(orig, None) except (OSError, IOError): Logs.debug('task: failed retrieving file') return None try: t2 = os.stat(dname).st_mtime except OSError: return None if t1 != t2: return None for node in self.outputs: node.sig = sig if self.generator.bld.progress_bar < 1: self.generator.bld.to_log('restoring from cache %r\n' % node.abspath()) self.cached = True return True
def put_files_cache(self): if getattr(self, 'cached', None): return None sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) dname = os.path.join(self.generator.bld.cache_global, ssig) tmpdir = tempfile.mkdtemp(prefix=self.generator.bld.cache_global + os.sep + 'waf') try: shutil.rmtree(dname) except: pass try: for node in self.outputs: dest = os.path.join(tmpdir, node.name) shutil.copy2(node.abspath(), dest) except (OSError, IOError): try: shutil.rmtree(tmpdir) except: pass else: try: os.rename(tmpdir, dname) except OSError: try: shutil.rmtree(tmpdir) except: pass else: try: os.chmod(dname, Utils.O755) except: pass
def can_retrieve_cache(self): """ Used by :py:meth:`waflib.Task.cache_outputs` Retrieve build nodes from the cache update the file timestamps to help cleaning the least used entries from the cache additionally, set an attribute 'cached' to avoid re-creating the same cache files Suppose there are files in `cache/dir1/file1` and `cache/dir2/file2`: #. read the timestamp of dir1 #. try to copy the files #. look at the timestamp again, if it has changed, the data may have been corrupt (cache update by another process) #. should an exception occur, ignore the data """ if not getattr(self, 'outputs', None): return None sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) # first try to access the cache folder for the task dname = os.path.join(self.generator.bld.cache_global, ssig) try: t1 = os.stat(dname).st_mtime except OSError: return None for node in self.outputs: orig = os.path.join(dname, node.name) try: shutil.copy2(orig, node.abspath()) # mark the cache file as used recently (modified) os.utime(orig, None) except (OSError, IOError): Logs.debug('task: failed retrieving file') return None # is it the same folder? try: t2 = os.stat(dname).st_mtime except OSError: return None if t1 != t2: return None for node in self.outputs: node.sig = sig if self.generator.bld.progress_bar < 1: self.generator.bld.to_log('restoring from cache %r\n' % node.abspath()) self.cached = True return True
def put_files_cache(self): """ Used by :py:func:`waflib.Task.cache_outputs` to store the build files in the cache """ # file caching, if possible # try to avoid data corruption as much as possible if not isinstance(self.generator.bld, Build.BuildContext): return if hasattr(self, 'cached'): return sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) dname = os.path.join(self.generator.bld.artifacts_cache, ssig) dname_tmp = dname + '_tmp' if os.path.exists(dname) or os.path.exists(dname_tmp): return else: try: os.makedirs(dname_tmp) except OSError: return for node in self.outputs: dest = os.path.join(dname_tmp, node.name) dest = Utils.extended_path(dest) try: if Utils.is_win32: os.system('copy {} {} /Y>nul'.format(node.abspath(), dest)) else: os.system('cp -f {} {}'.format(node.abspath(), dest)) except Exception as e: Logs.warn( '[WARN] task: failed caching file {} due to exception\n {}\n'. format(dest, e)) return try: os.utime(dname_tmp, None) os.chmod(dname_tmp, Utils.O755) if Utils.is_win32: # For rename in Windows, target path cannot be full path, it will remain in the same folder with source path os.system('rename {} {}'.format(dname_tmp, ssig)) else: os.system('mv {} {}'.format(dname_tmp, dname)) except Exception as e: Logs.warn( '[WARN] task: failed updating timestamp/permission for cached outputs folder for task signature {} due to exception\n {}\n' .format(dname, e)) pass self.cached = True
def rsync_and_ssh(task): # remove a warning task.uid_ = id(task) bld = task.generator.bld task.env.user, _, _ = task.env.login.partition('@') task.env.hdir = Utils.to_hex(Utils.h_list((task.generator.path.abspath(), task.env.variant))) task.env.remote_dir = '~%s/wafremote/%s' % (task.env.user, task.env.hdir) task.env.local_dir = bld.srcnode.abspath() + '/' task.env.remote_dir_variant = '%s/%s/%s' % (task.env.remote_dir, Context.g_module.out, task.env.variant) task.env.build_dir = bld.bldnode.abspath() ret = task.exec_command(bld.make_mkdir_command(task)) if ret: return ret ret = task.exec_command(bld.make_send_command(task)) if ret: return ret ret = task.exec_command(bld.make_exec_command(task)) if ret: return ret ret = task.exec_command(bld.make_save_command(task)) if ret: return ret
def rsync_and_ssh(task): # remove a warning task.uid_ = id(task) bld = task.generator.bld task.env.user, _, _ = task.env.login.partition("@") task.env.hdir = Utils.to_hex( Utils.h_list((task.generator.path.abspath(), task.env.variant))) task.env.remote_dir = f"~{task.env.user}/wafremote/{task.env.hdir}" task.env.local_dir = bld.srcnode.abspath() + "/" task.env.remote_dir_variant = f"{task.env.remote_dir}/{Context.g_module.out}/{task.env.variant}" task.env.build_dir = bld.bldnode.abspath() ret = task.exec_command(bld.make_mkdir_command(task)) if ret: return ret ret = task.exec_command(bld.make_send_command(task)) if ret: return ret ret = task.exec_command(bld.make_exec_command(task)) if ret: return ret ret = task.exec_command(bld.make_save_command(task)) if ret: return ret
def hash_env_vars(self, env, vars_lst): """ Override env signature computation, and make it to be engine path and 3rdParty path independent. """ if not env.table: env = env.parent if not env: return Utils.SIG_NIL idx = str(id(env)) + str(vars_lst) try: cache = self.cache_env except AttributeError: cache = self.cache_env = {} else: try: return self.cache_env[idx] except KeyError: pass lst = [ env[x] for x in vars_lst if x not in ['INCLUDES', 'INCPATHS', 'LIBPATH', 'STLIBPATH'] ] env_str = replace_engine_path_and_tp_root_in_string(self, str(lst)) m = Utils.md5() m.update(env_str.encode()) ret = m.digest() Logs.debug('envhash: %s %r', Utils.to_hex(ret), lst) cache[idx] = ret return ret
def put_files_cache(self): """ New method for waf Task classes """ if WAFCACHE_NO_PUSH or getattr(self, 'cached', None) or not self.outputs: return bld = self.generator.bld sig = self.signature() ssig = Utils.to_hex(self.uid() + sig) files_from = [node.abspath() for node in self.outputs] err = cache_command(ssig, files_from, []) if err.startswith(OK): if WAFCACHE_VERBOSITY: Logs.pprint('CYAN', ' Successfully uploaded %s to cache' % files_from) else: Logs.debug('wafcache: Successfully uploaded %r to cache', files_from) else: if WAFCACHE_VERBOSITY: Logs.pprint( 'RED', ' Error caching step results %s: %s' % (files_from, err)) else: Logs.debug('wafcache: Error caching results %s: %s', files_from, err) bld.task_sigs[self.uid()] = self.cache_sig
def put_files_cache(self): if not Task.push_addr: return if not self.outputs: return if getattr(self, 'cached', None): return #print "called put_files_cache", id(self) bld = self.generator.bld sig = self.signature() ssig = Utils.to_hex(self.uid() + sig) conn = None cnt = 0 try: for node in self.outputs: # We could re-create the signature of the task with the signature of the outputs # in practice, this means hashing the output files # this is unnecessary try: if not conn: conn = get_connection(push=True) sock_send(conn, ssig, cnt, node.abspath()) except Exception as e: Logs.debug("netcache: could not push the files %r" % e) # broken connection? remove this one close_connection(conn) conn = None cnt += 1 finally: release_connection(conn, push=True) bld.task_sigs[self.uid()] = self.cache_sig
def can_retrieve_cache(self): """ New method for waf Task classes """ if not self.outputs: return False self.cached = False sig = self.signature() ssig = Utils.to_hex(self.uid() + sig) if WAFCACHE_STATS: self.generator.bld.cache_reqs += 1 files_to = [node.abspath() for node in self.outputs] err = cache_command(ssig, [], files_to) if err.startswith(OK): if WAFCACHE_VERBOSITY: Logs.pprint('CYAN', ' Fetched %r from cache' % files_to) else: Logs.debug('wafcache: fetched %r from cache', files_to) if WAFCACHE_STATS: self.generator.bld.cache_hits += 1 else: if WAFCACHE_VERBOSITY: Logs.pprint('YELLOW', ' No cache entry %s' % files_to) else: Logs.debug('wafcache: No cache entry %s: %s', files_to, err) return False self.cached = True return True
def hash_env_vars(self, env, vars_lst): """ Hashes configuration set variables:: def build(bld): bld.hash_env_vars(bld.env, ['CXX', 'CC']) This method uses an internal cache. :param env: Configuration Set :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param vars_lst: list of variables :type vars_list: list of string """ if not env.table: env = env.parent if not env: return Utils.SIG_NIL idx = str(id(env)) + str(vars_lst) try: cache = self.cache_env except AttributeError: cache = self.cache_env = {} else: try: return self.cache_env[idx] except KeyError: pass lst = [env[a] for a in vars_lst] cache[idx] = ret = Utils.h_list(lst) Logs.debug('envhash: %s %r', Utils.to_hex(ret), lst) return ret
def rsync_and_ssh(task): # remove a warning task.uid_ = id(task) bld = task.generator.bld task.env.user, _, _ = task.env.login.partition('@') task.env.hdir = Utils.to_hex( Utils.h_list((task.generator.path.abspath(), task.env.variant))) task.env.remote_dir = '~%s/wafremote/%s' % (task.env.user, task.env.hdir) task.env.local_dir = bld.srcnode.abspath() + '/' task.env.remote_dir_variant = '%s/%s/%s' % ( task.env.remote_dir, Context.g_module.out, task.env.variant) task.env.build_dir = bld.bldnode.abspath() ret = task.exec_command(bld.make_mkdir_command(task)) if ret: return ret ret = task.exec_command(bld.make_send_command(task)) if ret: return ret ret = task.exec_command(bld.make_exec_command(task)) if ret: return ret ret = task.exec_command(bld.make_save_command(task)) if ret: return ret
def run_c_code(self, *k, **kw): lst = [str(v) for (p, v) in kw.items() if p != 'env'] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + ( sys.platform != 'win32' and '.' or '') + 'conf_check_' + Utils.to_hex(h) try: os.makedirs(dir) except: pass try: os.stat(dir) except: self.fatal('cannot use the configuration test folder %r' % dir) cachemode = getattr(Options.options, 'confcache', None) if cachemode == CACHE_RESULTS: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_c_code')) ret = proj['cache_run_c_code'] except: pass else: if isinstance(ret, str) and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld = bld = Build.BuildContext(top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' if kw['compile_filename']: node = bld.srcnode.make_node(kw['compile_filename']) node.write(kw['code']) bld.logger = self.logger bld.all_envs.update(self.all_envs) bld.env = kw['env'] o = bld(features=kw['features'], source=kw['compile_filename'], target='testprog') for k, v in kw.items(): setattr(o, k, v) self.to_log("==>\n%s\n<==" % kw['code']) bld.targets = '*' ret = -1 try: try: bld.compile() except Errors.WafError: ret = 'Test does not build: %s' % Utils.ex_stack() self.fatal(ret) else: ret = getattr(bld, 'retval', 0) finally: proj = ConfigSet.ConfigSet() proj['cache_run_c_code'] = ret proj.store(os.path.join(dir, 'cache_run_c_code')) return ret
def run(self): tsk = self env = self.env gen = self.generator bld = gen.bld zpy = bld.zpy py = bld.py if getattr(self, 'cwd', None) is None: self.cwd = pth.join(bld.bldnode.abspath(), self.dist.key) python = bld.zippy_dist_get('python') self._key = '%s-%s-%s' % (python.key, python.version, Utils.to_hex(self.signature())) self._cache_conf = pth.join(zpy.cache_tmp, 'conf-%s' % self._key) self._cache_prof = pth.join(zpy.cache_tmp, 'prof-%s' % self._key) ret = 0 with open(pth.join(self.cwd, 'zippy.sh'), mode='a') as fp: fd = fp.fileno() fstat = os.fstat(fd) fmode = fstat.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH os.fchmod(fd, fmode) if fp.tell() == 0: fp.write('#!/bin/bash\n\n') fp.write('cd ' + pipes.quote(self.cwd) + '\n') fp.write('unset $(compgen -e)' + '\n\n') for k, v in sorted(env.env.iteritems()): v = pipes.quote(v) fp.write('export {0}={1}\n'.format(k, v)) fp.write('\n') for app in Utils.to_list(self.app): if not isinstance(app, basestring): fp.write('# ' + str(app)) ret |= app(self) continue kwds = dict() if bld.zero_log: kwds = {'stdout': None, 'stderr': -2} larg = None app = app.format(**locals()) app = app.strip('\0').split('\0') for arg in map(pipes.quote, app): if larg is not None: fp.write(' \\\n ') fp.write(arg) larg = arg fp.write('\n\n') ret |= self.exec_command(app, cwd=self.cwd, env=env.env or None, **kwds) return ret
def run_build(self, *k, **kw): lst = [str(v) for (p, v) in kw.items() if p != 'env'] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + ( not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) try: os.makedirs(dir) except OSError: pass try: os.stat(dir) except OSError: self.fatal('cannot use the configuration test folder %r' % dir) cachemode = getattr(Options.options, 'confcache', None) if cachemode == 1: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_build')) except EnvironmentError: pass else: ret = proj['cache_run_build'] if isinstance(ret, str) and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) cls_name = kw.get('run_build_cls') or getattr(self, 'run_build_cls', 'build') self.test_bld = bld = Context.create_context(cls_name, top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' bld.logger = self.logger bld.all_envs.update(self.all_envs) bld.env = kw['env'] bld.kw = kw bld.conf = self kw['build_fun'](bld) ret = -1 try: try: bld.compile() except Errors.WafError: ret = 'Test does not build: %s' % traceback.format_exc() self.fatal(ret) else: ret = getattr(bld, 'retval', 0) finally: if cachemode == 1: proj = ConfigSet.ConfigSet() proj['cache_run_build'] = ret proj.store(os.path.join(dir, 'cache_run_build')) else: shutil.rmtree(dir) return ret
def put_files_cache(self): """ Used by :py:func:`waflib.Task.cache_outputs` to store the build files in the cache """ # file caching, if possible # try to avoid data corruption as much as possible if getattr(self, 'cached', None): return None if not getattr(self, 'outputs', None): return None sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) dname = os.path.join(self.generator.bld.cache_global, ssig) tmpdir = tempfile.mkdtemp(prefix=self.generator.bld.cache_global + os.sep + 'waf') try: shutil.rmtree(dname) except Exception: pass try: for node in self.outputs: dest = os.path.join(tmpdir, node.name) shutil.copy2(node.abspath(), dest) except (OSError, IOError): try: shutil.rmtree(tmpdir) except Exception: pass else: try: os.rename(tmpdir, dname) except OSError: try: shutil.rmtree(tmpdir) except Exception: pass else: try: os.chmod(dname, Utils.O755) except Exception: pass
def run_c_code(self,*k,**kw): lst=[str(v)for(p,v)in kw.items()if p!='env'] h=Utils.h_list(lst) dir=self.bldnode.abspath()+os.sep+(not Utils.is_win32 and'.'or'')+'conf_check_'+Utils.to_hex(h) try: os.makedirs(dir) except OSError: pass try: os.stat(dir) except OSError: self.fatal('cannot use the configuration test folder %r'%dir) cachemode=getattr(Options.options,'confcache',None) if cachemode==CACHE_RESULTS: try: proj=ConfigSet.ConfigSet(os.path.join(dir,'cache_run_c_code')) except OSError: pass else: ret=proj['cache_run_c_code'] if isinstance(ret,str)and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir=os.path.join(dir,'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld=bld=Build.BuildContext(top_dir=dir,out_dir=bdir) bld.init_dirs() bld.progress_bar=0 bld.targets='*' if kw['compile_filename']: node=bld.srcnode.make_node(kw['compile_filename']) node.write(kw['code']) bld.logger=self.logger bld.all_envs.update(self.all_envs) bld.env=kw['env'] o=bld(features=kw['features'],source=kw['compile_filename'],target='testprog') for k,v in kw.items(): setattr(o,k,v) if not kw.get('quiet',None): self.to_log("==>\n%s\n<=="%kw['code']) bld.targets='*' ret=-1 try: try: bld.compile() except Errors.WafError: ret='Test does not build: %s'%Utils.ex_stack() self.fatal(ret) else: ret=getattr(bld,'retval',0) finally: proj=ConfigSet.ConfigSet() proj['cache_run_c_code']=ret proj.store(os.path.join(dir,'cache_run_c_code')) return ret
def run_build(self,*k,**kw): lst=[str(v)for(p,v)in kw.items()if p!='env'] h=Utils.h_list(lst) dir=self.bldnode.abspath()+os.sep+(not Utils.is_win32 and'.'or'')+'conf_check_'+Utils.to_hex(h) try: os.makedirs(dir) except OSError: pass try: os.stat(dir) except OSError: self.fatal('cannot use the configuration test folder %r'%dir) cachemode=getattr(Options.options,'confcache',None) if cachemode==1: try: proj=ConfigSet.ConfigSet(os.path.join(dir,'cache_run_build')) except OSError: pass except IOError: pass else: ret=proj['cache_run_build'] if isinstance(ret,str)and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir=os.path.join(dir,'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld=bld=Build.BuildContext(top_dir=dir,out_dir=bdir) bld.init_dirs() bld.progress_bar=0 bld.targets='*' bld.logger=self.logger bld.all_envs.update(self.all_envs) bld.env=kw['env'] bld.kw=kw bld.conf=self kw['build_fun'](bld) ret=-1 try: try: bld.compile() except Errors.WafError: ret='Test does not build: %s'%Utils.ex_stack() self.fatal(ret) else: ret=getattr(bld,'retval',0) finally: if cachemode==1: proj=ConfigSet.ConfigSet() proj['cache_run_build']=ret proj.store(os.path.join(dir,'cache_run_build')) else: shutil.rmtree(dir) return ret
def run(self): for x in self.inputs: cmd = Utils.to_list(self.env.AR) + ["x", x.abspath() ] ar_dir_basename = x.name.replace(".a", "_a") ar_dir = self.generator.path.get_bld().make_node(ar_dir_basename) print(ar_dir.abspath()) try: ar_dir.delete() except: pass ar_dir.mkdir() d = ar_dir.abspath() self.exec_command(cmd, cwd=d) bdir = self.generator.path.get_bld() nodes = [] for _cwd, _dirs, _files in Node.os.walk(d): for f in _files: dirname = Node.os.path.basename(_cwd) filename = Node.os.path.join(_cwd, f) h = Utils.h_file(filename) new_filename = Node.os.path.join( _cwd, "%s-%s-%s" % (dirname, Utils.to_hex(h), f)) rd = Node.os.path.relpath(new_filename, bdir.abspath()) Node.os.rename(filename, new_filename) n = bdir.find_node(rd) n.sig = h # cache outputs for future runs try: self.generator.bld.pouet[self.uid()].append(n.bldpath()) except: self.generator.bld.pouet[self.uid()] = [n.bldpath()] self.generator.add_those_o_files(n) nodes.append(n) try: link = self.generator.link_task link.inputs += nodes link.inputs.sort(key=lambda x: x.abspath()) except: pass
def run_c_code(self, *k, **kw): lst = [str(v) for (p, v) in kw.items() if p != 'env'] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + '.conf_check_' + Utils.to_hex(h) try: os.makedirs(dir) except: pass try: os.stat(dir) except: self.fatal('cannot use the configuration test folder %r' % dir) bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld = bld = Build.BuildContext(top_dir=dir, out_dir=bdir) # keep the temporary build context on an attribute for debugging bld.load() # configuration test cache bld.targets = '*' if kw['compile_filename']: node = bld.srcnode.make_node(kw['compile_filename']) node.write(kw['code']) bld.logger = self.logger bld.all_envs.update(self.all_envs) bld.all_envs['default'] = kw['env'] o = bld(features=kw['features'], source=kw['compile_filename'], target='testprog') for k, v in kw.items(): setattr(o, k, v) self.to_log("==>\n%s\n<==" % kw['code']) # compile the program bld.targets = '*' try: bld.compile() except Errors.WafError: self.fatal('Test does not build: %s' % Utils.ex_stack()) return getattr(bld, 'retval', 0)
def can_retrieve_cache(self): if not Task.pull_addr: return False if not self.outputs: return False self.cached = False cnt = 0 sig = self.signature() ssig = Utils.to_hex(self.uid() + sig) conn = None err = False try: try: conn = get_connection() for node in self.outputs: p = node.abspath() recv_file(conn, ssig, cnt, p) cnt += 1 except MissingFile as e: Logs.debug('netcache: file is not in the cache %r' % e) err = True except Exception as e: Logs.debug('netcache: could not get the files %r' % e) err = True # broken connection? remove this one close_connection(conn) conn = None finally: release_connection(conn) if err: return False for node in self.outputs: node.sig = sig #if self.generator.bld.progress_bar < 1: # self.generator.bld.to_log('restoring from cache %r\n' % node.abspath()) self.cached = True return True
def hash_env_vars(self, env, vars_lst): if not env.table: env = env.parent if not env: return Utils.SIG_NIL idx = str(id(env)) + str(vars_lst) try: cache = self.cache_env except AttributeError: cache = self.cache_env = {} else: try: return self.cache_env[idx] except KeyError: pass lst = [env[a] for a in vars_lst] cache[idx] = ret = Utils.h_list(lst) Logs.debug('envhash: %s %r', Utils.to_hex(ret), lst) return ret
def scan(self): env = self.env gen = self.generator bld = gen.bld zpy = bld.zpy out = self.outputs[0].parent sig = Utils.to_hex( (self.inputs and getattr(self.inputs[0], 'sig', None)) or getattr(out, 'sig', None) or Utils.md5(self.dist.name_and_version).digest()) deps = ([], []) #self.signode = out.make_node(sig) self.signode = bld.bldnode.make_node(str('.%s.%s' % (out.name, sig)), ) self.signode.mkdir() #deps[0].append(self.signode) return deps
def hash_env_vars(self,env,vars_lst): if not env.table: env=env.parent if not env: return Utils.SIG_NIL idx=str(id(env))+str(vars_lst) try: cache=self.cache_env except AttributeError: cache=self.cache_env={} else: try: return self.cache_env[idx] except KeyError: pass lst=[env[a]for a in vars_lst] cache[idx]=ret=Utils.h_list(lst) Logs.debug('envhash: %s %r',Utils.to_hex(ret),lst) return ret
def can_retrieve_cache(self): if not Task.pull_addr: return False if not self.outputs: return False self.cached = False cnt = 0 sig = self.signature() ssig = Utils.to_hex(self.uid() + sig) conn = None err = False try: try: conn = get_connection() for node in self.outputs: p = node.abspath() recv_file(conn, ssig, cnt, p) cnt += 1 except MissingFile as e: Logs.debug('netcache: file is not in the cache %r', e) err = True except Exception as e: Logs.debug('netcache: could not get the files %r', self.outputs) if Logs.verbose > 1: Logs.debug('netcache: exception %r', e) err = True # broken connection? remove this one close_connection(conn) conn = None else: Logs.debug('netcache: obtained %r from cache', self.outputs) finally: release_connection(conn) if err: return False self.cached = True return True
def can_retrieve_cache(self): if not Task.pull_addr: return False if not self.outputs: return False self.cached = False cnt = 0 sig = self.signature() ssig = Utils.to_hex(self.uid() + sig) conn = None err = False try: try: conn = get_connection() for node in self.outputs: p = node.abspath() recv_file(conn, ssig, cnt, p) cnt += 1 else: Logs.debug("netcache: obtained %r from cache", self.outputs) except MissingFile as e: Logs.debug("netcache: file is not in the cache %r", e) err = True except Exception as e: Logs.debug("netcache: could not get the files %r", self.outputs) if Logs.verbose > 1: Logs.debug("netcache: exception %r", e) err = True # broken connection? remove this one close_connection(conn) conn = None finally: release_connection(conn) if err: return False self.cached = True return True
def can_retrieve_cache(self): """ New method for waf Task classes """ if not self.outputs: return False self.cached = False sig = self.signature() ssig = Utils.to_hex(self.uid() + sig) files_to = [node.abspath() for node in self.outputs] err = cache_command(ssig, [], files_to) if not err.startswith(OK): if Logs.verbose: Logs.debug('wafcache: error getting from cache %s', err) return False self.cached = True return True
def scan(self): env = self.env gen = self.generator bld = gen.bld zpy = bld.zpy out = self.outputs[0].parent sig = Utils.to_hex( (self.inputs and getattr(self.inputs[0], 'sig', None)) or getattr(out, 'sig', None) or Utils.md5(self.dist.name_and_version).digest() ) deps = ([], []) #self.signode = out.make_node(sig) self.signode = bld.bldnode.make_node( str('.%s.%s' % (out.name, sig)), ) self.signode.mkdir() #deps[0].append(self.signode) return deps
def put_files_cache(self): """ New method for waf Task classes """ if not self.outputs: return if getattr(self, 'cached', None): return bld = self.generator.bld sig = self.signature() ssig = Utils.to_hex(self.uid() + sig) files_from = [node.abspath() for node in self.outputs] err = cache_command(ssig, files_from, []) if not err.startswith(OK): if Logs.verbose: Logs.debug('wafcache: error caching %s', err) bld.task_sigs[self.uid()] = self.cache_sig
def run(self): tsk = self env = self.env gen = self.generator bld = gen.bld zpy = bld.zpy py = bld.py if getattr(self, 'cwd', None) is None: self.cwd = pth.join(bld.bldnode.abspath(), self.dist.key) python = bld.zippy_dist_get('python') self._key = '%s-%s-%s' % ( python.key, python.version, Utils.to_hex(self.signature()) ) self._cache_conf = pth.join(zpy.cache_tmp, 'conf-%s' % self._key) self._cache_prof = pth.join(zpy.cache_tmp, 'prof-%s' % self._key) ret = 0 with open(pth.join(self.cwd, 'zippy.sh'), mode='a') as fp: fd = fp.fileno() fstat = os.fstat(fd) fmode = fstat.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH os.fchmod(fd, fmode) if fp.tell() == 0: fp.write('#!/bin/bash\n\n') fp.write('cd ' + pipes.quote(self.cwd) + '\n') fp.write('unset $(compgen -e)' + '\n\n') for k,v in sorted(env.env.iteritems()): v = pipes.quote(v) fp.write('export {0}={1}\n'.format(k, v)) fp.write('\n') for app in Utils.to_list(self.app): if not isinstance(app, basestring): fp.write('# ' + str(app)) ret |= app(self) continue kwds = dict() if bld.zero_log: kwds = {'stdout': None, 'stderr': -2} larg = None app = app.format(**locals()) app = app.strip('\0').split('\0') for arg in map(pipes.quote, app): if larg is not None: fp.write(' \\\n ') fp.write(arg) larg = arg fp.write('\n\n') ret |= self.exec_command( app, cwd=self.cwd, env=env.env or None, **kwds ) return ret
def run_c_code(self, *k, **kw): lst = [str(v) for (p, v) in kw.items() if p != "env"] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + (sys.platform != "win32" and "." or "") + "conf_check_" + Utils.to_hex(h) try: os.makedirs(dir) except: pass try: os.stat(dir) except: self.fatal("cannot use the configuration test folder %r" % dir) cachemode = getattr(Options.options, "confcache", None) if cachemode == CACHE_RESULTS: try: proj = ConfigSet.ConfigSet(os.path.join(dir, "cache_run_c_code")) ret = proj["cache_run_c_code"] except: pass else: if isinstance(ret, str) and ret.startswith("Test does not build"): self.fatal(ret) return ret bdir = os.path.join(dir, "testbuild") if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld = bld = Build.BuildContext(top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = "*" if kw["compile_filename"]: node = bld.srcnode.make_node(kw["compile_filename"]) node.write(kw["code"]) bld.logger = self.logger bld.all_envs.update(self.all_envs) bld.env = kw["env"] o = bld(features=kw["features"], source=kw["compile_filename"], target="testprog") for k, v in kw.items(): setattr(o, k, v) self.to_log("==>\n%s\n<==" % kw["code"]) bld.targets = "*" ret = -1 try: try: bld.compile() except Errors.WafError: ret = "Test does not build: %s" % Utils.ex_stack() self.fatal(ret) else: ret = getattr(bld, "retval", 0) finally: proj = ConfigSet.ConfigSet() proj["cache_run_c_code"] = ret proj.store(os.path.join(dir, "cache_run_c_code")) return ret
def can_retrieve_cache(self): """ Used by :py:meth:`waflib.Task.cache_outputs` Retrieve build nodes from the cache update the file timestamps to help cleaning the least used entries from the cache additionally, set an attribute 'cached' to avoid re-creating the same cache files Suppose there are files in `cache/dir1/file1` and `cache/dir2/file2`: #. read the timestamp of dir1 #. try to copy the files #. look at the timestamp again, if it has changed, the data may have been corrupt (cache update by another process) #. should an exception occur, ignore the data """ bld = self.generator.bld if not isinstance(bld, Build.BuildContext): return False if not getattr(self, 'outputs', None): return False if not hasattr(self, 'can_retrieve_cache_checked'): self.can_retrieve_cache_checked = True else: return False bld.artifacts_cache_metrics.tasks_processed.add(self) sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) # first try to access the cache folder for the task dname = os.path.join(bld.artifacts_cache, ssig) if not os.path.exists(dname): bld.artifacts_cache_metrics.tasks_missed.add(self) return False for node in self.outputs: orig = os.path.join(dname, node.name) # Maximum Path Length Limitation on Windows is 260 characters, starting from Windows 10, we can enable long path to remove this limitation. # In case long path is not enabled, extended-length path to bypass this limitation. orig = Utils.extended_path(orig) try: t1 = os.stat(orig).st_mtime except OSError: bld.artifacts_cache_metrics.tasks_missed.add(self) return False dir_name = os.path.dirname(node.abspath()) try: os.makedirs(dir_name) except Exception: pass try: # Do not use shutil.copy2(orig, node.abspath()), otherwise, it will cause threading issue with compiler and linker. # shutil.copy2() first calls shutil.copyfile() to copy the file contents, and then calls os.copystat() to copy the file stats, after the file contents are copied, waf is able to get the node's signature and might think the runnable status of a task is ready to run, but the copied file is then opened by os.copystat(), and compiler or linker who use the copied file as input file will fail. if Utils.is_win32: os.system('copy {} {} /Y>nul'.format(orig, node.abspath())) else: os.system('cp {} {}'.format(orig, node.abspath())) # is it the same file? try: t2 = os.stat(orig).st_mtime if t1 != t2: bld.artifacts_cache_metrics.tasks_failed_to_retrieve.add( self) return False except OSError: bld.artifacts_cache_metrics.tasks_failed_to_retrieve.add(self) return False except Exception as e: Logs.warn( '[WARN] task: failed retrieving file {} due to exception\n{}\n' .format(node.abspath(), e)) bld.artifacts_cache_metrics.tasks_failed_to_retrieve.add(self) return False for node in self.outputs: node.sig = sig if bld.progress_bar < 1: bld.to_log('restoring from cache %r\n' % node.abspath()) # mark the cache file folder as used recently (modified) os.utime(dname, None) self.cached = True return True
def run_build(self, *k, **kw): """ Create a temporary build context to execute a build. A reference to that build context is kept on self.test_bld for debugging purposes, and you should not rely on it too much (read the note on the cache below). The parameters given in the arguments to this function are passed as arguments for a single task generator created in the build. Only three parameters are obligatory: :param features: features to pass to a task generator created in the build :type features: list of string :param compile_filename: file to create for the compilation (default: *test.c*) :type compile_filename: string :param code: code to write in the filename to compile :type code: string Though this function returns *0* by default, the build may set an attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. This function also provides a limited cache. To use it, provide the following option:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, action='count', help='Use a configuration cache') And execute the configuration with the following command-line:: $ waf configure --confcache """ lst = [str(v) for (p, v) in kw.items() if p != "env"] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and "." or "") + "conf_check_" + Utils.to_hex(h) try: os.makedirs(dir) except OSError: pass try: os.stat(dir) except OSError: self.fatal("cannot use the configuration test folder %r" % dir) cachemode = getattr(Options.options, "confcache", None) if cachemode == 1: try: proj = ConfigSet.ConfigSet(os.path.join(dir, "cache_run_build")) except OSError: pass except IOError: pass else: ret = proj["cache_run_build"] if isinstance(ret, str) and ret.startswith("Test does not build"): self.fatal(ret) return ret bdir = os.path.join(dir, "testbuild") if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld = bld = Build.BuildContext(top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = "*" bld.logger = self.logger bld.all_envs.update(self.all_envs) # not really necessary bld.env = kw["env"] # OMG huge hack bld.kw = kw bld.conf = self kw["build_fun"](bld) ret = -1 try: try: bld.compile() except Errors.WafError: ret = "Test does not build: %s" % Utils.ex_stack() self.fatal(ret) else: ret = getattr(bld, "retval", 0) finally: if cachemode == 1: # cache the results each time proj = ConfigSet.ConfigSet() proj["cache_run_build"] = ret proj.store(os.path.join(dir, "cache_run_build")) else: shutil.rmtree(dir) return ret
def run_c_code(self, *k, **kw): """ Create a temporary build context to execute a build. A reference to that build context is kept on self.test_bld for debugging purposes. The parameters given in the arguments to this function are passed as arguments for a single task generator created in the build. Only three parameters are obligatory: :param features: features to pass to a task generator created in the build :type features: list of string :param compile_filename: file to create for the compilation (default: *test.c*) :type compile_filename: string :param code: code to write in the filename to compile :type code: string Though this function returns *0* by default, the build may set an attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. This function also provides a limited cache. To use it, provide the following option:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, action='count', help='Use a configuration cache') And execute the configuration with the following command-line:: $ waf configure --confcache """ lst = [str(v) for (p, v) in kw.items() if p != 'env'] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + ( not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) try: os.makedirs(dir) except: pass try: os.stat(dir) except: self.fatal('cannot use the configuration test folder %r' % dir) cachemode = getattr(Options.options, 'confcache', None) if cachemode == CACHE_RESULTS: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_c_code')) ret = proj['cache_run_c_code'] except: pass else: if isinstance(ret, str) and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld = bld = Build.BuildContext(top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' if kw['compile_filename']: node = bld.srcnode.make_node(kw['compile_filename']) node.write(kw['code']) bld.logger = self.logger bld.all_envs.update(self.all_envs) # not really necessary bld.env = kw['env'] o = bld(features=kw['features'], source=kw['compile_filename'], target='testprog') for k, v in kw.items(): setattr(o, k, v) self.to_log("==>\n%s\n<==" % kw['code']) # compile the program bld.targets = '*' ret = -1 try: try: bld.compile() except Errors.WafError: ret = 'Test does not build: %s' % Utils.ex_stack() self.fatal(ret) else: ret = getattr(bld, 'retval', 0) finally: # cache the results each time proj = ConfigSet.ConfigSet() proj['cache_run_c_code'] = ret proj.store(os.path.join(dir, 'cache_run_c_code')) return ret
def run_c_code(self, *k, **kw): """ To use the cache in your scripts, provide the following option and execute "waf configure --confcache" def options(opt): opt.add_option('--confcache', dest='confcache', default=0, action='count', help='Use a configuration cache') The temporary build context created is kept on self.test_bld for debugging purposes """ lst = [str(v) for (p, v) in kw.items() if p != 'env'] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + (sys.platform != 'win32' and '.' or '') + 'conf_check_' + Utils.to_hex(h) try: os.makedirs(dir) except: pass try: os.stat(dir) except: self.fatal('cannot use the configuration test folder %r' % dir) cachemode = getattr(Options.options, 'confcache', None) if cachemode == CACHE_RESULTS: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_c_code')) ret = proj['cache_run_c_code'] except: pass else: if isinstance(ret, str) and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld = bld = Build.BuildContext(top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' if kw['compile_filename']: node = bld.srcnode.make_node(kw['compile_filename']) node.write(kw['code']) bld.logger = self.logger bld.all_envs.update(self.all_envs) # not really necessary bld.env = kw['env'] o = bld(features=kw['features'], source=kw['compile_filename'], target='testprog') for k, v in kw.items(): setattr(o, k, v) self.to_log("==>\n%s\n<==" % kw['code']) # compile the program bld.targets = '*' ret = -1 try: try: bld.compile() except Errors.WafError: ret = 'Test does not build: %s' % Utils.ex_stack() self.fatal(ret) else: ret = getattr(bld, 'retval', 0) finally: # cache the results each time proj = ConfigSet.ConfigSet() proj['cache_run_c_code'] = ret proj.store(os.path.join(dir, 'cache_run_c_code')) return ret
def run_build(self, *k, **kw): """ Create a temporary build context to execute a build. A reference to that build context is kept on self.test_bld for debugging purposes, and you should not rely on it too much (read the note on the cache below). The parameters given in the arguments to this function are passed as arguments for a single task generator created in the build. Only three parameters are obligatory: :param features: features to pass to a task generator created in the build :type features: list of string :param compile_filename: file to create for the compilation (default: *test.c*) :type compile_filename: string :param code: code to write in the filename to compile :type code: string Though this function returns *0* by default, the build may set an attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. This function also provides a limited cache. To use it, provide the following option:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, action='count', help='Use a configuration cache') And execute the configuration with the following command-line:: $ waf configure --confcache """ lst = [str(v) for (p, v) in kw.items() if p != 'env'] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) try: os.makedirs(dir) except OSError: pass try: os.stat(dir) except OSError: self.fatal('cannot use the configuration test folder %r' % dir) cachemode = getattr(Options.options, 'confcache', None) if cachemode == 1: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_build')) except EnvironmentError: pass else: ret = proj['cache_run_build'] if isinstance(ret, str) and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) cls_name = kw.get('run_build_cls') or getattr(self, 'run_build_cls', 'build') self.test_bld = bld = Context.create_context(cls_name, top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' bld.logger = self.logger bld.all_envs.update(self.all_envs) # not really necessary bld.env = kw['env'] bld.kw = kw bld.conf = self kw['build_fun'](bld) ret = -1 try: try: bld.compile() except Errors.WafError: ret = 'Test does not build: %s' % traceback.format_exc() self.fatal(ret) else: ret = getattr(bld, 'retval', 0) finally: if cachemode == 1: # cache the results each time proj = ConfigSet.ConfigSet() proj['cache_run_build'] = ret proj.store(os.path.join(dir, 'cache_run_build')) else: shutil.rmtree(dir) return ret
def v(x): return Utils.to_hex(x)
def run_c_code(self, *k, **kw): """ Create a temporary build context to execute a build. A reference to that build context is kept on self.test_bld for debugging purposes, and you should not rely on it too much (read the note on the cache below). The parameters given in the arguments to this function are passed as arguments for a single task generator created in the build. Only three parameters are obligatory: :param features: features to pass to a task generator created in the build :type features: list of string :param compile_filename: file to create for the compilation (default: *test.c*) :type compile_filename: string :param code: code to write in the filename to compile :type code: string Though this function returns *0* by default, the build may set an attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. This function also provides a limited cache. To use it, provide the following option:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, action='count', help='Use a configuration cache') And execute the configuration with the following command-line:: $ waf configure --confcache """ lst = [str(v) for (p, v) in kw.items() if p != 'env'] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) try: os.makedirs(dir) except: pass try: os.stat(dir) except: self.fatal('cannot use the configuration test folder %r' % dir) cachemode = getattr(Options.options, 'confcache', None) if cachemode == CACHE_RESULTS: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_c_code')) ret = proj['cache_run_c_code'] except: pass else: if isinstance(ret, str) and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld = bld = Build.BuildContext(top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' if kw['compile_filename']: node = bld.srcnode.make_node(kw['compile_filename']) node.write(kw['code']) bld.logger = self.logger bld.all_envs.update(self.all_envs) # not really necessary bld.env = kw['env'] o = bld(features=kw['features'], source=kw['compile_filename'], target='testprog') for k, v in kw.items(): setattr(o, k, v) self.to_log("==>\n%s\n<==" % kw['code']) # compile the program bld.targets = '*' ret = -1 try: try: bld.compile() except Errors.WafError: ret = 'Test does not build: %s' % Utils.ex_stack() self.fatal(ret) else: ret = getattr(bld, 'retval', 0) finally: # cache the results each time proj = ConfigSet.ConfigSet() proj['cache_run_c_code'] = ret proj.store(os.path.join(dir, 'cache_run_c_code')) return ret
def run_build(self, *k, **kw): """ Create a temporary build context to execute a build. A temporary reference to that build context is kept on self.test_bld for debugging purposes. The arguments to this function are passed to a single task generator for that build. Only three parameters are mandatory: :param features: features to pass to a task generator created in the build :type features: list of string :param compile_filename: file to create for the compilation (default: *test.c*) :type compile_filename: string :param code: input file contents :type code: string Though this function returns *0* by default, the build may bind attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. The temporary builds creates a temporary folder; the name of that folder is calculated by hashing input arguments to this function, with the exception of :py:class:`waflib.ConfigSet.ConfigSet` objects which are used for both reading and writing values. This function also features a cache which is disabled by default; that cache relies on the hash value calculated as indicated above:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, action='count', help='Use a configuration cache') And execute the configuration with the following command-line:: $ waf configure --confcache """ buf = [] for key in sorted(kw.keys()): v = kw[key] if isinstance(v, ConfigSet.ConfigSet): # values are being written to, so they are excluded from contributing to the hash continue elif hasattr(v, '__call__'): buf.append(Utils.h_fun(v)) else: buf.append(str(v)) h = Utils.h_list(buf) dir = self.bldnode.abspath() + os.sep + ( not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) cachemode = kw.get('confcache', getattr(Options.options, 'confcache', None)) if not cachemode and os.path.exists(dir): shutil.rmtree(dir) try: os.makedirs(dir) except OSError: pass try: os.stat(dir) except OSError: self.fatal('cannot use the configuration test folder %r' % dir) if cachemode == 1: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_build')) except EnvironmentError: pass else: ret = proj['cache_run_build'] if isinstance(ret, str) and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) cls_name = kw.get('run_build_cls') or getattr(self, 'run_build_cls', 'build') self.test_bld = bld = Context.create_context(cls_name, top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' bld.logger = self.logger bld.all_envs.update(self.all_envs) # not really necessary bld.env = kw['env'] bld.kw = kw bld.conf = self kw['build_fun'](bld) ret = -1 try: try: bld.compile() except Errors.WafError: ret = 'Test does not build: %s' % traceback.format_exc() self.fatal(ret) else: ret = getattr(bld, 'retval', 0) finally: if cachemode: # cache the results each time proj = ConfigSet.ConfigSet() proj['cache_run_build'] = ret proj.store(os.path.join(dir, 'cache_run_build')) else: shutil.rmtree(dir) return ret