Beispiel #1
0
    def generate_numpyconfig_h(ext, build_dir):
        """Depends on config.h: generate_config_h has to be called before !"""
        target = join(build_dir,'numpyconfig.h')
        if newer(__file__,target):
            config_cmd = config.get_config_cmd()
            log.info('Generating %s',target)
            testcode = generate_numpyconfig_code(target)

            from distutils import sysconfig
            python_include = sysconfig.get_python_inc()
            python_h = join(python_include, 'Python.h')
            if not os.path.isfile(python_h):
                raise SystemError,\
                      "Non-existing %s. Perhaps you need to install"\
                      " python-dev|python-devel." % (python_h)

            config.numpy_include_dirs
            result = config_cmd.try_run(testcode,
                                include_dirs = [python_include] + \
                                                       config.numpy_include_dirs,
                                        library_dirs = default_lib_dirs)

            if not result:
                raise SystemError,"Failed to generate numpy configuration. "\
                      "See previous error messages for more information."

            print 'File: %s' % target
            target_f = open(target)
            print target_f.read()
            target_f.close()
            print 'EOF'
        config.add_data_files((header_dir, target))
        return target
def generate_a_pyrex_source(self, base, ext_name, source, extension):
    ''' Monkey patch for numpy build_src.build_src method

    Uses Cython instead of Pyrex.

    Assumes Cython is present
    '''
    if self.inplace:
        target_dir = dirname(base)
    else:
        target_dir = appendpath(self.build_src, dirname(base))
    target_file = pjoin(target_dir, ext_name + '.c')
    depends = [source] + extension.depends
    # add distribution (package-wide) include directories, in order to
    # pick up needed .pxd files for cython compilation
    incl_dirs = extension.include_dirs[:]
    dist_incl_dirs = self.distribution.include_dirs
    if not dist_incl_dirs is None:
        incl_dirs += dist_incl_dirs
    if self.force or newer_group(depends, target_file, 'newer'):
        import Cython.Compiler.Main
        log.info("cythonc:> %s" % (target_file))
        self.mkpath(target_dir)
        options = Cython.Compiler.Main.CompilationOptions(
            defaults=Cython.Compiler.Main.default_options,
            include_path=incl_dirs,
            output_file=target_file)
        cython_result = Cython.Compiler.Main.compile(source,
                                                   options=options)
        if cython_result.num_errors != 0:
            raise DistutilsError("%d errors while compiling %r with Cython" \
                  % (cython_result.num_errors, source))
    return target_file
Beispiel #3
0
def configuration(parent_package='',top_path=None):
    config = Configuration('f2py', parent_package, top_path)

    config.add_subpackage('lib')

    config.add_data_dir('docs')

    config.add_data_files('src/fortranobject.c',
                          'src/fortranobject.h',
                          'f2py.1'
                          )

    config.make_svn_version_py()

    def generate_f2py_py(build_dir):
        f2py_exe = 'f2py'+os.path.basename(sys.executable)[6:]
        if f2py_exe[-4:]=='.exe':
            f2py_exe = f2py_exe[:-4] + '.py'
        if 'bdist_wininst' in sys.argv and f2py_exe[-3:] != '.py':
            f2py_exe = f2py_exe + '.py'
        target = os.path.join(build_dir,f2py_exe)
        if newer(__file__,target):
            log.info('Creating %s', target)
            f = open(target,'w')
            f.write('''\
#!/usr/bin/env %s
# See http://cens.ioc.ee/projects/f2py2e/
import os, sys
for mode in ["g3-numpy", "2e-numeric", "2e-numarray", "2e-numpy"]:
    try:
        i=sys.argv.index("--"+mode)
        del sys.argv[i]
        break
    except ValueError: pass
os.environ["NO_SCIPY_IMPORT"]="f2py"
if mode=="g3-numpy":
    try:
        from main import main
    except ImportError:
        from numpy.f2py.lib.api import main
elif mode=="2e-numeric":
    from f2py2e import main
elif mode=="2e-numarray":
    sys.argv.append("-DNUMARRAY")
    from f2py2e import main
elif mode=="2e-numpy":
    from numpy.f2py import main
else:
    print >> sys.stderr, "Unknown mode:",`mode`
    sys.exit(1)
main()
'''%(os.path.basename(sys.executable)))
            f.close()
        return target

    config.add_scripts(generate_f2py_py)

    log.info('F2PY Version %s', config.get_version())

    return config
Beispiel #4
0
 def finalize_options(self):
     log.info("unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options")
     build_clib = self.get_finalized_command("build_clib")
     build_ext = self.get_finalized_command("build_ext")
     config = self.get_finalized_command("config")
     build = self.get_finalized_command("build")
     cmd_list = [self, config, build_clib, build_ext, build]
     for a in ["fcompiler"]:
         l = []
         for c in cmd_list:
             v = getattr(c, a)
             if v is not None:
                 if not isinstance(v, str):
                     v = v.compiler_type
                 if v not in l:
                     l.append(v)
         if not l:
             v1 = None
         else:
             v1 = l[0]
         if len(l) > 1:
             log.warn("  commands have different --%s options: %s" ", using first in list as default" % (a, l))
         if v1:
             for c in cmd_list:
                 if getattr(c, a) is None:
                     setattr(c, a, v1)
Beispiel #5
0
def CCompiler_show_customization(self):
    """
    Print the compiler customizations to stdout.

    Parameters
    ----------
    None

    Returns
    -------
    None

    Notes
    -----
    Printing is only done if the distutils log threshold is < 2.

    """
    if 0:
        for attrname in ['include_dirs','define','undef',
                         'libraries','library_dirs',
                         'rpath','link_objects']:
            attr = getattr(self,attrname,None)
            if not attr:
                continue
            log.info("compiler '%s' is set to %s" % (attrname,attr))
    try:
        self.get_version()
    except:
        pass
    if log._global_log.threshold<2:
        print(('*'*80))
        print((self.__class__))
        print((_compiler_to_string(self)))
        print(('*'*80))
Beispiel #6
0
def configuration(parent_package="", top_path=None):
    config = Configuration("f2py", parent_package, top_path)

    config.add_data_dir("tests")

    config.add_data_files("src/fortranobject.c", "src/fortranobject.h")

    config.make_svn_version_py()

    def generate_f2py_py(build_dir):
        f2py_exe = "f2py" + os.path.basename(sys.executable)[6:]
        if f2py_exe[-4:] == ".exe":
            f2py_exe = f2py_exe[:-4] + ".py"
        if "bdist_wininst" in sys.argv and f2py_exe[-3:] != ".py":
            f2py_exe = f2py_exe + ".py"
        target = os.path.join(build_dir, f2py_exe)
        if newer(__file__, target):
            log.info("Creating %s", target)
            f = open(target, "w")
            f.write(_get_f2py_shebang() + "\n")
            mainloc = os.path.join(os.path.dirname(__file__), "__main__.py")
            with open(mainloc) as mf:
                f.write(mf.read())
            f.close()
        return target

    config.add_scripts(generate_f2py_py)

    log.info("F2PY Version %s", config.get_version())

    return config
Beispiel #7
0
    def build_data_files_sources(self):
        if not self.data_files:
            return
        log.info("building data_files sources")
        from numpy.distutils.misc_util import get_data_files

        new_data_files = []
        for data in self.data_files:
            if isinstance(data, str):
                new_data_files.append(data)
            elif isinstance(data, tuple):
                d, files = data
                if self.inplace:
                    build_dir = self.get_package_dir(".".join(d.split(os.sep)))
                else:
                    build_dir = os.path.join(self.build_src, d)
                funcs = filter(lambda f: hasattr(f, "__call__"), files)
                files = filter(lambda f: not hasattr(f, "__call__"), files)
                for f in funcs:
                    if f.func_code.co_argcount == 1:
                        s = f(build_dir)
                    else:
                        s = f()
                    if s is not None:
                        if isinstance(s, list):
                            files.extend(s)
                        elif isinstance(s, str):
                            files.append(s)
                        else:
                            raise TypeError(repr(s))
                filenames = get_data_files((d, files))
                new_data_files.append((d, filenames))
            else:
                raise TypeError(repr(data))
        self.data_files[:] = new_data_files
Beispiel #8
0
    def generate_a_pyrex_source(self, base, ext_name, source, extension):
        if self.inplace or not have_pyrex():
            target_dir = os.path.dirname(base)
        else:
            target_dir = appendpath(self.build_src, os.path.dirname(base))
        target_file = os.path.join(target_dir, ext_name + ".c")
        depends = [source] + extension.depends
        if self.force or newer_group(depends, target_file, "newer"):
            if have_pyrex():
                import Pyrex.Compiler.Main

                log.info("pyrexc:> %s" % (target_file))
                self.mkpath(target_dir)
                options = Pyrex.Compiler.Main.CompilationOptions(
                    defaults=Pyrex.Compiler.Main.default_options,
                    include_path=extension.include_dirs,
                    output_file=target_file,
                )
                pyrex_result = Pyrex.Compiler.Main.compile(source, options=options)
                if pyrex_result.num_errors != 0:
                    raise DistutilsError("%d errors while compiling %r with Pyrex" % (pyrex_result.num_errors, source))
            elif os.path.isfile(target_file):
                log.warn(
                    "Pyrex required for compiling %r but not available," " using old target %r" % (source, target_file)
                )
            else:
                raise DistutilsError("Pyrex required for compiling %r" " but notavailable" % (source,))
        return target_file
Beispiel #9
0
    def build_npy_pkg_config(self):
        log.info("build_src: building npy-pkg config files")

        # XXX: another ugly workaround to circumvent distutils brain damage. We
        # need the install prefix here, but finalizing the options of the
        # install command when only building sources cause error. Instead, we
        # copy the install command instance, and finalize the copy so that it
        # does not disrupt how distutils want to do things when with the
        # original install command instance.
        install_cmd = copy.copy(get_cmd("install"))
        if not install_cmd.finalized == 1:
            install_cmd.finalize_options()
        build_npkg = False
        gd = {}
        if self.inplace == 1:
            top_prefix = "."
            build_npkg = True
        elif hasattr(install_cmd, "install_libbase"):
            top_prefix = install_cmd.install_libbase
            build_npkg = True

        if build_npkg:
            for pkg, infos in self.distribution.installed_pkg_config.items():
                pkg_path = os.path.join(*pkg.split("."))
                prefix = os.path.join(os.path.abspath(top_prefix), pkg_path)
                d = {"prefix": prefix}
                for info in infos:
                    install_dir, generated = self._build_npy_pkg_config(info, d, prefix)
                    self.distribution.data_files.append((install_dir, [generated]))
Beispiel #10
0
 def build_py_modules_sources(self):
     if not self.py_modules:
         return
     log.info('building py_modules sources')
     new_py_modules = []
     for source in self.py_modules:
         if is_sequence(source) and len(source)==3:
             package, module_base, source = source
             if self.inplace:
                 build_dir = self.get_package_dir(package)
             else:
                 build_dir = os.path.join(self.build_src,
                                          os.path.join(*package.split('.')))
             if hasattr(source, '__call__'):
                 target = os.path.join(build_dir, module_base + '.py')
                 source = source(target)
             if source is None:
                 continue
             modules = [(package, module_base, source)]
             if package not in self.py_modules_dict:
                 self.py_modules_dict[package] = []
             self.py_modules_dict[package] += modules
         else:
             new_py_modules.append(source)
     self.py_modules[:] = new_py_modules
Beispiel #11
0
def generate_a_cython_source(self, base, ext_name, source, extension):
        if self.inplace or not have_cython():
            target_dir = os.path.dirname(base)
        else:
            target_dir = appendpath(self.build_src, os.path.dirname(base))
        target_file = os.path.join(target_dir, ext_name + '.c')
        depends = [source] + extension.depends
        if self.force or newer_group(depends, target_file, 'newer'):
            if have_cython():
                import Cython.Compiler.Main
                log.info("cythonc:> %s: %s " % (target_dir, target_file))
                log.info("cwd %s " % (os.getcwd()))
                self.mkpath(target_dir)
                options = Cython.Compiler.Main.CompilationOptions(
                    defaults=Cython.Compiler.Main.default_options,
                    include_path=extension.include_dirs,
                    output_file=target_file
                    )
                #log.info('\n'.join([s + ' ' + str(getattr(options, s)) for s in dir(options)]))
                # avoid calling compile_single, because it will give wrong module names.
                cython_result = Cython.Compiler.Main.compile([source],
                                                           options=options)
                if cython_result.num_errors != 0:
                    raise DistutilsError("%d errors while compiling %r with Cython" \
                          % (cython_result.num_errors, source))
            elif os.path.isfile(target_file):
                log.warn("Cython required for compiling %r but not available,"\
                         " using old target %r"\
                         % (source, target_file))
            else:
                raise DistutilsError("Cython required for compiling %r"\
                                     " but notavailable" % (source,))
        return target_file
def CCompiler_customize(self, dist, need_cxx=0):
    # See FCompiler.customize for suggested usage.
    log.info('customize %s' % (self.__class__.__name__))
    customize_compiler(self)
    if need_cxx:
        # In general, distutils uses -Wstrict-prototypes, but this option is
        # not valid for C++ code, only for C.  Remove it if it's there to
        # avoid a spurious warning on every compilation.  All the default
        # options used by distutils can be extracted with:

        # from distutils import sysconfig
        # sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'BASECFLAGS',
        # 'CCSHARED', 'LDSHARED', 'SO')
        print "compiler options1:", self.compiler_so
        try:
            self.compiler_so.remove('-Wstrict-prototypes')
        except (AttributeError, ValueError):
            pass
        print "compiler options2:", self.compiler_so
        if hasattr(self,'compiler') and self.compiler[0].find('cc')>=0:
            if not self.compiler_cxx:
                if self.compiler[0].startswith('gcc'):
                    a, b = 'gcc', 'g++'
                else:
                    a, b = 'cc', 'c++'
                self.compiler_cxx = [self.compiler[0].replace(a,b)]\
                                    + self.compiler[1:]
        else:
            if hasattr(self,'compiler'):
                 log.warn("#### %s #######" % (self.compiler,))
            log.warn('Missing compiler_cxx fix for '+self.__class__.__name__)
    return
Beispiel #13
0
def _build_import_library_amd64():
    dll_file = find_python_dll()

    out_name = "libpython%d%d.a" % tuple(sys.version_info[:2])
    out_file = os.path.join(sys.prefix, 'libs', out_name)
    if os.path.isfile(out_file):
        log.debug('Skip building import library: "%s" exists' %
                  (out_file))
        return

    # didn't exist in virtualenv, maybe in base distribution?
    base_file = os.path.join(sys.base_prefix, 'libs', out_name)
    if os.path.isfile(base_file):
        log.debug('Skip building import library: "%s" exists', base_file)
        return

    def_name = "python%d%d.def" % tuple(sys.version_info[:2])
    def_file = os.path.join(sys.prefix, 'libs', def_name)

    log.info('Building import library (arch=AMD64): "%s" (from %s)' %
             (out_file, dll_file))

    generate_def(dll_file, def_file)

    cmd = ['dlltool', '-d', def_file, '-l', out_file]
    subprocess.Popen(cmd)
Beispiel #14
0
    def generate_a_pyrex_source(self, base, ext_name, source, extension):
        ''' Monkey patch for numpy build_src.build_src method

        Uses Cython instead of Pyrex, iff source contains 'pymor'

        Assumes Cython is present
        '''
        if 'pymor' not in source:
            return _orig_generate_a_pyrex_source(self, base, ext_name, source, extension)

        if self.inplace:
            target_dir = dirname(base)
        else:
            target_dir = appendpath(self.build_src, dirname(base))
        target_file = pjoin(target_dir, ext_name + '.c')
        depends = [source] + extension.depends
        if self.force or newer_group(depends, target_file, 'newer'):
            import Cython.Compiler.Main
            log.info("cythonc:> %s" % (target_file))
            self.mkpath(target_dir)
            options = Cython.Compiler.Main.CompilationOptions(
                defaults=Cython.Compiler.Main.default_options,
                include_path=extension.include_dirs,
                output_file=target_file)
            cython_result = Cython.Compiler.Main.compile(source, options=options)
            if cython_result.num_errors != 0:
                raise DistutilsError("%d errors while compiling %r with Cython"
                                     % (cython_result.num_errors, source))
        return target_file
Beispiel #15
0
def configuration(parent_package='',top_path=None):
    config = Configuration('f2py', parent_package, top_path)

    config.add_data_dir('tests')

    config.add_data_files('src/fortranobject.c',
                          'src/fortranobject.h',
                          )

    config.make_svn_version_py()

    def generate_f2py_py(build_dir):
        f2py_exe = 'f2py'+os.path.basename(sys.executable)[6:]
        if f2py_exe[-4:]=='.exe':
            f2py_exe = f2py_exe[:-4] + '.py'
        if 'bdist_wininst' in sys.argv and f2py_exe[-3:] != '.py':
            f2py_exe = f2py_exe + '.py'
        target = os.path.join(build_dir, f2py_exe)
        if newer(__file__, target):
            log.info('Creating %s', target)
            f = open(target, 'w')
            f.write('#!%s\n' % (sys.executable))
            mainloc = os.path.join(os.path.dirname(__file__), "__main__.py")
            with open(mainloc) as mf:
                f.write(mf.read())
            f.close()
        return target

    config.add_scripts(generate_f2py_py)

    log.info('F2PY Version %s', config.get_version())

    return config
