[pypy-commit] pypy rffi-parser-2: Configure types using only the C source passed to parse_source()

rlamy pypy.commits at gmail.com
Fri Jan 13 11:13:52 EST 2017


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: rffi-parser-2
Changeset: r89544:bdd3e262b996
Date: 2017-01-13 16:13 +0000
http://bitbucket.org/pypy/pypy/changeset/bdd3e262b996/

Log:	Configure types using only the C source passed to parse_source()

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -974,7 +974,7 @@
 
 } PyTypeObject;
 
-""", configure_now=True)
+""", headers=['sys/types.h', 'stdarg.h', 'stdio.h'], configure_now=True)
 
 Py_ssize_t = object_h.gettype('Py_ssize_t')
 Py_ssize_tP = object_h.gettype('Py_ssize_t *')
diff --git a/pypy/module/cpyext/cparser.py b/pypy/module/cpyext/cparser.py
--- a/pypy/module/cpyext/cparser.py
+++ b/pypy/module/cpyext/cparser.py
@@ -6,6 +6,7 @@
 except ImportError:
     import pycparser
 import weakref, re
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.rlib.rfile import FILEP
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rtyper.tool import rfficache, rffi_platform
@@ -675,17 +676,15 @@
 
 
 class ParsedSource(object):
-    def __init__(self, source, parser, definitions=None, macros=None, eci=None):
+    def __init__(self, source, parser, definitions=None, macros=None, headers=None):
         from pypy.module.cpyext.api import configure_eci
         self.source = source
         self.definitions = definitions if definitions is not None else {}
         self.macros = macros if macros is not None else {}
         self.structs = {}
         self.ctx = parser
-        if eci is None:
-            eci = configure_eci
-        self._Config = type(
-            'Config', (object,), {'_compilation_info_': eci})
+        self.headers = headers if headers is not None else ['sys/types.h']
+        self._Config = type('Config', (object,), {})
         self._TYPES = {}
         self.includes = []
 
@@ -728,6 +727,16 @@
             cpython_struct(type_name, struct.fields, forward=struct.TYPE)
         return struct.TYPE
 
+    def build_eci(self):
+        all_sources = [x.source for x in self.includes] + [self.source]
+        all_headers = self.headers
+        for x in self.includes:
+            for hdr in x.headers:
+                if hdr not in all_headers:
+                    all_headers.append(hdr)
+        return ExternalCompilationInfo(
+            post_include_bits=all_sources, includes=all_headers)
+
     def configure_types(self, configure_now=False):
         for name, (obj, quals) in self.ctx._declarations.iteritems():
             if obj in self.ctx._included_declarations:
@@ -738,6 +747,7 @@
             elif name.startswith('macro '):
                 name = name[6:]
                 self.add_macro(name, obj)
+        self._Config._compilation_info_ = self.build_eci()
         for name, TYPE in rffi_platform.configure(self._Config).iteritems():
             if name in self._TYPES:
                 self._TYPES[name].become(TYPE)
@@ -794,9 +804,9 @@
         return decl.name, FUNCP.TO
 
 
-def parse_source(source, includes=None, eci=None, configure_now=False):
+def parse_source(source, includes=None, headers=None, configure_now=False):
     ctx = Parser()
-    src = ParsedSource(source, ctx, eci=eci)
+    src = ParsedSource(source, ctx, headers=headers)
     if includes is not None:
         for header in includes:
             src.include(header)
diff --git a/pypy/module/cpyext/test/test_cparser.py b/pypy/module/cpyext/test/test_cparser.py
--- a/pypy/module/cpyext/test/test_cparser.py
+++ b/pypy/module/cpyext/test/test_cparser.py
@@ -1,8 +1,7 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.module.cpyext.cparser import parse_source
 
-def test_configure(tmpdir):
+def test_configure():
     decl = """
     typedef ssize_t Py_ssize_t;
 
@@ -12,11 +11,7 @@
         double ob_fval;
     } TestFloatObject;
     """
-    hdr = tmpdir / 'header.h'
-    hdr.write(decl)
-    eci = ExternalCompilationInfo(
-        include_dirs=[str(tmpdir)], includes=['sys/types.h', 'header.h'])
-    res = parse_source(decl, eci=eci, configure_now=True)
+    res = parse_source(decl, configure_now=True)
     TestFloatObject = res.definitions['TestFloatObject']
     assert isinstance(TestFloatObject, lltype.Struct)
     assert TestFloatObject.c_ob_refcnt == rffi.SSIZE_T
@@ -45,7 +40,7 @@
     assert 'PyFloatObject' in hdr.definitions
     assert 'PyObject_HEAD' in hdr.macros
 
