~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to setup.py

  • Committer: Patch Queue Manager
  • Date: 2016-04-21 04:10:52 UTC
  • mfrom: (6616.1.1 fix-en-user-guide)
  • Revision ID: pqm@pqm.ubuntu.com-20160421041052-clcye7ns1qcl2n7w
(richard-wilbur) Ensure build of English use guide always uses English text
 even when user's locale specifies a different language. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
import os
10
10
import os.path
11
11
import sys
 
12
import copy
 
13
import glob
12
14
 
13
 
if sys.version_info < (2, 4):
14
 
    sys.stderr.write("[ERROR] Not a supported Python version. Need 2.4+\n")
 
15
if sys.version_info < (2, 6):
 
16
    sys.stderr.write("[ERROR] Not a supported Python version. Need 2.6+\n")
15
17
    sys.exit(1)
16
18
 
17
19
# NOTE: The directory containing setup.py, whether run by 'python setup.py' or
37
39
    'version':      bzrlib.__version__,
38
40
    'author':       'Canonical Ltd',
39
41
    'author_email': 'bazaar@lists.canonical.com',
40
 
    'url':          'http://www.bazaar-vcs.org/',
 
42
    'url':          'http://bazaar.canonical.com/',
41
43
    'description':  'Friendly distributed version control system',
42
44
    'license':      'GNU GPL v2',
43
 
    'download_url': 'http://bazaar-vcs.org/Download',
 
45
    'download_url': 'https://launchpad.net/bzr/+download',
44
46
    'long_description': get_long_description(),
45
47
    'classifiers': [
46
48
        'Development Status :: 6 - Mature',
65
67
            'package_data': {'bzrlib': ['doc/api/*.txt',
66
68
                                        'tests/test_patches_data/*',
67
69
                                        'help_topics/en/*.txt',
 
70
                                        'tests/ssl_certs/ca.crt',
68
71
                                        'tests/ssl_certs/server_without_pass.key',
69
72
                                        'tests/ssl_certs/server_with_pass.key',
70
 
                                        'tests/ssl_certs/server.crt'
 
73
                                        'tests/ssl_certs/server.crt',
71
74
                                       ]},
72
75
           }
73
 
 
 
76
I18N_FILES = []
 
77
for filepath in glob.glob("bzrlib/locale/*/LC_MESSAGES/*.mo"):
 
78
    langfile = filepath[len("bzrlib/locale/"):]
 
79
    targetpath = os.path.dirname(os.path.join("share/locale", langfile))
 
80
    I18N_FILES.append((targetpath, [filepath]))
74
81
 
75
82
def get_bzrlib_packages():
76
83
    """Recurse through the bzrlib directory, and extract the package names"""
98
105
 
99
106
from distutils import log
100
107
from distutils.core import setup
 
108
from distutils.version import LooseVersion
101
109
from distutils.command.install_scripts import install_scripts
102
110
from distutils.command.install_data import install_data
103
111
from distutils.command.build import build
125
133
                f = file(batch_path, "w")
126
134
                f.write(batch_str)
127
135
                f.close()
128
 
                print "Created:", batch_path
129
 
            except Exception, e:
130
 
                print "ERROR: Unable to create %s: %s" % (batch_path, e)
 
136
                print("Created: %s" % batch_path)
 
137
            except Exception:
 
138
                e = sys.exc_info()[1]
 
139
                print("ERROR: Unable to create %s: %s" % (batch_path, e))
131
140
 
132
141
    def _quoted_path(self, path):
133
142
        if ' ' in path:
149
158
    Generate bzr.1.