Beispiel #16
0
def CCompiler_customize(self, dist, need_cxx=0):
    """
    Do any platform-specific customization of a compiler instance.

    This method calls `distutils.sysconfig.customize_compiler` for
    platform-specific customization, as well as optionally remove a flag
    to suppress spurious warnings in case C++ code is being compiled.

    Parameters
    ----------
    dist : object
        This parameter is not used for anything.
    need_cxx : bool, optional
        Whether or not C++ has to be compiled. If so (True), the
        ``"-Wstrict-prototypes"`` option is removed to prevent spurious
        warnings. Default is False.

    Returns
    -------
    None

    Notes
    -----
    All the default options used by distutils can be extracted with::

      from distutils import sysconfig
      sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'BASECFLAGS',
                                'CCSHARED', 'LDSHARED', 'SO')

    """
    # See FCompiler.customize for suggested usage.
    log.info('customize %s' % (self.__class__.__name__))
    customize_compiler(self)
    if need_cxx:
        # In general, distutils uses -Wstrict-prototypes, but this option is
        # not valid for C++ code, only for C.  Remove it if it's there to
        # avoid a spurious warning on every compilation.  All the default
        # options used by distutils can be extracted with:

        # from distutils import sysconfig
        # sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'BASECFLAGS',
        # 'CCSHARED', 'LDSHARED', 'SO')
        try:
            self.compiler_so.remove('-Wstrict-prototypes')
        except (AttributeError, ValueError):
            pass

        if hasattr(self,'compiler') and 'cc' in self.compiler[0]:
            if not self.compiler_cxx:
                if self.compiler[0].startswith('gcc'):
                    a, b = 'gcc', 'g++'
                else:
                    a, b = 'cc', 'c++'
                self.compiler_cxx = [self.compiler[0].replace(a,b)]\
                                    + self.compiler[1:]
        else:
            if hasattr(self,'compiler'):
                log.warn("#### %s #######" % (self.compiler,))
            log.warn('Missing compiler_cxx fix for '+self.__class__.__name__)
    return
Beispiel #17
0
def new_compiler (plat=None,
                  compiler=None,
                  verbose=0,
                  dry_run=0,
                  force=0):
    # Try first C compilers from numpy.distutils.
    if plat is None:
        plat = os.name
    try:
        if compiler is None:
            compiler = get_default_compiler(plat)
        (module_name, class_name, long_description) = compiler_class[compiler]
    except KeyError:
        msg = "don't know how to compile C/C++ code on platform '%s'" % plat
        if compiler is not None:
            msg = msg + " with '%s' compiler" % compiler
        raise DistutilsPlatformError, msg
    module_name = "numpy.distutils." + module_name
    try:
        __import__ (module_name)
    except ImportError, msg:
        log.info('%s in numpy.distutils; trying from distutils',
                 str(msg))
        module_name = module_name[6:]
        try:
            __import__(module_name)
        except ImportError, msg:
            raise DistutilsModuleError, \
                  "can't compile C/C++ code: unable to load module '%s'" % \
                  module_name
def _build_import_library_x86():
    """ Build the import libraries for Mingw32-gcc on Windows
    """
    lib_name = "python%d%d.lib" % tuple(sys.version_info[:2])
    lib_file = os.path.join(sys.prefix, 'libs', lib_name)
    out_name = "libpython%d%d.a" % tuple(sys.version_info[:2])
    out_file = os.path.join(sys.prefix, 'libs', out_name)
    if not os.path.isfile(lib_file):
        log.warn('Cannot build import library: "%s" not found' % (lib_file))
        return
    if os.path.isfile(out_file):
        log.debug('Skip building import library: "%s" exists' % (out_file))
        return
    log.info('Building import library (ARCH=x86): "%s"' % (out_file))

    from numpy.distutils import lib2def

    def_name = "python%d%d.def" % tuple(sys.version_info[:2])
    def_file = os.path.join(sys.prefix, 'libs', def_name)
    nm_cmd = '%s %s' % (lib2def.DEFAULT_NM, lib_file)
    nm_output = lib2def.getnm(nm_cmd)
    dlist, flist = lib2def.parse_nm(nm_output)
    lib2def.output_def(dlist, flist, lib2def.DEF_HEADER, open(def_file, 'w'))

    dll_name = "python%d%d.dll" % tuple(sys.version_info[:2])
    args = (dll_name, def_file, out_file)
    cmd = 'dlltool --dllname %s --def %s --output-lib %s' % args
    status = os.system(cmd)
    # for now, fail silently
    if status:
        log.warn('Failed to build import library for gcc. Linking will fail.')
    return
Beispiel #19
0
    def generate_numpyconfig_h(ext, build_dir):
        """Depends on config.h: generate_config_h has to be called before !"""
        target = join(build_dir,header_dir,'numpyconfig.h')
        d = os.path.dirname(target)
        if not os.path.exists(d):
            os.makedirs(d)
        if newer(__file__,target):
            config_cmd = config.get_config_cmd()
            log.info('Generating %s',target)

            # Check sizeof
            ignored, moredefs = cocache.check_types(config_cmd, ext, build_dir)

            if is_npy_no_signal():
                moredefs.append(('NPY_NO_SIGNAL', 1))

            if is_npy_no_smp():
                moredefs.append(('NPY_NO_SMP', 1))
            else:
                moredefs.append(('NPY_NO_SMP', 0))

            moredefs.extend(cocache.check_ieee_macros(config_cmd)[1])

            # Check wether we can use inttypes (C99) formats
            if config_cmd.check_decl('PRIdPTR', headers = ['inttypes.h']):
                moredefs.append(('NPY_USE_C99_FORMATS', 1))
            else:
                moredefs.append(('NPY_USE_C99_FORMATS', 0))

            # Inline check
            inline = config_cmd.check_inline()

            # Add moredefs to header
            target_f = open(target,'a')
            for d in moredefs:
                if isinstance(d,str):
                    target_f.write('#define %s\n' % (d))
                else:
                    target_f.write('#define %s %s\n' % (d[0],d[1]))

            # define NPY_INLINE to recognized keyword
            target_f.write('#define NPY_INLINE %s\n' % inline)

            # Define __STDC_FORMAT_MACROS
            target_f.write("""
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#endif
""")
            target_f.close()

            # Dump the numpyconfig.h header to stdout
            print 'File: %s' % target
            target_f = open(target)
            print target_f.read()
            target_f.close()
            print 'EOF'
        config.add_data_files((header_dir, target))
        return target
Beispiel #20
0
    def finalize_options(self):
        self.set_undefined_options('build',
                                   ('build_base', 'build_base'),
                                   ('build_lib', 'build_lib'),
                                   ('force', 'force'))
        if self.package is None:
            self.package = self.distribution.ext_package
        self.extensions = self.distribution.ext_modules
        self.libraries = self.distribution.libraries or []
        self.shared_libraries = self.distribution.shared_libraries or []
        self.py_modules = self.distribution.py_modules or []
        self.data_files = self.distribution.data_files or []

        if self.build_src is None:
            plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3])
            self.build_src = os.path.join(self.build_base, 'src'+plat_specifier)

        # py_modules_dict is used in build_py.find_package_modules
        self.py_modules_dict = {}

        if self.f2pyflags:
            if self.f2py_opts:
                log.warn('ignoring --f2pyflags as --f2py-opts already used')
            else:
                self.f2py_opts = self.f2pyflags
            self.f2pyflags = None
        if self.f2py_opts is None:
            self.f2py_opts = []
        else:
            self.f2py_opts = shlex.split(self.f2py_opts)

        if self.swigflags:
            if self.swig_opts:
                log.warn('ignoring --swigflags as --swig-opts already used')
            else:
                self.swig_opts = self.swigflags
            self.swigflags = None

        if self.swig_opts is None:
            self.swig_opts = []
        else:
            self.swig_opts = shlex.split(self.swig_opts)

        # use options from build_ext command
        build_ext = self.get_finalized_command('build_ext')
        if self.inplace is None:
            self.inplace = build_ext.inplace
        if self.swig_cpp is None:
            self.swig_cpp = build_ext.swig_cpp
        for c in ['swig', 'swig_opt']:
            o = '--'+c.replace('_', '-')
            v = getattr(build_ext, c, None)
            if v:
                if getattr(self, c):
                    log.warn('both build_src and build_ext define %s option' % (o))
                else:
                    log.info('using "%s=%s" option from build_ext command' % (o, v))
                    setattr(self, c, v)
Beispiel #21
0
def CCompiler_spawn(self, cmd, display=None):
    """
    Execute a command in a sub-process.

    Parameters
    ----------
    cmd : str
        The command to execute.
    display : str or sequence of str, optional
        The text to add to the log file kept by `numpy.distutils`.
        If not given, `display` is equal to `cmd`.

    Returns
    -------
    None

    Raises
    ------
    DistutilsExecError
        If the command failed, i.e. the exit status was not 0.

    """
    if display is None:
        display = cmd
        if is_sequence(display):
            display = ' '.join(list(display))
    log.info(display)
    try:
        subprocess.check_output(cmd)
    except subprocess.CalledProcessError as exc:
        o = exc.output
        s = exc.returncode
    except OSError:
        # OSError doesn't have the same hooks for the exception
        # output, but exec_command() historically would use an
        # empty string for EnvironmentError (base class for
        # OSError)
        o = b''
        # status previously used by exec_command() for parent
        # of OSError
        s = 127
    else:
        # use a convenience return here so that any kind of
        # caught exception will execute the default code after the
        # try / except block, which handles various exceptions
        return None

    if is_sequence(cmd):
        cmd = ' '.join(list(cmd))

    forward_bytes_to_stdout(o)

    if re.search(b'Too many open files', o):
        msg = '\nTry rerunning setup command until build succeeds.'
    else:
        msg = ''
    raise DistutilsExecError('Command "%s" failed with exit status %d%s' %
                            (cmd, s, msg))
def build_msvcr_library(debug=False):
    if os.name != 'nt':
        return False

    # If the version number is None, then we couldn't find the MSVC runtime at
    # all, because we are running on a Python distribution which is customed
    # compiled; trust that the compiler is the same as the one available to us
    # now, and that it is capable of linking with the correct runtime without
    # any extra options.
    msvcr_ver = msvc_runtime_major()
    if msvcr_ver is None:
        log.debug('Skip building import library: '
                  'Runtime is not compiled with MSVC')
        return False

    # Skip using a custom library for versions < MSVC 8.0
    if msvcr_ver < 80:
        log.debug('Skip building msvcr library:'
                  ' custom functionality not present')
        return False

    msvcr_name = msvc_runtime_library()
    if debug:
        msvcr_name += 'd'

    # Skip if custom library already exists
    out_name = "lib%s.a" % msvcr_name
    out_file = os.path.join(sys.prefix, 'libs', out_name)
    if os.path.isfile(out_file):
        log.debug('Skip building msvcr library: "%s" exists' %
                  (out_file,))
        return True

    # Find the msvcr dll
    msvcr_dll_name = msvcr_name + '.dll'
    dll_file = find_dll(msvcr_dll_name)
    if not dll_file:
        log.warn('Cannot build msvcr library: "%s" not found' %
                 msvcr_dll_name)
        return False

    def_name = "lib%s.def" % msvcr_name
    def_file = os.path.join(sys.prefix, 'libs', def_name)

    log.info('Building msvcr library: "%s" (from %s)' \
             % (out_file, dll_file))

    # Generate a symbol definition file from the msvcr dll
    generate_def(dll_file, def_file)

    # Create a custom mingw library for the given symbol definitions
    cmd = ['dlltool', '-d', def_file, '-l', out_file]
    retcode = subprocess.call(cmd)

    # Clean up symbol definitions
    os.remove(def_file)

    return (not retcode)
Beispiel #23
0
def configuration(parent_package='',top_path=None):
    config = Configuration('f2py', parent_package, top_path)

    config.add_data_dir('docs')
    config.add_data_dir('tests')

    config.add_data_files('src/fortranobject.c',
                          'src/fortranobject.h',
                          'f2py.1'
                          )

    config.make_svn_version_py()

    def generate_f2py_py(build_dir):
        f2py_exe = 'f2py'
        if f2py_exe[-4:]=='.exe':
            f2py_exe = f2py_exe[:-4] + '.py'
        if 'bdist_wininst' in sys.argv and f2py_exe[-3:] != '.py':
            f2py_exe = f2py_exe + '.py'
        target = os.path.join(build_dir, f2py_exe)
        if newer(__file__, target):
            log.info('Creating %s', target)
            f = open(target, 'w')
            f.write('''\
#!/opt/local/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
# See http://cens.ioc.ee/projects/f2py2e/
import os, sys
for mode in ["g3-numpy", "2e-numeric", "2e-numarray", "2e-numpy"]:
    try:
        i=sys.argv.index("--"+mode)
        del sys.argv[i]
        break
    except ValueError: pass
os.environ["NO_SCIPY_IMPORT"]="f2py"
if mode=="g3-numpy":
    sys.stderr.write("G3 f2py support is not implemented, yet.\\n")
    sys.exit(1)
elif mode=="2e-numeric":
    from f2py2e import main
elif mode=="2e-numarray":
    sys.argv.append("-DNUMARRAY")
    from f2py2e import main
elif mode=="2e-numpy":
    from numpy.f2py import main
else:
    sys.stderr.write("Unknown mode: " + repr(mode) + "\\n")
    sys.exit(1)
main()
''')
            f.close()
        return target

    config.add_scripts(generate_f2py_py)

    log.info('F2PY Version %s', config.get_version())

    return config
Beispiel #24
0
    def generate_numpyconfig_h(ext, build_dir):
        """Depends on config.h: generate_config_h has to be called before !"""
        target = join(build_dir,header_dir,'_numpyconfig.h')
        d = dirname(target)
        if not exists(d):
            os.makedirs(d)
        if newer(__file__,target):
            config_cmd = config.get_config_cmd()
            log.info('Generating %s',target)
            moredefs = []

            if is_npy_no_signal():
                moredefs.append(('NPY_NO_SIGNAL', 1))

            if is_npy_no_smp():
                moredefs.append(('NPY_NO_SMP', 1))
            else:
                moredefs.append(('NPY_NO_SMP', 0))

            mathlibs = check_mathlib(config_cmd)

            # Check wether we can use inttypes (C99) formats
            if config_cmd.check_decl('PRIdPTR', headers = ['inttypes.h']):
                moredefs.append(('NPY_USE_C99_FORMATS', 1))

            # visibility check
            hidden_visibility = visibility_define(config_cmd)
            moredefs.append(('NPY_VISIBILITY_HIDDEN', hidden_visibility))

            # Add the C API/ABI versions
            moredefs.append(('NUMPY_ABI_VERSION', '2.0.0'))
            moredefs.append(('NUMPY_API_VERSION', '2.0.0'))

            # Add moredefs to header
            target_f = open(target, 'w')
            for d in moredefs:
                if isinstance(d,str):
                    target_f.write('#define %s\n' % (d))
                else:
                    target_f.write('#define %s %s\n' % (d[0],d[1]))

            # Define __STDC_FORMAT_MACROS
            target_f.write("""
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#endif
""")
            target_f.close()

            # Dump the numpyconfig.h header to stdout
            print('File: %s' % target)
            target_f = open(target)
            print(target_f.read())
            target_f.close()
            print('EOF')
        config.add_data_files((header_dir, target))
        return target
Beispiel #25
0
    def finalize_options(self):
        self.set_undefined_options(
            "build", ("build_base", "build_base"), ("build_lib", "build_lib"), ("force", "force")
        )
        if self.package is None:
            self.package = self.distribution.ext_package
        self.extensions = self.distribution.ext_modules
        self.libraries = self.distribution.libraries or []
        self.py_modules = self.distribution.py_modules or []
        self.data_files = self.distribution.data_files or []

        if self.build_src is None:
            plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3])
            self.build_src = os.path.join(self.build_base, "src" + plat_specifier)

        # py_modules_dict is used in build_py.find_package_modules
        self.py_modules_dict = {}

        if self.f2pyflags:
            if self.f2py_opts:
                log.warn("ignoring --f2pyflags as --f2py-opts already used")
            else:
                self.f2py_opts = self.f2pyflags
            self.f2pyflags = None
        if self.f2py_opts is None:
            self.f2py_opts = []
        else:
            self.f2py_opts = shlex.split(self.f2py_opts)

        if self.swigflags:
            if self.swig_opts:
                log.warn("ignoring --swigflags as --swig-opts already used")
            else:
                self.swig_opts = self.swigflags
            self.swigflags = None

        if self.swig_opts is None:
            self.swig_opts = []
        else:
            self.swig_opts = shlex.split(self.swig_opts)

        # use options from build_ext command
        build_ext = self.get_finalized_command("build_ext")
        if self.inplace is None:
            self.inplace = build_ext.inplace
        if self.swig_cpp is None:
            self.swig_cpp = build_ext.swig_cpp
        for c in ["swig", "swig_opt"]:
            o = "--" + c.replace("_", "-")
            v = getattr(build_ext, c, None)
            if v:
                if getattr(self, c):
                    log.warn("both build_src and build_ext define %s option" % (o))
                else:
                    log.info('using "%s=%s" option from build_ext command' % (o, v))
                    setattr(self, c, v)
Beispiel #26
0
 def generate_api(ext, build_dir):
     script = join(codegen_dir, module_name + ".py")
     sys.path.insert(0, codegen_dir)
     try:
         m = __import__(module_name)
         log.info("executing %s", script)
         h_file, c_file, doc_file = m.generate_api(os.path.join(build_dir, header_dir))
     finally:
         del sys.path[0]
     config.add_data_files((header_dir, h_file), (header_dir, doc_file))
     return (h_file,)
Beispiel #27
0
def get_default_fcompiler(osname=None, platform=None, requiref90=False,
                          c_compiler=None):
    """Determine the default Fortran compiler to use for the given
    platform."""
    matching_compiler_types = available_fcompilers_for_platform(osname,
                                                                platform)
    log.info("get_default_fcompiler: matching types: '%s'",
             matching_compiler_types)
    compiler_type =  _find_existing_fcompiler(matching_compiler_types,
                                              osname=osname,
                                              platform=platform,
                                              requiref90=requiref90,
                                              c_compiler=c_compiler)
    return compiler_type
Beispiel #28
0
def build_msvcr_library(debug=False):
    if os.name != 'nt':
        return False

    msvcr_name = msvc_runtime_library()

    # Skip using a custom library for versions < MSVC 8.0
    msvcr_ver = msvc_runtime_major()
    if msvcr_ver and msvcr_ver < 80:
        log.debug('Skip building msvcr library:'
                  ' custom functionality not present')
        return False

    if debug:
        msvcr_name += 'd'

    # Skip if custom library already exists
    out_name = "lib%s.a" % msvcr_name
    out_file = os.path.join(sys.prefix, 'libs', out_name)
    if os.path.isfile(out_file):
        log.debug('Skip building msvcr library: "%s" exists' %
                  (out_file,))
        return True

    # Find the msvcr dll
    msvcr_dll_name = msvcr_name + '.dll'
    dll_file = find_dll(msvcr_dll_name)
    if not dll_file:
        log.warn('Cannot build msvcr library: "%s" not found' %
                 msvcr_dll_name)
        return False

    def_name = "lib%s.def" % msvcr_name
    def_file = os.path.join(sys.prefix, 'libs', def_name)

    log.info('Building msvcr library: "%s" (from %s)' \
             % (out_file, dll_file))

    # Generate a symbol definition file from the msvcr dll
    generate_def(dll_file, def_file)

    # Create a custom mingw library for the given symbol definitions
    cmd = ['dlltool', '-d', def_file, '-l', out_file]
    retcode = subprocess.call(cmd)

    # Clean up symbol definitions
    os.remove(def_file)

    return (not retcode)