-def test_include(tmpdir):
+def test_include():
     cdef1 = """
     typedef ssize_t Py_ssize_t;
 
@@ -57,8 +52,6 @@
         char *name;
     } Type;
     """
-    base_name = tmpdir / 'base.h'
-    base_name.write(cdef1)
     cdef2 = """
     typedef struct {
         PyObject_HEAD
@@ -66,19 +59,15 @@
         Type *type;
     } Object;
     """
-    (tmpdir / 'object.h').write(cdef2)
-    eci = ExternalCompilationInfo(
-        include_dirs=[str(tmpdir)],
-        includes=['sys/types.h', 'base.h', 'object.h'])
-    hdr1 = parse_source(cdef1, eci=eci, configure_now=True)
+    hdr1 = parse_source(cdef1, configure_now=True)
     Type = hdr1.definitions['Type']
     assert isinstance(Type, lltype.Struct)
-    hdr2 = parse_source(cdef2, includes=[hdr1], eci=eci, configure_now=True)
+    hdr2 = parse_source(cdef2, includes=[hdr1], configure_now=True)
     assert 'Type' not in hdr2.definitions
     Object = hdr2.definitions['Object']
     assert Object.c_type.TO is Type
 
-def test_incomplete(tmpdir):
+def test_incomplete():
     cdef = """
     typedef ssize_t Py_ssize_t;
 
@@ -94,15 +83,11 @@
     } Buffer;
 
     """
-    (tmpdir / 'foo.h').write(cdef)
-    eci = ExternalCompilationInfo(
-        include_dirs=[str(tmpdir)],
-        includes=['sys/types.h', 'foo.h'])
-    foo_h = parse_source(cdef, eci=eci)
+    foo_h = parse_source(cdef)
     Object = foo_h.gettype('Object')
     assert isinstance(Object, lltype.ForwardReference)
 
-def test_recursive(tmpdir):
+def test_recursive():
     cdef = """
     typedef ssize_t Py_ssize_t;
 
@@ -121,29 +106,21 @@
         Object *obj;
     } Type;
     """
-    (tmpdir / 'foo.h').write(cdef)
-    eci = ExternalCompilationInfo(
-        include_dirs=[str(tmpdir)],
-        includes=['sys/types.h', 'foo.h'])
-    foo_h = parse_source(cdef, eci=eci, configure_now=True)
+    foo_h = parse_source(cdef, configure_now=True)
     Object = foo_h.definitions['Object']
     assert isinstance(Object, lltype.Struct)
     hash(Object)
 
-def test_const(tmpdir):
+def test_const():
     cdef = """
     typedef struct {
         const char * const foo;
     } bar;
     """
-    (tmpdir / 'foo.h').write(cdef)
-    eci = ExternalCompilationInfo(
-        include_dirs=[str(tmpdir)],
-        includes=['sys/types.h', 'foo.h'])
-    hdr = parse_source(cdef, eci=eci, configure_now=True)
+    hdr = parse_source(cdef, configure_now=True)
     assert hdr.definitions['bar'].c_foo == rffi.CONST_CCHARP != rffi.CCHARP
 
-def test_gettype(tmpdir):
+def test_gettype():
     decl = """
     typedef ssize_t Py_ssize_t;
 
@@ -156,15 +133,11 @@
         double ob_fval;
     } TestFloatObject;
     """
-    hdr = tmpdir / 'header.h'
-    hdr.write(decl)
-    eci = ExternalCompilationInfo(
-        include_dirs=[str(tmpdir)], includes=['sys/types.h', 'header.h'])
-    res = parse_source(decl, eci=eci, configure_now=True)
+    res = parse_source(decl, configure_now=True)
     assert res.gettype('Py_ssize_t') == rffi.SSIZE_T
     assert res.gettype('TestFloatObject *').TO.c_ob_refcnt == rffi.SSIZE_T
 
-def test_parse_funcdecl(tmpdir):
+def test_parse_funcdecl():
     decl = """
     typedef ssize_t Py_ssize_t;
 
@@ -179,11 +152,7 @@
 
     typedef TestFloatObject* (*func_t)(int, int);
     """
-    hdr = tmpdir / 'header.h'
-    hdr.write(decl)
-    eci = ExternalCompilationInfo(
-        include_dirs=[str(tmpdir)], includes=['sys/types.h', 'header.h'])
-    res = parse_source(decl, eci=eci, configure_now=True)
+    res = parse_source(decl, configure_now=True)
     name, FUNC = res.parse_func("func_t some_func(TestFloatObject*)")
     assert name == 'some_func'
     assert FUNC.RESULT == res.gettype('func_t')


More information about the pypy-commit mailing list