150
159
    """
151
160
 
 
161
    sub_commands = build.sub_commands + [
 
162
            ('build_mo', lambda _: True),
 
163
            ]
 
164
 
152
165
    def run(self):
153
166
        build.run(self)
154
167
 
160
173
## Setup
161
174
########################
162
175
 
 
176
from bzrlib.bzr_distutils import build_mo
 
177
 
163
178
command_classes = {'install_scripts': my_install_scripts,
164
 
                   'build': bzr_build}
 
179
                   'build': bzr_build,
 
180
                   'build_mo': build_mo,
 
181
                   }
165
182
from distutils import log
166
183
from distutils.errors import CCompilerError, DistutilsPlatformError
167
184
from distutils.extension import Extension
168
185
ext_modules = []
169
186
try:
170
 
    from Pyrex.Distutils import build_ext
 
187
    try:
 
188
        from Cython.Distutils import build_ext
 
189
        from Cython.Compiler.Version import version as pyrex_version
 
190
    except ImportError:
 
191
        print("No Cython, trying Pyrex...")
 
192
        from Pyrex.Distutils import build_ext
 
193
        from Pyrex.Compiler.Version import version as pyrex_version
171
194
except ImportError:
172
195
    have_pyrex = False
173
196
    # try to build the extension from the prior generated source.
174
 
    print
175
 
    print ("The python package 'Pyrex' is not available."
176
 
           " If the .c files are available,")
177
 
    print ("they will be built,"
178
 
           " but modifying the .pyx files will not rebuild them.")
179
 
    print
 
197
    print("")
 
198
    print("The python package 'Pyrex' is not available."
 
199
          " If the .c files are available,")
 
200
    print("they will be built,"
 
201
          " but modifying the .pyx files will not rebuild them.")
 
202
    print("")
180
203
    from distutils.command.build_ext import build_ext
181
204
else:
182
205
    have_pyrex = True
183
 
    from Pyrex.Compiler.Version import version as pyrex_version
 
206
    pyrex_version_info = LooseVersion(pyrex_version)
184
207
 
185
208
 
186
209
class build_ext_if_possible(build_ext):
198
221
    def run(self):
199
222
        try:
200
223
            build_ext.run(self)
201
 
        except DistutilsPlatformError, e:
 
224
        except DistutilsPlatformError:
 
225
            e = sys.exc_info()[1]
202
226
            if not self.allow_python_fallback:
203
227
                log.warn('\n  Cannot build extensions.\n'
204
228
                         '  Use "build_ext --allow-python-fallback" to use'
265
289
 
266
290
add_pyrex_extension('bzrlib._annotator_pyx')
267
291
add_pyrex_extension('bzrlib._bencode_pyx')
268
 
add_pyrex_extension('bzrlib._btree_serializer_pyx')
269
292
add_pyrex_extension('bzrlib._chunks_to_lines_pyx')
270
293
add_pyrex_extension('bzrlib._groupcompress_pyx',
271
294
                    extra_source=['bzrlib/diff-delta.c'])
276
299
    add_pyrex_extension('bzrlib._dirstate_helpers_pyx',
277
300
                        libraries=['Ws2_32'])
278
301
    add_pyrex_extension('bzrlib._walkdirs_win32')
279
 
    z_lib = 'zdll'
280
302
else:
281
 
    if have_pyrex and pyrex_version == '0.9.4.1':
 
303
    if have_pyrex and pyrex_version_info == LooseVersion("0.9.4.1"):
282
304
        # Pyrex 0.9.4.1 fails to compile this extension correctly
283
305
        # The code it generates re-uses a "local" pointer and
284
306
        # calls "PY_DECREF" after having set it to NULL. (It mixes PY_XDECREF
285
307
        # which is NULL safe with PY_DECREF which is not.)
286
 
        print 'Cannot build extension "bzrlib._dirstate_helpers_pyx" using'
287
 
        print 'your version of pyrex "%s". Please upgrade your pyrex' % (
288
 
            pyrex_version,)
289
 
        print 'install. For now, the non-compiled (python) version will'
290
 
        print 'be used instead.'
 
308
        # <https://bugs.launchpad.net/bzr/+bug/449372>
 
309
        # <https://bugs.launchpad.net/bzr/+bug/276868>
 
310
        print('Cannot build extension "bzrlib._dirstate_helpers_pyx" using')
 
311
        print('your version of pyrex "%s". Please upgrade your pyrex'
 
312
              % (pyrex_version,))
 
313
        print('install. For now, the non-compiled (python) version will')
 
314
        print('be used instead.')
291
315
    else:
292
316
        add_pyrex_extension('bzrlib._dirstate_helpers_pyx')
293
317
    add_pyrex_extension('bzrlib._readdir_pyx')
294
 
    z_lib = 'z'
295
 
add_pyrex_extension('bzrlib._chk_map_pyx', libraries=[z_lib])
 
318
add_pyrex_extension('bzrlib._chk_map_pyx')
296
319
ext_modules.append(Extension('bzrlib._patiencediff_c',
297
320
                             ['bzrlib/_patiencediff_c.c']))
 
321
if have_pyrex and pyrex_version_info < LooseVersion("0.9.6.3"):
 
322
    print("")
 
323
    print('Your Pyrex/Cython version %s is too old to build the simple_set' % (
 
324
        pyrex_version))
 
325
    print('and static_tuple extensions.')
 
326
    print('Please upgrade to at least Pyrex 0.9.6.3')
 
327
    print("")
 
328
    # TODO: Should this be a fatal error?
 
329
else:
 
330
    # We only need 0.9.6.3 to build _simple_set_pyx, but static_tuple depends
 
331
    # on simple_set
 
332
    add_pyrex_extension('bzrlib._simple_set_pyx')
 
333
    ext_modules.append(Extension('bzrlib._static_tuple_c',
 
334
                                 ['bzrlib/_static_tuple_c.c']))
 
335
add_pyrex_extension('bzrlib._btree_serializer_pyx')
298
336
 
299
337
 
300
338
if unavailable_files:
301
 
    print 'C extension(s) not found:'
302
 
    print '   %s' % ('\n  '.join(unavailable_files),)
303
 
    print 'The python versions will be used instead.'
304
 
    print
 
339
    print('C extension(s) not found:')
 
340
    print('   %s' % ('\n  '.join(unavailable_files),))
 
341
    print('The python versions will be used instead.')
 
342
    print("")
305
343
 
306
344
 
307
345
def get_tbzr_py2exe_info(includes, excludes, packages, console_targets,
327
365
    # Ensure tbzrlib itself is on sys.path
328
366
    sys.path.append(tbzr_root)
329
367
 
330
 
    # Ensure our COM "entry-point" is on sys.path
331
 
    sys.path.append(os.path.join(tbzr_root, "shellext", "python"))
332
 
 
333
368
    packages.append("tbzrlib")
334
369
 
335
370
    # collect up our icons.
357
392
    excludes.extend("""pywin pywin.dialogs pywin.dialogs.list