Beispiel #29
0
    def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
        """Compile 'src' to product 'obj'."""
        src_flags = {}
        if is_f_file(src) and not has_f90_header(src):
            flavor = ':f77'
            compiler = self.compiler_f77
            src_flags = get_f77flags(src)
            extra_compile_args = self.extra_f77_compile_args or []
        elif is_free_format(src):
            flavor = ':f90'
            compiler = self.compiler_f90
            if compiler is None:
                raise DistutilsExecError('f90 not supported by %s needed for %s'\
                      % (self.__class__.__name__, src))
            extra_compile_args = self.extra_f90_compile_args or []
        else:
            flavor = ':fix'
            compiler = self.compiler_fix
            if compiler is None:
                raise DistutilsExecError('f90 (fixed) not supported by %s needed for %s'\
                      % (self.__class__.__name__, src))
            extra_compile_args = self.extra_f90_compile_args or []
        if self.object_switch[-1]==' ':
            o_args = [self.object_switch.strip(), obj]
        else:
            o_args = [self.object_switch.strip()+obj]

        assert self.compile_switch.strip()
        s_args = [self.compile_switch, src]

        if extra_compile_args:
            log.info('extra %s options: %r' \
                     % (flavor[1:], ' '.join(extra_compile_args)))

        extra_flags = src_flags.get(self.compiler_type, [])
        if extra_flags:
            log.info('using compile options from source: %r' \
                     % ' '.join(extra_flags))

        command = compiler + cc_args + extra_flags + s_args + o_args \
                  + extra_postargs + extra_compile_args

        display = '%s: %s' % (os.path.basename(compiler[0]) + flavor,
                              src)
        try:
            self.spawn(command, display=display)
        except DistutilsExecError:
            msg = str(get_exception())
            raise CompileError(msg)
Beispiel #30
0
        def generate_a_script(build_dir, script=script, config=config):
            dist = config.get_distribution()
            install_lib = dist.get_command_obj('install_lib')
            if not install_lib.finalized:
                install_lib.finalize_options()

            script_replace_text = ''
            install_lib = install_lib.install_dir
            if install_lib is not None:
                script_replace_text = '''
import sys
if %(d)r not in sys.path:
    sys.path.insert(0, %(d)r)
''' % dict(d=install_lib)
            if multiprocessing is not None:
                mp_install_lib = dirname(dirname(multiprocessing.__file__))
                script_replace_text += '''
if %(d)r not in sys.path:
    sys.path.insert(0, %(d)r)
''' % dict(d=mp_install_lib)

            start_mark = '### START UPDATE SYS.PATH ###'
            end_mark = '### END UPDATE SYS.PATH ###'
            name = basename(script)
            if name.startswith (script_prefix):
                target_name = name
            elif wininst:
                target_name = script_prefix + '_' + name
            else:
                target_name = script_prefix + '.' + splitext(name)[0]
            target = join(build_dir, target_name)
            if newer(script, target) or 1:
                log.info('Creating %r', target)
                f = open (script, 'r')
                text = f.read()
                f.close()

                i = text.find(start_mark)
                if i != -1:
                    j = text.find (end_mark)
                    if j == -1:
                        log.warn ("%r missing %r line", script, start_mark)
                    new_text = text[:i+len (start_mark)] + script_replace_text + text[j:]
                else:
                    new_text = text

                f = open(target, 'w')
                f.write(new_text)
                f.close()
Beispiel #31
0
    def swig_sources(self, sources, extension):
        # Assuming SWIG 1.3.14 or later. See compatibility note in
        #   http://www.swig.org/Doc1.3/Python.html#Python_nn6

        new_sources = []
        swig_sources = []
        swig_targets = {}
        target_dirs = []
        py_files = []  # swig generated .py files
        target_ext = '.c'
        if '-c++' in extension.swig_opts:
            typ = 'c++'
            is_cpp = True
            extension.swig_opts.remove('-c++')
        elif self.swig_cpp:
            typ = 'c++'
            is_cpp = True
        else:
            typ = None
            is_cpp = False
        skip_swig = 0
        ext_name = extension.name.split('.')[-1]

        for source in sources:
            (base, ext) = os.path.splitext(source)
            if ext == '.i':  # SWIG interface file
                # the code below assumes that the sources list
                # contains not more than one .i SWIG interface file
                if self.inplace:
                    target_dir = os.path.dirname(base)
                    py_target_dir = self.ext_target_dir
                else:
                    target_dir = appendpath(self.build_src,
                                            os.path.dirname(base))
                    py_target_dir = target_dir
                if os.path.isfile(source):
                    name = get_swig_modulename(source)
                    if name != ext_name[1:]:
                        raise DistutilsSetupError(
                            'mismatch of extension names: %s provides %r'
                            ' but expected %r' % (source, name, ext_name[1:]))
                    if typ is None:
                        typ = get_swig_target(source)
                        is_cpp = typ == 'c++'
                    else:
                        typ2 = get_swig_target(source)
                        if typ2 is None:
                            log.warn('source %r does not define swig target, assuming %s swig target' \
                                     % (source, typ))
                        elif typ != typ2:
                            log.warn('expected %r but source %r defines %r swig target' \
                                     % (typ, source, typ2))
                            if typ2 == 'c++':
                                log.warn(
                                    'resetting swig target to c++ (some targets may have .c extension)'
                                )
                                is_cpp = True
                            else:
                                log.warn(
                                    'assuming that %r has c++ swig target' %
                                    (source))
                    if is_cpp:
                        target_ext = '.cpp'
                    target_file = os.path.join(target_dir, '%s_wrap%s' \
                                               % (name, target_ext))
                else:
                    log.warn('  source %s does not exist: skipping swig\'ing.' \
                             % (source))
                    name = ext_name[1:]
                    skip_swig = 1
                    target_file = _find_swig_target(target_dir, name)
                    if not os.path.isfile(target_file):
                        log.warn('  target %s does not exist:\n   ' \
                                 'Assuming %s_wrap.{c,cpp} was generated with ' \
                                 '"build_src --inplace" command.' \
                                 % (target_file, name))
                        target_dir = os.path.dirname(base)
                        target_file = _find_swig_target(target_dir, name)
                        if not os.path.isfile(target_file):
                            raise DistutilsSetupError("%r missing" %
                                                      (target_file, ))
                        log.warn('   Yes! Using %r as up-to-date target.' \
                                 % (target_file))
                target_dirs.append(target_dir)
                new_sources.append(target_file)
                py_files.append(os.path.join(py_target_dir, name + '.py'))
                swig_sources.append(source)
                swig_targets[source] = new_sources[-1]
            else:
                new_sources.append(source)

        if not swig_sources:
            return new_sources

        if skip_swig:
            return new_sources + py_files

        for d in target_dirs:
            self.mkpath(d)

        swig = self.swig or self.find_swig()
        swig_cmd = [swig, "-python"] + extension.swig_opts
        if is_cpp:
            swig_cmd.append('-c++')
        for d in extension.include_dirs:
            swig_cmd.append('-I' + d)
        for source in swig_sources:
            target = swig_targets[source]
            depends = [source] + extension.depends
            if self.force or newer_group(depends, target, 'newer'):
                log.info("%s: %s" % (os.path.basename(swig) \
                                     + (is_cpp and '++' or ''), source))
                self.spawn(swig_cmd + self.swig_opts \
                           + ["-o", target, '-outdir', py_target_dir, source])
            else:
                log.debug("  skipping '%s' swig interface (up-to-date)" \
                          % (source))

        return new_sources + py_files
Beispiel #32
0
def swig_sources(self, sources, extension):
    # Assuming SWIG 1.3.14 or later. See compatibility note in
    #   http://www.swig.org/Doc1.3/Python.html#Python_nn6

    new_sources = []
    swig_sources = []
    swig_targets = {}
    target_dirs = []
    py_files = []  # swig generated .py files
    target_ext = ".c"
    if self.swig_cpp:
        typ = "c++"
        is_cpp = True
    else:
        typ = None
        is_cpp = False
    skip_swig = 0
    ext_name = extension.name.split(".")[-1]

    for source in sources:
        (base, ext) = os.path.splitext(source)
        if ext == ".i":  # SWIG interface file
            if self.inplace:
                target_dir = os.path.dirname(base)
                py_target_dir = self.ext_target_dir
            else:
                target_dir = appendpath(self.build_src, os.path.dirname(base))
                py_target_dir = target_dir
            if os.path.isfile(source):
                name = get_swig_modulename(source)
                # 				if name != ext_name:
                # 					raise DistutilsSetupError(
                # 						'mismatch of extension names: %s provides %r'
                # 						' but expected %r' % (source, name, ext_name))
                if typ is None:
                    typ = get_swig_target(source)
                    is_cpp = typ == "c++"
                    if is_cpp:
                        target_ext = ".cpp"
                else:
                    typ2 = get_swig_target(source)
                    if typ != typ2:
                        log.warn(
                            "expected %r but source %r defines %r swig target"
                            % (typ, source, typ2))
                        if typ2 == "c++":
                            log.warn(
                                "resetting swig target to c++ (some targets may have .c extension)"
                            )
                            is_cpp = True
                            target_ext = ".cpp"
                        else:
                            log.warn("assuming that %r has c++ swig target" %
                                     (source))
                target_file = os.path.join(target_dir,
                                           "%s_wrap%s" % (name, target_ext))
            else:
                log.warn("  source %s does not exist: skipping swig'ing." %
                         (source))
                name = ext_name
                skip_swig = 1
                target_file = _find_swig_target(target_dir, name)
                if not os.path.isfile(target_file):
                    log.warn((
                        "target {} does not exist:\n" +
                        "Assuming {}_wrap.{c,cpp} was generated with 'build_src --inplace' command."
                    ).format(target_file, name))
                    target_dir = os.path.dirname(base)
                    target_file = _find_swig_target(target_dir, name)
                    if not os.path.isfile(target_file):
                        raise DistutilsSetupError("%r missing" %
                                                  (target_file, ))
                    log.warn("   Yes! Using %r as up-to-date target." %
                             (target_file))
            target_dirs.append(target_dir)
            new_sources.append(target_file)
            # py_files.append(os.path.join(py_target_dir, name+'.py'))
            swig_sources.append(source)
            swig_targets[source] = new_sources[-1]
        else:
            new_sources.append(source)

    if not swig_sources:
        return new_sources

    if skip_swig:
        return new_sources + py_files

    for d in target_dirs:
        self.mkpath(d)

    swig = self.swig or self.find_swig()
    swig_cmd = [swig, "-python"] + extension.swig_opts
    if is_cpp:
        swig_cmd.append("-c++")
    for d in extension.include_dirs:
        swig_cmd.append("-I" + d)
    for source in swig_sources:
        target = swig_targets[source]
        depends = [source] + extension.depends
        if self.force or newer_group(depends, target, "newer"):
            log.info("%s: %s" % (os.path.basename(swig) +
                                 (is_cpp and "++" or ""), source))
            self.spawn(swig_cmd + self.swig_opts +
                       ["-o", target, "-outdir", py_target_dir, source])
        else:
            log.debug("  skipping '%s' swig interface (up-to-date)" % (source))

    return new_sources + py_files
Beispiel #33
0
    def run(self):
        if not self.extensions:
            return

        # Make sure that extension sources are complete.
        self.run_command('build_src')

        if self.distribution.has_c_libraries():
            if self.inplace:
                if self.distribution.have_run.get('build_clib'):
                    log.warn('build_clib already run, it is too late to '
                             'ensure in-place build of build_clib')
                    build_clib = self.distribution.get_command_obj(
                        'build_clib')
                else:
                    build_clib = self.distribution.get_command_obj(
                        'build_clib')
                    build_clib.inplace = 1
                    build_clib.ensure_finalized()
                    build_clib.run()
                    self.distribution.have_run['build_clib'] = 1

            else:
                self.run_command('build_clib')
                build_clib = self.get_finalized_command('build_clib')
            self.library_dirs.append(build_clib.build_clib)
        else:
            build_clib = None

        # Not including C libraries to the list of
        # extension libraries automatically to prevent
        # bogus linking commands. Extensions must
        # explicitly specify the C libraries that they use.

        from distutils.ccompiler import new_compiler
        from numpy.distutils.fcompiler import new_fcompiler

        compiler_type = self.compiler
        # Initialize C compiler:
        self.compiler = new_compiler(compiler=compiler_type,
                                     verbose=self.verbose,
                                     dry_run=self.dry_run,
                                     force=self.force)
        self.compiler.customize(self.distribution)
        self.compiler.customize_cmd(self)

        if self.warn_error:
            self.compiler.compiler.append('-Werror')
            self.compiler.compiler_so.append('-Werror')

        self.compiler.show_customization()

        # Setup directory for storing generated extra DLL files on Windows
        self.extra_dll_dir = os.path.join(self.build_temp, '.libs')
        if not os.path.isdir(self.extra_dll_dir):
            os.makedirs(self.extra_dll_dir)

        # Create mapping of libraries built by build_clib:
        clibs = {}
        if build_clib is not None:
            for libname, build_info in build_clib.libraries or []:
                if libname in clibs and clibs[libname] != build_info:
                    log.warn('library %r defined more than once,'
                             ' overwriting build_info\n%s... \nwith\n%s...' %
                             (libname, repr(clibs[libname])[:300],
                              repr(build_info)[:300]))
                clibs[libname] = build_info
        # .. and distribution libraries:
        for libname, build_info in self.distribution.libraries or []:
            if libname in clibs:
                # build_clib libraries have a precedence before distribution ones
                continue
            clibs[libname] = build_info

        # Determine if C++/Fortran 77/Fortran 90 compilers are needed.
        # Update extension libraries, library_dirs, and macros.
        all_languages = set()
        for ext in self.extensions:
            ext_languages = set()
            c_libs = []
            c_lib_dirs = []
            macros = []
            for libname in ext.libraries:
                if libname in clibs:
                    binfo = clibs[libname]
                    c_libs += binfo.get('libraries', [])
                    c_lib_dirs += binfo.get('library_dirs', [])
                    for m in binfo.get('macros', []):
                        if m not in macros:
                            macros.append(m)

                for l in clibs.get(libname, {}).get('source_languages', []):
                    ext_languages.add(l)
            if c_libs:
                new_c_libs = ext.libraries + c_libs
                log.info('updating extension %r libraries from %r to %r' %
                         (ext.name, ext.libraries, new_c_libs))
                ext.libraries = new_c_libs
                ext.library_dirs = ext.library_dirs + c_lib_dirs
            if macros:
                log.info('extending extension %r defined_macros with %r' %
                         (ext.name, macros))
                ext.define_macros = ext.define_macros + macros

            # determine extension languages
            if has_f_sources(ext.sources):
                ext_languages.add('f77')
            if has_cxx_sources(ext.sources):
                ext_languages.add('c++')
            l = ext.language or self.compiler.detect_language(ext.sources)
            if l:
                ext_languages.add(l)
            # reset language attribute for choosing proper linker
            if 'c++' in ext_languages:
                ext_language = 'c++'
            elif 'f90' in ext_languages:
                ext_language = 'f90'
            elif 'f77' in ext_languages:
                ext_language = 'f77'
            else:
                ext_language = 'c'  # default
            if l and l != ext_language and ext.language:
                log.warn('resetting extension %r language from %r to %r.' %
                         (ext.name, l, ext_language))
            ext.language = ext_language
            # global language
            all_languages.update(ext_languages)

        need_f90_compiler = 'f90' in all_languages
        need_f77_compiler = 'f77' in all_languages
        need_cxx_compiler = 'c++' in all_languages

        # Initialize C++ compiler:
        if need_cxx_compiler:
            self._cxx_compiler = new_compiler(compiler=compiler_type,
                                              verbose=self.verbose,
                                              dry_run=self.dry_run,
                                              force=self.force)
            compiler = self._cxx_compiler
            compiler.customize(self.distribution, need_cxx=need_cxx_compiler)
            compiler.customize_cmd(self)
            compiler.show_customization()
            self._cxx_compiler = compiler.cxx_compiler()
        else:
            self._cxx_compiler = None

        # Initialize Fortran 77 compiler:
        if need_f77_compiler:
            ctype = self.fcompiler
            self._f77_compiler = new_fcompiler(compiler=self.fcompiler,
                                               verbose=self.verbose,
                                               dry_run=self.dry_run,
                                               force=self.force,
                                               requiref90=False,
                                               c_compiler=self.compiler)
            fcompiler = self._f77_compiler
            if fcompiler:
                ctype = fcompiler.compiler_type
                fcompiler.customize(self.distribution)
            if fcompiler and fcompiler.get_version():
                fcompiler.customize_cmd(self)
                fcompiler.show_customization()
            else:
                self.warn('f77_compiler=%s is not available.' % (ctype))
                self._f77_compiler = None
        else:
            self._f77_compiler = None

        # Initialize Fortran 90 compiler:
        if need_f90_compiler:
            ctype = self.fcompiler
            self._f90_compiler = new_fcompiler(compiler=self.fcompiler,
                                               verbose=self.verbose,
                                               dry_run=self.dry_run,
                                               force=self.force,
                                               requiref90=True,
                                               c_compiler=self.compiler)
            fcompiler = self._f90_compiler
            if fcompiler:
                ctype = fcompiler.compiler_type
                fcompiler.customize(self.distribution)
            if fcompiler and fcompiler.get_version():
                fcompiler.customize_cmd(self)
                fcompiler.show_customization()
            else:
                self.warn('f90_compiler=%s is not available.' % (ctype))
                self._f90_compiler = None
        else:
            self._f90_compiler = None

        # Build extensions
        self.build_extensions()

        # Copy over any extra DLL files
        # FIXME: In the case where there are more than two packages,
        # we blindly assume that both packages need all of the libraries,
        # resulting in a larger wheel than is required. This should be fixed,
        # but it's so rare that I won't bother to handle it.
        pkg_roots = {
            self.get_ext_fullname(ext.name).split('.')[0]
            for ext in self.extensions
        }
        for pkg_root in pkg_roots:
            shared_lib_dir = os.path.join(pkg_root, '.libs')
            if not self.inplace:
                shared_lib_dir = os.path.join(self.build_lib, shared_lib_dir)
            for fn in os.listdir(self.extra_dll_dir):
                if not os.path.isdir(shared_lib_dir):
                    os.makedirs(shared_lib_dir)
                if not fn.lower().endswith('.dll'):
                    continue
                runtime_lib = os.path.join(self.extra_dll_dir, fn)
                copy_file(runtime_lib, shared_lib_dir)
