new script to compile+run Python files directly in Cython
authorStefan Behnel <scoder@users.berlios.de>
Sun, 10 Apr 2011 20:49:41 +0000 (22:49 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Sun, 10 Apr 2011 20:49:41 +0000 (22:49 +0200)
bin/cythonrun [new file with mode: 0755]

diff --git a/bin/cythonrun b/bin/cythonrun
new file mode 100755 (executable)
index 0000000..0cd1c28
--- /dev/null
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+"""
+Compile a Python script into an executable that embeds CPython and run it.
+Requires CPython to be built as a shared library ('libpythonX.Y').
+
+Basic usage:
+
+    python cythonrun somefile.py [ARGS]
+"""
+
+DEBUG = True
+
+import sys
+import os
+import subprocess
+from distutils import sysconfig
+
+INCDIR = sysconfig.get_python_inc()
+LIBDIR1 = sysconfig.get_config_var('LIBDIR')
+LIBDIR2 = sysconfig.get_config_var('LIBPL')
+PYLIB = sysconfig.get_config_var('LIBRARY')[3:-2]
+
+CC = sysconfig.get_config_var('CC')
+CFLAGS = sysconfig.get_config_var('CFLAGS') + ' ' + os.environ.get('CFLAGS', '')
+LINKCC = sysconfig.get_config_var('LINKCC')
+LINKFORSHARED = sysconfig.get_config_var('LINKFORSHARED')
+LIBS = sysconfig.get_config_var('LIBS')
+SYSLIBS = sysconfig.get_config_var('SYSLIBS')
+
+def runcmd(cmd, shell=True):
+    cmd = ' '.join(cmd)
+    if DEBUG:
+        print(cmd)
+    returncode = subprocess.call(cmd, shell=True)
+    if returncode:
+        sys.exit(returncode)
+
+def clink(basename):
+    runcmd([LINKCC, '-o', basename, basename+'.o', '-L'+LIBDIR1, '-L'+LIBDIR2, '-l'+PYLIB]
+           + LIBS.split() + SYSLIBS.split() + LINKFORSHARED.split())
+
+def ccompile(basename):
+    runcmd([CC, '-c', '-o', basename+'.o', basename+'.c', '-I' + INCDIR] + CFLAGS.split())
+
+def cycompile(input_file):
+    from Cython.Compiler import Version, CmdLine, Main
+    options, sources = CmdLine.parse_command_line(['--embed', input_file])
+    if DEBUG:
+        print('Using Cython %s to compile %s' % (Version.version, input_file))
+    result = Main.compile(sources, options)
+    if result.num_errors > 0:
+        sys.exit(1)
+
+def exec_file(basename, *args):
+    runcmd([os.path.abspath(basename)] + list(args), shell=False)
+
+def main(input_file, *args):
+    basename = os.path.splitext(input_file)[0]
+    cycompile(input_file)
+    ccompile(basename)
+    clink(basename)
+    exec_file(basename)
+
+if __name__ == '__main__':
+    main(*sys.argv[1:])