358
393
                       win32ui crawler.Crawler""".split())
359
394
 
360
 
    # NOTE: We still create a DLL version of the Python implemented shell
361
 
    # extension for testing purposes - but it is *not* registered by
362
 
    # default - our C++ one is instead.  To discourage people thinking
363
 
    # this DLL is still necessary, its called 'tbzr_old.dll'
364
 
    tbzr = dict(
365
 
        modules=["tbzr"],
366
 
        create_exe = False, # we only want a .dll
367
 
        dest_base = 'tbzr_old',
368
 
    )
369
 
    com_targets.append(tbzr)
370
 
 
371
395
    # tbzrcache executables - a "console" version for debugging and a
372
396
    # GUI version that is generally used.
373
397
    tbzrcache = dict(
385
409
    # ditto for the tbzrcommand tool
386
410
    tbzrcommand = dict(
387
411
        script = os.path.join(tbzr_root, "scripts", "tbzrcommand.py"),
388
 
        icon_resources = [(0,'bzr.ico')],
 
412
        icon_resources = icon_resources,
 
413
        other_resources = other_resources,
389
414
    )
390
415
    console_targets.append(tbzrcommand)
391
416
    tbzrcommandw = tbzrcommand.copy()
398
423
    console_targets.append(tracer)
399
424
 
400
425
    # The C++ implemented shell extensions.
401
 
    dist_dir = os.path.join(tbzr_root, "shellext", "cpp", "tbzrshellext",
402
 
                            "build", "dist")
 
426
    dist_dir = os.path.join(tbzr_root, "shellext", "build")
403
427
    data_files.append(('', [os.path.join(dist_dir, 'tbzrshellext_x86.dll')]))
404
428
    data_files.append(('', [os.path.join(dist_dir, 'tbzrshellext_x64.dll')]))
405
429
 
406
430
 
407
431
def get_qbzr_py2exe_info(includes, excludes, packages, data_files):
408
432
    # PyQt4 itself still escapes the plugin detection code for some reason...
409
 
    packages.append('PyQt4')
410
 
    excludes.append('PyQt4.elementtree.ElementTree')
 
433
    includes.append('PyQt4.QtCore')
 
434
    includes.append('PyQt4.QtGui')
 
435
    includes.append('PyQt4.QtTest')
411
436
    includes.append('sip') # extension module required for Qt.
412
437
    packages.append('pygments') # colorizer for qbzr
413
438
    packages.append('docutils') # html formatting
414
 
    # but we can avoid many Qt4 Dlls.
415
 
    dll_excludes.extend(
416
 
        """QtAssistantClient4.dll QtCLucene4.dll QtDesigner4.dll
417
 
        QtHelp4.dll QtNetwork4.dll QtOpenGL4.dll QtScript4.dll
418
 
        QtSql4.dll QtTest4.dll QtWebKit4.dll QtXml4.dll