Beispiel #34
0
def exec_command( command,
                  execute_in='', use_shell=None, use_tee = None,
                  _with_python = 1,
                  **env ):
    """ Return (status,output) of executed command.

    command is a concatenated string of executable and arguments.
    The output contains both stdout and stderr messages.
    The following special keyword arguments can be used:
      use_shell - execute `sh -c command`
      use_tee   - pipe the output of command through tee
      execute_in - before run command `cd execute_in` and after `cd -`.

    On NT, DOS systems the returned status is correct for external commands.
    Wild cards will not work for non-posix systems or when use_shell=0.
    """
    if isinstance(command, str):
        log.info(command)
    else:
        log.info(' '.join(command))

    log.debug('exec_command(%r,%s)' % (command,
                  ','.join(['%s=%r'%kv for kv in env.items()])))

    if use_tee is None:
        use_tee = os.name=='posix'
    if use_shell is None:
        use_shell = os.name=='posix'
    execute_in = os.path.abspath(execute_in)
    oldcwd = os.path.abspath(os.getcwd())

    if __name__[-12:] == 'exec_command':
        exec_dir = os.path.dirname(os.path.abspath(__file__))
    elif os.path.isfile('exec_command.py'):
        exec_dir = os.path.abspath('.')
    else:
        exec_dir = os.path.abspath(sys.argv[0])
        if os.path.isfile(exec_dir):
            exec_dir = os.path.dirname(exec_dir)

    if oldcwd!=execute_in:
        os.chdir(execute_in)
        log.debug('New cwd: %s' % execute_in)
    else:
        log.debug('Retaining cwd: %s' % oldcwd)

    oldenv = _preserve_environment( env.keys() )
    _update_environment( **env )

    try:
        # _exec_command is robust but slow, it relies on
        # usable sys.std*.fileno() descriptors. If they
        # are bad (like in win32 Idle, PyCrust environments)
        # then _exec_command_python (even slower)
        # will be used as a last resort.
        #
        # _exec_command_posix uses os.system and is faster
        # but not on all platforms os.system will return
        # a correct status.
        if _with_python and (0 or sys.__stdout__.fileno()==-1):
            st = _exec_command_python(command,
                                      exec_command_dir = exec_dir,
                                      **env)
        elif os.name=='posix':
            st = _exec_command_posix(command,
                                     use_shell=use_shell,
                                     use_tee=use_tee,
                                     **env)
        else:
            st = _exec_command(command, use_shell=use_shell,
                               use_tee=use_tee,**env)
    finally:
        if oldcwd!=execute_in:
            os.chdir(oldcwd)
            log.debug('Restored cwd to %s' % oldcwd)
        _update_environment(**oldenv)

    return st
Beispiel #35
0
    ("linux.*", "pathcc"),
    ("nt", "intelw"),
    ("nt", "intelemw"),
)

if sys.platform == "win32":
    compiler_class["mingw32"] = (
        "mingw32ccompiler",
        "Mingw32CCompiler",
        "Mingw32 port of GNU C Compiler for Win32"
        "(for MSC built Python)",
    )
    if mingw32():
        # On windows platforms, we want to default to mingw32 (gcc)
        # because msvc can't build blitz stuff.
        log.info("Setting mingw32 as default compiler for nt.")
        ccompiler._default_compilers = (
            ("nt", "mingw32"), ) + ccompiler._default_compilers

_distutils_new_compiler = new_compiler


def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):
    # Try first C compilers from numpy.distutils.
    if plat is None:
        plat = os.name
    try:
        if compiler is None:
            compiler = get_default_compiler(plat)
        (module_name, class_name, long_description) = compiler_class[compiler]
    except KeyError:
Beispiel #36
0
    def build_extension(self, ext):
        sources = ext.sources
        if sources is None or not is_sequence(sources):
            raise DistutilsSetupError(
                ("in 'ext_modules' option (extension '%s'), " +
                 "'sources' must be present and must be " +
                 "a list of source filenames") % ext.name)
        sources = list(sources)

        if not sources:
            return

        fullname = self.get_ext_fullname(ext.name)
        if self.inplace:
            modpath = fullname.split('.')
            package = '.'.join(modpath[0:-1])
            base = modpath[-1]
            build_py = self.get_finalized_command('build_py')
            package_dir = build_py.get_package_dir(package)
            ext_filename = os.path.join(package_dir,
                                        self.get_ext_filename(base))
        else:
            ext_filename = os.path.join(self.build_lib,
                                        self.get_ext_filename(fullname))
        depends = sources + ext.depends

        if not (self.force or newer_group(depends, ext_filename, 'newer')):
            log.debug("skipping '%s' extension (up-to-date)", ext.name)
            return
        else:
            log.info("building '%s' extension", ext.name)

        extra_args = ext.extra_compile_args or []
        macros = ext.define_macros[:]
        for undef in ext.undef_macros:
            macros.append((undef, ))

        c_sources, cxx_sources, f_sources, fmodule_sources = \
                   filter_sources(ext.sources)

        if self.compiler.compiler_type == 'msvc':
            if cxx_sources:
                # Needed to compile kiva.agg._agg extension.
                extra_args.append('/Zm1000')
            # this hack works around the msvc compiler attributes
            # problem, msvc uses its own convention :(
            c_sources += cxx_sources
            cxx_sources = []

        # Set Fortran/C++ compilers for compilation and linking.
        if ext.language == 'f90':
            fcompiler = self._f90_compiler
        elif ext.language == 'f77':
            fcompiler = self._f77_compiler
        else:  # in case ext.language is c++, for instance
            fcompiler = self._f90_compiler or self._f77_compiler
        if fcompiler is not None:
            fcompiler.extra_f77_compile_args = (
                ext.extra_f77_compile_args or []) if hasattr(
                    ext, 'extra_f77_compile_args') else []
            fcompiler.extra_f90_compile_args = (
                ext.extra_f90_compile_args or []) if hasattr(
                    ext, 'extra_f90_compile_args') else []
        cxx_compiler = self._cxx_compiler

        # check for the availability of required compilers
        if cxx_sources and cxx_compiler is None:
            raise DistutilsError("extension %r has C++ sources" \
                  "but no C++ compiler found" % (ext.name))
        if (f_sources or fmodule_sources) and fcompiler is None:
            raise DistutilsError("extension %r has Fortran sources " \
                  "but no Fortran compiler found" % (ext.name))
        if ext.language in ['f77', 'f90'] and fcompiler is None:
            self.warn("extension %r has Fortran libraries " \
                  "but no Fortran linker found, using default linker" % (ext.name))
        if ext.language == 'c++' and cxx_compiler is None:
            self.warn("extension %r has C++ libraries " \
                  "but no C++ linker found, using default linker" % (ext.name))

        kws = {'depends': ext.depends}
        output_dir = self.build_temp

        include_dirs = ext.include_dirs + get_numpy_include_dirs()

        c_objects = []
        if c_sources:
            log.info("compiling C sources")
            c_objects = self.compiler.compile(c_sources,
                                              output_dir=output_dir,
                                              macros=macros,
                                              include_dirs=include_dirs,
                                              debug=self.debug,
                                              extra_postargs=extra_args,
                                              **kws)

        if cxx_sources:
            log.info("compiling C++ sources")
            c_objects += cxx_compiler.compile(cxx_sources,
                                              output_dir=output_dir,
                                              macros=macros,
                                              include_dirs=include_dirs,
                                              debug=self.debug,
                                              extra_postargs=extra_args,
                                              **kws)

        extra_postargs = []
        f_objects = []
        if fmodule_sources:
            log.info("compiling Fortran 90 module sources")
            module_dirs = ext.module_dirs[:]
            module_build_dir = os.path.join(
                self.build_temp,
                os.path.dirname(self.get_ext_filename(fullname)))

            self.mkpath(module_build_dir)
            if fcompiler.module_dir_switch is None:
                existing_modules = glob('*.mod')
            extra_postargs += fcompiler.module_options(module_dirs,
                                                       module_build_dir)
            f_objects += fcompiler.compile(fmodule_sources,
                                           output_dir=self.build_temp,
                                           macros=macros,
                                           include_dirs=include_dirs,
                                           debug=self.debug,
                                           extra_postargs=extra_postargs,
                                           depends=ext.depends)

            if fcompiler.module_dir_switch is None:
                for f in glob('*.mod'):
                    if f in existing_modules:
                        continue
                    t = os.path.join(module_build_dir, f)
                    if os.path.abspath(f) == os.path.abspath(t):
                        continue
                    if os.path.isfile(t):
                        os.remove(t)
                    try:
                        self.move_file(f, module_build_dir)
                    except DistutilsFileError:
                        log.warn('failed to move %r to %r' %
                                 (f, module_build_dir))
        if f_sources:
            log.info("compiling Fortran sources")
            f_objects += fcompiler.compile(f_sources,
                                           output_dir=self.build_temp,
                                           macros=macros,
                                           include_dirs=include_dirs,
                                           debug=self.debug,
                                           extra_postargs=extra_postargs,
                                           depends=ext.depends)

        objects = c_objects + f_objects

        if ext.extra_objects:
            objects.extend(ext.extra_objects)
        extra_args = ext.extra_link_args or []
        libraries = self.get_libraries(ext)[:]
        library_dirs = ext.library_dirs[:]

        linker = self.compiler.link_shared_object
        # Always use system linker when using MSVC compiler.
        if self.compiler.compiler_type == 'msvc':
            # expand libraries with fcompiler libraries as we are
            # not using fcompiler linker
            self._libs_with_msvc_and_fortran(fcompiler, libraries,
                                             library_dirs)

        elif ext.language in ['f77', 'f90'] and fcompiler is not None:
            linker = fcompiler.link_shared_object
        if ext.language == 'c++' and cxx_compiler is not None:
            linker = cxx_compiler.link_shared_object

        linker(objects,
               ext_filename,
               libraries=libraries,
               library_dirs=library_dirs,
               runtime_library_dirs=ext.runtime_library_dirs,
               extra_postargs=extra_args,
               export_symbols=self.get_export_symbols(ext),
               debug=self.debug,
               build_temp=self.build_temp,
               target_lang=ext.language)
Beispiel #37
0
    def run(self):
        if not self.extensions:
            return

        # Make sure that extension sources are complete.
        self.run_command('build_src')

        if self.distribution.has_c_libraries():
            if self.inplace:
                if self.distribution.have_run.get('build_clib'):
                    log.warn('build_clib already run, it is too late to ' \
                            'ensure in-place build of build_clib')
                    build_clib = self.distribution.get_command_obj(
                        'build_clib')
                else:
                    build_clib = self.distribution.get_command_obj(
                        'build_clib')
                    build_clib.inplace = 1
                    build_clib.ensure_finalized()
                    build_clib.run()
                    self.distribution.have_run['build_clib'] = 1

            else:
                self.run_command('build_clib')
                build_clib = self.get_finalized_command('build_clib')
            self.library_dirs.append(build_clib.build_clib)
        else:
            build_clib = None

        # Not including C libraries to the list of
        # extension libraries automatically to prevent
        # bogus linking commands. Extensions must
        # explicitly specify the C libraries that they use.

        from distutils.ccompiler import new_compiler
        from numpy.distutils.fcompiler import new_fcompiler

        compiler_type = self.compiler
        # Initialize C compiler:
        self.compiler = new_compiler(compiler=compiler_type,
                                     verbose=self.verbose,
                                     dry_run=self.dry_run,
                                     force=self.force)
        self.compiler.customize(self.distribution)
        self.compiler.customize_cmd(self)
        self.compiler.show_customization()

        # Create mapping of libraries built by build_clib:
        clibs = {}
        if build_clib is not None:
            for libname, build_info in build_clib.libraries or []:
                if libname in clibs and clibs[libname] != build_info:
                    log.warn('library %r defined more than once,'\
                             ' overwriting build_info\n%s... \nwith\n%s...' \
                             % (libname, repr(clibs[libname])[:300], repr(build_info)[:300]))
                clibs[libname] = build_info
        # .. and distribution libraries:
        for libname, build_info in self.distribution.libraries or []:
            if libname in clibs:
                # build_clib libraries have a precedence before distribution ones
                continue
            clibs[libname] = build_info

        # Determine if C++/Fortran 77/Fortran 90 compilers are needed.
        # Update extension libraries, library_dirs, and macros.
        all_languages = set()
        for ext in self.extensions:
            ext_languages = set()
            c_libs = []
            c_lib_dirs = []
            macros = []
            for libname in ext.libraries:
                if libname in clibs:
                    binfo = clibs[libname]
                    c_libs += binfo.get('libraries', [])
                    c_lib_dirs += binfo.get('library_dirs', [])
                    for m in binfo.get('macros', []):
                        if m not in macros:
                            macros.append(m)

                for l in clibs.get(libname, {}).get('source_languages', []):
                    ext_languages.add(l)
            if c_libs:
                new_c_libs = ext.libraries + c_libs
                log.info('updating extension %r libraries from %r to %r' %
                         (ext.name, ext.libraries, new_c_libs))
                ext.libraries = new_c_libs
                ext.library_dirs = ext.library_dirs + c_lib_dirs
            if macros:
                log.info('extending extension %r defined_macros with %r' %
                         (ext.name, macros))
                ext.define_macros = ext.define_macros + macros

            # determine extension languages
            if has_f_sources(ext.sources):
                ext_languages.add('f77')
            if has_cxx_sources(ext.sources):
                ext_languages.add('c++')
            l = ext.language or self.compiler.detect_language(ext.sources)
            if l:
                ext_languages.add(l)
            # reset language attribute for choosing proper linker
            if 'c++' in ext_languages:
                ext_language = 'c++'
            elif 'f90' in ext_languages:
                ext_language = 'f90'
            elif 'f77' in ext_languages:
                ext_language = 'f77'
            else:
                ext_language = 'c'  # default
            if l and l != ext_language and ext.language:
                log.warn('resetting extension %r language from %r to %r.' %
                         (ext.name, l, ext_language))
            ext.language = ext_language
            # global language
            all_languages.update(ext_languages)

        need_f90_compiler = 'f90' in all_languages
        need_f77_compiler = 'f77' in all_languages
        need_cxx_compiler = 'c++' in all_languages

        # Initialize C++ compiler:
        if need_cxx_compiler:
            self._cxx_compiler = new_compiler(compiler=compiler_type,
                                              verbose=self.verbose,
                                              dry_run=self.dry_run,
                                              force=self.force)
            compiler = self._cxx_compiler
            compiler.customize(self.distribution, need_cxx=need_cxx_compiler)
            compiler.customize_cmd(self)
            compiler.show_customization()
            self._cxx_compiler = compiler.cxx_compiler()
        else:
            self._cxx_compiler = None

        # Initialize Fortran 77 compiler:
        if need_f77_compiler:
            ctype = self.fcompiler
            self._f77_compiler = new_fcompiler(compiler=self.fcompiler,
                                               verbose=self.verbose,
                                               dry_run=self.dry_run,
                                               force=self.force,
                                               requiref90=False,
                                               c_compiler=self.compiler)
            fcompiler = self._f77_compiler
            if fcompiler:
                ctype = fcompiler.compiler_type
                fcompiler.customize(self.distribution)
            if fcompiler and fcompiler.get_version():
                fcompiler.customize_cmd(self)
                fcompiler.show_customization()
            else:
                self.warn('f77_compiler=%s is not available.' % (ctype))
                self._f77_compiler = None
        else:
            self._f77_compiler = None

        # Initialize Fortran 90 compiler:
        if need_f90_compiler:
            ctype = self.fcompiler
            self._f90_compiler = new_fcompiler(compiler=self.fcompiler,
                                               verbose=self.verbose,
                                               dry_run=self.dry_run,
                                               force=self.force,
                                               requiref90=True,
                                               c_compiler=self.compiler)
            fcompiler = self._f90_compiler
            if fcompiler:
                ctype = fcompiler.compiler_type
                fcompiler.customize(self.distribution)
            if fcompiler and fcompiler.get_version():
                fcompiler.customize_cmd(self)
                fcompiler.show_customization()
            else:
                self.warn('f90_compiler=%s is not available.' % (ctype))
                self._f90_compiler = None
        else:
            self._f90_compiler = None

        # Build extensions
        self.build_extensions()
    def build_extension(self, ext):
        sources = ext.sources
        if sources is None or not is_sequence(sources):
            raise DistutilsSetupError(
                ("in 'ext_modules' option (extension '%s'), " +
                 "'sources' must be present and must be " +
                 "a list of source filenames") % ext.name)
        sources = list(sources)

        if not sources:
            return

        fullname = self.get_ext_fullname(ext.name)
        if self.inplace:
            modpath = fullname.split(".")
            package = ".".join(modpath[0:-1])
            base = modpath[-1]
            build_py = self.get_finalized_command("build_py")
            package_dir = build_py.get_package_dir(package)
            ext_filename = os.path.join(package_dir,
                                        self.get_ext_filename(base))
        else:
            ext_filename = os.path.join(self.build_lib,
                                        self.get_ext_filename(fullname))
        depends = sources + ext.depends

        if not (self.force or newer_group(depends, ext_filename, "newer")):
            log.debug("skipping '%s' extension (up-to-date)", ext.name)
            return
        else:
            log.info("building '%s' extension", ext.name)

        extra_args = ext.extra_compile_args or []
        macros = ext.define_macros[:]
        for undef in ext.undef_macros:
            macros.append((undef, ))

        c_sources, cxx_sources, f_sources, fmodule_sources = filter_sources(
            ext.sources)

        if self.compiler.compiler_type == "msvc":
            if cxx_sources:
                # Needed to compile kiva.agg._agg extension.
                extra_args.append("/Zm1000")
            # this hack works around the msvc compiler attributes
            # problem, msvc uses its own convention :(
            c_sources += cxx_sources
            cxx_sources = []

        # Set Fortran/C++ compilers for compilation and linking.
        if ext.language == "f90":
            fcompiler = self._f90_compiler
        elif ext.language == "f77":
            fcompiler = self._f77_compiler
        else:  # in case ext.language is c++, for instance
            fcompiler = self._f90_compiler or self._f77_compiler
        if fcompiler is not None:
            fcompiler.extra_f77_compile_args = ((
                ext.extra_f77_compile_args or []) if hasattr(
                    ext, "extra_f77_compile_args") else [])
            fcompiler.extra_f90_compile_args = ((
                ext.extra_f90_compile_args or []) if hasattr(
                    ext, "extra_f90_compile_args") else [])
        cxx_compiler = self._cxx_compiler

        # check for the availability of required compilers
        if cxx_sources and cxx_compiler is None:
            raise DistutilsError("extension %r has C++ sources"
                                 "but no C++ compiler found" % (ext.name))
        if (f_sources or fmodule_sources) and fcompiler is None:
            raise DistutilsError("extension %r has Fortran sources "
                                 "but no Fortran compiler found" % (ext.name))
        if ext.language in ["f77", "f90"] and fcompiler is None:
            self.warn("extension %r has Fortran libraries "
                      "but no Fortran linker found, using default linker" %
                      (ext.name))
        if ext.language == "c++" and cxx_compiler is None:
            self.warn("extension %r has C++ libraries "
                      "but no C++ linker found, using default linker" %
                      (ext.name))

        kws = {"depends": ext.depends}
        output_dir = self.build_temp

        include_dirs = ext.include_dirs + get_numpy_include_dirs()

        # filtering C dispatch-table sources when optimization is not disabled,
        # otherwise treated as normal sources.
        copt_c_sources = []
        copt_baseline_flags = []
        copt_macros = []
        if not self.disable_optimization:
            bsrc_dir = self.get_finalized_command("build_src").build_src
            dispatch_hpath = os.path.join("numpy", "distutils", "include")
            dispatch_hpath = os.path.join(bsrc_dir, dispatch_hpath)
            include_dirs.append(dispatch_hpath)

            copt_build_src = None if self.inplace else bsrc_dir
            copt_c_sources = [
                c_sources.pop(c_sources.index(src)) for src in c_sources[:]
                if src.endswith(".dispatch.c")
            ]
            copt_baseline_flags = self.compiler_opt.cpu_baseline_flags()
        else:
            copt_macros.append(("NPY_DISABLE_OPTIMIZATION", 1))

        c_objects = []
        if copt_c_sources:
            log.info("compiling C dispatch-able sources")
            c_objects += self.compiler_opt.try_dispatch(
                copt_c_sources,
                output_dir=output_dir,
                src_dir=copt_build_src,
                macros=macros + copt_macros,
                include_dirs=include_dirs,
                debug=self.debug,
                extra_postargs=extra_args,
                **kws)
        if c_sources:
            log.info("compiling C sources")
            c_objects += self.compiler.compile(c_sources,
                                               output_dir=output_dir,
                                               macros=macros + copt_macros,
                                               include_dirs=include_dirs,
                                               debug=self.debug,
                                               extra_postargs=extra_args +
                                               copt_baseline_flags,
                                               **kws)
        if cxx_sources:
            log.info("compiling C++ sources")
            c_objects += cxx_compiler.compile(cxx_sources,
                                              output_dir=output_dir,
                                              macros=macros + copt_macros,
                                              include_dirs=include_dirs,
                                              debug=self.debug,
                                              extra_postargs=extra_args +
                                              copt_baseline_flags,
                                              **kws)

        extra_postargs = []
        f_objects = []
        if fmodule_sources:
            log.info("compiling Fortran 90 module sources")
            module_dirs = ext.module_dirs[:]
            module_build_dir = os.path.join(
                self.build_temp,
                os.path.dirname(self.get_ext_filename(fullname)))

            self.mkpath(module_build_dir)
            if fcompiler.module_dir_switch is None:
                existing_modules = glob("*.mod")
            extra_postargs += fcompiler.module_options(module_dirs,
                                                       module_build_dir)
            f_objects += fcompiler.compile(
                fmodule_sources,
                output_dir=self.build_temp,
                macros=macros,
                include_dirs=include_dirs,
                debug=self.debug,
                extra_postargs=extra_postargs,
                depends=ext.depends,
            )

            if fcompiler.module_dir_switch is None:
                for f in glob("*.mod"):
                    if f in existing_modules:
                        continue
                    t = os.path.join(module_build_dir, f)
                    if os.path.abspath(f) == os.path.abspath(t):
                        continue
                    if os.path.isfile(t):
                        os.remove(t)
                    try:
                        self.move_file(f, module_build_dir)
                    except DistutilsFileError:
                        log.warn("failed to move %r to %r" %
                                 (f, module_build_dir))
        if f_sources:
            log.info("compiling Fortran sources")
            f_objects += fcompiler.compile(
                f_sources,
                output_dir=self.build_temp,
                macros=macros,
                include_dirs=include_dirs,
                debug=self.debug,
                extra_postargs=extra_postargs,
                depends=ext.depends,
            )

        if f_objects and not fcompiler.can_ccompiler_link(self.compiler):
            unlinkable_fobjects = f_objects
            objects = c_objects
        else:
            unlinkable_fobjects = []
            objects = c_objects + f_objects

        if ext.extra_objects:
            objects.extend(ext.extra_objects)
        extra_args = ext.extra_link_args or []
        libraries = self.get_libraries(ext)[:]
        library_dirs = ext.library_dirs[:]

        linker = self.compiler.link_shared_object
        # Always use system linker when using MSVC compiler.
        if self.compiler.compiler_type in ("msvc", "intelw", "intelemw"):
            # expand libraries with fcompiler libraries as we are
            # not using fcompiler linker
            self._libs_with_msvc_and_fortran(fcompiler, libraries,
                                             library_dirs)

        elif ext.language in ["f77", "f90"] and fcompiler is not None:
            linker = fcompiler.link_shared_object
        if ext.language == "c++" and cxx_compiler is not None:
            linker = cxx_compiler.link_shared_object

        if fcompiler is not None:
            objects, libraries = self._process_unlinkable_fobjects(
                objects, libraries, fcompiler, library_dirs,
                unlinkable_fobjects)

        linker(
            objects,
            ext_filename,
            libraries=libraries,
            library_dirs=library_dirs,
            runtime_library_dirs=ext.runtime_library_dirs,
            extra_postargs=extra_args,
            export_symbols=self.get_export_symbols(ext),
            debug=self.debug,
            build_temp=self.build_temp,
            target_lang=ext.language,
        )
