source: orange/setup.py @ 11665:102abd2f5a1e

Revision 11665:102abd2f5a1e, 31.2 KB checked in by Ales Erjavec <ales.erjavec@…>, 8 months ago (diff)

Extended 'setup-site.cfg' configuration options.

  • Property exe set to *
RevLine 
[11014]1#!/usr/bin/env python2
[10818]2
[10881]3try:
4    import distribute_setup
[11622]5    # require distutils >= 0.6.26 or setuptools >= 0.7
6    distribute_setup.use_setuptools(version='0.6.26')
[10881]7except ImportError:
8    # For documentation we load setup.py to get version
9    # so it does not matter if importing fails
10    pass
[10818]11
[10825]12import glob, os, sys, types
13from distutils import log
[10792]14from distutils.command.build import build
[9185]15from distutils.command.build_ext import build_ext
16from distutils.command.install_lib import install_lib
[10825]17from distutils.dep_util import newer_group
[10792]18from distutils.errors import DistutilsSetupError
[10825]19from distutils.file_util import copy_file
[9185]20from distutils.msvccompiler import MSVCCompiler
21from distutils.unixccompiler import UnixCCompiler
[10825]22from distutils.util import convert_path
23from distutils.sysconfig import get_python_inc, get_config_var
[10424]24import subprocess
[9185]25from subprocess import check_call
[11665]26from collections import namedtuple
27from ConfigParser import SafeConfigParser
[9185]28
[10825]29from setuptools import setup, find_packages
30from setuptools.command.install import install
[9185]31
[10830]32# Has to be last import as it seems something is changing it somewhere
33from distutils.extension import Extension
34
[10825]35NAME = 'Orange'
[9185]36
[11555]37VERSION = '2.7.1'
38ISRELEASED = False
[10825]39
40DESCRIPTION = 'Orange, a component-based data mining framework.'
[10845]41LONG_DESCRIPTION = open(os.path.join(os.path.dirname(__file__), 'README.txt')).read()
[10825]42AUTHOR = 'Bioinformatics Laboratory, FRI UL'
43AUTHOR_EMAIL = 'contact@orange.biolab.si'
44URL = 'http://orange.biolab.si/'
45DOWNLOAD_URL = 'https://bitbucket.org/biolab/orange/downloads'
46LICENSE = 'GPLv3'
47
48KEYWORDS = (
49    'data mining',
50    'machine learning',
51    'artificial intelligence',
52)
53
54CLASSIFIERS = (
55    'Development Status :: 4 - Beta',
56    'Environment :: X11 Applications :: Qt',
57    'Environment :: Console',
58    'Environment :: Plugins',
59    'Programming Language :: Python',
60    'Framework :: Orange',
61    'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
62    'Operating System :: POSIX',
63    'Operating System :: Microsoft :: Windows',
64    'Topic :: Scientific/Engineering :: Artificial Intelligence',
65    'Topic :: Scientific/Engineering :: Visualization',
66    'Topic :: Software Development :: Libraries :: Python Modules',
67    'Intended Audience :: Education',
68    'Intended Audience :: Science/Research',
69    'Intended Audience :: Developers',
70)
[9581]71
[10352]72try:
73    import numpy
74    numpy_include_dir = numpy.get_include()
75except ImportError:
76    # When setup.py is first run to install orange, numpy can still be missing
77    pass
78    numpy_include_dir = None
[10792]79
[9185]80python_include_dir = get_python_inc(plat_specific=1)
81
[10825]82include_dirs = [python_include_dir, numpy_include_dir, 'source/include']
[9185]83
[10825]84if sys.platform == 'darwin':
[11362]85    extra_compile_args = '-fPIC -fno-common -w -DDARWIN'.split()
[10825]86    extra_link_args = '-headerpad_max_install_names -undefined dynamic_lookup'.split()
87elif sys.platform == 'win32':
88    extra_compile_args = ['-EHsc']
[9185]89    extra_link_args = []
[10825]90elif sys.platform.startswith('linux'):
[11362]91    extra_compile_args = '-fPIC -w -DLINUX'.split()
[10825]92    extra_link_args = ['-Wl,-R$ORIGIN']
[9185]93else:
94    extra_compile_args = []
95    extra_link_args = []
[10792]96
[11665]97lib_cfg = namedtuple(
98    "lib_cfg", ["libraries", "library_dirs", "include_dirs"])
99
100site_cfg = namedtuple(
101    "site_cfg", ["libsvm", "liblinear", "blas", "R", "qhull"])
102
103
104def libs_parse(text):
105    return [lib.strip() for lib in text.strip().split()]
106
107
108def dirs_parse(text):
109    return text.strip().split(os.path.pathsep)
110
111
112def parse_lib_opt(parser, section):
113    libs, library_dirs, include_dirs = [], [], []
114
115    if parser.has_option(section, "libraries"):
116        libs = libs_parse(parser.get(section, "libraries"))
117    elif parser.has_option(section, "library"):
118        libs = libs_parse(parser.get(section, "library"))
119
120    if parser.has_option(section, "library_dirs"):
121        library_dirs = \
122            dirs_parse(parser.get(section, "library_dirs"))
123
124    if parser.has_option(section, "include_dirs"):
125        include_dirs = dirs_parse(parser.get(section, "include_dirs"))
126
127    if libs or library_dirs or include_dirs:
128        return lib_cfg(libs, library_dirs, include_dirs)
129    else:
130        return None
131
132
133def site_config():
134    """Return the parsed site configuration.
135    """
136    parser = SafeConfigParser()
137    parser.read(["setup-site.cfg",
138                 os.path.expanduser("~/.orange-site.cfg")])
139
140    libsvm = parse_lib_opt(parser, "libsvm")
141    liblinear = parse_lib_opt(parser, "liblinear")
142    blas = parse_lib_opt(parser, "blas")
143    R = parse_lib_opt(parser, "R")
144    qhull = parse_lib_opt(parser, "qhull")
145
146    return site_cfg(libsvm, liblinear, blas, R, qhull)
147
148
[10792]149# Get the command for building orangeqt extension from
[10793]150# source/orangeqt/setup.py file.
[10825]151# Fails without PyQt4.
[10792]152import imp
[10793]153try:
[10881]154    orangeqt_setup = imp.load_source('orangeqt_setup', os.path.join(os.path.dirname(__file__), 'source/orangeqt/setup.py'))
[10793]155    build_pyqt_ext = orangeqt_setup.build_pyqt_ext
156except ImportError:
157    orangeqt_setup = None
158    build_pyqt_ext = None
[10792]159
[9185]160class LibStatic(Extension):
161    pass
162
163class PyXtractExtension(Extension):
164    def __init__(self, *args, **kwargs):
165        for name, default in [("extra_pyxtract_cmds", []), ("lib_type", "dynamic")]:
166            setattr(self, name, kwargs.get(name, default))
[10792]167            if name in kwargs:
[9185]168                del kwargs[name]
[10792]169
[9185]170        Extension.__init__(self, *args, **kwargs)
[10792]171
[9185]172class PyXtractSharedExtension(PyXtractExtension):
173    pass
[10792]174
[9185]175class pyxtract_build_ext(build_ext):
176    def run_pyxtract(self, ext, dir):
177        original_dir = os.path.realpath(os.path.curdir)
178        log.info("running pyxtract for %s" % ext.name)
179        try:
180            os.chdir(dir)
181            ## we use the commands which are used for building under windows
182            pyxtract_cmds = [cmd.split() for cmd in getattr(ext, "extra_pyxtract_cmds", [])]
[10792]183            if os.path.exists("_pyxtract.bat"):
[9185]184                pyxtract_cmds.extend([cmd.split()[1:] for cmd in open("_pyxtract.bat").read().strip().splitlines()])
185            for cmd in pyxtract_cmds:
186                log.info(" ".join([sys.executable] + cmd))
187                check_call([sys.executable] + cmd)
188            if pyxtract_cmds:
189                ext.include_dirs.append(os.path.join(dir, "ppp"))
190                ext.include_dirs.append(os.path.join(dir, "px"))
191
192        finally:
193            os.chdir(original_dir)
[10792]194
[9185]195    def finalize_options(self):
196        build_ext.finalize_options(self)
[9581]197        # add the build_lib dir and build_temp (for
[10792]198        # liborange_include and liborange linking)
[9185]199        if not self.inplace:
[9879]200            # for linking with liborange.so (it is in Orange package)
201            self.library_dirs.append(os.path.join(self.build_lib, "Orange"))
202            # for linking with liborange_include.a
203            self.library_dirs.append(self.build_temp)
[9185]204        else:
[9879]205            # for linking with liborange.so
206            self.library_dirs.append("./Orange") 
207            # for linking with liborange_include.a
208            self.library_dirs.append(self.build_temp)
[10792]209
[9185]210    def build_extension(self, ext):
211        if isinstance(ext, LibStatic):
[10792]212            # Build static library
[9185]213            self.build_static(ext)
214        elif isinstance(ext, PyXtractExtension):
[10792]215            # Build pyextract extension
[9185]216            self.build_pyxtract(ext)
[10793]217        elif orangeqt_setup and isinstance(ext, orangeqt_setup.PyQt4Extension):
[10792]218            # Skip the build (will be handled by build_pyqt_ext command)
219            return
[9185]220        else:
221            build_ext.build_extension(self, ext)
[10792]222
[9185]223        if isinstance(ext, PyXtractSharedExtension):
[10792]224            # Fix extension modules so they can be linked
225            # by other modules
[10982]226            if self.dry_run:
227                # No need to do anything here.
228                return
229
[9185]230            if isinstance(self.compiler, MSVCCompiler):
231                # Copy ${TEMP}/orange/orange.lib to ${BUILD}/orange.lib
232                ext_fullpath = self.get_ext_fullpath(ext.name)
[9925]233                # Get the last component of the name
234                ext_name = ext.name.rsplit(".", 1)[-1]
[10982]235                libs = glob.glob(os.path.join(self.build_temp,
[9925]236                                              "*", "*", ext_name + ".lib"))
237                if not libs:
238                    log.info("Could not locate library %r in directory %r" \
[10982]239                             % (ext_name, self.build_temp))
[9925]240                else:
241                    lib = libs[0]
[10982]242                    lib_path = os.path.splitext(ext_fullpath)[0] + ".lib"
243                    copy_file(lib, lib_path, dry_run=self.dry_run)
[9185]244            else:
245                # Make lib{name}.so link to {name}.so
246                ext_path = self.get_ext_fullpath(ext.name)
247                ext_path, ext_filename = os.path.split(ext_path)
248                realpath = os.path.realpath(os.curdir)
249                try:
250                    os.chdir(ext_path)
251                    # Get the shared library name
[9879]252                    _, name = ext.name.rsplit(".", 1)
253                    lib_filename = self.compiler.library_filename(name, lib_type="shared")
[9185]254                    # Create the link
[10982]255                    copy_file(ext_filename, lib_filename, link="sym",
256                              dry_run=self.dry_run)
[9185]257                except OSError, ex:
258                    log.info("failed to create shared library for %s: %s" % (ext.name, str(ex)))
259                finally:
260                    os.chdir(realpath)
[10792]261
[9185]262    def build_pyxtract(self, ext):
263        ## mostly copied from build_extension
264        sources = ext.sources
265        if sources is None or type(sources) not in (types.ListType, types.TupleType):
266            raise DistutilsSetupError, \
267                  ("in 'ext_modules' option (extension '%s'), " +
268                   "'sources' must be present and must be " +
269                   "a list of source filenames") % ext.name
270        sources = list(sources)
[10792]271
[9185]272        ext_path = self.get_ext_fullpath(ext.name)
[10792]273
[9185]274        depends = sources + ext.depends
275        if not (self.force or newer_group(depends, ext_path, 'newer')):
276            log.debug("skipping '%s' extension (up-to-date)", ext.name)
277            return
278        else:
279            log.info("building '%s' extension", ext.name)
280
281        # First, scan the sources for SWIG definition files (.i), run
282        # SWIG on 'em to create .c files, and modify the sources list
283        # accordingly.
284        sources = self.swig_sources(sources, ext)
[10792]285
[9185]286        # Run pyxtract in dir this adds ppp and px dirs to include_dirs
287        dir = os.path.commonprefix([os.path.split(s)[0] for s in ext.sources])
288        self.run_pyxtract(ext, dir)
289
290        # Next, compile the source code to object files.
291
292        # XXX not honouring 'define_macros' or 'undef_macros' -- the
293        # CCompiler API needs to change to accommodate this, and I
294        # want to do one thing at a time!
295
296        # Two possible sources for extra compiler arguments:
297        #   - 'extra_compile_args' in Extension object
298        #   - CFLAGS environment variable (not particularly
299        #     elegant, but people seem to expect it and I
300        #     guess it's useful)
301        # The environment variable should take precedence, and
302        # any sensible compiler will give precedence to later
303        # command line args.  Hence we combine them in order:
304        extra_args = ext.extra_compile_args or []
305
306        macros = ext.define_macros[:]
307        for undef in ext.undef_macros:
308            macros.append((undef,))
309
310        objects = self.compiler.compile(sources,
311                                         output_dir=self.build_temp,
312                                         macros=macros,
313                                         include_dirs=ext.include_dirs,
314                                         debug=self.debug,
315                                         extra_postargs=extra_args,
316                                         depends=ext.depends)
317
318        # XXX -- this is a Vile HACK!
319        #
320        # The setup.py script for Python on Unix needs to be able to
321        # get this list so it can perform all the clean up needed to
322        # avoid keeping object files around when cleaning out a failed
323        # build of an extension module.  Since Distutils does not
324        # track dependencies, we have to get rid of intermediates to
325        # ensure all the intermediates will be properly re-built.
326        #
327        self._built_objects = objects[:]
328
329        # Now link the object files together into a "shared object" --
330        # of course, first we have to figure out all the other things
331        # that go into the mix.
332        if ext.extra_objects:
333            objects.extend(ext.extra_objects)
334        extra_args = ext.extra_link_args or []
335
336        # Detect target language, if not provided
337        language = ext.language or self.compiler.detect_language(sources)
338
339        self.compiler.link_shared_object(
340            objects, ext_path,
341            libraries=self.get_libraries(ext),
342            library_dirs=ext.library_dirs,
343            runtime_library_dirs=ext.runtime_library_dirs,
344            extra_postargs=extra_args,
345            export_symbols=self.get_export_symbols(ext),
346            debug=self.debug,
347            build_temp=self.build_temp,
348            target_lang=language)
[10792]349
350
[9185]351    def build_static(self, ext):
352        ## mostly copied from build_extension, changed
353        sources = ext.sources
354        if sources is None or type(sources) not in (types.ListType, types.TupleType):
355            raise DistutilsSetupError, \
356                  ("in 'ext_modules' option (extension '%s'), " +
357                   "'sources' must be present and must be " +
358                   "a list of source filenames") % ext.name
359        sources = list(sources)
[10792]360
[9581]361        # Static libs get build in the build_temp directory
362        output_dir = self.build_temp
[9185]363        if not os.path.exists(output_dir): #VSC fails if the dir does not exist
364            os.makedirs(output_dir)
[10792]365
[9185]366        lib_filename = self.compiler.library_filename(ext.name, lib_type='static', output_dir=output_dir)
[10792]367
[9185]368        depends = sources + ext.depends
369        if not (self.force or newer_group(depends, lib_filename, 'newer')):
370            log.debug("skipping '%s' extension (up-to-date)", ext.name)
371            return
372        else:
373            log.info("building '%s' extension", ext.name)
374
375        # First, scan the sources for SWIG definition files (.i), run
376        # SWIG on 'em to create .c files, and modify the sources list
377        # accordingly.
378        sources = self.swig_sources(sources, ext)
379
380        # Next, compile the source code to object files.
381
382        # XXX not honouring 'define_macros' or 'undef_macros' -- the
383        # CCompiler API needs to change to accommodate this, and I
384        # want to do one thing at a time!
385
386        # Two possible sources for extra compiler arguments:
387        #   - 'extra_compile_args' in Extension object
388        #   - CFLAGS environment variable (not particularly
389        #     elegant, but people seem to expect it and I
390        #     guess it's useful)
391        # The environment variable should take precedence, and
392        # any sensible compiler will give precedence to later
393        # command line args.  Hence we combine them in order:
394        extra_args = ext.extra_compile_args or []
395
396        macros = ext.define_macros[:]
397        for undef in ext.undef_macros:
398            macros.append((undef,))
399
400        objects = self.compiler.compile(sources,
401                                         output_dir=self.build_temp,
402                                         macros=macros,
403                                         include_dirs=ext.include_dirs,
404                                         debug=self.debug,
405                                         extra_postargs=extra_args,
406                                         depends=ext.depends)
407
408        # XXX -- this is a Vile HACK!
409        #
410        # The setup.py script for Python on Unix needs to be able to
411        # get this list so it can perform all the clean up needed to
412        # avoid keeping object files around when cleaning out a failed
413        # build of an extension module.  Since Distutils does not
414        # track dependencies, we have to get rid of intermediates to
415        # ensure all the intermediates will be properly re-built.
416        #
417        self._built_objects = objects[:]
418
419        # Now link the object files together into a "shared object" --
420        # of course, first we have to figure out all the other things
421        # that go into the mix.
422        if ext.extra_objects:
423            objects.extend(ext.extra_objects)
424        extra_args = ext.extra_link_args or []
425
426        # Detect target language, if not provided
427        language = ext.language or self.compiler.detect_language(sources)
428       
[9581]429        #first remove old library (ar only appends the contents if archive already exists)
[9185]430        try:
431            os.remove(lib_filename)
432        except OSError, ex:
433            log.debug("failed to remove obsolete static library %s: %s" %(ext.name, str(ex)))
434
[9581]435        # The static library is created in the temp dir, it is used during the compile step only
436        # it should not be included in the final install
[9185]437        self.compiler.create_static_lib(
438            objects, ext.name, output_dir,
439            debug=self.debug,
440            target_lang=language)
[10792]441
[9610]442    def get_libraries(self, ext):
443        """ Change the 'orange' library name to 'orange_d' if
444        building in debug mode. Using ``get_ext_filename`` to discover if
445        _d postfix is required.
446       
447        """
448        libraries = build_ext.get_libraries(self, ext)
449        if "orange" in libraries and self.debug:
450            filename = self.get_ext_filename("orange")
451            basename = os.path.basename(filename)
452            name, ext = os.path.splitext(basename)
453            if name.endswith("_d"):
454                index = libraries.index("orange")
455                libraries[index] = "orange_d"
[10792]456
[9610]457        return libraries
[10792]458
[9185]459    if not hasattr(build_ext, "get_ext_fullpath"):
460        #On mac OS X python 2.6.1 distutils does not have this method
461        def get_ext_fullpath(self, ext_name):
462            """Returns the path of the filename for a given extension.
463           
464            The file is located in `build_lib` or directly in the package
465            (inplace option).
466            """
467            import string
468            # makes sure the extension name is only using dots
469            all_dots = string.maketrans('/' + os.sep, '..')
470            ext_name = ext_name.translate(all_dots)
471            fullname = self.get_ext_fullname(ext_name)
472            modpath = fullname.split('.')
473            filename = self.get_ext_filename(ext_name)
474            filename = os.path.split(filename)[-1]
475            if not self.inplace:
476                # no further work needed
477                # returning :
478                #   build_dir/package/path/filename
479                filename = os.path.join(*modpath[:-1] + [filename])
480                return os.path.join(self.build_lib, filename)
481            # the inplace option requires to find the package directory
482            # using the build_py command for that
483            package = '.'.join(modpath[0:-1])
484            build_py = self.get_finalized_command('build_py')
485            package_dir = os.path.abspath(build_py.get_package_dir(package))
486            # returning
487            #   package_dir/filename
488            return os.path.join(package_dir, filename)
[10792]489
490# Add build_pyqt_ext to build subcommands
491class orange_build(build):
492    def has_pyqt_extensions(self):
493        # For now this is disabled unless specifically requested
494        # using build_pyqt_ext command
495        return False
496#        return any([isinstance(ext, orangeqt_setup.PyQt4Extension) \
497#                   for ext in self.distribution.ext_modules]
498#                   )
499
[10793]500    sub_commands = build.sub_commands
501    if orangeqt_setup:
502        sub_commands += [("build_pyqt_ext", has_pyqt_extensions)]
[10792]503
[10982]504
[10792]505class orange_install_lib(install_lib):
[9185]506    """ An command to install orange (preserves liborange.so -> orange.so symlink)
507    """
508    def run(self):
509        install_lib.run(self)
[10792]510
[10982]511    def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1,
512                  preserve_symlinks=1, level=1):
[9185]513        """ Run copy_tree with preserve_symlinks=1 as default
[10982]514        """
515        install_lib.copy_tree(self, infile, outfile, preserve_mode,
516                              preserve_times, preserve_symlinks, level)
[10792]517
[9185]518    def install(self):
519        """ Copy build_dir to install_dir
520        """
521        # A Hack to unlink liborange.so -> orange.so if it already exists,
522        # because copy_tree fails to overwrite it
[10982]523        #
[9879]524        liborange = os.path.join(self.install_dir, "Orange", "liborange.so")
[10763]525        if os.path.exists(liborange) and os.path.islink(liborange):
[10982]526            log.info("unlinking %s -> %s", liborange,
527                     os.path.join(self.install_dir, "orange.so"))
528
529            if not self.dry_run:
530                os.unlink(liborange)
[10792]531
[9185]532        return install_lib.install(self)
[10792]533
[10982]534
[10792]535class orange_install(install):
[9879]536    """ A command to install orange while also creating
[10982]537    a .pth path to access the old orng* modules and orange,
538    orangeom etc.
539
[9879]540    """
541    def run(self):
542        install.run(self)
[9893]543        # Create a .pth file with a path inside the Orange/orng directory
[9879]544        # so the old modules are importable
[10350]545        self.path_file, self.extra_dirs = ("Orange-orng-modules", "Orange/orng")
[9879]546        self.extra_dirs = convert_path(self.extra_dirs)
547        log.info("creating portal path for orange compatibility.")
548        self.create_path_file()
549        self.path_file, self.extra_dirs = None, None
[10792]550
[10982]551
[9185]552def get_source_files(path, ext="cpp", exclude=[]):
553    files = glob.glob(os.path.join(path, "*." + ext))
554    files = [file for file in files if os.path.basename(file) not in exclude]
555    return files
556
[11665]557# common library statically linked into orange, orangeom, ...
558include_ext = LibStatic(
559    "orange_include",
560    get_source_files("source/include/"),
561    include_dirs=include_dirs,
562    extra_compile_args=extra_compile_args
563)
[9185]564
565
566if sys.platform == "win32": # ?? mingw/cygwin
567    libraries = ["orange_include"]
568else:
569    libraries = ["stdc++", "orange_include"]
570
[10250]571
[11665]572# Custom site configuration
573
574site = site_config()
[9185]575
576orange_sources = get_source_files("source/orange/")
[11665]577
[9185]578orange_include_dirs = list(include_dirs)
[11665]579orange_library_dirs = []
[9185]580orange_libraries = list(libraries)
581
[11665]582if site.blas:
[9185]583    # Link external blas library
[11665]584    orange_libraries += site.blas.libraries
585    orange_library_dirs += site.blas.library_dirs
[9185]586else:
587    orange_sources += get_source_files("source/orange/blas/", "c")
[10792]588
[11665]589if site.R:
[9185]590    # Link external R library (for linpack)
[11665]591    orange_libraries += site.R.libraries
592    orange_library_dirs += site.R.library_dirs
[9185]593else:
594    orange_sources += get_source_files("source/orange/linpack/", "c")
[10792]595
[11665]596if site.liblinear:
[9185]597    # Link external LIBLINEAR library
[11665]598    orange_libraries += site.liblinear.libraries
599    orange_include_dirs += site.liblinear.include_dirs
600    orange_library_dirs += site.liblinear.library_dirs
[9185]601else:
602    orange_sources += get_source_files("source/orange/liblinear/", "cpp")
603    orange_include_dirs += ["source/orange/liblinear"]
[10792]604
[11665]605if site.libsvm:
[9185]606    # Link external LibSVM library
[11665]607    orange_libraries += site.libsvm.libraries
608    orange_include_dirs += site.libsvm.include_dirs
609    orange_library_dirs += site.libsvm.library_dirs
[9185]610else:
611    orange_sources += get_source_files("source/orange/libsvm/", "cpp")
[10792]612
[11665]613
614orange_ext = PyXtractSharedExtension(
615    "Orange.orange",
616    orange_sources,
617    include_dirs=orange_include_dirs,
618    extra_compile_args=extra_compile_args + ["-DORANGE_EXPORTS"],
619    extra_link_args=extra_link_args,
620    libraries=orange_libraries,
621    library_dirs=orange_library_dirs,
622    extra_pyxtract_cmds=["../pyxtract/defvectors.py"],
623)
624
[9185]625
626if sys.platform == "darwin":
627    build_shared_cmd = get_config_var("BLDSHARED")
[9879]628    # Dont link liborange.so with orangeom and orangene - MacOS X treats
629    # loadable modules and shared libraries different
630    if "-bundle" in build_shared_cmd.split():
[9185]631        shared_libs = libraries
632    else:
633        shared_libs = libraries + ["orange"]
634else:
635    shared_libs = libraries + ["orange"]
[10792]636
[11665]637orangeom_sources = get_source_files(
638    "source/orangeom/", exclude=["lib_vectors.cpp"])
639
[9185]640orangeom_libraries = list(shared_libs)
641orangeom_include_dirs = list(include_dirs)
[11665]642orangeom_library_dirs = []
[9185]643
[11665]644
645if site.qhull:
[9185]646    # Link external qhull library
[11665]647    orangeom_libraries += site.qhull.libraries
648    orangeom_include_dirs += site.qhull.include_dirs
649    orangeom_library_dirs += site.qhull.library_dirs
[9185]650else:
651    orangeom_sources += get_source_files("source/orangeom/qhull/", "c")
652    orangeom_include_dirs += ["source/orangeom"]
653
[11665]654orangeom_ext = PyXtractExtension(
655    "Orange.orangeom",
656    orangeom_sources,
657    include_dirs=orangeom_include_dirs + ["source/orange/"],
658    extra_compile_args=extra_compile_args + ["-DORANGEOM_EXPORTS"],
659    extra_link_args=extra_link_args,
660    libraries=orangeom_libraries,
661    library_dirs=orangeom_library_dirs
662 )
[9185]663
[11665]664orangene_ext = PyXtractExtension(
665    "Orange.orangene",
[9757]666    get_source_files("source/orangene/", exclude=["lib_vectors.cpp"]),
[11665]667    include_dirs=include_dirs + ["source/orange/"],
668    extra_compile_args=extra_compile_args + ["-DORANGENE_EXPORTS"],
669    extra_link_args=extra_link_args,
670    libraries=shared_libs,
671)
[9185]672
[11665]673corn_ext = Extension(
674    "Orange.corn", get_source_files("source/corn/"),
675    include_dirs=include_dirs + ["source/orange/"],
676    extra_compile_args=extra_compile_args + ["-DCORN_EXPORTS"],
677    extra_link_args=extra_link_args,
678    libraries=libraries
679)
[9185]680
[11665]681statc_ext = Extension(
682    "Orange.statc", get_source_files("source/statc/"),
683    include_dirs=include_dirs + ["source/orange/"],
684    extra_compile_args=extra_compile_args + ["-DSTATC_EXPORTS"],
685    extra_link_args=extra_link_args,
686    libraries=libraries
687)
[10433]688
[10792]689
[10793]690ext_modules = [include_ext, orange_ext, orangeom_ext,
691               orangene_ext, corn_ext, statc_ext]
692
693cmdclass = {"build": orange_build,
694            "build_ext": pyxtract_build_ext,
695            "install_lib": orange_install_lib,
696            "install": orange_install}
697                   
698if orangeqt_setup:
699    orangeqt_ext = orangeqt_setup.orangeqt_ext
700    # Fix relative paths, name etc.
701    orangeqt_ext.name = "Orange.orangeqt"
702    orangeqt_ext.sources = ["source/orangeqt/orangeqt.sip"] + \
703                           get_source_files("source/orangeqt", "cpp",
704                                exclude=["canvas3d.cpp", "plot3d.cpp", 
705                                         "glextensions.cpp"]
706                                            )
707
708    orangeqt_ext.include_dirs += ["source/orangeqt"]
709
710    ext_modules += [orangeqt_ext]
711
712    cmdclass["build_pyqt_ext"] = build_pyqt_ext
713
[10825]714def all_with_extension(path, extensions):
715    return [os.path.join(path, "*.%s"%extension) for extension in extensions]
[10792]716
[10825]717# TODO: Simply replace with include_package_data = True and configure missed files in MANIFEST.in?
[11085]718
719#Marko 20120128: Removed "doc/style.css", "doc/widgets/*/*.*" from the package
720
[10424]721def get_package_data():
722    package_data = {
723        "Orange":
[11085]724            ["orangerc.cfg" ] +\
725             all_with_extension(path="datasets", extensions=("tab", "csv", "basket")) +\
[10424]726             all_with_extension(path="testing/regression/tests_20", extensions=("net", "tab", "basket", "csv")),
[11173]727        "Orange.OrangeCanvas": ["icons/*.png", "icons/*.svg",
728                                "orngCanvas.pyw", "WidgetTabs.txt"],
729        "Orange.OrangeCanvas.styles": ["*.qss", "orange/*.svg"],
[11537]730        "Orange.OrangeCanvas.application.tutorials": ["*.ows"],
[11173]731        "Orange.OrangeWidgets": ["icons/*.png", "icons/backgrounds/*.png",
732                                 "report/index.html"],
733        "Orange.OrangeWidgets.Associate": ["icons/*.png", "icons/*.svg"],
734        "Orange.OrangeWidgets.Classify": ["icons/*.png", "icons/*.svg"],
735        "Orange.OrangeWidgets.Data": ["icons/*.png", "icons/*.svg"],
736        "Orange.OrangeWidgets.Evaluate": ["icons/*.png", "icons/*.svg"],
737        "Orange.OrangeWidgets.Prototypes": ["icons/*.png", "icons/*.svg"],
738        "Orange.OrangeWidgets.Regression": ["icons/*.png", "icons/*.svg"],
739        "Orange.OrangeWidgets.Unsupervised": ["icons/*.png", "icons/*.svg"],
740        "Orange.OrangeWidgets.Visualize": ["icons/*.png", "icons/*.svg"],
741        "Orange.OrangeWidgets.Visualize Qt": ["icons/*.png", "icons/*.svg"],
[10424]742        "Orange.OrangeWidgets.plot": ["*.gs", "*.vs"],
743        "Orange.OrangeWidgets.plot.primitives": ["*.obj"],
744    }
[10383]745
[10424]746    return package_data
[10383]747
[10424]748def hg_revision():
749    # Copied from numpy setup.py and modified to work with hg
750    def _minimal_ext_cmd(cmd):
751        # construct minimal environment
752        env = {}
753        for k in ['SYSTEMROOT', 'PATH']:
754            v = os.environ.get(k)
755            if v is not None:
756                env[k] = v
757        # LANGUAGE is used on win32
758        env['LANGUAGE'] = 'C'
759        env['LANG'] = 'C'
760        env['LC_ALL'] = 'C'
761        out = subprocess.Popen(cmd, stdout = subprocess.PIPE, env=env).communicate()[0]
762        return out
[9185]763
[10424]764    try:
765        out = _minimal_ext_cmd(['hg', 'ide', '-i'])
[10471]766        HG_REVISION = str(out.strip().decode('ascii'))
[10424]767    except OSError:
768        HG_REVISION = "Unknown"
[9185]769
[10424]770    return HG_REVISION
771
772def write_version_py(filename='Orange/version.py'):
773    # Copied from numpy setup.py
774    cnt = """
775# THIS FILE IS GENERATED FROM ORANGE SETUP.PY
776short_version = '%(version)s'
777version = '%(version)s'
778full_version = '%(full_version)s'
779hg_revision = '%(hg_revision)s'
780release = %(isrelease)s
781
782if not release:
783    version = full_version
784"""
785    FULLVERSION = VERSION
786    if os.path.exists('.hg'):
787        HG_REVISION = hg_revision()
788    elif os.path.exists('Orange/version.py'):
789        # must be a source distribution, use existing version file
[10471]790        version = imp.load_source("Orange.version", "Orange/version.py")
791        HG_REVISION = version.hg_revision
[10424]792    else:
793        HG_REVISION = "Unknown"
794
795    if not ISRELEASED:
796        FULLVERSION += '.dev-' + HG_REVISION[:7]
797
798    a = open(filename, 'w')
799    try:
800        a.write(cnt % {'version': VERSION,
801                       'full_version' : FULLVERSION,
802                       'hg_revision' : HG_REVISION,
803                       'isrelease': str(ISRELEASED)})
804    finally:
805        a.close()
806
[10825]807PACKAGES = find_packages()
808
809PACKAGE_DATA = get_package_data()
810
811SETUP_REQUIRES = (
[10880]812    'setuptools',
[10825]813)
814
[10991]815# If you change the requirements, check whether all ADD-ons still work!
816
[10825]817INSTALL_REQUIRES = (
[10880]818    'setuptools',
[10825]819    'numpy',
820)
821
822EXTRAS_REQUIRE = {
823    'GUI': (
824        'PyQt4',
825        'PyQwt',
826    ),
[10991]827    'reST': (
828        'numpydoc',
829    ),
[10825]830}
831
832DEPENDENCY_LINKS = (
833)
834
835ENTRY_POINTS = {
[11533]836    'gui_scripts': (
837            'orange-canvas = Orange.OrangeCanvas.main:main',
838    ),
[11264]839    'orange.canvas.help': (
840            'intersphinx = Orange.OrangeWidgets:intersphinx',
[11128]841    )
[10825]842}
[10792]843
[11264]844
[10424]845def setup_package():
846    write_version_py()
[10825]847    setup(
848        name = NAME,
849        version = VERSION,
850        description = DESCRIPTION,
851        long_description = LONG_DESCRIPTION,
852        author = AUTHOR,
853        author_email = AUTHOR_EMAIL,
854        url = URL,
855        download_url = DOWNLOAD_URL,
856        license = LICENSE,
857        keywords = KEYWORDS,
858        classifiers = CLASSIFIERS,
859        packages = PACKAGES,
860        package_data = PACKAGE_DATA,
861        setup_requires = SETUP_REQUIRES,
862        extras_require = EXTRAS_REQUIRE,
863        install_requires = INSTALL_REQUIRES,
864        dependency_links = DEPENDENCY_LINKS,
865        entry_points = ENTRY_POINTS,
866        include_package_data = True,
867        zip_safe = False,
[11580]868        test_suite = 'Orange.testing.unit.tests.test_suite',
[10825]869        cmdclass = cmdclass,
870        ext_modules = ext_modules,
871    )
[10424]872
873if __name__ == '__main__':
[10507]874    setup_package()
Note: See TracBrowser for help on using the repository browser.