def test_compilationerror_repr(): # compilation error output/stdout may be large, but we don't want # repr to create a limited version c = CompilationError('', '*'*1000) assert repr(c) == 'CompilationError(err="""\n\t%s""")' % ('*'*1000,) c = CompilationError('*'*1000, '') assert repr(c) == 'CompilationError(out="""\n\t%s""")' % ('*'*1000,)
def try_compile_cache(c_files, eci): "Try to compile a program. Cache success, and error message on failure" # Import 'platform' every time, the compiler may have been changed from rpython.translator.platform import platform, CompilationError path = cache_file_path(c_files, eci, 'try_compile_cache') try: data = path.read() if data == 'True': return True else: raise CompilationError(data, '') except py.error.Error: pass # _previous = platform.log_errors try: platform.log_errors = False platform.compile(c_files, eci) except CompilationError as e: msg = e.out + e.err if msg != 'True': try_atomic_write(path, msg) raise finally: del platform.log_errors # ^^^remove from the instance --- needed so that it can # compare equal to another instance without it if platform.log_errors != _previous: platform.log_errors = _previous try_atomic_write(path, "True") return True
def _handle_error(self, returncode, stdout, stderr, outname): if returncode != 0: # Microsoft compilers write compilation errors to stdout stderr = stdout + stderr errorfile = outname.new(ext='errors') errorfile.write(stderr, mode='wb') if self.log_errors: stderrlines = stderr.splitlines() for line in stderrlines: log.Error(line) # ^^^ don't use ERROR, because it might actually be fine. # Also, ERROR confuses lib-python/conftest.py. raise CompilationError(stdout, stderr)
def configure_external_library(name, eci, configurations, symbol=None, _cache={}): """try to find the external library. On Unix, this simply tests and returns the given eci. On Windows, various configurations may be tried to compile the given eci object. These configurations are a list of dicts, containing: - prefix: if an absolute path, will prefix each include and library directories. If a relative path, the external directory is searched for directories which names start with the prefix. The last one in alphabetical order chosen, and becomes the prefix. - include_dir: prefix + include_dir is added to the include directories - library_dir: prefix + library_dir is added to the library directories """ if sys.platform != 'win32': configurations = [] key = (name, eci) try: return _cache[key] except KeyError: last_error = None # Always try the default configuration if {} not in configurations: configurations.append({}) for configuration in configurations: prefix = configuration.get('prefix', '') include_dir = configuration.get('include_dir', '') library_dir = configuration.get('library_dir', '') if prefix and not os.path.isabs(prefix): import glob entries = glob.glob(str(PYPY_EXTERNAL_DIR.join(prefix + '*'))) if entries: # Get last version prefix = sorted(entries)[-1] else: continue include_dir = os.path.join(prefix, include_dir) library_dir = os.path.join(prefix, library_dir) eci_lib = ExternalCompilationInfo( include_dirs=include_dir and [include_dir] or [], library_dirs=library_dir and [library_dir] or [], ) eci_lib = eci_lib.merge(eci) # verify that this eci can be compiled try: verify_eci(eci_lib) except CompilationError as e: last_error = e else: _cache[key] = eci_lib return eci_lib # Nothing found if last_error: raise last_error else: raise CompilationError("Library %s is not installed" % (name, ))
def compile(self, cfilenames, eci, outputfilename=None, standalone=True): self._ensure_correct_math() self.cfilenames = cfilenames if standalone: ext = '' else: ext = so_ext self.standalone = standalone self.libraries = list(eci.libraries) self.include_dirs = list(eci.include_dirs) self.library_dirs = list(eci.library_dirs) self.compile_extra = list(eci.compile_extra) self.link_extra = list(eci.link_extra) self.frameworks = list(eci.frameworks) if not self.name in ('win32', 'darwin', 'cygwin'): # xxx if 'm' not in self.libraries: self.libraries.append('m') self.compile_extra += CFLAGS + ['-fomit-frame-pointer'] if 'pthread' not in self.libraries: self.libraries.append('pthread') if self.name != 'sunos5': self.compile_extra += ['-pthread'] self.link_extra += ['-pthread'] else: self.compile_extra += ['-pthreads'] self.link_extra += ['-lpthread'] if self.name == 'win32': self.link_extra += ['/DEBUG'] # generate .pdb file if self.name == 'darwin': # support Fink & Darwinports for s in ('/sw/', '/opt/local/'): if s + 'include' not in self.include_dirs and \ os.path.exists(s + 'include'): self.include_dirs.append(s + 'include') if s + 'lib' not in self.library_dirs and \ os.path.exists(s + 'lib'): self.library_dirs.append(s + 'lib') self.compile_extra += CFLAGS + ['-fomit-frame-pointer'] for framework in self.frameworks: self.link_extra += ['-framework', framework] if outputfilename is None: self.outputfilename = py.path.local(cfilenames[0]).new(ext=ext) else: self.outputfilename = py.path.local(outputfilename) self.eci = eci import distutils.errors basename = self.outputfilename.new(ext='') data = '' try: saved_environ = os.environ.copy() c = stdoutcapture.Capture(mixed_out_err=True) try: self._build() finally: # workaround for a distutils bugs where some env vars can # become longer and longer every time it is used for key, value in saved_environ.items(): if os.environ.get(key) != value: os.environ[key] = value foutput, foutput = c.done() data = foutput.read() if data: fdump = basename.new(ext='errors').open("wb") fdump.write(data) fdump.close() except (distutils.errors.CompileError, distutils.errors.LinkError): raise CompilationError('', data) except: print >> sys.stderr, data raise return self.outputfilename