Beispiel #39
0
 def report():
     log.info("\n########### EXT COMPILER OPTIMIZATION ###########")
     log.info(self.compiler_opt.report(full=True))
Beispiel #40
0
    def generate_config_h(ext, build_dir):
        target = join(build_dir, header_dir, 'config.h')
        d = os.path.dirname(target)
        if not os.path.exists(d):
            os.makedirs(d)

        if newer(__file__, target):
            config_cmd = config.get_config_cmd()
            log.info('Generating %s', target)

            # Check that the toolchain works, to fail early if it doesn't
            # (avoid late errors with MATHLIB which are confusing if the
            # compiler does not work).
            config_cmd.try_link('int main(void) { return 0;}')

            # Check sizeof
            moredefs, ignored = cocache.check_types(config_cmd, ext, build_dir)

            # Check math library and C99 math funcs availability
            mathlibs = check_mathlib(config_cmd)
            moredefs.append(('MATHLIB', ','.join(mathlibs)))

            check_math_capabilities(config_cmd, moredefs, mathlibs)
            moredefs.extend(cocache.check_ieee_macros(config_cmd)[0])

            # Signal check
            if is_npy_no_signal():
                moredefs.append('__NPY_PRIVATE_NO_SIGNAL')

            # Windows checks
            if sys.platform == 'win32' or os.name == 'nt':
                win32_checks(moredefs)

            # Inline check
            inline = config_cmd.check_inline()

            # Check whether we need our own wide character support
            if not config_cmd.check_decl('Py_UNICODE_WIDE',
                                         headers=['Python.h']):
                PYTHON_HAS_UNICODE_WIDE = True
            else:
                PYTHON_HAS_UNICODE_WIDE = False

            if ENABLE_SEPARATE_COMPILATION:
                moredefs.append(('ENABLE_SEPARATE_COMPILATION', 1))

            # Generate the config.h file from moredefs
            target_f = open(target, 'w')
            for d in moredefs:
                if isinstance(d, str):
                    target_f.write('#define %s\n' % (d))
                else:
                    target_f.write('#define %s %s\n' % (d[0], d[1]))

            # define inline to our keyword, or nothing
            target_f.write('#ifndef __cplusplus\n')
            if inline == 'inline':
                target_f.write('/* #undef inline */\n')
            else:
                target_f.write('#define inline %s\n' % inline)
            target_f.write('#endif\n')

            target_f.close()
            print 'File:', target
            target_f = open(target)
            print target_f.read()
            target_f.close()
            print 'EOF'
        else:
            mathlibs = []
            target_f = open(target)
            for line in target_f.readlines():
                s = '#define MATHLIB'
                if line.startswith(s):
                    value = line[len(s):].strip()
                    if value:
                        mathlibs.extend(value.split(','))
            target_f.close()

        # Ugly: this can be called within a library and not an extension,
        # in which case there is no libraries attributes (and none is
        # needed).
        if hasattr(ext, 'libraries'):
            ext.libraries.extend(mathlibs)

        incl_dir = os.path.dirname(target)
        if incl_dir not in config.numpy_include_dirs:
            config.numpy_include_dirs.append(incl_dir)

        return target
