source: orange/setup.py @ 11689:b3d7eae5e2c4

Revision 11689:b3d7eae5e2c4, 31.2 KB checked in by Ales Erjavec <ales.erjavec@…>, 7 months ago (diff)

Release 2.7.1

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