[pypy-svn] r19297 - in pypy/dist/pypy/translator: c c/test tool

arigo at codespeak.net arigo at codespeak.net
Mon Oct 31 20:52:27 CET 2005


Author: arigo
Date: Mon Oct 31 20:52:22 2005
New Revision: 19297

Modified:
   pypy/dist/pypy/translator/c/genc.py
   pypy/dist/pypy/translator/c/test/test_stackless.py
   pypy/dist/pypy/translator/c/test/test_standalone.py
   pypy/dist/pypy/translator/tool/cbuild.py
Log:
Generate a Makefile for stand-alone targets.
(cbuild.py is quite messy, so this involved some refactoring...)


Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Mon Oct 31 20:52:22 2005
@@ -5,7 +5,7 @@
 from pypy.translator.c.extfunc import pre_include_code_lines
 from pypy.translator.gensupp import uniquemodulename, NameManager
 from pypy.translator.tool.cbuild import compile_c_module
-from pypy.translator.tool.cbuild import build_executable
+from pypy.translator.tool.cbuild import build_executable, CCompiler
 from pypy.translator.tool.cbuild import import_module_from_directory
 from pypy.rpython.rmodel import getfunctionptr
 from pypy.rpython.lltypesystem import lltype
@@ -76,6 +76,8 @@
                                                  defines = defines)
         self.c_source_filename = py.path.local(cfile)
         self.extrafiles = extra
+        if self.standalone:
+            self.gen_makefile(targetdir)
         return cfile 
 
 
@@ -120,16 +122,21 @@
         # signature:  list-of-strings -> int
         return getfunctionptr(self.translator, self.translator.entrypoint)
 
-    def compile(self):
-        assert self.c_source_filename
-        assert not self._compiled
+    def getccompiler(self, extra_includes):
         # XXX for now, we always include Python.h
         from distutils import sysconfig
         python_inc = sysconfig.get_python_inc()
-        self.executable_name = build_executable(
+        return CCompiler(
             [self.c_source_filename] + self.extrafiles,
-            include_dirs = [autopath.this_dir, python_inc, str(self.targetdir)],
-            libraries=self.libraries)
+            include_dirs = [autopath.this_dir, python_inc] + extra_includes,
+            libraries    = self.libraries)
+
+    def compile(self):
+        assert self.c_source_filename
+        assert not self._compiled
+        compiler = self.getccompiler(extra_includes=[str(self.targetdir)])
+        compiler.build()
+        self.executable_name = str(compiler.outputfilename)
         self._compiled = True
         return self.executable_name
 
@@ -137,6 +144,46 @@
         assert self._compiled
         return py.process.cmdexec('"%s" %s' % (self.executable_name, args))
 
+    def gen_makefile(self, targetdir):
+        def write_list(lst, prefix):
+            for i, fn in enumerate(lst):
+                print >> f, prefix, fn,
+                if i < len(lst)-1:
+                    print >> f, '\\'
+                else:
+                    print >> f
+                prefix = ' ' * len(prefix)
+
+        compiler = self.getccompiler(extra_includes=['.'])
+        cfiles = []
+        ofiles = []
+        for fn in compiler.cfilenames:
+            fn = py.path.local(fn).basename
+            assert fn.endswith('.c')
+            cfiles.append(fn)
+            ofiles.append(fn[:-2] + '.o')
+
+        f = targetdir.join('Makefile').open('w')
+        print >> f, '# automatically generated Makefile'
+        print >> f
+        print >> f, 'TARGET =', py.path.local(compiler.outputfilename).basename
+        print >> f
+        write_list(cfiles, 'SOURCES =')
+        print >> f
+        write_list(ofiles, 'OBJECTS =')
+        print >> f
+        args = ['-l'+libname for libname in compiler.libraries]
+        print >> f, 'LIBS =', ' '.join(args)
+        args = ['-L'+path for path in compiler.library_dirs]
+        print >> f, 'LIBDIRS =', ' '.join(args)
+        args = ['-I'+path for path in compiler.include_dirs]
+        write_list(args, 'INCLUDEDIRS =')
+        print >> f
+        print >> f, 'CFLAGS =', ' '.join(compiler.compile_extra)
+        print >> f, 'LDFLAGS =', ' '.join(compiler.link_extra)
+        print >> f, MAKEFILE.strip()
+        f.close()
+
 
 def translator2database(translator):
     pf = lltype.pyobjectptr(translator.entrypoint)
@@ -345,6 +392,7 @@
             fc.close()
         print >> f
 
+
 # this function acts as the fallback for small sources for now.
 # Maybe we drop this completely if source splitting is the way
 # to go. Currently, I'm quite fine with keeping a working fallback.