Beispiel #41
0
def CCompiler_spawn(self, cmd, display=None):
    """
    Execute a command in a sub-process.

    Parameters
    ----------
    cmd : str
        The command to execute.
    display : str or sequence of str, optional
        The text to add to the log file kept by `numpy.distutils`.
        If not given, `display` is equal to `cmd`.

    Returns
    -------
    None

    Raises
    ------
    DistutilsExecError
        If the command failed, i.e. the exit status was not 0.

    """
    if display is None:
        display = cmd
        if is_sequence(display):
            display = ' '.join(list(display))
    log.info(display)
    try:
        if self.verbose:
            subprocess.check_output(cmd)
        else:
            subprocess.check_output(cmd, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as exc:
        o = exc.output
        s = exc.returncode
    except OSError:
        # OSError doesn't have the same hooks for the exception
        # output, but exec_command() historically would use an
        # empty string for EnvironmentError (base class for
        # OSError)
        o = b''
        # status previously used by exec_command() for parent
        # of OSError
        s = 127
    else:
        # use a convenience return here so that any kind of
        # caught exception will execute the default code after the
        # try / except block, which handles various exceptions
        return None

    if is_sequence(cmd):
        cmd = ' '.join(list(cmd))

    if self.verbose:
        forward_bytes_to_stdout(o)

    if re.search(b'Too many open files', o):
        msg = '\nTry rerunning setup command until build succeeds.'
    else:
        msg = ''
    raise DistutilsExecError('Command "%s" failed with exit status %d%s' %
                             (cmd, s, msg))
Beispiel #42
0
def CCompiler_compile(self,
                      sources,
                      output_dir=None,
                      macros=None,
                      include_dirs=None,
                      debug=0,
                      extra_preargs=None,
                      extra_postargs=None,
                      depends=None):
    """
    Compile one or more source files.

    Please refer to the Python distutils API reference for more details.

    Parameters
    ----------
    sources : list of str
        A list of filenames
    output_dir : str, optional
        Path to the output directory.
    macros : list of tuples
        A list of macro definitions.
    include_dirs : list of str, optional
        The directories to add to the default include file search path for
        this compilation only.
    debug : bool, optional
        Whether or not to output debug symbols in or alongside the object
        file(s).
    extra_preargs, extra_postargs : ?
        Extra pre- and post-arguments.
    depends : list of str, optional
        A list of file names that all targets depend on.

    Returns
    -------
    objects : list of str
        A list of object file names, one per source file `sources`.

    Raises
    ------
    CompileError
        If compilation fails.

    """
    # This method is effective only with Python >=2.3 distutils.
    # Any changes here should be applied also to fcompiler.compile
    # method to support pre Python 2.3 distutils.
    global _job_semaphore

    jobs = get_num_build_jobs()

    # setup semaphore to not exceed number of compile jobs when parallelized at
    # extension level (python >= 3.5)
    with _global_lock:
        if _job_semaphore is None:
            _job_semaphore = threading.Semaphore(jobs)

    if not sources:
        return []
    # FIXME:RELATIVE_IMPORT
    if sys.version_info[0] < 3:
        from .fcompiler import FCompiler, is_f_file, has_f90_header
    else:
        from numpy.distutils.fcompiler import (FCompiler, is_f_file,
                                               has_f90_header)
    if isinstance(self, FCompiler):
        display = []
        for fc in ['f77', 'f90', 'fix']:
            fcomp = getattr(self, 'compiler_' + fc)
            if fcomp is None:
                continue
            display.append("Fortran %s compiler: %s" % (fc, ' '.join(fcomp)))
        display = '\n'.join(display)
    else:
        ccomp = self.compiler_so
        display = "C compiler: %s\n" % (' '.join(ccomp), )
    log.info(display)
    macros, objects, extra_postargs, pp_opts, build = \
            self._setup_compile(output_dir, macros, include_dirs, sources,
                                depends, extra_postargs)
    cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
    display = "compile options: '%s'" % (' '.join(cc_args))
    if extra_postargs:
        display += "\nextra options: '%s'" % (' '.join(extra_postargs))
    log.info(display)

    def single_compile(args):
        obj, (src, ext) = args
        if not _needs_build(obj, cc_args, extra_postargs, pp_opts):
            return

        # check if we are currently already processing the same object
        # happens when using the same source in multiple extensions
        while True:
            # need explicit lock as there is no atomic check and add with GIL
            with _global_lock:
                # file not being worked on, start working
                if obj not in _processing_files:
                    _processing_files.add(obj)
                    break
            # wait for the processing to end
            time.sleep(0.1)

        try:
            # retrieve slot from our #job semaphore and build
            with _job_semaphore:
                self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
        finally:
            # register being done processing
            with _global_lock:
                _processing_files.remove(obj)

    if isinstance(self, FCompiler):
        objects_to_build = list(build.keys())
        f77_objects, other_objects = [], []
        for obj in objects:
            if obj in objects_to_build:
                src, ext = build[obj]
                if self.compiler_type == 'absoft':
                    obj = cyg2win32(obj)
                    src = cyg2win32(src)
                if is_f_file(src) and not has_f90_header(src):
                    f77_objects.append((obj, (src, ext)))
                else:
                    other_objects.append((obj, (src, ext)))

        # f77 objects can be built in parallel
        build_items = f77_objects
        # build f90 modules serial, module files are generated during
        # compilation and may be used by files later in the list so the
        # ordering is important
        for o in other_objects:
            single_compile(o)
    else:
        build_items = build.items()

    if len(build) > 1 and jobs > 1:
        # build parallel
        import multiprocessing.pool
        pool = multiprocessing.pool.ThreadPool(jobs)
        pool.map(single_compile, build_items)
        pool.close()
    else:
        # build serial
        for o in build_items:
            single_compile(o)

    # Return *all* object filenames, not just the ones we just built.
    return objects
Beispiel #43
0
    def generate_config_h(ext, build_dir):
        target = join(build_dir, header_dir, 'config.h')
        d = os.path.dirname(target)
        if not os.path.exists(d):
            os.makedirs(d)

        if newer(__file__, target):
            config_cmd = config.get_config_cmd()
            log.info('Generating %s', target)

            # Check sizeof
            moredefs, ignored = cocache.check_types(config_cmd, ext, build_dir)

            # Check math library and C99 math funcs availability
            mathlibs = check_mathlib(config_cmd)
            moredefs.append(('MATHLIB', ','.join(mathlibs)))

            check_math_capabilities(config_cmd, moredefs, mathlibs)
            moredefs.extend(cocache.check_ieee_macros(config_cmd)[0])
            moredefs.extend(cocache.check_complex(config_cmd, mathlibs)[0])

            # Signal check
            if is_npy_no_signal():
                moredefs.append('__NPY_PRIVATE_NO_SIGNAL')

            # Windows checks
            if sys.platform == 'win32' or os.name == 'nt':
                win32_checks(moredefs)

            # C99 restrict keyword
            moredefs.append(('NPY_RESTRICT', config_cmd.check_restrict()))

            # Inline check
            inline = config_cmd.check_inline()

            # Use relaxed stride checking
            if NPY_RELAXED_STRIDES_CHECKING:
                moredefs.append(('NPY_RELAXED_STRIDES_CHECKING', 1))

            # Use bogus stride debug aid when relaxed strides are enabled
            if NPY_RELAXED_STRIDES_DEBUG:
                moredefs.append(('NPY_RELAXED_STRIDES_DEBUG', 1))

            # Get long double representation
            rep = check_long_double_representation(config_cmd)
            moredefs.append(('HAVE_LDOUBLE_%s' % rep, 1))

            if check_for_right_shift_internal_compiler_error(config_cmd):
                moredefs.append('NPY_DO_NOT_OPTIMIZE_LONG_right_shift')
                moredefs.append('NPY_DO_NOT_OPTIMIZE_ULONG_right_shift')
                moredefs.append('NPY_DO_NOT_OPTIMIZE_LONGLONG_right_shift')
                moredefs.append('NPY_DO_NOT_OPTIMIZE_ULONGLONG_right_shift')

            # Py3K check
            if sys.version_info[0] >= 3:
                moredefs.append(('NPY_PY3K', 1))

            # Generate the config.h file from moredefs
            with open(target, 'w') as target_f:
                for d in moredefs:
                    if isinstance(d, str):
                        target_f.write('#define %s\n' % (d))
                    else:
                        target_f.write('#define %s %s\n' % (d[0], d[1]))

                # define inline to our keyword, or nothing
                target_f.write('#ifndef __cplusplus\n')
                if inline == 'inline':
                    target_f.write('/* #undef inline */\n')
                else:
                    target_f.write('#define inline %s\n' % inline)
                target_f.write('#endif\n')

                # add the guard to make sure config.h is never included directly,
                # but always through npy_config.h
                target_f.write(
                    textwrap.dedent("""
                    #ifndef _NPY_NPY_CONFIG_H_
                    #error config.h should never be included directly, include npy_config.h instead
                    #endif
                    """))

            print('File:', target)
            with open(target) as target_f:
                print(target_f.read())
            print('EOF')
        else:
            mathlibs = []
            with open(target) as target_f:
                for line in target_f:
                    s = '#define MATHLIB'
                    if line.startswith(s):
                        value = line[len(s):].strip()
                        if value:
                            mathlibs.extend(value.split(','))

        # Ugly: this can be called within a library and not an extension,
        # in which case there is no libraries attributes (and none is
        # needed).
        if hasattr(ext, 'libraries'):
            ext.libraries.extend(mathlibs)

        incl_dir = os.path.dirname(target)
        if incl_dir not in config.numpy_include_dirs:
            config.numpy_include_dirs.append(incl_dir)

        return target
Beispiel #44
0
    def build_a_library(self, build_info, lib_name, libraries):
        # default compilers
        compiler = self.compiler
        fcompiler = self._f_compiler

        sources = build_info.get('sources')
        if sources is None or not is_sequence(sources):
            raise DistutilsSetupError(
                ("in 'libraries' option (library '%s'), " +
                 "'sources' must be present and must be " +
                 "a list of source filenames") % lib_name)
        sources = list(sources)

        c_sources, cxx_sources, f_sources, fmodule_sources \
            = filter_sources(sources)
        requiref90 = not not fmodule_sources or \
            build_info.get('language', 'c') == 'f90'

        # save source type information so that build_ext can use it.
        source_languages = []
        if c_sources:
            source_languages.append('c')
        if cxx_sources:
            source_languages.append('c++')
        if requiref90:
            source_languages.append('f90')
        elif f_sources:
            source_languages.append('f77')
        build_info['source_languages'] = source_languages

        lib_file = compiler.library_filename(lib_name,
                                             output_dir=self.build_clib)
        depends = sources + build_info.get('depends', [])
        if not (self.force or newer_group(depends, lib_file, 'newer')):
            log.debug("skipping '%s' library (up-to-date)", lib_name)
            return
        else:
            log.info("building '%s' library", lib_name)

        config_fc = build_info.get('config_fc', {})
        if fcompiler is not None and config_fc:
            log.info('using additional config_fc from setup script '
                     'for fortran compiler: %s' % (config_fc, ))
            from numpy.distutils.fcompiler import new_fcompiler
            fcompiler = new_fcompiler(compiler=fcompiler.compiler_type,
                                      verbose=self.verbose,
                                      dry_run=self.dry_run,
                                      force=self.force,
                                      requiref90=requiref90,
                                      c_compiler=self.compiler)
            if fcompiler is not None:
                dist = self.distribution
                base_config_fc = dist.get_option_dict('config_fc').copy()
                base_config_fc.update(config_fc)
                fcompiler.customize(base_config_fc)

        # check availability of Fortran compilers
        if (f_sources or fmodule_sources) and fcompiler is None:
            raise DistutilsError("library %s has Fortran sources"
                                 " but no Fortran compiler found" % (lib_name))

        if fcompiler is not None:
            fcompiler.extra_f77_compile_args = build_info.get(
                'extra_f77_compile_args') or []
            fcompiler.extra_f90_compile_args = build_info.get(
                'extra_f90_compile_args') or []

        macros = build_info.get('macros')
        include_dirs = build_info.get('include_dirs')
        if include_dirs is None:
            include_dirs = []
        extra_postargs = build_info.get('extra_compiler_args') or []

        include_dirs.extend(get_numpy_include_dirs())
        # where compiled F90 module files are:
        module_dirs = build_info.get('module_dirs') or []
        module_build_dir = os.path.dirname(lib_file)
        if requiref90:
            self.mkpath(module_build_dir)

        if compiler.compiler_type == 'msvc':
            # this hack works around the msvc compiler attributes
            # problem, msvc uses its own convention :(
            c_sources += cxx_sources
            cxx_sources = []

        objects = []
        if c_sources:
            log.info("compiling C sources")
            objects = compiler.compile(c_sources,
                                       output_dir=self.build_temp,
                                       macros=macros,
                                       include_dirs=include_dirs,
                                       debug=self.debug,
                                       extra_postargs=extra_postargs)

        if cxx_sources:
            log.info("compiling C++ sources")
            cxx_compiler = compiler.cxx_compiler()
            cxx_objects = cxx_compiler.compile(cxx_sources,
                                               output_dir=self.build_temp,
                                               macros=macros,
                                               include_dirs=include_dirs,
                                               debug=self.debug,
                                               extra_postargs=extra_postargs)
            objects.extend(cxx_objects)

        if f_sources or fmodule_sources:
            extra_postargs = []
            f_objects = []

            if requiref90:
                if fcompiler.module_dir_switch is None:
                    existing_modules = glob('*.mod')
                extra_postargs += fcompiler.module_options(
                    module_dirs, module_build_dir)

            if fmodule_sources:
                log.info("compiling Fortran 90 module sources")
                f_objects += fcompiler.compile(fmodule_sources,
                                               output_dir=self.build_temp,
                                               macros=macros,
                                               include_dirs=include_dirs,
                                               debug=self.debug,
                                               extra_postargs=extra_postargs)

            if requiref90 and self._f_compiler.module_dir_switch is None:
                # move new compiled F90 module files to module_build_dir
                for f in glob('*.mod'):
                    if f in existing_modules:
                        continue
                    t = os.path.join(module_build_dir, f)
                    if os.path.abspath(f) == os.path.abspath(t):
                        continue
                    if os.path.isfile(t):
                        os.remove(t)
                    try:
                        self.move_file(f, module_build_dir)
                    except DistutilsFileError:
                        log.warn('failed to move %r to %r' %
                                 (f, module_build_dir))

            if f_sources:
                log.info("compiling Fortran sources")
                f_objects += fcompiler.compile(f_sources,
                                               output_dir=self.build_temp,
                                               macros=macros,
                                               include_dirs=include_dirs,
                                               debug=self.debug,
                                               extra_postargs=extra_postargs)
        else:
            f_objects = []

        if f_objects and not fcompiler.can_ccompiler_link(compiler):
            # Default linker cannot link Fortran object files, and results
            # need to be wrapped later. Instead of creating a real static
            # library, just keep track of the object files.
            listfn = os.path.join(self.build_clib, lib_name + '.fobjects')
            with open(listfn, 'w') as f:
                f.write("\n".join(os.path.abspath(obj) for obj in f_objects))

            listfn = os.path.join(self.build_clib, lib_name + '.cobjects')
            with open(listfn, 'w') as f:
                f.write("\n".join(os.path.abspath(obj) for obj in objects))

            # create empty "library" file for dependency tracking
            lib_fname = os.path.join(self.build_clib,
                                     lib_name + compiler.static_lib_extension)
            with open(lib_fname, 'wb') as f:
                pass
        else:
            # assume that default linker is suitable for
            # linking Fortran object files
            objects.extend(f_objects)
            compiler.create_static_lib(objects,
                                       lib_name,
                                       output_dir=self.build_clib,
                                       debug=self.debug)

        # fix library dependencies
        clib_libraries = build_info.get('libraries', [])
        for lname, binfo in libraries:
            if lname in clib_libraries:
                clib_libraries.extend(binfo.get('libraries', []))
        if clib_libraries:
            build_info['libraries'] = clib_libraries
Beispiel #45
0
    def generate_config_h(ext, build_dir):
        target = join(build_dir,header_dir,'config.h')
        d = os.path.dirname(target)
        if not os.path.exists(d):
            os.makedirs(d)
        if newer(__file__,target):
            config_cmd = config.get_config_cmd()
            log.info('Generating %s',target)

            # Check sizeof
            moredefs, ignored = cocache.check_types(config_cmd, ext, build_dir)

            # Check math library and C99 math funcs availability
            mathlibs = check_mathlib(config_cmd)
            moredefs.append(('MATHLIB',','.join(mathlibs)))

            check_math_capabilities(config_cmd, moredefs, mathlibs)
            moredefs.extend(cocache.check_ieee_macros(config_cmd)[0])

            # Signal check
            if is_npy_no_signal():
                moredefs.append('__NPY_PRIVATE_NO_SIGNAL')

            # Windows checks
            if sys.platform=='win32' or os.name=='nt':
                win32_checks(moredefs)

            # Inline check
            inline = config_cmd.check_inline()

            # Generate the config.h file from moredefs
            target_f = open(target,'a')
            for d in moredefs:
                if isinstance(d,str):
                    target_f.write('#define %s\n' % (d))
                else:
                    target_f.write('#define %s %s\n' % (d[0],d[1]))

            # define inline to our keyword, or nothing
            target_f.write('#ifndef __cplusplus\n')
            if inline == 'inline':
                target_f.write('/* #undef inline */\n')
            else:
                target_f.write('#define inline %s\n' % inline)
            target_f.write('#endif\n')

            target_f.close()
            print 'File:',target
            target_f = open(target)
            print target_f.read()
            target_f.close()
            print 'EOF'
        else:
            mathlibs = []
            target_f = open(target)
            for line in target_f.readlines():
                s = '#define MATHLIB'
                if line.startswith(s):
                    value = line[len(s):].strip()
                    if value:
                        mathlibs.extend(value.split(','))
            target_f.close()

        # Ugly: this can be called within a library and not an extension,
        # in which case there is no libraries attributes (and none is
        # needed).
        if hasattr(ext, 'libraries'):
            ext.libraries.extend(mathlibs)

        incl_dir = os.path.dirname(target)
        if incl_dir not in config.numpy_include_dirs:
            config.numpy_include_dirs.append(incl_dir)

        return target
Beispiel #46
0
    def generate_config_h(ext, build_dir):
        target = join(build_dir, header_dir, 'config.h')
        d = os.path.dirname(target)
        if not os.path.exists(d):
            os.makedirs(d)

        if newer(__file__, target):
            config_cmd = config.get_config_cmd()
            log.info('Generating %s', target)

            # Check sizeof
            moredefs, ignored = cocache.check_types(config_cmd, ext, build_dir)

            # Check math library and C99 math funcs availability
            mathlibs = check_mathlib(config_cmd)
            moredefs.append(('MATHLIB', ','.join(mathlibs)))

            check_math_capabilities(config_cmd, moredefs, mathlibs)
            moredefs.extend(cocache.check_ieee_macros(config_cmd)[0])
            moredefs.extend(cocache.check_complex(config_cmd, mathlibs)[0])

            # Signal check
            if is_npy_no_signal():
                moredefs.append('__NPY_PRIVATE_NO_SIGNAL')

            # Windows checks
            if sys.platform=='win32' or os.name=='nt':
                win32_checks(moredefs)

            # C99 restrict keyword
            moredefs.append(('NPY_RESTRICT', config_cmd.check_restrict()))

            # Inline check
            inline = config_cmd.check_inline()

            # Check whether we need our own wide character support
            if not config_cmd.check_decl('Py_UNICODE_WIDE', headers=['Python.h']):
                PYTHON_HAS_UNICODE_WIDE = True
            else:
                PYTHON_HAS_UNICODE_WIDE = False

            if ENABLE_SEPARATE_COMPILATION:
                moredefs.append(('ENABLE_SEPARATE_COMPILATION', 1))

            if NPY_RELAXED_STRIDES_CHECKING:
                moredefs.append(('NPY_RELAXED_STRIDES_CHECKING', 1))

            # Get long double representation
            if sys.platform != 'darwin':
                rep = check_long_double_representation(config_cmd)
                if rep in ['INTEL_EXTENDED_12_BYTES_LE',
                           'INTEL_EXTENDED_16_BYTES_LE',
                           'MOTOROLA_EXTENDED_12_BYTES_BE',
                           'IEEE_QUAD_LE', 'IEEE_QUAD_BE',
                           'IEEE_DOUBLE_LE', 'IEEE_DOUBLE_BE',
                           'DOUBLE_DOUBLE_BE', 'DOUBLE_DOUBLE_LE']:
                    moredefs.append(('HAVE_LDOUBLE_%s' % rep, 1))
                else:
                    raise ValueError("Unrecognized long double format: %s" % rep)

            # Py3K check
            if sys.version_info[0] == 3:
                moredefs.append(('NPY_PY3K', 1))

            # Generate the config.h file from moredefs
            target_f = open(target, 'w')
            for d in moredefs:
                if isinstance(d, str):
                    target_f.write('#define %s\n' % (d))
                else:
                    target_f.write('#define %s %s\n' % (d[0], d[1]))

            # define inline to our keyword, or nothing
            target_f.write('#ifndef __cplusplus\n')
            if inline == 'inline':
                target_f.write('/* #undef inline */\n')
            else:
                target_f.write('#define inline %s\n' % inline)
            target_f.write('#endif\n')

            # add the guard to make sure config.h is never included directly,
            # but always through npy_config.h
            target_f.write("""
#ifndef _NPY_NPY_CONFIG_H_
#error config.h should never be included directly, include npy_config.h instead
#endif
""")

            target_f.close()
            print('File:', target)
            target_f = open(target)
            print(target_f.read())
            target_f.close()
            print('EOF')
        else:
            mathlibs = []
            target_f = open(target)
            for line in target_f:
                s = '#define MATHLIB'
                if line.startswith(s):
                    value = line[len(s):].strip()
                    if value:
                        mathlibs.extend(value.split(','))
            target_f.close()

        # Ugly: this can be called within a library and not an extension,
        # in which case there is no libraries attributes (and none is
        # needed).
        if hasattr(ext, 'libraries'):
            ext.libraries.extend(mathlibs)

        incl_dir = os.path.dirname(target)
        if incl_dir not in config.numpy_include_dirs:
            config.numpy_include_dirs.append(incl_dir)

        return target
    def finalize_options(self):
        self.set_undefined_options(
            "build",
            ("build_base", "build_base"),
            ("build_lib", "build_lib"),
            ("force", "force"),
        )
        if self.package is None:
            self.package = self.distribution.ext_package
        self.extensions = self.distribution.ext_modules
        self.libraries = self.distribution.libraries or []
        self.py_modules = self.distribution.py_modules or []
        self.data_files = self.distribution.data_files or []

        if self.build_src is None:
            plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3])
            self.build_src = os.path.join(self.build_base,
                                          "src" + plat_specifier)

        # py_modules_dict is used in build_py.find_package_modules
        self.py_modules_dict = {}

        if self.f2pyflags:
            if self.f2py_opts:
                log.warn("ignoring --f2pyflags as --f2py-opts already used")
            else:
                self.f2py_opts = self.f2pyflags
            self.f2pyflags = None
        if self.f2py_opts is None:
            self.f2py_opts = []
        else:
            self.f2py_opts = shlex.split(self.f2py_opts)

        if self.swigflags:
            if self.swig_opts:
                log.warn("ignoring --swigflags as --swig-opts already used")
            else:
                self.swig_opts = self.swigflags
            self.swigflags = None

        if self.swig_opts is None:
            self.swig_opts = []
        else:
            self.swig_opts = shlex.split(self.swig_opts)

        # use options from build_ext command
        build_ext = self.get_finalized_command("build_ext")
        if self.inplace is None:
            self.inplace = build_ext.inplace
        if self.swig_cpp is None:
            self.swig_cpp = build_ext.swig_cpp
        for c in ["swig", "swig_opt"]:
            o = "--" + c.replace("_", "-")
            v = getattr(build_ext, c, None)
            if v:
                if getattr(self, c):
                    log.warn("both build_src and build_ext define %s option" %
                             (o))
                else:
                    log.info('using "%s=%s" option from build_ext command' %
                             (o, v))
                    setattr(self, c, v)
Beispiel #48
0
    def generate_numpyconfig_h(ext, build_dir):
        """Depends on config.h: generate_config_h has to be called before !"""
        # put private include directory in build_dir on search path
        # allows using code generation in headers headers
        config.add_include_dirs(join(build_dir, "src", "private"))

        target = join(build_dir, header_dir, '_numpyconfig.h')
        d = os.path.dirname(target)
        if not os.path.exists(d):
            os.makedirs(d)
        if newer(__file__, target):
            config_cmd = config.get_config_cmd()
            log.info('Generating %s', target)

            # Check sizeof
            ignored, moredefs = cocache.check_types(config_cmd, ext, build_dir)

            if is_npy_no_signal():
                moredefs.append(('NPY_NO_SIGNAL', 1))

            if is_npy_no_smp():
                moredefs.append(('NPY_NO_SMP', 1))
            else:
                moredefs.append(('NPY_NO_SMP', 0))

            mathlibs = check_mathlib(config_cmd)
            moredefs.extend(cocache.check_ieee_macros(config_cmd)[1])
            moredefs.extend(cocache.check_complex(config_cmd, mathlibs)[1])

            if ENABLE_SEPARATE_COMPILATION:
                moredefs.append(('NPY_ENABLE_SEPARATE_COMPILATION', 1))

            if NPY_RELAXED_STRIDES_CHECKING:
                moredefs.append(('NPY_RELAXED_STRIDES_CHECKING', 1))

            # Check wether we can use inttypes (C99) formats
            if config_cmd.check_decl('PRIdPTR', headers = ['inttypes.h']):
                moredefs.append(('NPY_USE_C99_FORMATS', 1))

            # visibility check
            hidden_visibility = visibility_define(config_cmd)
            moredefs.append(('NPY_VISIBILITY_HIDDEN', hidden_visibility))

            # Add the C API/ABI versions
            moredefs.append(('NPY_ABI_VERSION', '0x%.8X' % C_ABI_VERSION))
            moredefs.append(('NPY_API_VERSION', '0x%.8X' % C_API_VERSION))

            # Add moredefs to header
            target_f = open(target, 'w')
            for d in moredefs:
                if isinstance(d, str):
                    target_f.write('#define %s\n' % (d))
                else:
                    target_f.write('#define %s %s\n' % (d[0], d[1]))

            # Define __STDC_FORMAT_MACROS
            target_f.write("""
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#endif
""")
            target_f.close()

            # Dump the numpyconfig.h header to stdout
            print('File: %s' % target)
            target_f = open(target)
            print(target_f.read())
            target_f.close()
            print('EOF')
        config.add_data_files((header_dir, target))
        return target
