summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bradshaw <robertwb@gmail.com>2015-02-04 22:33:48 -0800
committerRobert Bradshaw <robertwb@gmail.com>2015-02-04 22:33:48 -0800
commit4298c9f929d253687fbee674ef80a4a8bba7b225 (patch)
tree7001e0080f40ccf43ffee4131239f15b1338678d
parent760da3f8e7b1b8a1b5df32f8deeb5768a917fd7d (diff)
downloadcython-4298c9f929d253687fbee674ef80a4a8bba7b225.tar.gz
Add a mechanism to store metadata in the generated output file.
This will be useful for, e.g., implementing a fake cythonize that can leverage the deductions made by the real cythonize, but could have other uses as well.
-rw-r--r--Cython/Build/Dependencies.py16
-rw-r--r--Cython/Compiler/Main.py5
-rw-r--r--Cython/Compiler/ModuleNode.py11
3 files changed, 25 insertions, 7 deletions
diff --git a/Cython/Build/Dependencies.py b/Cython/Build/Dependencies.py
index 9c015d1c3..e22f8caac 100644
--- a/Cython/Build/Dependencies.py
+++ b/Cython/Build/Dependencies.py
@@ -621,6 +621,7 @@ def create_extension_list(patterns, exclude=[], ctx=None, aliases=None, quiet=Fa
to_exclude.update(map(os.path.abspath, extended_iglob(pattern)))
module_list = []
+ module_metadata = {}
for pattern in patterns:
if isinstance(pattern, str):
filepattern = pattern
@@ -677,7 +678,10 @@ def create_extension_list(patterns, exclude=[], ctx=None, aliases=None, quiet=Fa
source = encode_filename_in_py2(source)
if source not in sources:
sources.append(source)
+ extra_sources = kwds['sources']
del kwds['sources']
+ else:
+ extra_sources = None
if 'depends' in kwds:
depends = resolve_depends(kwds['depends'], (kwds.get('include_dirs') or []) + [find_root_package_dir(file)])
if template is not None:
@@ -692,9 +696,12 @@ def create_extension_list(patterns, exclude=[], ctx=None, aliases=None, quiet=Fa
name=module_name,
sources=sources,
**kwds))
+ if extra_sources:
+ kwds['sources'] = extra_sources
+ module_metadata[module_name] = {'distutils': kwds}
m = module_list[-1]
seen.add(name)
- return module_list
+ return module_list, module_metadata
# This is the user-exposed entry point.
@@ -737,7 +744,7 @@ def cythonize(module_list, exclude=[], nthreads=0, aliases=None, quiet=False, fo
cpp_options = CompilationOptions(**options); cpp_options.cplus = True
ctx = c_options.create_context()
options = c_options
- module_list = create_extension_list(
+ module_list, module_metadata = create_extension_list(
module_list,
exclude=exclude,
ctx=ctx,
@@ -809,7 +816,7 @@ def cythonize(module_list, exclude=[], nthreads=0, aliases=None, quiet=False, fo
else:
fingerprint = None
to_compile.append((priority, source, c_file, fingerprint, quiet,
- options, not exclude_failures))
+ options, not exclude_failures, module_metadata.get(m.name)))
new_sources.append(c_file)
if c_file not in modules_by_cfile:
modules_by_cfile[c_file] = [m]
@@ -920,7 +927,7 @@ else:
# TODO: Share context? Issue: pyx processing leaks into pxd module
@record_results
-def cythonize_one(pyx_file, c_file, fingerprint, quiet, options=None, raise_on_failure=True):
+def cythonize_one(pyx_file, c_file, fingerprint, quiet, options=None, raise_on_failure=True, embedded_metadata=None):
from ..Compiler.Main import compile, default_options
from ..Compiler.Errors import CompileError, PyrexError
@@ -954,6 +961,7 @@ def cythonize_one(pyx_file, c_file, fingerprint, quiet, options=None, raise_on_f
if options is None:
options = CompilationOptions(default_options)
options.output_file = c_file
+ options.embedded_metadata = embedded_metadata
any_failures = 0
try:
diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py
index 4ee84cd9b..29756bc80 100644
--- a/Cython/Compiler/Main.py
+++ b/Cython/Compiler/Main.py
@@ -400,6 +400,7 @@ def create_default_resultobj(compilation_source, options):
else:
c_suffix = ".c"
result.c_file = Utils.replace_suffix(source_desc.filename, c_suffix)
+ result.embedded_metadata = options.embedded_metadata
return result
def run_pipeline(source, options, full_module_name=None, context=None):
@@ -479,7 +480,8 @@ class CompilationOptions(object):
header files.
timestamps boolean Only compile changed source files.
verbose boolean Always print source names being compiled
- compiler_directives dict Overrides for pragma options (see Options.py)
+ compiler_directives dict Overrides for pragma options (see Options.py)
+ embedded_metadata dict Metadata to embed in the C file as json.
evaluate_tree_assertions boolean Test support: evaluate parse tree assertions
language_level integer The Python language level: 2 or 3
formal_grammar boolean Parse the file with the formal grammar
@@ -690,6 +692,7 @@ default_options = dict(
verbose = 0,
quiet = 0,
compiler_directives = {},
+ embedded_metadata = {},
evaluate_tree_assertions = False,
emit_linenums = False,
relative_path_in_code_position_comments = True,
diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index 3cbdbd993..94d60724c 100644
--- a/Cython/Compiler/ModuleNode.py
+++ b/Cython/Compiler/ModuleNode.py
@@ -9,6 +9,7 @@ cython.declare(Naming=object, Options=object, PyrexTypes=object, TypeSlots=objec
error=object, warning=object, py_object_type=object, UtilityCode=object,
EncodedString=object)
+import json
import os
import operator
from .PyrexTypes import CPtrType
@@ -308,7 +309,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
globalstate.initialize_main_c_code()
h_code = globalstate['h_code']
- self.generate_module_preamble(env, modules, h_code)
+ self.generate_module_preamble(env, modules, result.embedded_metadata, h_code)
globalstate.module_pos = self.pos
globalstate.directives = self.directives
@@ -547,9 +548,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_cvariable_declarations(module, modulecode, defined_here)
self.generate_cfunction_declarations(module, modulecode, defined_here)
- def generate_module_preamble(self, env, cimported_modules, code):
+ def generate_module_preamble(self, env, cimported_modules, metadata, code):
code.putln("/* Generated by Cython %s */" % Version.watermark)
code.putln("")
+ if metadata:
+ code.putln("/* Cython Metadata */")
+ code.putln("/*")
+ code.putln(json.dumps(metadata, indent=4))
+ code.putln("*/")
+ code.putln("")
code.putln("#define PY_SSIZE_T_CLEAN")
# sizeof(PyLongObject.ob_digit[0]) may have been determined dynamically