2
# ------------------------------
5
# ------------------------------
7
# Your cheese is so fresh most people think it's a cream: Mascarpone
8
# ------------------------------
9
from __future__ import print_function
12
import platform as plat
17
from distutils.command.build_ext import build_ext
20
host_platform = sysconfig.get_platform()
22
from distutils import sysconfig
23
host_platform = sys.platform
25
from setuptools import Extension, setup, find_packages
29
"decode", "encode", "map", "display", "outline", "path")
32
"Access", "AlphaComposite", "Antialias", "Bands", "BitDecode", "Blend",
33
"Chops", "Convert", "ConvertYCbCr", "Copy", "Crc32", "Crop", "Dib", "Draw",
34
"Effects", "EpsEncode", "File", "Fill", "Filter", "FliDecode",
35
"Geometry", "GetBBox", "GifDecode", "GifEncode", "HexDecode",
36
"Histo", "JpegDecode", "JpegEncode", "LzwDecode", "Matrix",
37
"ModeFilter", "MspDecode", "Negative", "Offset", "Pack",
38
"PackDecode", "Palette", "Paste", "Quant", "QuantOctree", "QuantHash",
39
"QuantHeap", "PcdDecode", "PcxDecode", "PcxEncode", "Point",
40
"RankFilter", "RawDecode", "RawEncode", "Storage", "SunRleDecode",
41
"TgaRleDecode", "Unpack", "UnpackYCC", "UnsharpMask", "XbmDecode",
42
"XbmEncode", "ZipDecode", "ZipEncode", "TiffDecode")
45
def _add_directory(path, dir, where=None):
46
if dir and os.path.isdir(dir) and dir not in path:
50
path.insert(where, dir)
53
def _find_include_file(self, include):
54
for directory in self.compiler.include_dirs:
55
if os.path.isfile(os.path.join(directory, include)):
60
def _find_library_file(self, library):
61
# Fix for 3.2.x <3.2.4, 3.3.0, shared lib extension is the python shared
62
# lib extension, not the system shared lib extension: e.g. .cpython-33.so
63
# vs .so. See Python bug http://bugs.python.org/16754
64
if 'cpython' in self.compiler.shared_lib_extension:
65
existing = self.compiler.shared_lib_extension
66
self.compiler.shared_lib_extension = "." + existing.split('.')[-1]
67
ret = self.compiler.find_library_file(
68
self.compiler.library_dirs, library)
69
self.compiler.shared_lib_extension = existing
72
return self.compiler.find_library_file(
73
self.compiler.library_dirs, library)
76
def _lib_include(root):
77
# map root to (root/lib, root/include)
78
return os.path.join(root, "lib"), os.path.join(root, "include")
82
return open(file, 'rb').read()
88
print('XXXXX _tkinter not found XXXXX')
101
class pil_build_ext(build_ext):
104
zlib = jpeg = tiff = freetype = tcl = tk = lcms = webp = webpmux = None
107
def require(self, feat):
108
return feat in self.required
109
def want(self, feat):
110
return getattr(self, feat) is None
119
user_options = build_ext.user_options + [
120
('disable-%s' % x, None, 'Disable support for %s' % x)
123
('enable-%s' % x, None, 'Enable support for %s' % x)
127
def initialize_options(self):
128
build_ext.initialize_options(self)
129
for x in self.feature:
130
setattr(self, 'disable_%s' % x, None)
131
setattr(self, 'enable_%s' % x, None)
133
def finalize_options(self):
134
build_ext.finalize_options(self)
135
for x in self.feature:
136
if getattr(self, 'disable_%s' % x):
137
setattr(self.feature, x, False)
138
if getattr(self, 'enable_%s' % x):
140
'Conflicting options: --enable-%s and --disable-%s'
142
if getattr(self, 'enable_%s' % x):
143
self.feature.required.append(x)
145
def add_gcc_paths(self):
146
gcc = sysconfig.get_config_var('CC')
147
tmpfile = os.path.join(self.build_temp, 'gccpaths')
148
if not os.path.exists(self.build_temp):
149
os.makedirs(self.build_temp)
150
ret = os.system('%s -E -v - </dev/null 2>%s 1>/dev/null' % (gcc, tmpfile))
157
with open(tmpfile) as fp:
158
for line in fp.readlines():
159
if line.startswith("gcc version"):
161
elif line.startswith("#include <...>"):
163
elif line.startswith("End of search list"):
165
elif is_gcc and line.startswith("LIBRARY_PATH"):
166
for d in line.strip().split("=")[1].split(":"):
167
d = os.path.normpath(d)
169
_add_directory(self.compiler.library_dirs,
171
elif is_gcc and in_incdirs and '/gcc/' not in line:
172
_add_directory(self.compiler.include_dirs,
177
def build_extensions(self):
184
_add_directory(include_dirs, "libImaging")
187
# add configured kits
189
for root in (TCL_ROOT, JPEG_ROOT, TIFF_ROOT, ZLIB_ROOT,
190
FREETYPE_ROOT, LCMS_ROOT):
191
if isinstance(root, type(())):
192
lib_root, include_root = root
194
lib_root = include_root = root
195
_add_directory(library_dirs, lib_root)
196
_add_directory(include_dirs, include_root)
199
# add platform directories
201
if host_platform == "cygwin":
202
# pythonX.Y.dll.a is in the /usr/lib/pythonX.Y/config directory
203
_add_directory(library_dirs, os.path.join(
204
"/usr/lib", "python%s" % sys.version[:3], "config"))
206
elif host_platform == "darwin":
207
# attempt to make sure we pick freetype2 over other versions
208
_add_directory(include_dirs, "/sw/include/freetype2")
209
_add_directory(include_dirs, "/sw/lib/freetype2/include")
210
# fink installation directories
211
_add_directory(library_dirs, "/sw/lib")
212
_add_directory(include_dirs, "/sw/include")
213
# darwin ports installation directories
214
_add_directory(library_dirs, "/opt/local/lib")
215
_add_directory(include_dirs, "/opt/local/include")
216
# freetype2 ships with X11
217
_add_directory(library_dirs, "/usr/X11/lib")
218
_add_directory(include_dirs, "/usr/X11/include")
219
# if homebrew is installed, use its lib and include directories
222
prefix = subprocess.check_output(['brew', '--prefix'])
224
prefix = prefix.strip()
225
_add_directory(library_dirs, os.path.join(prefix, 'lib'))
226
_add_directory(include_dirs, os.path.join(prefix, 'include'))
228
pass # homebrew not installed
230
elif host_platform.startswith("linux"):
231
self.add_multiarch_paths()
233
_add_directory(library_dirs, "/usr/local/lib")
234
# FIXME: check /opt/stuff directories here?
236
# include, rpath, if set as environment variables:
237
for k in 'C_INCLUDE_PATH INCLUDE'.split():
239
for d in os.environ[k].split(os.path.pathsep):
240
_add_directory(include_dirs, d)
242
for k in 'LD_RUN_PATH LIBRARY_PATH LIB'.split():
244
for d in os.environ[k].split(os.path.pathsep):
245
_add_directory(library_dirs, d)
247
prefix = sysconfig.get_config_var("prefix")
249
_add_directory(library_dirs, os.path.join(prefix, "lib"))
250
_add_directory(include_dirs, os.path.join(prefix, "include"))
253
# locate tkinter libraries
256
TCL_VERSION = _tkinter.TCL_VERSION[:3]
258
if _tkinter and not TCL_ROOT:
259
# we have Tkinter but the TCL_ROOT variable was not set;
260
# try to locate appropriate Tcl/Tk libraries
261
PYVERSION = sys.version[0] + sys.version[2]
262
TCLVERSION = TCL_VERSION[0] + TCL_VERSION[2]
264
# common installation directories, mostly for Windows
265
# (for Unix-style platforms, we'll check in well-known
267
os.path.join("/py" + PYVERSION, "Tcl"),
268
os.path.join("/python" + PYVERSION, "Tcl"),
269
"/Tcl", "/Tcl" + TCLVERSION, "/Tcl" + TCL_VERSION,
270
os.path.join(os.environ.get("ProgramFiles", ""), "Tcl"), ]
271
for TCL_ROOT in roots:
272
TCL_ROOT = os.path.abspath(TCL_ROOT)
273
if os.path.isfile(os.path.join(TCL_ROOT, "include", "tk.h")):
274
# FIXME: use distutils logging (?)
275
print("--- using Tcl/Tk libraries at", TCL_ROOT)
276
print("--- using Tcl/Tk version", TCL_VERSION)
277
TCL_ROOT = _lib_include(TCL_ROOT)
282
# add standard directories
284
# look for tcl specific subdirectory (e.g debian)
286
tcl_dir = "/usr/include/tcl" + TCL_VERSION
287
if os.path.isfile(os.path.join(tcl_dir, "tk.h")):
288
_add_directory(include_dirs, tcl_dir)
291
_add_directory(library_dirs, "/usr/local/lib")
292
_add_directory(include_dirs, "/usr/local/include")
294
_add_directory(library_dirs, "/usr/lib")
295
_add_directory(include_dirs, "/usr/include")
298
# insert new dirs *before* default libs, to avoid conflicts
299
# between Python PYD stub libs and real libraries
301
self.compiler.library_dirs = library_dirs + self.compiler.library_dirs
302
self.compiler.include_dirs = include_dirs + self.compiler.include_dirs
305
# look for available libraries
307
feature = self.feature
309
if feature.want('zlib'):
310
if _find_include_file(self, "zlib.h"):
311
if _find_library_file(self, "z"):
313
elif host_platform == "win32" and _find_library_file(self, "zlib"):
314
feature.zlib = "zlib" # alternative name
316
if feature.want('jpeg'):
317
if _find_include_file(self, "jpeglib.h"):
318
if _find_library_file(self, "jpeg"):
319
feature.jpeg = "jpeg"
321
host_platform == "win32" and
322
_find_library_file(self, "libjpeg")):
323
feature.jpeg = "libjpeg" # alternative name
325
if feature.want('tiff'):
326
if _find_library_file(self, "tiff"):
327
feature.tiff = "tiff"
328
if host_platform == "win32" and _find_library_file(self, "libtiff"):
329
feature.tiff = "libtiff"
330
if host_platform == "darwin" and _find_library_file(self, "libtiff"):
331
feature.tiff = "libtiff"
333
if feature.want('freetype'):
334
if _find_library_file(self, "freetype"):
335
# look for freetype2 include files
337
for dir in self.compiler.include_dirs:
338
if os.path.isfile(os.path.join(dir, "ft2build.h")):
339
freetype_version = 21
340
dir = os.path.join(dir, "freetype2")
342
dir = os.path.join(dir, "freetype2")
343
if os.path.isfile(os.path.join(dir, "ft2build.h")):
344
freetype_version = 21
346
if os.path.isdir(os.path.join(dir, "freetype")):
347
freetype_version = 20
350
feature.freetype = "freetype"
351
feature.freetype_version = freetype_version
353
_add_directory(self.compiler.include_dirs, dir, 0)
355
if feature.want('lcms'):
356
if _find_include_file(self, "lcms.h"):
357
if _find_library_file(self, "lcms"):
358
feature.lcms = "lcms"
360
if _tkinter and _find_include_file(self, "tk.h"):
361
# the library names may vary somewhat (e.g. tcl84 or tcl8.4)
362
version = TCL_VERSION[0] + TCL_VERSION[2]
363
if feature.want('tcl'):
364
if _find_library_file(self, "tcl" + version):
365
feature.tcl = "tcl" + version
366
elif _find_library_file(self, "tcl" + TCL_VERSION):
367
feature.tcl = "tcl" + TCL_VERSION
368
if feature.want('tk'):
369
if _find_library_file(self, "tk" + version):
370
feature.tk = "tk" + version
371
elif _find_library_file(self, "tk" + TCL_VERSION):
372
feature.tk = "tk" + TCL_VERSION
374
if feature.want('webp'):
375
if (_find_include_file(self, "webp/encode.h") and
376
_find_include_file(self, "webp/decode.h")):
377
if _find_library_file(self, "webp"): # in googles precompiled zip it is call "libwebp"
378
feature.webp = "webp"
380
if feature.want('webpmux'):
381
if (_find_include_file(self, "webp/mux.h") and
382
_find_include_file(self, "webp/demux.h")):
383
if _find_library_file(self, "webpmux") and _find_library_file(self, "webpdemux"):
384
feature.webpmux = "webpmux"
387
if not getattr(feature, f) and feature.require(f):
389
'--enable-%s requested but %s not found, aborting.'
395
files = ["_imaging.c"]
396
for file in _IMAGING:
397
files.append(file + ".c")
398
for file in _LIB_IMAGING:
399
files.append(os.path.join("libImaging", file + ".c"))
404
libs.append(feature.jpeg)
405
defs.append(("HAVE_LIBJPEG", None))
407
libs.append(feature.zlib)
408
defs.append(("HAVE_LIBZ", None))
410
libs.append(feature.tiff)
411
defs.append(("HAVE_LIBTIFF", None))
412
if host_platform == "win32":
413
libs.extend(["kernel32", "user32", "gdi32"])
414
if struct.unpack("h", "\0\1".encode('ascii'))[0] == 1:
415
defs.append(("WORDS_BIGENDIAN", None))
418
"PIL._imaging", files, libraries=libs, define_macros=defs))]
421
# additional libraries
425
if feature.freetype_version == 20:
426
defs.append(("USE_FREETYPE_2_0", None))
427
exts.append(Extension(
428
"PIL._imagingft", ["_imagingft.c"], libraries=["freetype"],
431
if os.path.isfile("_imagingtiff.c") and feature.tiff:
432
exts.append(Extension(
433
"PIL._imagingtiff", ["_imagingtiff.c"], libraries=["tiff"]))
435
if os.path.isfile("_imagingcms.c") and feature.lcms:
437
if host_platform == "win32":
438
extra.extend(["user32", "gdi32"])
439
exts.append(Extension(
440
"PIL._imagingcms", ["_imagingcms.c"], libraries=["lcms"] + extra))
442
if os.path.isfile("_webp.c") and feature.webp:
447
defs.append(("HAVE_WEBPMUX", None))
448
libs.append("webpmux")
449
libs.append("webpdemux")
451
exts.append(Extension(
452
"PIL._webp", ["_webp.c"], libraries=libs, define_macros=defs))
454
if host_platform == "darwin":
455
# locate Tcl/Tk frameworks
458
"/Library/Frameworks",
459
"/System/Library/Frameworks"]
460
for root in framework_roots:
462
os.path.exists(os.path.join(root, "Tcl.framework")) and
463
os.path.exists(os.path.join(root, "Tk.framework"))):
464
print("--- using frameworks at %s" % root)
465
frameworks = ["-framework", "Tcl", "-framework", "Tk"]
466
dir = os.path.join(root, "Tcl.framework", "Headers")
467
_add_directory(self.compiler.include_dirs, dir, 0)
468
dir = os.path.join(root, "Tk.framework", "Headers")
469
_add_directory(self.compiler.include_dirs, dir, 1)
472
exts.append(Extension(
473
"PIL._imagingtk", ["_imagingtk.c", "Tk/tkImaging.c"],
474
extra_compile_args=frameworks, extra_link_args=frameworks))
475
feature.tcl = feature.tk = 1 # mark as present
476
elif feature.tcl and feature.tk:
477
exts.append(Extension(
478
"PIL._imagingtk", ["_imagingtk.c", "Tk/tkImaging.c"],
479
libraries=[feature.tcl, feature.tk]))
481
if os.path.isfile("_imagingmath.c"):
482
exts.append(Extension("PIL._imagingmath", ["_imagingmath.c"]))
484
self.extensions[:] = exts
486
build_ext.build_extensions(self)
489
# sanity and security checks
494
unsafe_zlib = self.check_zlib_version(self.compiler.include_dirs)
496
self.summary_report(feature, unsafe_zlib)
498
def summary_report(self, feature, unsafe_zlib):
501
print("PIL SETUP SUMMARY")
503
print("version Pillow %s" % VERSION)
504
v = sys.version.split("[")
505
print("platform %s %s" % (host_platform, v[0].strip()))
507
print(" [%s" % v.strip())
511
(feature.tcl and feature.tk, "TKINTER"),
512
(feature.jpeg, "JPEG"),
513
(feature.zlib, "ZLIB (PNG/ZIP)"),
514
(feature.tiff, "TIFF G3/G4 (experimental)"),
515
(feature.freetype, "FREETYPE2"),
516
(feature.lcms, "LITTLECMS"),
517
(feature.webp, "WEBP"),
518
(feature.webpmux, "WEBPMUX"), ]
521
for option in options:
523
print("--- %s support available" % option[1])
525
print("*** %s support not available" % option[1])
526
if option[1] == "TKINTER" and _tkinter:
527
version = _tkinter.TCL_VERSION
528
print("(Tcl/Tk %s libraries needed)" % version)
531
if feature.zlib and unsafe_zlib:
533
print("*** Warning: zlib", unsafe_zlib)
534
print("may contain a security vulnerability.")
535
print("*** Consider upgrading to zlib 1.2.3 or newer.")
536
print("*** See: http://www.kb.cert.org/vuls/id/238678")
537
print(" http://www.kb.cert.org/vuls/id/680620")
538
print(" http://www.gzip.org/zlib/advisory-2002-03-11.txt")
544
print("To add a missing option, make sure you have the required")
545
print("library, and set the corresponding ROOT variable in the")
546
print("setup.py script.")
549
print("To check the build, run the selftest.py script.")
552
def check_zlib_version(self, include_dirs):
553
# look for unsafe versions of zlib
554
for dir in include_dirs:
555
zlibfile = os.path.join(dir, "zlib.h")
556
if os.path.isfile(zlibfile):
560
for line in open(zlibfile).readlines():
561
m = re.match('#define\s+ZLIB_VERSION\s+"([^"]*)"', line)
564
if m.group(1) < "1.2.3":
567
# http://hg.python.org/users/barry/rev/7e8deab93d5a
568
def add_multiarch_paths(self):
569
# Debian/Ubuntu multiarch support.
570
# https://wiki.ubuntu.com/MultiarchSpec
572
tmpfile = os.path.join(self.build_temp, 'multiarch')
573
if not os.path.exists(self.build_temp):
574
os.makedirs(self.build_temp)
576
'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
580
fp = open(tmpfile, 'r')
581
multiarch_path_component = fp.readline().strip()
583
self.compiler.library_dirs,
584
'/usr/lib/' + multiarch_path_component)
586
self.compiler.include_dirs,
587
'/usr/include/' + multiarch_path_component)
594
description='Python Imaging Library (Fork)',
596
_read('README.rst') + b'\n' +
597
_read('CHANGES.rst') + b'\n' +
598
_read('CONTRIBUTORS.rst')).decode('utf-8'),
599
author='Alex Clark (fork author)',
600
author_email='aclark@aclark.net',
601
url='http://python-imaging.github.io/',
603
"Development Status :: 6 - Mature",
604
"Topic :: Multimedia :: Graphics",
605
"Topic :: Multimedia :: Graphics :: Capture :: Digital Camera",
606
"Topic :: Multimedia :: Graphics :: Capture :: Scanners",
607
"Topic :: Multimedia :: Graphics :: Capture :: Screen Capture",
608
"Topic :: Multimedia :: Graphics :: Graphics Conversion",
609
"Topic :: Multimedia :: Graphics :: Viewers",
610
"Programming Language :: Python :: 2",
611
"Programming Language :: Python :: 2.6",
612
"Programming Language :: Python :: 2.7",
613
"Programming Language :: Python :: 3",
614
"Programming Language :: Python :: 3.2",
615
"Programming Language :: Python :: 3.3", ],
616
cmdclass={"build_ext": pil_build_ext},
617
ext_modules=[Extension("PIL._imaging", ["_imaging.c"])],
618
include_package_data=True,
619
packages=find_packages(),
620
scripts=glob.glob("Scripts/pil*.py"),
621
test_suite='PIL.tests',
622
keywords=["Imaging",],
623
license='Standard PIL License',