~ubuntu-branches/ubuntu/wily/python-imaging/wily

« back to all changes in this revision

Viewing changes to .pc/git-updates.diff/setup.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-01-31 20:49:20 UTC
  • mfrom: (27.1.1 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20130131204920-b5zshy6vgfvdionl
Tags: 1.1.7+1.7.8-1ubuntu1
Rewrite build dependencies to allow cross builds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import glob
 
2
import os
 
3
import platform
 
4
import re
 
5
import struct
 
6
import sys
 
7
 
 
8
from distutils.command.build_ext import build_ext
 
9
from distutils import sysconfig
 
10
from setuptools import Extension, setup, find_packages
 
11
 
 
12
 
 
13
_IMAGING = (
 
14
    "decode", "encode", "map", "display", "outline", "path",
 
15
    )
 
16
 
 
17
_LIB_IMAGING = (
 
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")
 
29
 
 
30
 
 
31
def _add_directory(path, dir, where=None):
 
32
    if dir and os.path.isdir(dir) and dir not in path:
 
33
        if where is None:
 
34
            path.append(dir)
 
35
        else:
 
36
            path.insert(where, dir)
 
37
 
 
38
 
 
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)):
 
42
            return 1
 
43
    return 0
 
44
 
 
45
 
 
46
def _find_library_file(self, library):
 
47
    return self.compiler.find_library_file(self.compiler.library_dirs, library)
 
48
 
 
49
 
 
50
def _find_version(filename):
 
51
    for line in open(filename).readlines():
 
52
        m = re.search("VERSION\s*=\s*\"([^\"]+)\"", line)
 
53
        if m:
 
54
            return m.group(1)
 
55
    return None
 
56
 
 
57
 
 
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")
 
61
 
 
62
 
 
63
def _read(file):
 
64
    return open(file, 'rb').read()
 
65
 
 
66
try:
 
67
    import _tkinter
 
68
except ImportError:
 
69
    _tkinter = None
 
70
 
 
71
 
 
72
NAME = 'Pillow'
 
73
VERSION = '1.7.8'
 
74
PIL_VERSION = '1.1.7'
 
75
TCL_ROOT = None
 
76
JPEG_ROOT = None
 
77
ZLIB_ROOT = None
 
78
TIFF_ROOT = None
 
79
FREETYPE_ROOT = None
 
80
LCMS_ROOT = None
 
81
 
 
82
 
 
83
class pil_build_ext(build_ext):
 
84
 
 
85
    def build_extensions(self):
 
86
 
 
87
        global TCL_ROOT
 
88
 
 
89
        library_dirs = []
 
90
        include_dirs = []
 
91
 
 
92
        _add_directory(include_dirs, "libImaging")
 
93
 
 
94
        #
 
95
        # add platform directories
 
96
 
 
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"))
 
101
 
 
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")
 
115
 
 
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
 
119
            # work ;-)
 
120
            self.add_multiarch_paths()
 
121
 
 
122
        _add_directory(library_dirs, "/usr/local/lib")
 
123
        # FIXME: check /opt/stuff directories here?
 
124
 
 
125
        prefix = sysconfig.get_config_var("prefix")
 
126
        if prefix:
 
127
            _add_directory(library_dirs, os.path.join(prefix, "lib"))
 
128
            _add_directory(include_dirs, os.path.join(prefix, "include"))
 
129
 
 
130
        #
 
131
        # locate tkinter libraries
 
132
 
 
133
        if _tkinter:
 
134
            TCL_VERSION = _tkinter.TCL_VERSION[:3]
 
135
 
 
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]
 
141
            roots = [
 
142
                # common installation directories, mostly for Windows
 
143
                # (for Unix-style platforms, we'll check in well-known
 
144
                # locations later)
 
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"),
 
149
                ]
 
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)
 
157
                    break
 
158
            else:
 
159
                TCL_ROOT = None
 
160
 
 
161
        #
 
162
        # add configured kits
 
163
 
 
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
 
168
            else:
 
169
                lib_root = include_root = root
 
170
            _add_directory(library_dirs, lib_root)
 
171
            _add_directory(include_dirs, include_root)
 
172
 
 
173
        #
 
174
        # add standard directories
 
175
 
 
176
        # look for tcl specific subdirectory (e.g debian)
 
177
        if _tkinter:
 
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)
 
181
 
 
182
        # standard locations
 
183
        _add_directory(library_dirs, "/usr/local/lib")
 
184
        _add_directory(include_dirs, "/usr/local/include")
 
185
 
 
186
        _add_directory(library_dirs, "/usr/lib")
 
187
        _add_directory(include_dirs, "/usr/include")
 
188
 
 
189
        #
 
190
        # insert new dirs *before* default libs, to avoid conflicts
 
191
        # between Python PYD stub libs and real libraries
 
192
 
 
193
        self.compiler.library_dirs = library_dirs + self.compiler.library_dirs
 
194
        self.compiler.include_dirs = include_dirs + self.compiler.include_dirs
 
195
 
 
196
        #
 
197
        # look for available libraries
 
198
 
 
199
        class feature:
 
200
            zlib = jpeg = tiff = freetype = tcl = tk = lcms = None
 
201
        feature = feature()
 
202
 
 
203
        if _find_include_file(self, "zlib.h"):
 
204
            if _find_library_file(self, "z"):
 
205
                feature.zlib = "z"
 
206
            elif sys.platform == "win32" and _find_library_file(self, "zlib"):
 
207
                feature.zlib = "zlib"  # alternative name
 
208
 
 
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,
 
213
                    "libjpeg"):
 
214
                feature.jpeg = "libjpeg"  # alternative name
 