Beispiel #49
0
    def generate_numpyconfig_h(ext, build_dir):
        """Depends on config.h: generate_config_h has to be called before !"""
        target = join(build_dir, header_dir, 'numpyconfig.h')
        d = os.path.dirname(target)
        if not os.path.exists(d):
            os.makedirs(d)
        if newer(__file__, target):
            config_cmd = config.get_config_cmd()
            log.info('Generating %s', target)

            # Check sizeof
            ignored, moredefs = cocache.check_types(config_cmd, ext, build_dir)

            if is_npy_no_signal():
                moredefs.append(('NPY_NO_SIGNAL', 1))

            if is_npy_no_smp():
                moredefs.append(('NPY_NO_SMP', 1))
            else:
                moredefs.append(('NPY_NO_SMP', 0))

            moredefs.extend(cocache.check_ieee_macros(config_cmd)[1])

            if ENABLE_SEPARATE_COMPILATION:
                moredefs.append(('NPY_ENABLE_SEPARATE_COMPILATION', 1))

            # Check wether we can use inttypes (C99) formats
            if config_cmd.check_decl('PRIdPTR', headers=['inttypes.h']):
                moredefs.append(('NPY_USE_C99_FORMATS', 1))

            # Inline check
            inline = config_cmd.check_inline()

            # visibility check
            hidden_visibility = visibility_define(config_cmd)
            moredefs.append(('NPY_VISIBILITY_HIDDEN', hidden_visibility))

            # Add the C API/ABI versions
            moredefs.append(('NPY_ABI_VERSION', '0x%.8X' % C_ABI_VERSION))
            moredefs.append(('NPY_API_VERSION', '0x%.8X' % C_API_VERSION))

            # Add moredefs to header
            target_f = open(target, 'w')
            for d in moredefs:
                if isinstance(d, str):
                    target_f.write('#define %s\n' % (d))
                else:
                    target_f.write('#define %s %s\n' % (d[0], d[1]))

            # define NPY_INLINE to recognized keyword
            target_f.write('#define NPY_INLINE %s\n' % inline)

            # Define __STDC_FORMAT_MACROS
            target_f.write("""
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#endif
""")
            target_f.close()

            # Dump the numpyconfig.h header to stdout
            print 'File: %s' % target
            target_f = open(target)
            print target_f.read()
            target_f.close()
            print 'EOF'
        config.add_data_files((header_dir, target))
        return target
Beispiel #50
0
def CCompiler_compile(self, sources, output_dir=None, macros=None,
                      include_dirs=None, debug=0, extra_preargs=None,
                      extra_postargs=None, depends=None):
    """
    Compile one or more source files.

    Please refer to the Python distutils API reference for more details.

    Parameters
    ----------
    sources : list of str
        A list of filenames
    output_dir : str, optional
        Path to the output directory.
    macros : list of tuples
        A list of macro definitions.
    include_dirs : list of str, optional
        The directories to add to the default include file search path for
        this compilation only.
    debug : bool, optional
        Whether or not to output debug symbols in or alongside the object
        file(s).
    extra_preargs, extra_postargs : ?
        Extra pre- and post-arguments.
    depends : list of str, optional
        A list of file names that all targets depend on.

    Returns
    -------
    objects : list of str
        A list of object file names, one per source file `sources`.

    Raises
    ------
    CompileError
        If compilation fails.

    """
    # This method is effective only with Python >=2.3 distutils.
    # Any changes here should be applied also to fcompiler.compile
    # method to support pre Python 2.3 distutils.
    if not sources:
        return []
    # FIXME:RELATIVE_IMPORT
    if sys.version_info[0] < 3:
        from fcompiler import FCompiler
    else:
        from numpy.distutils.fcompiler import FCompiler
    if isinstance(self, FCompiler):
        display = []
        for fc in ['f77','f90','fix']:
            fcomp = getattr(self,'compiler_'+fc)
            if fcomp is None:
                continue
            display.append("Fortran %s compiler: %s" % (fc, ' '.join(fcomp)))
        display = '\n'.join(display)
    else:
        ccomp = self.compiler_so
        display = "C compiler: %s\n" % (' '.join(ccomp),)
    log.info(display)
    macros, objects, extra_postargs, pp_opts, build = \
            self._setup_compile(output_dir, macros, include_dirs, sources,
                                depends, extra_postargs)
    cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
    display = "compile options: '%s'" % (' '.join(cc_args))
    if extra_postargs:
        display += "\nextra options: '%s'" % (' '.join(extra_postargs))
    log.info(display)

    # build any sources in same order as they were originally specified
    #   especially important for fortran .f90 files using modules
    if isinstance(self, FCompiler):
        objects_to_build = build.keys()
        for obj in objects:
            if obj in objects_to_build:
                src, ext = build[obj]
                if self.compiler_type=='absoft':
                    obj = cyg2win32(obj)
                    src = cyg2win32(src)
                self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
    else:
        for obj, (src, ext) in build.items():
            self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)

    # Return *all* object filenames, not just the ones we just built.
    return objects
Beispiel #51
0
    'pathccompiler', 'PathScaleCCompiler',
    "PathScale Compiler for SiCortex-based applications")
compiler_class['arm'] = ('armccompiler', 'ArmCCompiler', "Arm C Compiler")

ccompiler._default_compilers += (('linux.*', 'intel'), ('linux.*', 'intele'),
                                 ('linux.*', 'intelem'), ('linux.*', 'pathcc'),
                                 ('nt', 'intelw'), ('nt', 'intelemw'))

if sys.platform == 'win32':
    compiler_class['mingw32'] = ('mingw32ccompiler', 'Mingw32CCompiler',
                                 "Mingw32 port of GNU C Compiler for Win32"\
                                 "(for MSC built Python)")
    if mingw32():
        # On windows platforms, we want to default to mingw32 (gcc)
        # because msvc can't build blitz stuff.
        log.info('Setting mingw32 as default compiler for nt.')
        ccompiler._default_compilers = (('nt', 'mingw32'),) \
                                       + ccompiler._default_compilers

_distutils_new_compiler = new_compiler


def new_compiler(plat=None, compiler=None, verbose=None, dry_run=0, force=0):
    # Try first C compilers from numpy.distutils.
    if verbose is None:
        verbose = log.get_threshold() <= log.INFO
    if plat is None:
        plat = os.name
    try:
        if compiler is None:
            compiler = get_default_compiler(plat)
Beispiel #52
0
def CCompiler_customize(self, dist, need_cxx=0):
    """
    Do any platform-specific customization of a compiler instance.

    This method calls `distutils.sysconfig.customize_compiler` for
    platform-specific customization, as well as optionally remove a flag
    to suppress spurious warnings in case C++ code is being compiled.

    Parameters
    ----------
    dist : object
        This parameter is not used for anything.
    need_cxx : bool, optional
        Whether or not C++ has to be compiled. If so (True), the
        ``"-Wstrict-prototypes"`` option is removed to prevent spurious
        warnings. Default is False.

    Returns
    -------
    None

    Notes
    -----
    All the default options used by distutils can be extracted with::

      from distutils import sysconfig
      sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'BASECFLAGS',
                                'CCSHARED', 'LDSHARED', 'SO')

    """
    # See FCompiler.customize for suggested usage.
    log.info('customize %s' % (self.__class__.__name__))
    customize_compiler(self)
    if need_cxx:
        # In general, distutils uses -Wstrict-prototypes, but this option is
        # not valid for C++ code, only for C.  Remove it if it's there to
        # avoid a spurious warning on every compilation.
        try:
            self.compiler_so.remove('-Wstrict-prototypes')
        except (AttributeError, ValueError):
            pass

        if hasattr(self, 'compiler') and 'cc' in self.compiler[0]:
            if not self.compiler_cxx:
                if self.compiler[0].startswith('gcc'):
                    a, b = 'gcc', 'g++'
                else:
                    a, b = 'cc', 'c++'
                self.compiler_cxx = [self.compiler[0].replace(a, b)]\
                                    + self.compiler[1:]
        else:
            if hasattr(self, 'compiler'):
                log.warn("#### %s #######" % (self.compiler, ))
            if not hasattr(self, 'compiler_cxx'):
                log.warn('Missing compiler_cxx fix for ' +
                         self.__class__.__name__)

    # check if compiler supports gcc style automatic dependencies
    # run on every extension so skip for known good compilers
    if hasattr(self, 'compiler') and ('gcc' in self.compiler[0]
                                      or 'g++' in self.compiler[0]
                                      or 'clang' in self.compiler[0]):
        self._auto_depends = True
    elif os.name == 'posix':
        import tempfile
        import shutil
        tmpdir = tempfile.mkdtemp()
        try:
            fn = os.path.join(tmpdir, "file.c")
            with open(fn, "w") as f:
                f.write("int a;\n")
            self.compile([fn],
                         output_dir=tmpdir,
                         extra_preargs=['-MMD', '-MF', fn + '.d'])
            self._auto_depends = True
        except CompileError:
            self._auto_depends = False
        finally:
            shutil.rmtree(tmpdir)

    return
Beispiel #53
0
    def run(self):
        if not self.libraries:
            return

        # Make sure that library sources are complete.
        languages = []

        # Make sure that extension sources are complete.
        self.run_command('build_src')

        for (lib_name, build_info) in self.libraries:
            l = build_info.get('language', None)
            if l and l not in languages:
                languages.append(l)

        from distutils.ccompiler import new_compiler
        self.compiler = new_compiler(compiler=self.compiler,
                                     dry_run=self.dry_run,
                                     force=self.force)
        self.compiler.customize(self.distribution,
                                need_cxx=self.have_cxx_sources())

        if self.warn_error:
            self.compiler.compiler.append('-Werror')
            self.compiler.compiler_so.append('-Werror')

        libraries = self.libraries
        self.libraries = None
        self.compiler.customize_cmd(self)
        self.libraries = libraries

        self.compiler.show_customization()

        if not self.disable_optimization:
            dispatch_hpath = os.path.join("numpy", "distutils", "include",
                                          "npy_cpu_dispatch_config.h")
            dispatch_hpath = os.path.join(
                self.get_finalized_command("build_src").build_src,
                dispatch_hpath)
            opt_cache_path = os.path.abspath(
                os.path.join(self.build_temp, 'ccompiler_opt_cache_clib.py'))
            self.compiler_opt = new_ccompiler_opt(
                compiler=self.compiler,
                dispatch_hpath=dispatch_hpath,
                cpu_baseline=self.cpu_baseline,
                cpu_dispatch=self.cpu_dispatch,
                cache_path=opt_cache_path)
            if not self.compiler_opt.is_cached():
                log.info(
                    "Detected changes on compiler optimizations, force rebuilding"
                )
                self.force = True

            def report(copt):
                log.info(
                    "\n########### CLIB COMPILER OPTIMIZATION ###########")
                log.info(copt.report(full=True))

            import atexit
            atexit.register(report, self.compiler_opt)

        if self.have_f_sources():
            from numpy.distutils.fcompiler import new_fcompiler
            self._f_compiler = new_fcompiler(compiler=self.fcompiler,
                                             verbose=self.verbose,
                                             dry_run=self.dry_run,
                                             force=self.force,
                                             requiref90='f90' in languages,
                                             c_compiler=self.compiler)
            if self._f_compiler is not None:
                self._f_compiler.customize(self.distribution)

                libraries = self.libraries
                self.libraries = None
                self._f_compiler.customize_cmd(self)
                self.libraries = libraries

                self._f_compiler.show_customization()
        else:
            self._f_compiler = None

        self.build_libraries(self.libraries)

        if self.inplace:
            for l in self.distribution.installed_libraries:
                libname = self.compiler.library_filename(l.name)
                source = os.path.join(self.build_clib, libname)
                target = os.path.join(l.target_dir, libname)
                self.mkpath(l.target_dir)
                shutil.copy(source, target)
Beispiel #54
0
    def customize(self, dist=None):
        """Customize Fortran compiler.

        This method gets Fortran compiler specific information from
        (i) class definition, (ii) environment, (iii) distutils config
        files, and (iv) command line (later overrides earlier).

        This method should be always called after constructing a
        compiler instance. But not in __init__ because Distribution
        instance is needed for (iii) and (iv).
        """
        log.info("customize %s" % (self.__class__.__name__))

        self._is_customised = True

        self.distutils_vars.use_distribution(dist)
        self.command_vars.use_distribution(dist)
        self.flag_vars.use_distribution(dist)

        self.update_executables()

        # find_executables takes care of setting the compiler commands,
        # version_cmd, linker_so, linker_exe, ar, and ranlib
        self.find_executables()

        noopt = self.distutils_vars.get("noopt", False)
        noarch = self.distutils_vars.get("noarch", noopt)
        debug = self.distutils_vars.get("debug", False)

        f77 = self.command_vars.compiler_f77
        f90 = self.command_vars.compiler_f90

        f77flags = []
        f90flags = []
        freeflags = []
        fixflags = []

        if f77:
            f77 = _shell_utils.NativeParser.split(f77)
            f77flags = self.flag_vars.f77
        if f90:
            f90 = _shell_utils.NativeParser.split(f90)
            f90flags = self.flag_vars.f90
            freeflags = self.flag_vars.free
        # XXX Assuming that free format is default for f90 compiler.
        fix = self.command_vars.compiler_fix
        # NOTE: this and similar examples are probably just
        # exluding --coverage flag when F90 = gfortran --coverage
        # instead of putting that flag somewhere more appropriate
        # this and similar examples where a Fortran compiler
        # environment variable has been customized by CI or a user
        # should perhaps eventually be more throughly tested and more
        # robustly handled
        if fix:
            fix = _shell_utils.NativeParser.split(fix)
            fixflags = self.flag_vars.fix + f90flags

        oflags, aflags, dflags = [], [], []
        # examine get_flags_<tag>_<compiler> for extra flags
        # only add them if the method is different from get_flags_<tag>
        def get_flags(tag, flags):
            # note that self.flag_vars.<tag> calls self.get_flags_<tag>()
            flags.extend(getattr(self.flag_vars, tag))
            this_get = getattr(self, "get_flags_" + tag)
            for name, c, flagvar in [
                ("f77", f77, f77flags),
                ("f90", f90, f90flags),
                ("f90", fix, fixflags),
            ]:
                t = "%s_%s" % (tag, name)
                if c and this_get is not getattr(self, "get_flags_" + t):
                    flagvar.extend(getattr(self.flag_vars, t))

        if not noopt:
            get_flags("opt", oflags)
            if not noarch:
                get_flags("arch", aflags)
        if debug:
            get_flags("debug", dflags)

        fflags = self.flag_vars.flags + dflags + oflags + aflags

        if f77:
            self.set_commands(compiler_f77=f77 + f77flags + fflags)
        if f90:
            self.set_commands(compiler_f90=f90 + freeflags + f90flags + fflags)
        if fix:
            self.set_commands(compiler_fix=fix + fixflags + fflags)

        # XXX: Do we need LDSHARED->SOSHARED, LDFLAGS->SOFLAGS
        linker_so = self.linker_so
        if linker_so:
            linker_so_flags = self.flag_vars.linker_so
            if sys.platform.startswith("aix"):
                python_lib = get_python_lib(standard_lib=1)
                ld_so_aix = os.path.join(python_lib, "config", "ld_so_aix")
                python_exp = os.path.join(python_lib, "config", "python.exp")
                linker_so = [ld_so_aix] + linker_so + ["-bI:" + python_exp]
            self.set_commands(linker_so=linker_so + linker_so_flags)

        linker_exe = self.linker_exe
        if linker_exe:
            linker_exe_flags = self.flag_vars.linker_exe
            self.set_commands(linker_exe=linker_exe + linker_exe_flags)

        ar = self.command_vars.archiver
        if ar:
            arflags = self.flag_vars.ar
            self.set_commands(archiver=[ar] + arflags)

        self.set_library_dirs(self.get_library_dirs())
        self.set_libraries(self.get_libraries())
Beispiel #55
0
def package_check(pkg_name,
                  version=None,
                  optional=False,
                  checker=LooseVersion,
                  version_getter=None,
                  messages=None,
                  show_only=False):
    """
    Check if package `pkg_name` is present, and in correct version.

    Parameters
    ----------
    pkg_name : str or sequence of str
       The name of the package as imported into python. Alternative names
       (e.g. for different versions) may be given in a list.
    version : str, optional
       The minimum version of the package that is required. If not given, the
       version is not checked.
    optional : bool, optional
       If False, raise error for absent package or wrong version;
       otherwise warn
    checker : callable, optional
       If given, the callable with which to return a comparable thing from a
       version string. The default is ``distutils.version.LooseVersion``.
    version_getter : callable, optional:
       If given, the callable that takes `pkg_name` as argument, and returns
       the package version string - as in::

          ``version = version_getter(pkg_name)``

       The default is equivalent to::

          mod = __import__(pkg_name); version = mod.__version__``
    messages : dict, optional
       If given, the dictionary providing (some of) output messages.
    show_only : bool
       If True, do not raise exceptions, only show the package name and version
       information.
    """
    if version_getter is None:

        def version_getter(pkg_name):
            mod = __import__(pkg_name)
            return mod.__version__

    if messages is None:
        messages = {}

    msgs = {
        'available': '%s is available',
        'missing': '%s is missing',
        'opt suffix': '; you may get run-time errors',
        'version': '%s is available in version %s',
        'version old': '%s is available in version %s, but >= %s is needed',
        'no version': '%s is available, cannot determine version',
    }
    msgs.update(messages)

    if isinstance(pkg_name, str):
        names = [pkg_name]

    else:
        names = pkg_name

    import_ok = False
    for pkg_name in names:
        try:
            __import__(pkg_name)
        except ImportError:
            pass
        else:
            import_ok = True

    pkg_info = pkg_name + (' (optional)' if optional else '')

    if not import_ok:
        if not (optional or show_only):
            raise RuntimeError(msgs['missing'] % pkg_name)
        log.warn(msgs['missing'] % pkg_info + msgs['opt suffix'])
        return

    if not version:
        if show_only:
            log.info(msgs['available'] % pkg_info)

        return

    try:
        have_version = version_getter(pkg_name)

    except AttributeError:
        raise RuntimeError(msgs['no version'] % pkg_info)

    if not have_version:
        if optional or show_only:
            log.warn(msgs['no version'] % pkg_info)

        else:
            raise RuntimeError(msgs['no version'] % pkg_info)

    elif checker(have_version) < checker(version):
        if optional or show_only:
            log.warn(msgs['version old'] % (pkg_info, have_version, version) +
                     msgs['opt suffix'])

        else:
            raise RuntimeError(msgs['version old'] %
                               (pkg_info, have_version, version))

    elif show_only:
        log.info(msgs['version'] % (pkg_info, have_version))
