blob: 9df1135e69b16ae4cfecbf424bde84516caffde0 [file] [log] [blame]
Cosimo Lupoc3540e22015-08-10 18:01:29 +01001import distutils
Cosimo Lupo77c23992015-03-31 09:30:56 +01002from distutils.core import setup, Extension
3from distutils.command.build_ext import build_ext
4from distutils.cmd import Command
5import platform
Cosimo Lupod2c8b272015-08-11 10:38:20 +01006import os
7import re
Cosimo Lupo77c23992015-03-31 09:30:56 +01008
9
Cosimo Lupod2c8b272015-08-11 10:38:20 +010010CURR_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
11
Cosimo Lupoc3540e22015-08-10 18:01:29 +010012# when compiling for Windows Python 2.7, force distutils to use Visual Studio
13# 2010 instead of 2008, as the latter doesn't support c++0x
14if platform.system() == 'Windows':
15 try:
16 import distutils.msvc9compiler
17 except distutils.errors.DistutilsPlatformError:
18 pass # importing msvc9compiler raises when running under MinGW
19 else:
20 orig_find_vcvarsall = distutils.msvc9compiler.find_vcvarsall
21 def patched_find_vcvarsall(version):
22 return orig_find_vcvarsall(version if version != 9.0 else 10.0)
23 distutils.msvc9compiler.find_vcvarsall = patched_find_vcvarsall
24
25
Cosimo Lupod2c8b272015-08-11 10:38:20 +010026def get_version():
27 """ Return BROTLI_VERSION string as defined in 'brotlimodule.cc' file. """
28 brotlimodule = os.path.join(CURR_DIR, 'python', 'brotlimodule.cc')
29 with open(brotlimodule, 'r') as f:
30 for line in f:
31 m = re.match(r'#define\sBROTLI_VERSION\s"(.*)"', line)
32 if m:
33 return m.group(1)
34 return ""
35
36
Cosimo Lupo77c23992015-03-31 09:30:56 +010037class TestCommand(Command):
38 """ Run all *_test.py scripts in 'tests' folder with the same Python
39 interpreter used to run setup.py.
40 """
41
42 user_options = []
43
44 def initialize_options(self):
45 pass
46
47 def finalize_options(self):
48 pass
49
50 def run(self):
Cosimo Lupod2c8b272015-08-11 10:38:20 +010051 import sys, subprocess, glob
Cosimo Lupo77c23992015-03-31 09:30:56 +010052
Cosimo Lupod2c8b272015-08-11 10:38:20 +010053 test_dir = os.path.join(CURR_DIR, 'python', 'tests')
Cosimo Lupo77c23992015-03-31 09:30:56 +010054 os.chdir(test_dir)
55
56 for test in glob.glob("*_test.py"):
57 try:
58 subprocess.check_call([sys.executable, test])
59 except subprocess.CalledProcessError:
60 raise SystemExit(1)
61
62
63class BuildExt(build_ext):
64 def get_source_files(self):
65 filenames = build_ext.get_source_files(self)
66 for ext in self.extensions:
67 filenames.extend(ext.depends)
68 return filenames
69
70 def build_extension(self, ext):
71 c_sources = []
72 cxx_sources = []
73 for source in ext.sources:
74 if source.endswith(".c"):
75 c_sources.append(source)
76 else:
77 cxx_sources.append(source)
78 extra_args = ext.extra_compile_args or []
79
80 objects = []
81 for lang, sources in (("c", c_sources), ("c++", cxx_sources)):
82 if lang == "c++":
83 if self.compiler.compiler_type in ["unix", "cygwin", "mingw32"]:
84 extra_args.append("-std=c++0x")
85 elif self.compiler.compiler_type == "msvc":
86 extra_args.append("/EHsc")
87
88 macros = ext.define_macros[:]
89 if platform.system() == "Darwin":
90 macros.append(("OS_MACOSX", "1"))
Cosimo Lupo54baf432015-08-10 18:04:30 +010091 elif self.compiler.compiler_type == "mingw32":
92 # On Windows Python 2.7, pyconfig.h defines "hypot" as "_hypot",
93 # This clashes with GCC's cmath, and causes compilation errors when
94 # building under MinGW: http://bugs.python.org/issue11566
95 macros.append(("_hypot", "hypot"))
Cosimo Lupo77c23992015-03-31 09:30:56 +010096 for undef in ext.undef_macros:
97 macros.append((undef,))
98
99 objs = self.compiler.compile(sources,
100 output_dir=self.build_temp,
101 macros=macros,
102 include_dirs=ext.include_dirs,
103 debug=self.debug,
104 extra_postargs=extra_args,
105 depends=ext.depends)
106 objects.extend(objs)
107
108 self._built_objects = objects[:]
109 if ext.extra_objects:
110 objects.extend(ext.extra_objects)
111 extra_args = ext.extra_link_args or []
Cosimo Lupo54baf432015-08-10 18:04:30 +0100112 # when using GCC on Windows, we statically link libgcc and libstdc++,
113 # so that we don't need to package extra DLLs
114 if self.compiler.compiler_type == "mingw32":
115 extra_args.extend(['-static-libgcc', '-static-libstdc++'])
Cosimo Lupo77c23992015-03-31 09:30:56 +0100116
117 ext_path = self.get_ext_fullpath(ext.name)
118 # Detect target language, if not provided
119 language = ext.language or self.compiler.detect_language(sources)
120
121 self.compiler.link_shared_object(
122 objects, ext_path,
123 libraries=self.get_libraries(ext),
124 library_dirs=ext.library_dirs,
125 runtime_library_dirs=ext.runtime_library_dirs,
126 extra_postargs=extra_args,
127 export_symbols=self.get_export_symbols(ext),
128 debug=self.debug,
129 build_temp=self.build_temp,
130 target_lang=language)
131
132brotli = Extension("brotli",
133 sources=[
134 "python/brotlimodule.cc",
135 "enc/backward_references.cc",
136 "enc/block_splitter.cc",
137 "enc/brotli_bit_stream.cc",
138 "enc/encode.cc",
139 "enc/entropy_encode.cc",
140 "enc/histogram.cc",
141 "enc/literal_cost.cc",
142 "enc/metablock.cc",
Zoltan Szabadka66098832015-06-12 16:45:17 +0200143 "enc/static_dict.cc",
Zoltan Szabadka09aa9ca2015-04-23 14:35:43 +0200144 "enc/streams.cc",
Cosimo Lupo77c23992015-03-31 09:30:56 +0100145 "dec/bit_reader.c",
146 "dec/decode.c",
147 "dec/huffman.c",
Cosimo Lupo77c23992015-03-31 09:30:56 +0100148 "dec/streams.c",
149 "dec/state.c",
150 ],
151 depends=[
152 "enc/backward_references.h",
153 "enc/bit_cost.h",
154 "enc/block_splitter.h",
155 "enc/brotli_bit_stream.h",
156 "enc/cluster.h",
157 "enc/command.h",
158 "enc/context.h",
159 "enc/dictionary.h",
Zoltan Szabadkae91a4492015-04-23 15:55:43 +0200160 "enc/dictionary_hash.h",
Cosimo Lupo77c23992015-03-31 09:30:56 +0100161 "enc/encode.h",
162 "enc/entropy_encode.h",
163 "enc/fast_log.h",
164 "enc/find_match_length.h",
165 "enc/hash.h",
166 "enc/histogram.h",
167 "enc/literal_cost.h",
168 "enc/metablock.h",
169 "enc/port.h",
170 "enc/prefix.h",
171 "enc/ringbuffer.h",
172 "enc/static_dict.h",
Zoltan Szabadka66098832015-06-12 16:45:17 +0200173 "enc/static_dict_lut.h",
Zoltan Szabadka09aa9ca2015-04-23 14:35:43 +0200174 "enc/streams.h",
Cosimo Lupo77c23992015-03-31 09:30:56 +0100175 "enc/transform.h",
176 "enc/write_bits.h",
177 "dec/bit_reader.h",
178 "dec/context.h",
179 "dec/decode.h",
180 "dec/dictionary.h",
181 "dec/huffman.h",
182 "dec/prefix.h",
Zoltan Szabadka83aa24d2015-05-07 16:53:43 +0200183 "dec/port.h",
Cosimo Lupo77c23992015-03-31 09:30:56 +0100184 "dec/streams.h",
185 "dec/transform.h",
186 "dec/types.h",
187 "dec/state.h",
188 ],
189 language="c++",
190 )
191
192setup(
193 name="Brotli",
Cosimo Lupod2c8b272015-08-11 10:38:20 +0100194 version=get_version(),
Cosimo Lupo77c23992015-03-31 09:30:56 +0100195 url="https://github.com/google/brotli",
196 description="Python binding of the Brotli compression library",
197 author="Khaled Hosny",
198 author_email="khaledhosny@eglug.org",
199 license="Apache 2.0",
200 ext_modules=[brotli],
201 cmdclass={
202 'build_ext': BuildExt,
203 'test': TestCommand
204 },
205)