215
 
 
216
        if _find_library_file(self, "tiff"):
 
217
            feature.tiff = "tiff"
 
218
 
 
219
        if _find_library_file(self, "freetype"):
 
220
            # look for freetype2 include files
 
221
            freetype_version = 0
 
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")
 
226
                    break
 
227
                dir = os.path.join(dir, "freetype2")
 
228
                if os.path.isfile(os.path.join(dir, "ft2build.h")):
 
229
                    freetype_version = 21
 
230
                    break
 
231
                if os.path.isdir(os.path.join(dir, "freetype")):
 
232
                    freetype_version = 20
 
233
                    break
 
234
            if freetype_version:
 
235
                feature.freetype = "freetype"
 
236
                feature.freetype_version = freetype_version
 
237
                if dir:
 
238
                    _add_directory(self.compiler.include_dirs, dir, 0)
 
239
 
 
240
        if _find_include_file(self, "lcms.h"):
 
241
            if _find_library_file(self, "lcms"):
 
242
                feature.lcms = "lcms"
 
243
 
 
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
 
255
 
 
256
        #
 
257
        # core library
 
258
 
 
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"))
 
264
 
 
265
        libs = []
 
266
        defs = []
 
267
        if feature.jpeg:
 
268
            libs.append(feature.jpeg)
 
269
            defs.append(("HAVE_LIBJPEG", None))
 
270
        if feature.zlib:
 
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))
 
277
 
 
278
        exts = [(Extension(
 
279
            "_imaging", files, libraries=libs, define_macros=defs))]
 
280
 
 
281
        #
 
282
        # additional libraries
 
283
 
 
284
        if feature.freetype:
 
285
            defs = []
 
286
            if feature.freetype_version == 20:
 
287
                defs.append(("USE_FREETYPE_2_0", None))
 
288
            exts.append(Extension(
 
289
                "_imagingft", ["_imagingft.c"], libraries=["freetype"],
 
290
                define_macros=defs))
 
291
 
 
292
        if os.path.isfile("_imagingtiff.c") and feature.tiff:
 
293
            exts.append(Extension(
 
294
                "_imagingtiff", ["_imagingtiff.c"], libraries=["tiff"]))
 
295
 
 
296
        if os.path.isfile("_imagingcms.c") and feature.lcms:
 
297
            extra = []
 
298
            if sys.platform == "win32":
 
299
                extra.extend(["user32", "gdi32"])
 
300
            exts.append(Extension(
 
301
                "_imagingcms", ["_imagingcms.c"], libraries=["lcms"] + extra))
 
302
 
 
303
        if sys.platform == "darwin":
 
304
            # locate Tcl/Tk frameworks
 
305
            frameworks = []
 
306
            framework_roots = [
 
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)
 
318
                    break
 
319
            if frameworks:
 
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]))
 
328
 
 
329
        if os.path.isfile("_imagingmath.c"):
 
330
            exts.append(Extension("_imagingmath", ["_imagingmath.c"]))
 
331
 
 
332
        self.extensions[:] = exts
 
333
 
 
334
        build_ext.build_extensions(self)
 
335
 
 
336
        #
 
337
        # sanity and security checks
 
338
 
 
339
        unsafe_zlib = None
 
340
 
 
341
        if feature.zlib:
 
342
            unsafe_zlib = self.check_zlib_version(self.compiler.include_dirs)
 
343
 
 
344
        self.summary_report(feature, unsafe_zlib)
 
345
 
 
346
    def summary_report(self, feature, unsafe_zlib):
 
347
 
 
348
        print("-" * 68)
 
349
        print("SETUP SUMMARY (Pillow %s / PIL %s)" % (VERSION, PIL_VERSION))
 
350
        print("-" * 68)
 
351
        print("version      %s" % VERSION)
 
352
        v = sys.version.split("[")
 
353
        print("platform     %s %s" % (sys.platform, v[0].strip()))
 
354
        for v in v[1:]:
 
355
            print("             [%s" % v.strip())
 
356
        print("-" * 68)
 
357
 
 
358
        options = [
 
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"),
 
365
            ]
 
366
 
 
367
        all = 1
 
368
        for option in options:
 
369
            if option[0]:
 
370
                print("--- %s support available" % option[1])
 
371
            else:
 
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)
 
376
                print("")
 
377
                all = 0
 
378
 
 
379
        if feature.zlib and unsafe_zlib:
 
380
            print("")
 
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")
 
387
            print("")
 
388
 
 
389
        print("-" * 68)
 
390
 
 
391
        if not all:
 
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.")
 
395
            print("\n")
 
396
 
 
397
        print("To check the build, run the selftest.py script.")
 
398
 
 
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):
 
404
                break
 
405
        else:
 
406
            return
 
407
        for line in open(zlibfile).readlines():
 
408
            m = re.match('#define\s+ZLIB_VERSION\s+"([^"]*)"', line)
 
409
            if not m:
 
410
                continue
 
411
            if m.group(1) < "1.2.3":
 
412
                return m.group(1)
 
413
 
 
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
 
418
        # self.build_temp
 
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' %
 
423
                        tmpfile)
 
424
        ret = os.system(
 
425
            'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
 
426
            tmpfile)
 
427
        try:
 
428
            if ret >> 8 == 0:
 
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)
 
435
        finally:
 
436
            os.unlink(tmpfile)
 
437
 
 
438
setup(
 
439
    name=NAME,
 
440
    version=VERSION,
 
441
    description='Python Imaging Library (fork)',
 
442
    long_description=(
 
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',
 
449
    use_2to3=True,
 
450
    classifiers=[
 
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
        ],
 
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"),
 
463
    )