419
 
        qscintilla2.dll""".split())
 
439
    includes.append('win32event')  # for qsubprocess stuff
420
440
    # the qt binaries might not be on PATH...
421
441
    # They seem to install to a place like C:\Python25\PyQt4\*
422
442
    # Which is not the same as C:\Python25\Lib\site-packages\PyQt4
461
481
 
462
482
def get_svn_py2exe_info(includes, excludes, packages):
463
483
    packages.append('subvertpy')
 
484
    packages.append('sqlite3')
 
485
 
 
486
 
 
487
def get_git_py2exe_info(includes, excludes, packages):
 
488
    packages.append('dulwich')
 
489
 
 
490
 
 
491
def get_fastimport_py2exe_info(includes, excludes, packages):
 
492
    # This is the python-fastimport package, not to be confused with the
 
493
    # bzr-fastimport plugin.
 
494
    packages.append('fastimport')
464
495
 
465
496
 
466
497
if 'bdist_wininst' in sys.argv:
487
518
            # help pages
488
519
            'data_files': find_docs(),
489
520
            # for building pyrex extensions
490
 
            'cmdclass': {'build_ext': build_ext_if_possible},
 
521
            'cmdclass': command_classes,
491
522
           }
492
523
 
493
524
    ARGS.update(META_INFO)
494
525
    ARGS.update(BZRLIB)
 
526
    PKG_DATA['package_data']['bzrlib'].append('locale/*/LC_MESSAGES/*.mo')
495
527
    ARGS.update(PKG_DATA)
496
 
    
 
528
 
497
529
    setup(**ARGS)
498
530
 
499
531
elif 'py2exe' in sys.argv:
500
 
    import glob
501
532
    # py2exe setup
502
533
    import py2exe
503
534
 
524
555
            install_data.run(self)
525
556
 
526
557
            py2exe = self.distribution.get_command_obj('py2exe', False)
527
 
            optimize = py2exe.optimize
 
558
            # GZ 2010-04-19: Setup has py2exe.optimize as 2, but give plugins
 
559
            #                time before living with docstring stripping
 
560
            optimize = 1
528
561
            compile_names = [f for f in self.outfiles if f.endswith('.py')]
 
562
            # Round mtime to nearest even second so that installing on a FAT
 
563
            # filesystem bytecode internal and script timestamps will match
 
564
            for f in compile_names:
 
565
                mtime = os.stat(f).st_mtime
 
566
                remainder = mtime % 2
 
567
                if remainder:
 
568
                    mtime -= remainder
 
569
                    os.utime(f, (mtime, mtime))
529
570
            byte_compile(compile_names,
530
571
                         optimize=optimize,
531
572
                         force=self.force, prefix=self.install_dir,
532
573
                         dry_run=self.dry_run)
533
 
            if optimize:
534
 
                suffix = 'o'
535
 
            else:
536
 
                suffix = 'c'
537
 
            self.outfiles.extend([f + suffix for f in compile_names])
 
574
            self.outfiles.extend([f + 'o' for f in compile_names])
538
575
    # end of class install_data_with_bytecompile
539
576
 
540
577
    target = py2exe.build_exe.Target(script = "bzr",
544
581
                                     version = version_str,
545
582
                                     description = META_INFO['description'],
546
583
                                     author = META_INFO['author'],
547
 
                                     copyright = "(c) Canonical Ltd, 2005-2009",
 
584
                                     copyright = "(c) Canonical Ltd, 2005-2010",
548
585
                                     company_name = "Canonical Ltd.",
549
586
                                     comments = META_INFO['description'],
550
587
                                    )
 
588
    gui_target = copy.copy(target)
 
589
    gui_target.dest_base = "bzrw"
551
590
 
552
591
    packages = BZRLIB['packages']
553
592
    packages.remove('bzrlib')
563
602
    if sys.version.startswith('2.4'):
564
603
        # adding elementtree package
565
604
        additional_packages.add('elementtree')
566
 
    elif sys.version.startswith('2.5'):
 
605
    elif sys.version.startswith('2.6') or sys.version.startswith('2.5'):
567
606
        additional_packages.add('xml.etree')
568
607
    else:
569
608
        import warnings
615
654
            excludes.extend(["bzrlib.plugins." + d for d in dirs])
616
655
        x = []
617
656
        for i in files:
618
 
            if os.path.splitext(i)[1] not in [".py", ".pyd", ".dll", ".mo"]:
 
657
            # Throw away files we don't want packaged. Note that plugins may
 
658
            # have data files with all sorts of extensions so we need to
 
659
            # be conservative here about what we ditch.
 
660
            ext = os.path.splitext(i)[1]
 
661
            if ext.endswith('~') or ext in [".pyc", ".swp"]:
619
662
                continue
620
663
            if i == '__init__.py' and root == 'bzrlib/plugins':
621
664
                continue
634
677
    console_targets = [target,
635
678
                       'tools/win32/bzr_postinstall.py',
636
679
                       ]
637
 
    gui_targets = []
638
 
    com_targets = []
639
 
    data_files = topics_files + plugins_files
 
680
    gui_targets = [gui_target]
 
681
    data_files = topics_files + plugins_files + I18N_FILES
640
682
 
641
683
    if 'qbzr' in plugins:
642
684
        get_qbzr_py2exe_info(includes, excludes, packages, data_files)
644
686
    if 'svn' in plugins:
645
687
        get_svn_py2exe_info(includes, excludes, packages)
646
688
 
 
689
    if 'git' in plugins:
 
690
        get_git_py2exe_info(includes, excludes, packages)
 
691
 
 
692
    if 'fastimport' in plugins:
 
693
        get_fastimport_py2exe_info(includes, excludes, packages)
 
694
 
647
695
    if "TBZR" in os.environ:
648
696
        # TORTOISE_OVERLAYS_MSI_WIN32 must be set to the location of the
649
697
        # TortoiseOverlays MSI installer file. It is in the TSVN svn repo and
668
716
        # print this warning to stderr as output is redirected, so it is seen
669
717
        # at build time.  Also to stdout so it appears in the log
670
718
        for f in (sys.stderr, sys.stdout):
671
 
            print >> f, \
672
 
                "Skipping TBZR binaries - please set TBZR to a directory to enable"
 
719
            f.write("Skipping TBZR binaries - "
 
720
                "please set TBZR to a directory to enable\n")
673
721
 
674
722
    # MSWSOCK.dll is a system-specific library, which py2exe accidentally pulls
675
723
    # in on Vista.
676
 
    dll_excludes.extend(["MSWSOCK.dll", "MSVCP60.dll", "powrprof.dll"])
 
724
    dll_excludes.extend(["MSWSOCK.dll",
 
725
                         "MSVCP60.dll",
 
726
                         "MSVCP90.dll",
 
727
                         "powrprof.dll",
 
728
                         "SHFOLDER.dll"])
677
729
    options_list = {"py2exe": {"packages": packages + list(additional_packages),
678
730
                               "includes": includes,
679
731
                               "excludes": excludes,
680
732
                               "dll_excludes": dll_excludes,
681
733
                               "dist_dir": "win32_bzr.exe",
682
 
                               "optimize": 1,
 
734
                               "optimize": 2,
 
735
                               "custom_boot_script":
 
736
                                        "tools/win32/py2exe_boot_common.py",
683
737
                              },
684
738
                   }
685
739
 
686
 
    setup(options=options_list,
687
 
          console=console_targets,
688
 
          windows=gui_targets,
689
 
          com_server=com_targets,
690
 
          zipfile='lib/library.zip',
691
 
          data_files=data_files,
692
 
          cmdclass={'install_data': install_data_with_bytecompile},
693
 
          )
 
740
    # We want the libaray.zip to have optimize = 2, but the exe to have
 
741
    # optimize = 1, so that .py files that get compilied at run time
 
742
    # (e.g. user installed plugins) dont have their doc strings removed.
 
743
    class py2exe_no_oo_exe(py2exe.build_exe.py2exe):
 
744
        def build_executable(self, *args, **kwargs):
 
745
            self.optimize = 1
 
746
            py2exe.build_exe.py2exe.build_executable(self, *args, **kwargs)
 
747
            self.optimize = 2
 
748
 
 
749
    if __name__ == '__main__':
 
750
        command_classes['install_data'] = install_data_with_bytecompile
 
751
        command_classes['py2exe'] = py2exe_no_oo_exe
 
752
        setup(options=options_list,
 
753
              console=console_targets,
 
754
              windows=gui_targets,
 
755
              zipfile='lib/library.zip',
 
756
              data_files=data_files,
 
757
              cmdclass=command_classes,
 
758
              )
694
759
 
695
760
else:
696
761
    # ad-hoc for easy_install
700
765
        # easy_install one
701
766
        DATA_FILES = [('man/man1', ['bzr.1'])]
702
767
 
 
768
    DATA_FILES = DATA_FILES + I18N_FILES
703
769
    # std setup
704
770
    ARGS = {'scripts': ['bzr'],
705
771
            'data_files': DATA_FILES,
711
777
    ARGS.update(BZRLIB)
712
778
    ARGS.update(PKG_DATA)
713
779
 
714
 
    setup(**ARGS)
 
780
    if __name__ == '__main__':
 
781
        setup(**ARGS)