@@ -655,3 +703,16 @@
                  extra_compile_args = extra_compile_args,
                        include_dirs = [PYPY_INCLUDE_DIR])])
 '''
+
+MAKEFILE = '''
+CC = gcc
+
+$(TARGET): $(OBJECTS)
+\t$(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBDIRS) $(LIBS)
+
+%.o: %.c
+\t$(CC) $(CFLAGS) -o $@ -c $< $(INCLUDEDIRS)
+
+clean:
+\trm -f $(OBJECTS)
+'''

Modified: pypy/dist/pypy/translator/c/test/test_stackless.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_stackless.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_stackless.py	Mon Oct 31 20:52:22 2005
@@ -1,5 +1,4 @@
 from pypy.translator.translator import Translator
-from pypy.translator.tool.cbuild import build_executable
 from pypy.annotation.model import SomeList, SomeString
 from pypy.annotation.listdef import ListDef
 from pypy.rpython.rstack import stack_unwind, stack_frames_depth, stack_too_big

Modified: pypy/dist/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_standalone.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_standalone.py	Mon Oct 31 20:52:22 2005
@@ -1,5 +1,4 @@
 from pypy.translator.translator import Translator
-from pypy.translator.tool.cbuild import build_executable
 from pypy.annotation.model import SomeList, SomeString
 from pypy.annotation.listdef import ListDef
 import os

Modified: pypy/dist/pypy/translator/tool/cbuild.py
==============================================================================
--- pypy/dist/pypy/translator/tool/cbuild.py	(original)
+++ pypy/dist/pypy/translator/tool/cbuild.py	Mon Oct 31 20:52:22 2005
@@ -254,55 +254,64 @@
         return spawn(cmd, *args, **kwds)
     return spawn_and_log
 
-def build_executable(cfilenames, outputfilename=None, include_dirs=None,
-                     libraries=[], library_dirs=None):
-    from distutils.ccompiler import new_compiler 
-    ext = ''
-    compile_extra = []
-    link_extra = []
-
-    if not include_dirs:
-        include_dirs = []
-    if not library_dirs:
-        library_dirs = []
-    if not sys.platform in ('win32', 'darwin'): # xxx
-        libraries.append('m')
-        libraries.append('pthread')
-        compile_extra += ['-O2', '-pthread']
-        link_extra += ['-pthread']
-    if sys.platform == 'darwin':
-        include_dirs.append('/sw/include')
-        compile_extra += ['-O2']
-        
-    if outputfilename is None:
-        outputfilename = py.path.local(cfilenames[0]).new(ext=ext)
-    else: 
-        outputfilename = py.path.local(outputfilename) 
-
-    if sys.platform == 'darwin':
-        library_dirs=['/sw/lib']
-
-    compiler = new_compiler()
-    compiler.spawn = log_spawned_cmd(compiler.spawn)
-    objects = []
-    for cfile in cfilenames: 
-        cfile = py.path.local(cfile)
-        old = cfile.dirpath().chdir() 
-        try: 
-            res = compiler.compile([cfile.basename], 
-                                   include_dirs=include_dirs,
-                                   extra_preargs=compile_extra)
-            assert len(res) == 1
-            cobjfile = py.path.local(res[0]) 
-            assert cobjfile.check()
-            objects.append(str(cobjfile))
-        finally: 
-            old.chdir() 
-    compiler.link_executable(objects, str(outputfilename),
-                             libraries=libraries,
-                             extra_preargs=link_extra,
-                             library_dirs=library_dirs)
-    return str(outputfilename)
+
+class CCompiler:
+
+    def __init__(self, cfilenames, outputfilename=None, include_dirs=[],
+                 libraries=[], library_dirs=[]):
+        self.cfilenames = cfilenames
+        ext = ''
+        self.compile_extra = []
+        self.link_extra = []
+        self.libraries = list(libraries)
+        self.include_dirs = list(include_dirs)
+        self.library_dirs = list(library_dirs)
+        if not sys.platform in ('win32', 'darwin'): # xxx
+            if 'm' not in self.libraries:
+                self.libraries.append('m')
+            if 'pthread' not in self.libraries:
+                self.libraries.append('pthread')
+            self.compile_extra += ['-O2', '-pthread']
+            self.link_extra += ['-pthread']
+        if sys.platform == 'darwin':
+            if '/sw/include' not in self.include_dirs:
+                self.include_dirs.append('/sw/include')
+            if '/sw/lib' not in self.library_dirs:
+                self.library_dirs.append('/sw/lib')
+            self.compile_extra += ['-O2']
+
+        if outputfilename is None:
+            self.outputfilename = py.path.local(cfilenames[0]).new(ext=ext)
+        else: 
+            self.outputfilename = py.path.local(outputfilename) 
+
+    def build(self):
+        from distutils.ccompiler import new_compiler 
+        compiler = new_compiler()
+        compiler.spawn = log_spawned_cmd(compiler.spawn)
+        objects = []
+        for cfile in self.cfilenames: 
+            cfile = py.path.local(cfile)
+            old = cfile.dirpath().chdir() 
+            try: 
+                res = compiler.compile([cfile.basename], 
+                                       include_dirs=self.include_dirs,
+                                       extra_preargs=self.compile_extra)
+                assert len(res) == 1
+                cobjfile = py.path.local(res[0]) 
+                assert cobjfile.check()
+                objects.append(str(cobjfile))
+            finally: 
+                old.chdir() 
+        compiler.link_executable(objects, str(self.outputfilename),
+                                 libraries=self.libraries,
+                                 extra_preargs=self.link_extra,
+                                 library_dirs=self.library_dirs)
+
+def build_executable(*args, **kwds):
+    compiler = CCompiler(*args, **kwds)
+    compiler.build()
+    return str(compiler.outputfilename)
 
 def check_boehm_presence():
     from pypy.tool.udir import udir



More information about the Pypy-commit mailing list