8
from distutils.command.build_ext import build_ext
9
from distutils import sysconfig
10
from setuptools import Extension, setup, find_packages
14
"decode", "encode", "map", "display", "outline", "path",
18
"Access", "Antialias", "Bands", "BitDecode", "Blend", "Chops",
19
"Convert", "ConvertYCbCr", "Copy", "Crc32", "Crop", "Dib", "Draw",
20
"Effects", "EpsEncode", "File", "Fill", "Filter", "FliDecode",
21
"Geometry", "GetBBox", "GifDecode", "GifEncode", "HexDecode",
22
"Histo", "JpegDecode", "JpegEncode", "LzwDecode", "Matrix",
23
"ModeFilter", "MspDecode", "Negative", "Offset", "Pack",
24
"PackDecode", "Palette", "Paste", "Quant", "QuantHash",
25
"QuantHeap", "PcdDecode", "PcxDecode", "PcxEncode", "Point",
26
"RankFilter", "RawDecode", "RawEncode", "Storage", "SunRleDecode",
27
"TgaRleDecode", "Unpack", "UnpackYCC", "UnsharpMask", "XbmDecode",
28
"XbmEncode", "ZipDecode", "ZipEncode")
31
def _add_directory(path, dir, where=None):
32
if dir and os.path.isdir(dir) and dir not in path:
36
path.insert(where, dir)
39
def _find_include_file(self, include):
40
for directory in self.compiler.include_dirs:
41
if os.path.isfile(os.path.join(directory, include)):
46
def _find_library_file(self, library):
47
return self.compiler.find_library_file(self.compiler.library_dirs, library)
50
def _find_version(filename):
51
for line in open(filename).readlines():
52
m = re.search("VERSION\s*=\s*\"([^\"]+)\"", line)
58
def _lib_include(root):
59
# map root to (root/lib, root/include)
60
return os.path.join(root, "lib"), os.path.join(root, "include")
64
return open(file, 'rb').read()
83
class pil_build_ext(build_ext):
85
def build_extensions(self):
92
_add_directory(include_dirs, "libImaging")
95
# add platform directories
97
if sys.platform == "cygwin":
98
# pythonX.Y.dll.a is in the /usr/lib/pythonX.Y/config directory
99
_add_directory(library_dirs, os.path.join(
100
"/usr/lib", "python%s" % sys.version[:3], "config"))
102
elif sys.platform == "darwin":
103
# attempt to make sure we pick freetype2 over other versions
104
_add_directory(include_dirs, "/sw/include/freetype2")
105
_add_directory(include_dirs, "/sw/lib/freetype2/include")
106
# fink installation directories
107
_add_directory(library_dirs, "/sw/lib")
108
_add_directory(include_dirs, "/sw/include")
109
# darwin ports installation directories
110
_add_directory(library_dirs, "/opt/local/lib")
111
_add_directory(include_dirs, "/opt/local/include")
112
# freetype2 ships with X11
113
_add_directory(library_dirs, "/usr/X11/lib")
114
_add_directory(include_dirs, "/usr/X11/include")
116
elif sys.platform.startswith("linux"):
117
# XXX Kludge. Above /\ we brute force support multiarch. Here we
118
# try Barry's more general approach. Afterward, something should
120
self.add_multiarch_paths()
122
_add_directory(library_dirs, "/usr/local/lib")
123
# FIXME: check /opt/stuff directories here?
125
prefix = sysconfig.get_config_var("prefix")
127
_add_directory(library_dirs, os.path.join(prefix, "lib"))
128
_add_directory(include_dirs, os.path.join(prefix, "include"))
131
# locate tkinter libraries
134
TCL_VERSION = _tkinter.TCL_VERSION[:3]
136
if _tkinter and not TCL_ROOT:
137
# we have Tkinter but the TCL_ROOT variable was not set;
138
# try to locate appropriate Tcl/Tk libraries
139
PYVERSION = sys.version[0] + sys.version[2]
140
TCLVERSION = TCL_VERSION[0] + TCL_VERSION[2]
142
# common installation directories, mostly for Windows
143
# (for Unix-style platforms, we'll check in well-known
145
os.path.join("/py" + PYVERSION, "Tcl"),
146
os.path.join("/python" + PYVERSION, "Tcl"),
147
"/Tcl", "/Tcl" + TCLVERSION, "/Tcl" + TCL_VERSION,
148
os.path.join(os.environ.get("ProgramFiles", ""), "Tcl"),
150
for TCL_ROOT in roots:
151
TCL_ROOT = os.path.abspath(TCL_ROOT)
152
if os.path.isfile(os.path.join(TCL_ROOT, "include", "tk.h")):
153
# FIXME: use distutils logging (?)
154
print("--- using Tcl/Tk libraries at", TCL_ROOT)
155
print("--- using Tcl/Tk version", TCL_VERSION)
156
TCL_ROOT = _lib_include(TCL_ROOT)
162
# add configured kits
164
for root in (TCL_ROOT, JPEG_ROOT, TCL_ROOT, TIFF_ROOT, ZLIB_ROOT,
165
FREETYPE_ROOT, LCMS_ROOT):
166
if isinstance(root, type(())):
167
lib_root, include_root = root
169
lib_root = include_root = root
170
_add_directory(library_dirs, lib_root)
171
_add_directory(include_dirs, include_root)
174
# add standard directories
176
# look for tcl specific subdirectory (e.g debian)
178
tcl_dir = "/usr/include/tcl" + TCL_VERSION
179
if os.path.isfile(os.path.join(tcl_dir, "tk.h")):
180
_add_directory(include_dirs, tcl_dir)
183
_add_directory(library_dirs, "/usr/local/lib")
184
_add_directory(include_dirs, "/usr/local/include")
186
_add_directory(library_dirs, "/usr/lib")
187
_add_directory(include_dirs, "/usr/include")
190
# insert new dirs *before* default libs, to avoid conflicts
191
# between Python PYD stub libs and real libraries
193
self.compiler.library_dirs = library_dirs + self.compiler.library_dirs
194
self.compiler.include_dirs = include_dirs + self.compiler.include_dirs
197
# look for available libraries
200
zlib = jpeg = tiff = freetype = tcl = tk = lcms = None
203
if _find_include_file(self, "zlib.h"):
204
if _find_library_file(self, "z"):
206
elif sys.platform == "win32" and _find_library_file(self, "zlib"):
207
feature.zlib = "zlib" # alternative name
209
if _find_include_file(self, "jpeglib.h"):
210
if _find_library_file(self, "jpeg"):
211
feature.jpeg = "jpeg"
212
elif sys.platform == "win32" and _find_library_file(self,
214
feature.jpeg = "libjpeg" # alternative name
216
if _find_library_file(self, "tiff"):
217
feature.tiff = "tiff"
219
if _find_library_file(self, "freetype"):
220
# look for freetype2 include files
222
for dir in self.compiler.include_dirs:
223
if os.path.isfile(os.path.join(dir, "ft2build.h")):
224
freetype_version = 21
225
dir = os.path.join(dir, "freetype2")
227
dir = os.path.join(dir, "freetype2")
228
if os.path.isfile(os.path.join(dir, "ft2build.h")):
229
freetype_version = 21
231
if os.path.isdir(os.path.join(dir, "freetype")):
232
freetype_version = 20
235
feature.freetype = "freetype"
236
feature.freetype_version = freetype_version
238
_add_directory(self.compiler.include_dirs, dir, 0)
240
if _find_include_file(self, "lcms.h"):
241
if _find_library_file(self, "lcms"):
242
feature.lcms = "lcms"
244
if _tkinter and _find_include_file(self, "tk.h"):
245
# the library names may vary somewhat (e.g. tcl84 or tcl8.4)
246
version = TCL_VERSION[0] + TCL_VERSION[2]
247
if _find_library_file(self, "tcl" + version):
248
feature.tcl = "tcl" + version
249
elif _find_library_file(self, "tcl" + TCL_VERSION):
250
feature.tcl = "tcl" + TCL_VERSION
251
if _find_library_file(self, "tk" + version):
252
feature.tk = "tk" + version
253
elif _find_library_file(self, "tk" + TCL_VERSION):
254
feature.tk = "tk" + TCL_VERSION
259
files = ["_imaging.c"]
260
for file in _IMAGING:
261
files.append(file + ".c")
262
for file in _LIB_IMAGING:
263
files.append(os.path.join("libImaging", file + ".c"))
268
libs.append(feature.jpeg)
269
defs.append(("HAVE_LIBJPEG", None))
271
libs.append(feature.zlib)
272
defs.append(("HAVE_LIBZ", None))
273
if sys.platform == "win32":
274
libs.extend(["kernel32", "user32", "gdi32"])
275
if struct.unpack("h", "\0\1".encode('ascii'))[0] == 1:
276
defs.append(("WORDS_BIGENDIAN", None))
279
"_imaging", files, libraries=libs, define_macros=defs))]
282
# additional libraries
286
if feature.freetype_version == 20:
287
defs.append(("USE_FREETYPE_2_0", None))
288
exts.append(Extension(
289
"_imagingft", ["_imagingft.c"], libraries=["freetype"],
292
if os.path.isfile("_imagingtiff.c") and feature.tiff:
293
exts.append(Extension(
294
"_imagingtiff", ["_imagingtiff.c"], libraries=["tiff"]))
296
if os.path.isfile("_imagingcms.c") and feature.lcms:
298
if sys.platform == "win32":
299
extra.extend(["user32", "gdi32"])
300
exts.append(Extension(
301
"_imagingcms", ["_imagingcms.c"], libraries=["lcms"] + extra))
303
if sys.platform == "darwin":
304
# locate Tcl/Tk frameworks
307
"/Library/Frameworks",
308
"/System/Library/Frameworks"]
309
for root in framework_roots:
310
if (os.path.exists(os.path.join(root, "Tcl.framework")) and
311
os.path.exists(os.path.join(root, "Tk.framework"))):
312
print("--- using frameworks at %s" % root)
313
frameworks = ["-framework", "Tcl", "-framework", "Tk"]
314
dir = os.path.join(root, "Tcl.framework", "Headers")
315
_add_directory(self.compiler.include_dirs, dir, 0)
316
dir = os.path.join(root, "Tk.framework", "Headers")
317
_add_directory(self.compiler.include_dirs, dir, 1)
320
exts.append(Extension(
321
"_imagingtk", ["_imagingtk.c", "Tk/tkImaging.c"],
322
extra_compile_args=frameworks, extra_link_args=frameworks))
323
feature.tcl = feature.tk = 1 # mark as present
324
elif feature.tcl and feature.tk:
325
exts.append(Extension(
326
"_imagingtk", ["_imagingtk.c", "Tk/tkImaging.c"],
327
libraries=[feature.tcl, feature.tk]))
329
if os.path.isfile("_imagingmath.c"):
330
exts.append(Extension("_imagingmath", ["_imagingmath.c"]))
332
self.extensions[:] = exts
334
build_ext.build_extensions(self)
337
# sanity and security checks
342
unsafe_zlib = self.check_zlib_version(self.compiler.include_dirs)
344
self.summary_report(feature, unsafe_zlib)
346
def summary_report(self, feature, unsafe_zlib):
349
print("SETUP SUMMARY (Pillow %s / PIL %s)" % (VERSION, PIL_VERSION))
351
print("version %s" % VERSION)
352
v = sys.version.split("[")
353
print("platform %s %s" % (sys.platform, v[0].strip()))
355
print(" [%s" % v.strip())
359
(feature.tcl and feature.tk, "TKINTER"),
360
(feature.jpeg, "JPEG"),
361
(feature.zlib, "ZLIB (PNG/ZIP)"),
362
# (feature.tiff, "experimental TIFF G3/G4 read"),
363
(feature.freetype, "FREETYPE2"),
364
(feature.lcms, "LITTLECMS"),
368
for option in options:
370
print("--- %s support available" % option[1])
372
print("*** %s support not available" % option[1])
373
if option[1] == "TKINTER" and _tkinter:
374
version = _tkinter.TCL_VERSION
375
print("(Tcl/Tk %s libraries needed)" % version)
379
if feature.zlib and unsafe_zlib:
381
print("*** Warning: zlib", unsafe_zlib)
382
print("may contain a security vulnerability.")
383
print("*** Consider upgrading to zlib 1.2.3 or newer.")
384
print("*** See: http://www.kb.cert.org/vuls/id/238678")
385
print(" http://www.kb.cert.org/vuls/id/680620")
386
print(" http://www.gzip.org/zlib/advisory-2002-03-11.txt")
392
print("To add a missing option, make sure you have the required")
393
print("library, and set the corresponding ROOT variable in the")
394
print("setup.py script.")
397
print("To check the build, run the selftest.py script.")
399
def check_zlib_version(self, include_dirs):
400
# look for unsafe versions of zlib
401
for dir in include_dirs:
402
zlibfile = os.path.join(dir, "zlib.h")
403
if os.path.isfile(zlibfile):
407
for line in open(zlibfile).readlines():
408
m = re.match('#define\s+ZLIB_VERSION\s+"([^"]*)"', line)
411
if m.group(1) < "1.2.3":
414
# http://hg.python.org/users/barry/rev/7e8deab93d5a
415
def add_multiarch_paths(self):
416
# Debian/Ubuntu multiarch support.
417
# https://wiki.ubuntu.com/MultiarchSpec
419
tmpfile = os.path.join(self.build_temp, 'multiarch')
420
if not os.path.exists(self.build_temp):
421
os.makedirs(self.build_temp)
422
ret = os.system('dpkg-architecture -qDEB_HOST_MULTIARCH > %s' %
425
'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
429
fp = open(tmpfile, 'rb')
430
multiarch_path_component = fp.readline().strip()
431
_add_directory(self.compiler.library_dirs,
432
'/usr/lib/' + multiarch_path_component)
433
_add_directory(self.compiler.include_dirs,
434
'/usr/include/' + multiarch_path_component)
441
description='Python Imaging Library (fork)',
443
_read('README.rst') +
444
_read('docs/INSTALL.txt') +
445
_read('docs/HISTORY.txt')).decode('utf-8'),
446
author='Alex Clark (fork author)',
447
author_email='aclark@aclark.net',
448
url='http://github.com/python-imaging/Pillow',
451
"Development Status :: 6 - Mature",
452
"Topic :: Multimedia :: Graphics",
453
"Topic :: Multimedia :: Graphics :: Capture :: Digital Camera",
454
"Topic :: Multimedia :: Graphics :: Capture :: Scanners",
455
"Topic :: Multimedia :: Graphics :: Capture :: Screen Capture",
456
"Topic :: Multimedia :: Graphics :: Graphics Conversion",
457
"Topic :: Multimedia :: Graphics :: Viewers",
459
cmdclass={"build_ext": pil_build_ext},
460
ext_modules=[Extension("_imaging", ["_imaging.c"])],
461
packages=find_packages(),
462
scripts=glob.glob("Scripts/pil*.py"),