Beispiel #56
0
 def report(copt):
     log.info(
         "\n########### CLIB COMPILER OPTIMIZATION ###########")
     log.info(copt.report(full=True))
Beispiel #57
0
 def run(self):
     log.info("build_src")
     if not (self.extensions or self.libraries):
         return
     self.build_sources()
Beispiel #58
0
    def f2py_sources(self, sources, extension):
        new_sources = []
        f2py_sources = []
        f_sources = []
        f2py_targets = {}
        target_dirs = []
        ext_name = extension.name.split('.')[-1]
        skip_f2py = 0

        for source in sources:
            (base, ext) = os.path.splitext(source)
            if ext == '.pyf':  # F2PY interface file
                if self.inplace:
                    target_dir = os.path.dirname(base)
                else:
                    target_dir = appendpath(self.build_src,
                                            os.path.dirname(base))
                if os.path.isfile(source):
                    name = get_f2py_modulename(source)
                    if name != ext_name:
                        raise DistutilsSetupError(
                            'mismatch of extension names: %s '
                            'provides %r but expected %r' %
                            (source, name, ext_name))
                    target_file = os.path.join(target_dir, name + 'module.c')
                else:
                    log.debug('  source %s does not exist: skipping f2py\'ing.' \
                              % (source))
                    name = ext_name
                    skip_f2py = 1
                    target_file = os.path.join(target_dir, name + 'module.c')
                    if not os.path.isfile(target_file):
                        log.warn('  target %s does not exist:\n   ' \
                                 'Assuming %smodule.c was generated with ' \
                                 '"build_src --inplace" command.' \
                                 % (target_file, name))
                        target_dir = os.path.dirname(base)
                        target_file = os.path.join(target_dir,
                                                   name + 'module.c')
                        if not os.path.isfile(target_file):
                            raise DistutilsSetupError("%r missing" %
                                                      (target_file, ))
                        log.info('   Yes! Using %r as up-to-date target.' \
                                 % (target_file))
                target_dirs.append(target_dir)
                f2py_sources.append(source)
                f2py_targets[source] = target_file
                new_sources.append(target_file)
            elif fortran_ext_match(ext):
                f_sources.append(source)
            else:
                new_sources.append(source)

        if not (f2py_sources or f_sources):
            return new_sources

        for d in target_dirs:
            self.mkpath(d)

        f2py_options = extension.f2py_options + self.f2py_opts

        if self.distribution.libraries:
            for name, build_info in self.distribution.libraries:
                if name in extension.libraries:
                    f2py_options.extend(build_info.get('f2py_options', []))

        log.info("f2py options: %s" % (f2py_options))

        if f2py_sources:
            if len(f2py_sources) != 1:
                raise DistutilsSetupError(
                    'only one .pyf file is allowed per extension module but got' \
                    ' more: %r' % (f2py_sources,))
            source = f2py_sources[0]
            target_file = f2py_targets[source]
            target_dir = os.path.dirname(target_file) or '.'
            depends = [source] + extension.depends
            if (self.force or newer_group(depends, target_file, 'newer')) \
                    and not skip_f2py:
                log.info("f2py: %s" % (source))
                import numpy.f2py
                numpy.f2py.run_main(f2py_options +
                                    ['--build-dir', target_dir, source])
            else:
                log.debug("  skipping '%s' f2py interface (up-to-date)" %
                          (source))
        else:
            #XXX TODO: --inplace support for sdist command
            if is_sequence(extension):
                name = extension[0]
            else:
                name = extension.name
            target_dir = os.path.join(*([self.build_src] +
                                        name.split('.')[:-1]))
            target_file = os.path.join(target_dir, ext_name + 'module.c')
            new_sources.append(target_file)
            depends = f_sources + extension.depends
            if (self.force or newer_group(depends, target_file, 'newer')) \
                    and not skip_f2py:
                log.info("f2py:> %s" % (target_file))
                self.mkpath(target_dir)
                import numpy.f2py
                numpy.f2py.run_main(f2py_options + ['--lower',
                                                    '--build-dir', target_dir] + \
                                    ['-m', ext_name] + f_sources)
            else:
                log.debug("  skipping f2py fortran files for '%s' (up-to-date)" \
                          % (target_file))

        if not os.path.isfile(target_file):
            raise DistutilsError("f2py target file %r not generated" %
                                 (target_file, ))

        build_dir = os.path.join(self.build_src, target_dir)
        target_c = os.path.join(build_dir, 'fortranobject.c')
        target_h = os.path.join(build_dir, 'fortranobject.h')
        log.info("  adding '%s' to sources." % (target_c))
        new_sources.append(target_c)
        if build_dir not in extension.include_dirs:
            log.info("  adding '%s' to include_dirs." % (build_dir))
            extension.include_dirs.append(build_dir)

        if not skip_f2py:
            import numpy.f2py
            d = os.path.dirname(numpy.f2py.__file__)
            source_c = os.path.join(d, 'src', 'fortranobject.c')
            source_h = os.path.join(d, 'src', 'fortranobject.h')
            if newer(source_c, target_c) or newer(source_h, target_h):
                self.mkpath(os.path.dirname(target_c))
                self.copy_file(source_c, target_c)
                self.copy_file(source_h, target_h)
        else:
            if not os.path.isfile(target_c):
                raise DistutilsSetupError("f2py target_c file %r not found" %
                                          (target_c, ))
            if not os.path.isfile(target_h):
                raise DistutilsSetupError("f2py target_h file %r not found" %
                                          (target_h, ))

        for name_ext in ['-f2pywrappers.f', '-f2pywrappers2.f90']:
            filename = os.path.join(target_dir, ext_name + name_ext)
            if os.path.isfile(filename):
                log.info("  adding '%s' to sources." % (filename))
                f_sources.append(filename)

        return new_sources + f_sources
Beispiel #59
0
    def customize(self, dist=None):
        """Customize Fortran compiler.

        This method gets Fortran compiler specific information from
        (i) class definition, (ii) environment, (iii) distutils config
        files, and (iv) command line (later overrides earlier).

        This method should be always called after constructing a
        compiler instance. But not in __init__ because Distribution
        instance is needed for (iii) and (iv).
        """
        log.info('customize %s' % (self.__class__.__name__))

        self._is_customised = True

        self.distutils_vars.use_distribution(dist)
        self.command_vars.use_distribution(dist)
        self.flag_vars.use_distribution(dist)

        self.update_executables()

        # find_executables takes care of setting the compiler commands,
        # version_cmd, linker_so, linker_exe, ar, and ranlib
        self.find_executables()

        noopt = self.distutils_vars.get('noopt', False)
        noarch = self.distutils_vars.get('noarch', noopt)
        debug = self.distutils_vars.get('debug', False)

        f77 = self.command_vars.compiler_f77
        f90 = self.command_vars.compiler_f90

        f77flags = []
        f90flags = []
        freeflags = []
        fixflags = []

        if f77:
            f77flags = self.flag_vars.f77
        if f90:
            f90flags = self.flag_vars.f90
            freeflags = self.flag_vars.free
        # XXX Assuming that free format is default for f90 compiler.
        fix = self.command_vars.compiler_fix
        if fix:
            fixflags = self.flag_vars.fix + f90flags

        oflags, aflags, dflags = [], [], []

        # examine get_flags_<tag>_<compiler> for extra flags
        # only add them if the method is different from get_flags_<tag>
        def get_flags(tag, flags):
            # note that self.flag_vars.<tag> calls self.get_flags_<tag>()
            flags.extend(getattr(self.flag_vars, tag))
            this_get = getattr(self, 'get_flags_' + tag)
            for name, c, flagvar in [('f77', f77, f77flags),
                                     ('f90', f90, f90flags),
                                     ('f90', fix, fixflags)]:
                t = '%s_%s' % (tag, name)
                if c and this_get is not getattr(self, 'get_flags_' + t):
                    flagvar.extend(getattr(self.flag_vars, t))

        if not noopt:
            get_flags('opt', oflags)
            if not noarch:
                get_flags('arch', aflags)
        if debug:
            get_flags('debug', dflags)

        fflags = self.flag_vars.flags + dflags + oflags + aflags

        if f77:
            self.set_commands(compiler_f77=[f77] + f77flags + fflags)
        if f90:
            self.set_commands(compiler_f90=[f90] + freeflags + f90flags +
                              fflags)
        if fix:
            self.set_commands(compiler_fix=[fix] + fixflags + fflags)

        #XXX: Do we need LDSHARED->SOSHARED, LDFLAGS->SOFLAGS
        linker_so = self.linker_so
        if linker_so:
            linker_so_flags = self.flag_vars.linker_so
            if sys.platform.startswith('aix'):
                python_lib = get_python_lib(standard_lib=1)
                ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix')
                python_exp = os.path.join(python_lib, 'config', 'python.exp')
                linker_so = [ld_so_aix] + linker_so + ['-bI:' + python_exp]
            self.set_commands(linker_so=linker_so + linker_so_flags)

        linker_exe = self.linker_exe
        if linker_exe:
            linker_exe_flags = self.flag_vars.linker_exe
            self.set_commands(linker_exe=linker_exe + linker_exe_flags)

        ar = self.command_vars.archiver
        if ar:
            arflags = self.flag_vars.ar
            self.set_commands(archiver=[ar] + arflags)

        self.set_library_dirs(self.get_library_dirs())
        self.set_libraries(self.get_libraries())
    def run(self):
        if not self.extensions:
            return

        # Make sure that extension sources are complete.
        self.run_command("build_src")

        if self.distribution.has_c_libraries():
            if self.inplace:
                if self.distribution.have_run.get("build_clib"):
                    log.warn("build_clib already run, it is too late to "
                             "ensure in-place build of build_clib")
                    build_clib = self.distribution.get_command_obj(
                        "build_clib")
                else:
                    build_clib = self.distribution.get_command_obj(
                        "build_clib")
                    build_clib.inplace = 1
                    build_clib.ensure_finalized()
                    build_clib.run()
                    self.distribution.have_run["build_clib"] = 1

            else:
                self.run_command("build_clib")
                build_clib = self.get_finalized_command("build_clib")
            self.library_dirs.append(build_clib.build_clib)
        else:
            build_clib = None

        # Not including C libraries to the list of
        # extension libraries automatically to prevent
        # bogus linking commands. Extensions must
        # explicitly specify the C libraries that they use.

        from distutils.ccompiler import new_compiler
        from numpy.distutils.fcompiler import new_fcompiler

        compiler_type = self.compiler
        # Initialize C compiler:
        self.compiler = new_compiler(
            compiler=compiler_type,
            verbose=self.verbose,
            dry_run=self.dry_run,
            force=self.force,
        )
        self.compiler.customize(self.distribution)
        self.compiler.customize_cmd(self)

        if self.warn_error:
            self.compiler.compiler.append("-Werror")
            self.compiler.compiler_so.append("-Werror")

        self.compiler.show_customization()

        if not self.disable_optimization:
            dispatch_hpath = os.path.join("numpy", "distutils", "include",
                                          "npy_cpu_dispatch_config.h")
            dispatch_hpath = os.path.join(
                self.get_finalized_command("build_src").build_src,
                dispatch_hpath)
            opt_cache_path = os.path.abspath(
                os.path.join(self.build_temp, "ccompiler_opt_cache_ext.py"))
            self.compiler_opt = new_ccompiler_opt(
                compiler=self.compiler,
                dispatch_hpath=dispatch_hpath,
                cpu_baseline=self.cpu_baseline,
                cpu_dispatch=self.cpu_dispatch,
                cache_path=opt_cache_path,
            )
            if not self.compiler_opt.is_cached():
                log.info(
                    "Detected changes on compiler optimizations, force rebuilding"
                )
                self.force = True

            import atexit

            def report():
                log.info("\n########### EXT COMPILER OPTIMIZATION ###########")
                log.info(self.compiler_opt.report(full=True))

            atexit.register(report)

        # Setup directory for storing generated extra DLL files on Windows
        self.extra_dll_dir = os.path.join(self.build_temp, ".libs")
        if not os.path.isdir(self.extra_dll_dir):
            os.makedirs(self.extra_dll_dir)

        # Create mapping of libraries built by build_clib:
        clibs = {}
        if build_clib is not None:
            for libname, build_info in build_clib.libraries or []:
                if libname in clibs and clibs[libname] != build_info:
                    log.warn("library %r defined more than once,"
                             " overwriting build_info\n%s... \nwith\n%s..." %
                             (libname, repr(clibs[libname])[:300],
                              repr(build_info)[:300]))
                clibs[libname] = build_info
        # .. and distribution libraries:
        for libname, build_info in self.distribution.libraries or []:
            if libname in clibs:
                # build_clib libraries have a precedence before distribution ones
                continue
            clibs[libname] = build_info

        # Determine if C++/Fortran 77/Fortran 90 compilers are needed.
        # Update extension libraries, library_dirs, and macros.
        all_languages = set()
        for ext in self.extensions:
            ext_languages = set()
            c_libs = []
            c_lib_dirs = []
            macros = []
            for libname in ext.libraries:
                if libname in clibs:
                    binfo = clibs[libname]
                    c_libs += binfo.get("libraries", [])
                    c_lib_dirs += binfo.get("library_dirs", [])
                    for m in binfo.get("macros", []):
                        if m not in macros:
                            macros.append(m)

                for l in clibs.get(libname, {}).get("source_languages", []):
                    ext_languages.add(l)
            if c_libs:
                new_c_libs = ext.libraries + c_libs
                log.info("updating extension %r libraries from %r to %r" %
                         (ext.name, ext.libraries, new_c_libs))
                ext.libraries = new_c_libs
                ext.library_dirs = ext.library_dirs + c_lib_dirs
            if macros:
                log.info("extending extension %r defined_macros with %r" %
                         (ext.name, macros))
                ext.define_macros = ext.define_macros + macros

            # determine extension languages
            if has_f_sources(ext.sources):
                ext_languages.add("f77")
            if has_cxx_sources(ext.sources):
                ext_languages.add("c++")
            l = ext.language or self.compiler.detect_language(ext.sources)
            if l:
                ext_languages.add(l)
            # reset language attribute for choosing proper linker
            if "c++" in ext_languages:
                ext_language = "c++"
            elif "f90" in ext_languages:
                ext_language = "f90"
            elif "f77" in ext_languages:
                ext_language = "f77"
            else:
                ext_language = "c"  # default
            if l and l != ext_language and ext.language:
                log.warn("resetting extension %r language from %r to %r." %
                         (ext.name, l, ext_language))
            ext.language = ext_language
            # global language
            all_languages.update(ext_languages)

        need_f90_compiler = "f90" in all_languages
        need_f77_compiler = "f77" in all_languages
        need_cxx_compiler = "c++" in all_languages

        # Initialize C++ compiler:
        if need_cxx_compiler:
            self._cxx_compiler = new_compiler(
                compiler=compiler_type,
                verbose=self.verbose,
                dry_run=self.dry_run,
                force=self.force,
            )
            compiler = self._cxx_compiler
            compiler.customize(self.distribution, need_cxx=need_cxx_compiler)
            compiler.customize_cmd(self)
            compiler.show_customization()
            self._cxx_compiler = compiler.cxx_compiler()
        else:
            self._cxx_compiler = None

        # Initialize Fortran 77 compiler:
        if need_f77_compiler:
            ctype = self.fcompiler
            self._f77_compiler = new_fcompiler(
                compiler=self.fcompiler,
                verbose=self.verbose,
                dry_run=self.dry_run,
                force=self.force,
                requiref90=False,
                c_compiler=self.compiler,
            )
            fcompiler = self._f77_compiler
            if fcompiler:
                ctype = fcompiler.compiler_type
                fcompiler.customize(self.distribution)
            if fcompiler and fcompiler.get_version():
                fcompiler.customize_cmd(self)
                fcompiler.show_customization()
            else:
                self.warn("f77_compiler=%s is not available." % (ctype))
                self._f77_compiler = None
        else:
            self._f77_compiler = None

        # Initialize Fortran 90 compiler:
        if need_f90_compiler:
            ctype = self.fcompiler
            self._f90_compiler = new_fcompiler(
                compiler=self.fcompiler,
                verbose=self.verbose,
                dry_run=self.dry_run,
                force=self.force,
                requiref90=True,
                c_compiler=self.compiler,
            )
            fcompiler = self._f90_compiler
            if fcompiler:
                ctype = fcompiler.compiler_type
                fcompiler.customize(self.distribution)
            if fcompiler and fcompiler.get_version():
                fcompiler.customize_cmd(self)
                fcompiler.show_customization()
            else:
                self.warn("f90_compiler=%s is not available." % (ctype))
                self._f90_compiler = None
        else:
            self._f90_compiler = None

        # Build extensions
        self.build_extensions()

        # Copy over any extra DLL files
        # FIXME: In the case where there are more than two packages,
        # we blindly assume that both packages need all of the libraries,
        # resulting in a larger wheel than is required. This should be fixed,
        # but it's so rare that I won't bother to handle it.
        pkg_roots = {
            self.get_ext_fullname(ext.name).split(".")[0]
            for ext in self.extensions
        }
        for pkg_root in pkg_roots:
            shared_lib_dir = os.path.join(pkg_root, ".libs")
            if not self.inplace:
                shared_lib_dir = os.path.join(self.build_lib, shared_lib_dir)
            for fn in os.listdir(self.extra_dll_dir):
                if not os.path.isdir(shared_lib_dir):
                    os.makedirs(shared_lib_dir)
                if not fn.lower().endswith(".dll"):
                    continue
                runtime_lib = os.path.join(self.extra_dll_dir, fn)
                copy_file(runtime_lib, shared_lib_dir)