1
from __future__ import print_function
9
from distutils.command.build_ext import build_ext
10
from distutils import sysconfig
11
from setuptools import Extension, setup, find_packages
15
"decode", "encode", "map", "display", "outline", "path",
19
"Access", "AlphaComposite", "Antialias", "Bands", "BitDecode", "Blend",
20
"Chops", "Convert", "ConvertYCbCr", "Copy", "Crc32", "Crop", "Dib", "Draw",
21
"Effects", "EpsEncode", "File", "Fill", "Filter", "FliDecode",
22
"Geometry", "GetBBox", "GifDecode", "GifEncode", "HexDecode",
23
"Histo", "JpegDecode", "JpegEncode", "LzwDecode", "Matrix",
24
"ModeFilter", "MspDecode", "Negative", "Offset", "Pack",
25
"PackDecode", "Palette", "Paste", "Quant", "QuantHash",
26
"QuantHeap", "PcdDecode", "PcxDecode", "PcxEncode", "Point",
27
"RankFilter", "RawDecode", "RawEncode", "Storage", "SunRleDecode",
28
"TgaRleDecode", "Unpack", "UnpackYCC", "UnsharpMask", "XbmDecode",
29
"XbmEncode", "ZipDecode", "ZipEncode")
32
def _add_directory(path, dir, where=None):
33
if dir and os.path.isdir(dir) and dir not in path:
37
path.insert(where, dir)
40
def _find_include_file(self, include):
41
for directory in self.compiler.include_dirs:
42
if os.path.isfile(os.path.join(directory, include)):
47
def _find_library_file(self, library):
48
return self.compiler.find_library_file(self.compiler.library_dirs, library)
51
def _find_version(filename):
52
for line in open(filename).readlines():
53
m = re.search("VERSION\s*=\s*\"([^\"]+)\"", line)
59
def _lib_include(root):
60
# map root to (root/lib, root/include)
61
return os.path.join(root, "lib"), os.path.join(root, "include")
65
return open(file, 'rb').read()
84
class pil_build_ext(build_ext):
86
def build_extensions(self):
93
_add_directory(include_dirs, "libImaging")
98
for root in (TCL_ROOT, JPEG_ROOT, TCL_ROOT, TIFF_ROOT, ZLIB_ROOT,
99
FREETYPE_ROOT, LCMS_ROOT):
100
if isinstance(root, type(())):
101
lib_root, include_root = root
103
lib_root = include_root = root
104
_add_directory(library_dirs, lib_root)
105
_add_directory(include_dirs, include_root)
108
# add platform directories
110
if sys.platform == "cygwin":
111
# pythonX.Y.dll.a is in the /usr/lib/pythonX.Y/config directory
112
_add_directory(library_dirs, os.path.join(
113
"/usr/lib", "python%s" % sys.version[:3], "config"))
115
elif sys.platform == "darwin":
116
# attempt to make sure we pick freetype2 over other versions
117
_add_directory(include_dirs, "/sw/include/freetype2")
118
_add_directory(include_dirs, "/sw/lib/freetype2/include")
119
# fink installation directories
120
_add_directory(library_dirs, "/sw/lib")
121
_add_directory(include_dirs, "/sw/include")
122
# darwin ports installation directories
123
_add_directory(library_dirs, "/opt/local/lib")
124
_add_directory(include_dirs, "/opt/local/include")
125
# freetype2 ships with X11
126
_add_directory(library_dirs, "/usr/X11/lib")
127
_add_directory(include_dirs, "/usr/X11/include")
129
elif sys.platform.startswith("linux"):
130
# XXX Kludge. Above /\ we brute force support multiarch. Here we
131
# try Barry's more general approach. Afterward, something should
133
self.add_multiarch_paths()
135
_add_directory(library_dirs, "/usr/local/lib")
136
# FIXME: check /opt/stuff directories here?
138
prefix = sysconfig.get_config_var("prefix")
140
_add_directory(library_dirs, os.path.join(prefix, "lib"))
141
_add_directory(include_dirs, os.path.join(prefix, "include"))
144
# locate tkinter libraries
147
TCL_VERSION = _tkinter.TCL_VERSION[:3]
149
if _tkinter and not TCL_ROOT:
150
# we have Tkinter but the TCL_ROOT variable was not set;
151
# try to locate appropriate Tcl/Tk libraries
152
PYVERSION = sys.version[0] + sys.version[2]
153
TCLVERSION = TCL_VERSION[0] + TCL_VERSION[2]
155
# common installation directories, mostly for Windows
156
# (for Unix-style platforms, we'll check in well-known
158
os.path.join("/py" + PYVERSION, "Tcl"),
159
os.path.join("/python" + PYVERSION, "Tcl"),
160
"/Tcl", "/Tcl" + TCLVERSION, "/Tcl" + TCL_VERSION,
161
os.path.join(os.environ.get("ProgramFiles", ""), "Tcl"),
163
for TCL_ROOT in roots:
164
TCL_ROOT = os.path.abspath(TCL_ROOT)
165
if os.path.isfile(os.path.join(TCL_ROOT, "include", "tk.h")):
166
# FIXME: use distutils logging (?)
167
print("--- using Tcl/Tk libraries at", TCL_ROOT)
168
print("--- using Tcl/Tk version", TCL_VERSION)
169
TCL_ROOT = _lib_include(TCL_ROOT)
175
# add standard directories
177
# look for tcl specific subdirectory (e.g debian)
179
tcl_dir = "/usr/include/tcl" + TCL_VERSION
180
if os.path.isfile(os.path.join(tcl_dir, "tk.h")):
181
_add_directory(include_dirs, tcl_dir)
184
_add_directory(library_dirs, "/usr/local/lib")
185
_add_directory(include_dirs, "/usr/local/include")
187
_add_directory(library_dirs, "/usr/lib")
188
_add_directory(include_dirs, "/usr/include")
191
# insert new dirs *before* default libs, to avoid conflicts
192
# between Python PYD stub libs and real libraries
194
self.compiler.library_dirs = library_dirs + self.compiler.library_dirs
195
self.compiler.include_dirs = include_dirs + self.compiler.include_dirs
198
# look for available libraries
201
zlib = jpeg = tiff = freetype = tcl = tk = lcms = None
204
if _find_include_file(self, "zlib.h"):
205
if _find_library_file(self, "z"):
207
elif sys.platform == "win32" and _find_library_file(self, "zlib"):
208
feature.zlib = "zlib" # alternative name
210
if _find_include_file(self, "jpeglib.h"):
211
if _find_library_file(self, "jpeg"):
212
feature.jpeg = "jpeg"
213
elif sys.platform == "win32" and _find_library_file(self,
215
feature.jpeg = "libjpeg" # alternative name
217
if _find_library_file(self, "tiff"):
218
feature.tiff = "tiff"
220
if _find_library_file(self, "freetype"):
221
# look for freetype2 include files
223
for dir in self.compiler.include_dirs:
224
if os.path.isfile(os.path.join(dir, "ft2build.h")):
225
freetype_version = 21
226
dir = os.path.join(dir, "freetype2")
228
dir = os.path.join(dir, "freetype2")
229
if os.path.isfile(os.path.join(dir, "ft2build.h")):
230
freetype_version = 21
232
if os.path.isdir(os.path.join(dir, "freetype")):
233
freetype_version = 20
236
feature.freetype = "freetype"
237
feature.freetype_version = freetype_version
239
_add_directory(self.compiler.include_dirs, dir, 0)
241
if _find_include_file(self, "lcms.h"):
242
if _find_library_file(self, "lcms"):
243
feature.lcms = "lcms"
245
if _tkinter and _find_include_file(self, "tk.h"):
246
# the library names may vary somewhat (e.g. tcl84 or tcl8.4)
247
version = TCL_VERSION[0] + TCL_VERSION[2]
248
if _find_library_file(self, "tcl" + version):
249
feature.tcl = "tcl" + version
250
elif _find_library_file(self, "tcl" + TCL_VERSION):
251
feature.tcl = "tcl" + TCL_VERSION
252
if _find_library_file(self, "tk" + version):
253
feature.tk = "tk" + version
254
elif _find_library_file(self, "tk" + TCL_VERSION):
255
feature.tk = "tk" + TCL_VERSION
260
files = ["_imaging.c"]
261
for file in _IMAGING:
262
files.append(file + ".c")
263
for file in _LIB_IMAGING:
264
files.append(os.path.join("libImaging", file + ".c"))
269
libs.append(feature.jpeg)
270
defs.append(("HAVE_LIBJPEG", None))
272
libs.append(feature.zlib)
273
defs.append(("HAVE_LIBZ", None))
274
if sys.platform == "win32":
275
libs.extend(["kernel32", "user32", "gdi32"])
276
if struct.unpack("h", "\0\1".encode('ascii'))[0] == 1:
277
defs.append(("WORDS_BIGENDIAN", None))
280
"_imaging", files, libraries=libs, define_macros=defs))]
283
# additional libraries
287
if feature.freetype_version == 20:
288
defs.append(("USE_FREETYPE_2_0", None))
289
exts.append(Extension(
290
"_imagingft", ["_imagingft.c"], libraries=["freetype"],
293
if os.path.isfile("_imagingtiff.c") and feature.tiff:
294
exts.append(Extension(
295
"_imagingtiff", ["_imagingtiff.c"], libraries=["tiff"]))
297
if os.path.isfile("_imagingcms.c") and feature.lcms:
299
if sys.platform == "win32":
300
extra.extend(["user32", "gdi32"])
301
exts.append(Extension(
302
"_imagingcms", ["_imagingcms.c"], libraries=["lcms"] + extra))
304
if sys.platform == "darwin":
305
# locate Tcl/Tk frameworks
308
"/Library/Frameworks",
309
"/System/Library/Frameworks"]
310
for root in framework_roots:
311
if (os.path.exists(os.path.join(root, "Tcl.framework")) and
312
os.path.exists(os.path.join(root, "Tk.framework"))):
313
print("--- using frameworks at %s" % root)
314
frameworks = ["-framework", "Tcl", "-framework", "Tk"]
315
dir = os.path.join(root, "Tcl.framework", "Headers")
316
_add_directory(self.compiler.include_dirs, dir, 0)
317
dir = os.path.join(root, "Tk.framework", "Headers")
318
_add_directory(self.compiler.include_dirs, dir, 1)
321
exts.append(Extension(
322
"_imagingtk", ["_imagingtk.c", "Tk/tkImaging.c"],
323
extra_compile_args=frameworks, extra_link_args=frameworks))
324
feature.tcl = feature.tk = 1 # mark as present
325
elif feature.tcl and feature.tk:
326
exts.append(Extension(
327
"_imagingtk", ["_imagingtk.c", "Tk/tkImaging.c"],
328
libraries=[feature.tcl, feature.tk]))
330
if os.path.isfile("_imagingmath.c"):
331
exts.append(Extension("_imagingmath", ["_imagingmath.c"]))
333
self.extensions[:] = exts
335
build_ext.build_extensions(self)
338
# sanity and security checks
343
unsafe_zlib = self.check_zlib_version(self.compiler.include_dirs)
345
self.summary_report(feature, unsafe_zlib)
347
def summary_report(self, feature, unsafe_zlib):
350
print("SETUP SUMMARY (Pillow %s / PIL %s)" % (VERSION, PIL_VERSION))
352
print("version %s" % VERSION)
353
v = sys.version.split("[")
354
print("platform %s %s" % (sys.platform, v[0].strip()))
356
print(" [%s" % v.strip())
360
(feature.tcl and feature.tk, "TKINTER"),
361
(feature.jpeg, "JPEG"),
362
(feature.zlib, "ZLIB (PNG/ZIP)"),
363
# (feature.tiff, "experimental TIFF G3/G4 read"),
364
(feature.freetype, "FREETYPE2"),
365
(feature.lcms, "LITTLECMS"),
369
for option in options:
371
print("--- %s support available" % option[1])
373
print("*** %s support not available" % option[1])
374
if option[1] == "TKINTER" and _tkinter:
375
version = _tkinter.TCL_VERSION
376
print("(Tcl/Tk %s libraries needed)" % version)
380
if feature.zlib and unsafe_zlib:
382
print("*** Warning: zlib", unsafe_zlib)
383
print("may contain a security vulnerability.")
384
print("*** Consider upgrading to zlib 1.2.3 or newer.")
385
print("*** See: http://www.kb.cert.org/vuls/id/238678")
386
print(" http://www.kb.cert.org/vuls/id/680620")
387
print(" http://www.gzip.org/zlib/advisory-2002-03-11.txt")
393
print("To add a missing option, make sure you have the required")
394
print("library, and set the corresponding ROOT variable in the")
395
print("setup.py script.")
398
print("To check the build, run the selftest.py script.")
400
def check_zlib_version(self, include_dirs):
401
# look for unsafe versions of zlib
402
for dir in include_dirs:
403
zlibfile = os.path.join(dir, "zlib.h")
404
if os.path.isfile(zlibfile):
408
for line in open(zlibfile).readlines():
409
m = re.match('#define\s+ZLIB_VERSION\s+"([^"]*)"', line)
412
if m.group(1) < "1.2.3":
415
# http://hg.python.org/users/barry/rev/7e8deab93d5a
416
def add_multiarch_paths(self):
417
# Debian/Ubuntu multiarch support.
418
# https://wiki.ubuntu.com/MultiarchSpec
420
tmpfile = os.path.join(self.build_temp, 'multiarch')
421
if not os.path.exists(self.build_temp):
422
os.makedirs(self.build_temp)
423
ret = os.system('dpkg-architecture -qDEB_HOST_MULTIARCH > %s' %
426
'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
430
fp = open(tmpfile, 'r')
431
multiarch_path_component = fp.readline().strip()
432
_add_directory(self.compiler.library_dirs,
433
'/usr/lib/' + multiarch_path_component)
434
_add_directory(self.compiler.include_dirs,
435
'/usr/include/' + multiarch_path_component)
442
description='Python Imaging Library (fork)',
444
_read('README.rst') +
445
_read('docs/INSTALL.txt') +
446
_read('docs/HISTORY.txt')).decode('utf-8'),
447
author='Alex Clark (fork author)',
448
author_email='aclark@aclark.net',
449
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",
458
"Programming Language :: Python :: 2",
459
"Programming Language :: Python :: 2.6",
460
"Programming Language :: Python :: 2.7",
461
"Programming Language :: Python :: 3",
462
"Programming Language :: Python :: 3.2",
463
"Programming Language :: Python :: 3.3",
465
cmdclass={"build_ext": pil_build_ext},
466
ext_modules=[Extension("_imaging", ["_imaging.c"])],
467
packages=find_packages(),
468
scripts=glob.glob("Scripts/pil*.py"),