def _worker(): # XXX: this whole thing is an hack - find a better way to # notify task execution failure to all worker threads while not self.stop: task = self.worker_queue.get() try: run_task(self.ctx, task) except yaku.errors.TaskRunFailure: e = get_exception() self.failure_lock.acquire() self.stop = True self.failure_lock.release() task.error_msg = e.explain task.error_cmd = e.cmd self.error_out.put(task) except Exception: e = get_exception() exc_type, exc_value, tb = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, tb) self.failure_lock.acquire() self.stop = True self.failure_lock.release() task.error_msg = "".join(lines) task.error_cmd = [] self.error_out.put(task) self.worker_queue.task_done()
def exec_command(self, cmd, cwd, env=None): if cwd is None: cwd = self.gen.bld.bld_root.abspath() kw = {} if env is not None: kw["env"] = env if not self.disable_output: if self.env["VERBOSE"]: pprint('GREEN', " ".join([str(c) for c in cmd])) else: pprint('GREEN', "%-16s%s" % (self.name.upper(), " ".join([i.bldpath() for i in self.inputs]))) self.gen.bld.set_cmd_cache(self, cmd) try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cwd, **kw) stdout = p.communicate()[0].decode("utf-8") if p.returncode: raise TaskRunFailure(cmd, stdout) if sys.version_info >= (3,): stdout = stdout else: stdout = stdout.encode("utf-8") if self.disable_output: self.log.write(stdout) else: sys.stderr.write(stdout) self.gen.bld.set_stdout_cache(self, stdout) except OSError: e = get_exception() raise TaskRunFailure(cmd, str(e)) except WindowsError: e = get_exception() raise TaskRunFailure(cmd, str(e))
def try_task_maker(conf, task_maker, name, body, headers, env=None): if headers: head = "\n".join(["#include <%s>" % h for h in headers]) else: head = "" code = "\n".join([c for c in [head, body]]) sources = [create_file(conf, code, name, ".c")] task_gen = CompiledTaskGen("conf", conf, sources, name) task_gen.env.update(copy.deepcopy(conf.env)) task_gen.env = _merge_env(task_gen.env, env) task_gen.env.prepend("LIBDIR", conf.path.declare(".").abspath()) tasks = task_maker(task_gen, name) conf.last_task = tasks[-1] for t in tasks: t.disable_output = True t.log = conf.log succeed = False explanation = None try: try: run_tasks(conf, tasks) succeed = True except TaskRunFailure: e = get_exception() explanation = str(e) #raise finally: write_log(conf, conf.log, tasks, code, succeed, explanation) return succeed
def _try_task_maker(self, task_maker, name, body): conf = self.ctx code = body sources = [create_file(conf, code, name, ".f")] task_gen = CompiledTaskGen("conf", conf, sources, name) task_gen.env.update(copy.deepcopy(conf.env)) tasks = task_maker(task_gen, name) self.ctx.last_task = tasks[-1] for t in tasks: t.disable_output = True t.log = conf.log succeed = False explanation = None try: run_tasks(conf, tasks) succeed = True except TaskRunFailure: e = get_exception() explanation = str(e) write_log(conf, conf.log, tasks, code, succeed, explanation) return succeed
def configure(self, candidates=None, use_distutils=True): ctx = self.ctx # How we do it # 1: for distutils-based configuration # - get compile/flags flags from sysconfig # - detect yaku tool name from CC used by distutils: # - get the compiler executable used by distutils ($CC # variable) # - try to determine yaku tool name from $CC # - apply necessary variables from yaku tool to $PYEXT_ # "namespace" if candidates is None: compiler_type = "default" else: compiler_type = candidates[0] if use_distutils: dist_env = setup_pyext_env(ctx, compiler_type) ctx.env.update(dist_env) cc_exec = get_distutils_cc_exec(ctx, compiler_type) yaku_cc_type = detect_cc_type(ctx, cc_exec) if yaku_cc_type is None: raise ValueError("No adequate C compiler found (distutils mode)") _setup_compiler(ctx, yaku_cc_type) cxx_exec = get_distutils_cxx_exec(ctx, compiler_type) yaku_cxx_type = detect_cxx_type(ctx, cxx_exec) if yaku_cxx_type is None: raise ValueError("No adequate CXX compiler found (distutils mode)") _setup_cxxcompiler(ctx, yaku_cxx_type) else: dist_env = setup_pyext_env(ctx, compiler_type, False) ctx.env.update(dist_env) _setup_compiler(ctx, compiler_type) pycode = r"""\ #include <Python.h> #include <stdio.h> static PyObject* hello(PyObject *self, PyObject *args) { printf("Hello from C\n"); Py_INCREF(Py_None); return Py_None; } static PyMethodDef HelloMethods[] = { {"hello", hello, METH_VARARGS, "Print a hello world."}, {NULL, NULL, 0, NULL} /* Sentinel */ }; PyMODINIT_FUNC init_bar(void) { (void) Py_InitModule("_bar", HelloMethods); } """ ctx.start_message("Checking whether %s can build python object code" % compiler_type) try: self.try_compile("foo", pycode) ctx.end_message("yes") except TaskRunFailure: e = get_exception() ctx.end_message("no") ctx.fail_configuration(str(e)) ctx.start_message("Checking whether %s can build python extension" % compiler_type) try: self.try_extension("foo", pycode) ctx.end_message("yes") except TaskRunFailure: e = get_exception() ctx.end_message("no") ctx.fail_configuration(str(e)) self.configured = True
def configure(self, candidates=None, use_distutils=True): ctx = self.ctx # How we do it # 1: for distutils-based configuration # - get compile/flags flags from sysconfig # - detect yaku tool name from CC used by distutils: # - get the compiler executable used by distutils ($CC # variable) # - try to determine yaku tool name from $CC # - apply necessary variables from yaku tool to $PYEXT_ # "namespace" if candidates is None: compiler_type = "default" else: compiler_type = candidates[0] if use_distutils: dist_env = setup_pyext_env(ctx, compiler_type) ctx.env.update(dist_env) cc_exec = get_distutils_cc_exec(ctx, compiler_type) yaku_cc_type = detect_cc_type(ctx, cc_exec) if yaku_cc_type is None: raise ValueError( "No adequate C compiler found (distutils mode)") _setup_compiler(ctx, yaku_cc_type) cxx_exec = get_distutils_cxx_exec(ctx, compiler_type) yaku_cxx_type = detect_cxx_type(ctx, cxx_exec) if yaku_cxx_type is None: raise ValueError( "No adequate CXX compiler found (distutils mode)") _setup_cxxcompiler(ctx, yaku_cxx_type) else: dist_env = setup_pyext_env(ctx, compiler_type, False) ctx.env.update(dist_env) _setup_compiler(ctx, compiler_type) pycode = r"""\ #include <Python.h> #include <stdio.h> static PyObject* hello(PyObject *self, PyObject *args) { printf("Hello from C\n"); Py_INCREF(Py_None); return Py_None; } static PyMethodDef HelloMethods[] = { {"hello", hello, METH_VARARGS, "Print a hello world."}, {NULL, NULL, 0, NULL} /* Sentinel */ }; PyMODINIT_FUNC init_bar(void) { (void) Py_InitModule("_bar", HelloMethods); } """ ctx.start_message("Checking whether %s can build python object code" % compiler_type) try: self.try_compile("foo", pycode) ctx.end_message("yes") except TaskRunFailure: e = get_exception() ctx.end_message("no") ctx.fail_configuration(str(e)) ctx.start_message("Checking whether %s can build python extension" % compiler_type) try: self.try_extension("foo", pycode) ctx.end_message("yes") except TaskRunFailure: e = get_exception() ctx.end_message("no") ctx.fail_configuration(str(e)) self.configured = True