]>
Commit | Line | Data |
---|---|---|
53e6db90 DC |
1 | import re |
2 | import functools | |
3 | import distutils.core | |
4 | import distutils.errors | |
5 | import distutils.extension | |
6 | ||
7 | from .monkey import get_unpatched | |
8 | ||
9 | ||
10 | def _have_cython(): | |
11 | """ | |
12 | Return True if Cython can be imported. | |
13 | """ | |
14 | cython_impl = 'Cython.Distutils.build_ext' | |
15 | try: | |
16 | # from (cython_impl) import build_ext | |
17 | __import__(cython_impl, fromlist=['build_ext']).build_ext | |
18 | return True | |
19 | except Exception: | |
20 | pass | |
21 | return False | |
22 | ||
23 | ||
24 | # for compatibility | |
25 | have_pyrex = _have_cython | |
26 | ||
27 | _Extension = get_unpatched(distutils.core.Extension) | |
28 | ||
29 | ||
30 | class Extension(_Extension): | |
31 | """ | |
32 | Describes a single extension module. | |
33 | ||
34 | This means that all source files will be compiled into a single binary file | |
35 | ``<module path>.<suffix>`` (with ``<module path>`` derived from ``name`` and | |
36 | ``<suffix>`` defined by one of the values in | |
37 | ``importlib.machinery.EXTENSION_SUFFIXES``). | |
38 | ||
39 | In the case ``.pyx`` files are passed as ``sources and`` ``Cython`` is **not** | |
40 | installed in the build environment, ``setuptools`` may also try to look for the | |
41 | equivalent ``.cpp`` or ``.c`` files. | |
42 | ||
43 | :arg str name: | |
44 | the full name of the extension, including any packages -- ie. | |
45 | *not* a filename or pathname, but Python dotted name | |
46 | ||
47 | :arg list[str] sources: | |
48 | list of source filenames, relative to the distribution root | |
49 | (where the setup script lives), in Unix form (slash-separated) | |
50 | for portability. Source files may be C, C++, SWIG (.i), | |
51 | platform-specific resource files, or whatever else is recognized | |
52 | by the "build_ext" command as source for a Python extension. | |
53 | ||
54 | :keyword list[str] include_dirs: | |
55 | list of directories to search for C/C++ header files (in Unix | |
56 | form for portability) | |
57 | ||
58 | :keyword list[tuple[str, str|None]] define_macros: | |
59 | list of macros to define; each macro is defined using a 2-tuple: | |
60 | the first item corresponding to the name of the macro and the second | |
61 | item either a string with its value or None to | |
62 | define it without a particular value (equivalent of "#define | |
63 | FOO" in source or -DFOO on Unix C compiler command line) | |
64 | ||
65 | :keyword list[str] undef_macros: | |
66 | list of macros to undefine explicitly | |
67 | ||
68 | :keyword list[str] library_dirs: | |
69 | list of directories to search for C/C++ libraries at link time | |
70 | ||
71 | :keyword list[str] libraries: | |
72 | list of library names (not filenames or paths) to link against | |
73 | ||
74 | :keyword list[str] runtime_library_dirs: | |
75 | list of directories to search for C/C++ libraries at run time | |
76 | (for shared extensions, this is when the extension is loaded). | |
77 | Setting this will cause an exception during build on Windows | |
78 | platforms. | |
79 | ||
80 | :keyword list[str] extra_objects: | |
81 | list of extra files to link with (eg. object files not implied | |
82 | by 'sources', static library that must be explicitly specified, | |
83 | binary resource files, etc.) | |
84 | ||
85 | :keyword list[str] extra_compile_args: | |
86 | any extra platform- and compiler-specific information to use | |
87 | when compiling the source files in 'sources'. For platforms and | |
88 | compilers where "command line" makes sense, this is typically a | |
89 | list of command-line arguments, but for other platforms it could | |
90 | be anything. | |
91 | ||
92 | :keyword list[str] extra_link_args: | |
93 | any extra platform- and compiler-specific information to use | |
94 | when linking object files together to create the extension (or | |
95 | to create a new static Python interpreter). Similar | |
96 | interpretation as for 'extra_compile_args'. | |
97 | ||
98 | :keyword list[str] export_symbols: | |
99 | list of symbols to be exported from a shared extension. Not | |
100 | used on all platforms, and not generally necessary for Python | |
101 | extensions, which typically export exactly one symbol: "init" + | |
102 | extension_name. | |
103 | ||
104 | :keyword list[str] swig_opts: | |
105 | any extra options to pass to SWIG if a source file has the .i | |
106 | extension. | |
107 | ||
108 | :keyword list[str] depends: | |
109 | list of files that the extension depends on | |
110 | ||
111 | :keyword str language: | |
112 | extension language (i.e. "c", "c++", "objc"). Will be detected | |
113 | from the source extensions if not provided. | |
114 | ||
115 | :keyword bool optional: | |
116 | specifies that a build failure in the extension should not abort the | |
117 | build process, but simply not install the failing extension. | |
118 | ||
119 | :keyword bool py_limited_api: | |
120 | opt-in flag for the usage of :doc:`Python's limited API <python:c-api/stable>`. | |
121 | ||
122 | :raises setuptools.errors.PlatformError: if 'runtime_library_dirs' is | |
123 | specified on Windows. (since v63) | |
124 | """ | |
125 | ||
126 | def __init__(self, name, sources, *args, **kw): | |
127 | # The *args is needed for compatibility as calls may use positional | |
128 | # arguments. py_limited_api may be set only via keyword. | |
129 | self.py_limited_api = kw.pop("py_limited_api", False) | |
130 | super().__init__(name, sources, *args, **kw) | |
131 | ||
132 | def _convert_pyx_sources_to_lang(self): | |
133 | """ | |
134 | Replace sources with .pyx extensions to sources with the target | |
135 | language extension. This mechanism allows language authors to supply | |
136 | pre-converted sources but to prefer the .pyx sources. | |
137 | """ | |
138 | if _have_cython(): | |
139 | # the build has Cython, so allow it to compile the .pyx files | |
140 | return | |
141 | lang = self.language or '' | |
142 | target_ext = '.cpp' if lang.lower() == 'c++' else '.c' | |
143 | sub = functools.partial(re.sub, '.pyx$', target_ext) | |
144 | self.sources = list(map(sub, self.sources)) | |
145 | ||
146 | ||
147 | class Library(Extension): | |
148 | """Just like a regular Extension, but built as a library instead""" |