[pypy-svn] r73508 - in pypy/branch/cpython-extension/pypy: config doc/config translator translator/c translator/c/src translator/c/test
afa at codespeak.net
afa at codespeak.net
Wed Apr 7 16:27:51 CEST 2010
Author: afa
Date: Wed Apr 7 16:27:49 2010
New Revision: 73508
Added:
pypy/branch/cpython-extension/pypy/doc/config/translation.shared.txt (contents, props changed)
Modified:
pypy/branch/cpython-extension/pypy/config/pypyoption.py
pypy/branch/cpython-extension/pypy/config/translationoption.py
pypy/branch/cpython-extension/pypy/translator/c/genc.py
pypy/branch/cpython-extension/pypy/translator/c/src/main.h
pypy/branch/cpython-extension/pypy/translator/c/test/test_standalone.py
pypy/branch/cpython-extension/pypy/translator/driver.py
Log:
Add the --shared option to translation.
This allows to build pypy as a shared library, which can thus export the C API provided by cpyext.
On windows, this builds two files:
- pypy-c.exe.dll is the shared library containing all pypy
- pypy-c.exe is a tiny executable that calls the main function in the dll.
Modified: pypy/branch/cpython-extension/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/config/pypyoption.py (original)
+++ pypy/branch/cpython-extension/pypy/config/pypyoption.py Wed Apr 7 16:27:49 2010
@@ -62,12 +62,14 @@
module_dependencies = {}
-module_suggests = { # the reason you want _rawffi is for ctypes, which
- # itself needs the interp-level struct module
- # because 'P' is missing from the app-level one
- '_rawffi': [("objspace.usemodules.struct", True)],
- 'cpyext': [("translation.secondaryentrypoints", "cpyext")],
- }
+module_suggests = {
+ # the reason you want _rawffi is for ctypes, which
+ # itself needs the interp-level struct module
+ # because 'P' is missing from the app-level one
+ "_rawffi": [("objspace.usemodules.struct", True)],
+ "cpyext": [("translation.secondaryentrypoints", "cpyext"),
+ ("translation.shared", sys.platform == "win32")],
+ }
module_import_dependencies = {
# no _rawffi if importing pypy.rlib.libffi raises ImportError
Modified: pypy/branch/cpython-extension/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/config/translationoption.py (original)
+++ pypy/branch/cpython-extension/pypy/config/translationoption.py Wed Apr 7 16:27:49 2010
@@ -42,6 +42,9 @@
},
cmdline="-b --backend"),
+ BoolOption("shared", "Build as a shared library",
+ default=False, cmdline="--shared"),
+
BoolOption("log", "Include debug prints in the translation (PYPYLOG=...)",
default=True, cmdline="--log"),
Added: pypy/branch/cpython-extension/pypy/doc/config/translation.shared.txt
==============================================================================
--- (empty file)
+++ pypy/branch/cpython-extension/pypy/doc/config/translation.shared.txt Wed Apr 7 16:27:49 2010
@@ -0,0 +1,2 @@
+Build pypy as a shared library or a DLL, with a small executable to run it.
+This is necessary on Windows to expose the C API provided by the cpyext module.
Modified: pypy/branch/cpython-extension/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/translator/c/genc.py (original)
+++ pypy/branch/cpython-extension/pypy/translator/c/genc.py Wed Apr 7 16:27:49 2010
@@ -78,14 +78,15 @@
self.outputfilename = outputfilename
self.profbased = profbased
- def _build(self, eci=ExternalCompilationInfo()):
+ def _build(self, eci=ExternalCompilationInfo(), shared=False):
return self.platform.compile(self.cfiles, self.eci.merge(eci),
- outputfilename=self.outputfilename)
+ outputfilename=self.outputfilename,
+ standalone=not shared)
- def build(self):
+ def build(self, shared=False):
if self.profbased:
return self._do_profbased()
- return self._build()
+ return self._build(shared=shared)
def _do_profbased(self):
ProfDriver, args = self.profbased
@@ -252,6 +253,10 @@
if CBuilder.have___thread:
if not self.config.translation.no__thread:
defines['USE___THREAD'] = 1
+ if self.config.translation.shared:
+ defines['PYPY_MAIN_FUNCTION'] = "pypy_main_startup"
+ self.eci = self.eci.merge(ExternalCompilationInfo(
+ export_symbols=["pypy_main_startup"]))
self.eci, cfile, extra = gen_source_standalone(db, modulename,
targetdir,
self.eci,
@@ -422,6 +427,7 @@
class CStandaloneBuilder(CBuilder):
standalone = True
executable_name = None
+ shared_library_name = None
def getprofbased(self):
profbased = None
@@ -462,9 +468,33 @@
return res.out, res.err
return res.out
- def compile(self):
+ def build_main_for_shared(self, shared_library_name, entrypoint):
+ self.shared_library_name = shared_library_name
+ # build main program
+ eci = self.get_eci()
+ eci = eci.merge(ExternalCompilationInfo(
+ separate_module_sources=['''
+ int %s(argc, argv);
+
+ int main(int argc, char* argv[])
+ { %s(argc, argv); }
+ ''' % (entrypoint, entrypoint)
+ ],
+ libraries=[self.shared_library_name.new(ext='')]
+ ))
+ eci = eci.convert_sources_to_files(
+ cache_dir=self.targetdir)
+ outfilename = self.shared_library_name.new(ext='')
+ return self.translator.platform.compile(
+ [], eci,
+ outputfilename=str(outfilename))
+
+ def compile(self, exe_name=None):
assert self.c_source_filename
assert not self._compiled
+
+ shared = self.config.translation.shared
+
if (self.config.translation.gcrootfinder == "asmgcc" or
self.config.translation.force_make):
extra_opts = []
@@ -475,16 +505,21 @@
else:
compiler = CCompilerDriver(self.translator.platform,
[self.c_source_filename] + self.extrafiles,
- self.eci, profbased=self.getprofbased())
- self.executable_name = compiler.build()
+ self.eci, profbased=self.getprofbased(),
+ outputfilename=exe_name)
+ self.executable_name = compiler.build(shared=shared)
+ if shared:
+ self.executable_name = self.build_main_for_shared(
+ self.executable_name, "pypy_main_startup")
assert self.executable_name
self._compiled = True
return self.executable_name
- def gen_makefile(self, targetdir):
+ def gen_makefile(self, targetdir, exe_name=None):
cfiles = [self.c_source_filename] + self.extrafiles
mk = self.translator.platform.gen_makefile(cfiles, self.eci,
- path=targetdir)
+ path=targetdir,
+ exe_name=exe_name)
if self.has_profopt():
profopt = self.config.translation.profopt
mk.definition('ABS_TARGET', '$(shell python -c "import sys,os; print os.path.abspath(sys.argv[1])" $(TARGET))')
Modified: pypy/branch/cpython-extension/pypy/translator/c/src/main.h
==============================================================================
--- pypy/branch/cpython-extension/pypy/translator/c/src/main.h (original)
+++ pypy/branch/cpython-extension/pypy/translator/c/src/main.h Wed Apr 7 16:27:49 2010
@@ -15,11 +15,15 @@
#ifndef PYPY_NOT_MAIN_FILE
+#ifndef PYPY_MAIN_FUNCTION
+#define PYPY_MAIN_FUNCTION main
+#endif
+
#ifdef MS_WINDOWS
#include "src/winstuff.c"
#endif
-int main(int argc, char *argv[])
+int PYPY_MAIN_FUNCTION(int argc, char *argv[])
{
char *errmsg;
int i, exitcode;
Modified: pypy/branch/cpython-extension/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/translator/c/test/test_standalone.py (original)
+++ pypy/branch/cpython-extension/pypy/translator/c/test/test_standalone.py Wed Apr 7 16:27:49 2010
@@ -16,11 +16,13 @@
class StandaloneTests(object):
config = None
- def compile(self, entry_point, debug=True):
+ def compile(self, entry_point, debug=True, shared=False):
t = TranslationContext(self.config)
t.buildannotator().build_types(entry_point, [s_list_of_strings])
t.buildrtyper().specialize()
+ t.config.translation.shared = shared
+
cbuilder = CStandaloneBuilder(t, entry_point, t.config)
if debug:
cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
@@ -587,6 +589,17 @@
# The traceback stops at f() because it's the first function that
# captures the AssertionError, which makes the program abort.
+ def test_shared(self):
+ def f(argv):
+ print len(argv)
+ def entry_point(argv):
+ f(argv)
+ return 0
+ t, cbuilder = self.compile(entry_point, shared=True)
+ assert cbuilder.shared_library_name is not None
+ assert cbuilder.shared_library_name != cbuilder.executable_name
+ out, err = cbuilder.cmdexec("a b")
+ assert out == "3"
class TestMaemo(TestStandalone):
def setup_class(cls):
Modified: pypy/branch/cpython-extension/pypy/translator/driver.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/translator/driver.py (original)
+++ pypy/branch/cpython-extension/pypy/translator/driver.py Wed Apr 7 16:27:49 2010
@@ -516,12 +516,16 @@
exename = mkexename(self.c_entryp)
newexename = self.compute_exe_name()
shutil.copy(str(exename), str(newexename))
+ if self.cbuilder.shared_library_name is not None:
+ soname = self.cbuilder.shared_library_name
+ newsoname = newexename.new(basename=soname.basename)
+ shutil.copy(str(soname), str(newsoname))
self.c_entryp = newexename
self.log.info("created: %s" % (self.c_entryp,))
def task_compile_c(self): # xxx messy
cbuilder = self.cbuilder
- cbuilder.compile()
+ cbuilder.compile(exe_name=self.compute_exe_name().basename)
if self.standalone:
self.c_entryp = cbuilder.executable_name
More information about the Pypy-commit
mailing list