-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathcpyext.py
156 lines (118 loc) · 4.55 KB
/
cpyext.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"""
Compiled extension support.
"""
from __future__ import print_function
import sysconfig
import os
import os.path
from setuptools import Distribution
from setuptools.extension import Extension
from setuptools.command.build_ext import build_ext
import importlib
import importlib.machinery
# not used when generate is passed directly to Environment
def exists(env):
return True
def extension_filename(modname, abi3=False):
"""
Return the path for a new extension.
Given the Python dot-separated modname "a.b.c", return e.g.
"a/b/c.cpython-xyz.so".
If abi3=True and supported by the interpreter, return e.g.
"a/b/c.abi3.so".
"""
# we could probably just split modname by '.' instead of using ext here:
ext = get_build_ext()
fullname = ext.get_ext_fullname(modname)
modpath = fullname.split(".")
ext_filename = os.path.join(*modpath)
suffix = None
try:
suffixes = importlib.machinery.EXTENSION_SUFFIXES
suffix = suffixes[0] if suffixes else None
except AttributeError:
pass
suffix = sysconfig.get_config_var("EXT_SUFFIX")
if abi3:
suffix = get_abi3_suffix() or suffix
return ext_filename + suffix
class no_build_ext(build_ext):
output = [] # for testing
# Are you kidding me? We have to run build_ext() to finish configuring the compiler.
def build_extension(self, ext):
def noop_spawn(*args):
no_build_ext.output.append(args)
self.compiler.spawn = noop_spawn
build_ext.build_extension(self, ext)
def get_build_ext(name="zoot"):
"""
Naughty Zoot
"""
tmp_dir = "/tmp/enscons"
# from distutils.test.test_build_ext.py :
xx_c = os.path.join(tmp_dir, "xxmodule.c")
xy_cpp = os.path.join(tmp_dir, "xymodule.cc")
xx_ext = Extension("xx", [xx_c, xy_cpp])
dist = Distribution({"name": name, "ext_modules": [xx_ext]})
dist.package_dir = tmp_dir
cmd = no_build_ext(dist)
cmd.build_lib = tmp_dir
cmd.build_temp = tmp_dir
cmd.ensure_finalized()
cmd.run()
return cmd
# from setuptools
def get_abi3_suffix():
"""Return the file extension for an abi3-compliant Extension()"""
for suffix in importlib.machinery.EXTENSION_SUFFIXES:
if ".abi3" in suffix: # Unix
return suffix
elif suffix == ".pyd": # Windows
return suffix
def generate(env):
global ext # debugging
# Compare compiler with ext.compiler.
# Actually this has side effects adding redundant arguments to ext's compiler.
# Could copy the compiler from ext before run() is called.
if False:
compiler = setuptools.ccompiler.new_compiler()
setuptools.sysconfig.customize_compiler(compiler)
ext = get_build_ext()
# Sanity checks that shared compiler startswith normal compiler?
compiler = ext.compiler
if not hasattr(compiler, "compiler"): # assume Windows
return generate_msvc(env, compiler)
env.Replace(CC=compiler.compiler[0])
env.Replace(CFLAGS=compiler.compiler[1:])
env.Replace(CXX=compiler.compiler_cxx[0])
env.Replace(LINKFLAGS=compiler.linker_exe[1:])
env.Replace(SHLINKFLAGS=compiler.linker_so[1:])
# rebuild LDMODULE? Better as a tool? Use SharedLibrary?
# Some of these attributes are also available on ext
env.Append(CPPPATH=compiler.include_dirs)
env.Append(LIBPATH=compiler.library_dirs)
env.Append(LIBS=compiler.libraries)
# Interesting environment variables:
# CC, CXX, AS, AR, RANLIB, CPPPATH, CCFLAGS, CXXFLAGS, LINKFLAGS
# Windows will need env['ENV'] and basically is totally different
# as far as distutils is concerned; different class properties
def generate_msvc(env, compiler):
"""
Set SCons environment from distutils msvc9compiler
"""
import pprint
pprint.pprint(compiler.__dict__)
# Python 2.7 distutils does not find full compiler path.
# Ask Environment for correct MSVC during creation.
env.Replace(CC=env.File(compiler.cc)) # File helps with spaces
env.Replace(CFLAGS=compiler.compile_options)
env.Replace(CXX=env.File(compiler.cc))
env.Replace(LINK=env.File(compiler.linker)) # see mslink
env.Replace(LINKFLAGS=compiler.ldflags_static)
env.Replace(SHLINKFLAGS=compiler.ldflags_shared) # see also ldflags_shared_debug
env.Replace(RC=env.File(compiler.rc))
# rebuild LDMODULE? Better as a tool? Use SharedLibrary?
# Some of these attributes are also available on ext
env.Append(CPPPATH=compiler.include_dirs)
env.Append(LIBPATH=compiler.library_dirs)
env.Append(LIBS=compiler.libraries)