[pypy-svn] r54725 - in pypy/dist/pypy: rpython/lltypesystem rpython/lltypesystem/test translator/c translator/tool

afa at codespeak.net afa at codespeak.net
Wed May 14 11:16:49 CEST 2008


Author: afa
Date: Wed May 14 11:16:47 2008
New Revision: 54725

Modified:
   pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/dist/pypy/rpython/lltypesystem/rffi.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py
   pypy/dist/pypy/translator/c/genc.py
   pypy/dist/pypy/translator/tool/cbuild.py
Log:
Make CExtModuleBuilder and ll2ctypes work on win32:
- export all needed symbols when building a dll
- eventually compile with debug info
- load the correct libc, depending on compiler version and options.

test_rffi and test_ll2ctypes pass, and probably many others.


Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py	Wed May 14 11:16:47 2008
@@ -519,13 +519,27 @@
 
 if ctypes:
     if sys.platform == 'win32':
-        # trying to guess the correct libc... only a few tests fail if there
-        # is a mismatch between the one used by python2x.dll and the one
-        # loaded here
-        if sys.version_info < (2, 4):
-            standard_c_lib = ctypes.cdll.LoadLibrary('msvcrt.dll')
+        # Parses sys.version and deduces the version of the compiler
+        import distutils.msvccompiler
+        version = distutils.msvccompiler.get_build_version()
+        if version is None:
+            # This logic works with official builds of Python.
+            if sys.version_info < (2, 4):
+                clibname = 'msvcrt'
+            else:
+                clibname = 'msvcr71'
         else:
-            standard_c_lib = ctypes.cdll.LoadLibrary('msvcr71.dll')
+            if version <= 6:
+                clibname = 'msvcrt'
+            else:
+                clibname = 'msvcr%d' % (version * 10)
+
+        # If python was built with in debug mode
+        import imp
+        if imp.get_suffixes()[0][0] == '_d.pyd':
+            clibname += 'd'
+
+        standard_c_lib = ctypes.cdll.LoadLibrary(clibname+'.dll')
     else:
         standard_c_lib = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
 

Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rffi.py	Wed May 14 11:16:47 2008
@@ -406,6 +406,7 @@
     new_eci = eci.merge(ExternalCompilationInfo(
         separate_module_sources = sources,
         post_include_lines = [getter_prototype, setter_prototype],
+        export_symbols = [getter_name, setter_name],
     ))
 
     getter = llexternal(getter_name, [], TYPE, compilation_info=new_eci,

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	Wed May 14 11:16:47 2008
@@ -267,8 +267,11 @@
         assert not ALLOCATED     # detects memory leaks in the test
 
     def test_frexp(self):
-        eci = ExternalCompilationInfo(includes=['math.h'],
-                                      libraries=['m'])
+        if sys.platform != 'win32':
+            eci = ExternalCompilationInfo(includes=['math.h'],
+                                          libraries=['m'])
+        else:
+            eci = ExternalCompilationInfo(includes=['math.h'])
         A = lltype.FixedSizeArray(rffi.INT, 1)
         frexp = rffi.llexternal('frexp', [rffi.DOUBLE, lltype.Ptr(A)],
                                 rffi.DOUBLE, compilation_info=eci)
@@ -299,6 +302,8 @@
         assert not ALLOCATED     # detects memory leaks in the test
 
     def test_opaque_obj(self):
+        if sys.platform == 'win32':
+            py.test.skip("No gettimeofday on win32")
         eci = ExternalCompilationInfo(
             includes = ['sys/time.h', 'time.h']
         )
@@ -683,6 +688,8 @@
         assert abs(float(b[2]) - 2.2) < 1E-6
 
     def test_different_signatures(self):
+        if sys.platform=='win32':
+            py.test.skip("No fcntl on win32")
         fcntl_int = rffi.llexternal('fcntl', [rffi.INT, rffi.INT, rffi.INT],
                                     rffi.INT)
         fcntl_str = rffi.llexternal('fcntl', [rffi.INT, rffi.INT, rffi.CCHARP],
@@ -693,7 +700,8 @@
 
     def test_llexternal_source(self):
         eci = ExternalCompilationInfo(
-            separate_module_sources = ["int fn() { return 42; }"]
+            separate_module_sources = ["int fn() { return 42; }"],
+            export_symbols = ['fn'],
         )
         fn = rffi.llexternal('fn', [], rffi.INT, compilation_info=eci)
         res = fn()
@@ -745,7 +753,8 @@
         }
         """)
 
-        eci = ExternalCompilationInfo(separate_module_sources=[c_source])
+        eci = ExternalCompilationInfo(separate_module_sources=[c_source],
+                                      export_symbols=['eating_callback'])
 
         args = [rffi.INT, rffi.CCallback([rffi.INT], rffi.INT)]
         eating_callback = rffi.llexternal('eating_callback', args, rffi.INT,

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py	Wed May 14 11:16:47 2008
@@ -1,5 +1,6 @@
 
 import py
+import sys
 from pypy.rpython.lltypesystem.rffi import *
 from pypy.rpython.lltypesystem.rffi import _keeper_for_type # crap
 from pypy.rlib.rposix import get_errno, set_errno
@@ -347,7 +348,8 @@
 
         eci = ExternalCompilationInfo(includes=['callback.h'],
                                       include_dirs=[str(udir)],
-                                      separate_module_sources=[c_source])
+                                      separate_module_sources=[c_source],
+                                      export_symbols=['eating_callback'])
 
         args = [INT, CCallback([INT], INT)]
         eating_callback = llexternal('eating_callback', args, INT,
@@ -530,6 +532,8 @@
         assert interpret(f, [], backendopt=True) == 43    
     
     def test_around_extcall(self):
+        if sys.platform == "win32":
+            py.test.skip('No pipes on windows')
         import os
         from pypy.annotation import model as annmodel
         from pypy.rlib.objectmodel import invoke_around_extcall

Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Wed May 14 11:16:47 2008
@@ -181,7 +181,10 @@
 
     def __del__(self):
         import sys
-        from _ctypes import dlclose
+        if sys.platform == "win32":
+            from _ctypes import FreeLibrary as dlclose
+        else:
+            from _ctypes import dlclose
         # XXX fish fish fish
         mod = self.__dict__['mod']
         dlclose(mod._lib._handle)
@@ -204,9 +207,15 @@
     def compile(self):
         assert self.c_source_filename 
         assert not self._compiled
+        export_symbols = [self.db.get(self.getentrypointptr()),
+                          'RPython_StartupCode',
+                          ]
+        if self.config.translation.countmallocs:
+            export_symbols.append('malloc_counters')
         compile_c_module([self.c_source_filename] + self.extrafiles,
                          self.c_source_filename.purebasename, self.eci,
-                         tmpdir=self.c_source_filename.dirpath())
+                         tmpdir=self.c_source_filename.dirpath(),
+                         export_symbols=export_symbols)
         self._compiled = True
 
     def _make_wrapper_module(self):
@@ -219,7 +228,7 @@
         CODE = """
 import ctypes
 
-_lib = ctypes.PyDLL("%(so_name)s")
+_lib = ctypes.PyDLL(r"%(so_name)s")
 
 _entry_point = getattr(_lib, "%(c_entrypoint_name)s")
 _entry_point.restype = ctypes.py_object

Modified: pypy/dist/pypy/translator/tool/cbuild.py
==============================================================================
--- pypy/dist/pypy/translator/tool/cbuild.py	(original)
+++ pypy/dist/pypy/translator/tool/cbuild.py	Wed May 14 11:16:47 2008
@@ -16,7 +16,8 @@
 
     _ATTRIBUTES = ['pre_include_lines', 'includes', 'include_dirs',
                    'post_include_lines', 'libraries', 'library_dirs',
-                   'separate_module_sources', 'separate_module_files']
+                   'separate_module_sources', 'separate_module_files',
+                   'export_symbols']
     _AVOID_DUPLICATES = ['separate_module_files', 'libraries', 'includes',
                          'include_dirs', 'library_dirs', 'separate_module_sources']
 
