7
7
import platform
8
8
import re
9
9
import unittest
10
+ import sys
10
11
11
12
try :
12
13
from setuptools import Extension
15
16
from distutils .core import Extension
16
17
from distutils .core import setup
17
18
from distutils .command .build_ext import build_ext
18
- from distutils import errors
19
19
from distutils import dep_util
20
20
from distutils import log
21
21
22
22
23
+ IS_PYTHON3 = sys .version_info [0 ] == 3
24
+ BROTLI_PYTHON3_LIMITED_API = os .environ .get ('BROTLI_PYTHON3_LIMITED_API' , '0' ) == '1'
25
+
23
26
CURR_DIR = os .path .abspath (os .path .dirname (os .path .realpath (__file__ )))
24
27
25
28
26
29
def read_define (path , macro ):
27
30
""" Return macro value from the given file. """
28
31
with open (path , 'r' ) as f :
29
32
for line in f :
30
- m = re .match (rf '#define\s{ macro } \s+(.+)' , line )
33
+ m = re .match ('#define\\ s{macro}\\ s+(.+)' . format ( macro = macro ) , line )
31
34
if m :
32
35
return m .group (1 )
33
36
return ''
@@ -41,7 +44,7 @@ def get_version():
41
44
patch = read_define (version_file_path , 'BROTLI_VERSION_PATCH' )
42
45
if not major or not minor or not patch :
43
46
return ''
44
- return f '{ major } .{ minor } .{ patch } '
47
+ return '{major}.{minor}.{patch}' . format ( major = major , minor = minor , patch = patch )
45
48
46
49
47
50
def get_test_suite ():
@@ -51,20 +54,7 @@ def get_test_suite():
51
54
52
55
53
56
class BuildExt (build_ext ):
54
-
55
- def get_source_files (self ):
56
- filenames = build_ext .get_source_files (self )
57
- for ext in self .extensions :
58
- filenames .extend (ext .depends )
59
- return filenames
60
-
61
57
def build_extension (self , ext ):
62
- if ext .sources is None or not isinstance (ext .sources , (list , tuple )):
63
- raise errors .DistutilsSetupError (
64
- "in 'ext_modules' option (extension '%s'), "
65
- "'sources' must be present and must be "
66
- "a list of source filenames" % ext .name )
67
-
68
58
ext_path = self .get_ext_fullpath (ext .name )
69
59
depends = ext .sources + ext .depends
70
60
if not (self .force or dep_util .newer_group (depends , ext_path , 'newer' )):
@@ -73,59 +63,13 @@ def build_extension(self, ext):
73
63
else :
74
64
log .info ("building '%s' extension" , ext .name )
75
65
76
- c_sources = []
77
- for source in ext .sources :
78
- if source .endswith ('.c' ):
79
- c_sources .append (source )
80
- extra_args = ext .extra_compile_args or []
81
-
82
- objects = []
83
-
84
- macros = ext .define_macros [:]
85
- if platform .system () == 'Darwin' :
86
- macros .append (('OS_MACOSX' , '1' ))
87
- elif self .compiler .compiler_type == 'mingw32' :
66
+ if self .compiler .compiler_type == 'mingw32' :
88
67
# On Windows Python 2.7, pyconfig.h defines "hypot" as "_hypot",
89
68
# This clashes with GCC's cmath, and causes compilation errors when
90
69
# building under MinGW: http://bugs.python.org/issue11566
91
- macros .append (('_hypot' , 'hypot' ))
92
- for undef in ext .undef_macros :
93
- macros .append ((undef ,))
94
-
95
- objs = self .compiler .compile (
96
- c_sources ,
97
- output_dir = self .build_temp ,
98
- macros = macros ,
99
- include_dirs = ext .include_dirs ,
100
- debug = self .debug ,
101
- extra_postargs = extra_args ,
102
- depends = ext .depends )
103
- objects .extend (objs )
104
-
105
- self ._built_objects = objects [:]
106
- if ext .extra_objects :
107
- objects .extend (ext .extra_objects )
108
- extra_args = ext .extra_link_args or []
109
- # when using GCC on Windows, we statically link libgcc and libstdc++,
110
- # so that we don't need to package extra DLLs
111
- if self .compiler .compiler_type == 'mingw32' :
112
- extra_args .extend (['-static-libgcc' , '-static-libstdc++' ])
70
+ ext .define_macros .append (('_hypot' , 'hypot' ))
113
71
114
- ext_path = self .get_ext_fullpath (ext .name )
115
- # Detect target language, if not provided
116
- language = ext .language or self .compiler .detect_language (c_sources )
117
-
118
- self .compiler .link_shared_object (
119
- objects ,
120
- ext_path ,
121
- libraries = self .get_libraries (ext ),
122
- library_dirs = ext .library_dirs ,
123
- runtime_library_dirs = ext .runtime_library_dirs ,
124
- extra_postargs = extra_args ,
125
- export_symbols = self .get_export_symbols (ext ),
126
- debug = self .debug ,
127
- build_temp = self .build_temp ,
128
- target_lang = language )
72
+ build_ext .build_extension (self , ext )
129
73
130
74
131
75
NAME = 'Brotli'
@@ -170,11 +114,25 @@ def build_extension(self, ext):
170
114
171
115
PACKAGE_DIR = {'' : 'python' }
172
116
173
- PY_MODULES = ['brotli' ]
117
+ class VersionedExtension (Extension ):
118
+ def __init__ (self , * args , ** kwargs ):
119
+ define_macros = []
120
+
121
+ if IS_PYTHON3 and BROTLI_PYTHON3_LIMITED_API :
122
+ kwargs ['py_limited_api' ] = True
123
+ define_macros .append (('Py_LIMITED_API' , '0x03060000' ))
124
+
125
+ if platform .system () == 'Darwin' :
126
+ define_macros .append (('OS_MACOSX' , '1' ))
127
+
128
+ kwargs ['define_macros' ] = kwargs .get ('define_macros' , []) + define_macros
129
+
130
+ Extension .__init__ (self , * args , ** kwargs )
131
+
174
132
175
133
EXT_MODULES = [
176
- Extension (
177
- ' _brotli' ,
134
+ VersionedExtension (
135
+ name = 'brotli. _brotli' ,
178
136
sources = [
179
137
'python/_brotli.c' ,
180
138
'c/common/constants.c' ,
@@ -276,6 +234,23 @@ def build_extension(self, ext):
276
234
'build_ext' : BuildExt ,
277
235
}
278
236
237
+ if IS_PYTHON3 and BROTLI_PYTHON3_LIMITED_API :
238
+ from wheel .bdist_wheel import bdist_wheel
239
+ # adopted from:
240
+ # https://github.com/joerick/python-abi3-package-sample/blob/7f05b22b9e0cfb4e60293bc85252e95278a80720/setup.py
241
+ class bdist_wheel_abi3 (bdist_wheel ):
242
+ def get_tag (self ):
243
+ python , abi , plat = super ().get_tag ()
244
+
245
+ if python .startswith ("cp" ):
246
+ # on CPython, our wheels are abi3 and compatible back to 3.6
247
+ return "cp36" , "abi3" , plat
248
+
249
+ return python , abi , plat
250
+
251
+ CMD_CLASS ["bdist_wheel" ] = bdist_wheel_abi3
252
+
253
+
279
254
with open ("README.md" , "r" ) as f :
280
255
README = f .read ()
281
256
@@ -291,7 +266,7 @@ def build_extension(self, ext):
291
266
platforms = PLATFORMS ,
292
267
classifiers = CLASSIFIERS ,
293
268
package_dir = PACKAGE_DIR ,
294
- py_modules = PY_MODULES ,
269
+ packages = [ "brotli" ] ,
295
270
ext_modules = EXT_MODULES ,
296
271
test_suite = TEST_SUITE ,
297
272
cmdclass = CMD_CLASS )
0 commit comments