@@ -28,7 +29,8 @@
                  libraries               = [],
                  library_dirs            = [],
                  separate_module_sources = [],
-                 separate_module_files   = []):
+                 separate_module_files   = [],
+                 export_symbols          = []):
         """
         pre_include_lines: list of lines that should be put at the top
         of the generated .c files, before any #include.  They shouldn't
@@ -196,7 +198,8 @@
         opt += '/Op'
     gcv['OPT'] = opt
 
-def compile_c_module(cfiles, modbasename, eci, tmpdir=None):
+def compile_c_module(cfiles, modbasename, eci, tmpdir=None,
+                     export_symbols=None):
     #try:
     #    from distutils.log import set_threshold
     #    set_threshold(10000)
@@ -220,6 +223,11 @@
                os.path.exists(s + 'lib'):
                 library_dirs.append(s + 'lib')
 
+    if export_symbols is None:
+        export_symbols = list(eci.export_symbols)
+    else:
+        export_symbols = list(eci.export_symbols) + export_symbols
+
     num = 0
     modname = modbasename
     while 1:
@@ -253,11 +261,17 @@
                     from distutils.ccompiler import get_default_compiler
                     from distutils.command.build_ext import build_ext
 
-                    class build_ext_no_additional_symbol(build_ext):
+                    class build_shared_library(build_ext):
+                        """ We build shared libraries, not python modules.
+                            On windows, avoid to export the initXXX function,
+                            and don't use a .pyd extension. """
                         def get_export_symbols(self, ext):
-                            """ work around a 'feature' of distutils that forces every
-                                module to have a certain symbol on win """
                             return ext.export_symbols
+                        def get_ext_filename (self, ext_name):
+                            if sys.platform == 'win32':
+                                return ext_name + ".dll"
+                            else:
+                                return ext_name + ".so"
 
                     saved_environ = os.environ.items()
                     try:
@@ -290,7 +304,9 @@
                                     include_dirs=include_dirs,
                                     library_dirs=library_dirs,
                                     extra_compile_args=extra_compile_args,
-                                    libraries=list(libraries),)
+                                    libraries=list(libraries),
+                                    export_symbols=export_symbols,
+                                          )
                                 ],
                             'script_name': 'setup.py',
                             'script_args': ['-q', 'build_ext'], # don't remove 'build_ext' here
@@ -299,9 +315,11 @@
                         # patch our own command obj into distutils
                         # because it does not have a facility to accept
                         # custom objects
-                        cmdobj = build_ext_no_additional_symbol(dist)
+                        cmdobj = build_shared_library(dist)
                         cmdobj.inplace = True
                         cmdobj.force = True
+                        if sys.platform == 'win32' and sys.executable.endswith('_d.exe'):
+                            cmdobj.debug = True
                         dist.command_obj["build_ext"] = cmdobj
                         dist.have_run["build_ext"] = 0
 



More information about the Pypy-commit mailing list