numpy/distutils/tests/utilities.py

# Kanged out of numpy.f2py.tests.util for test_build_ext
from numpy.testing import IS_WASM
import textwrap
import shutil
import tempfile
import os
import re
import subprocess
import sys

#
# Check if compilers are available at all...
#

_compiler_status = None


def _get_compiler_status():
    global _compiler_status
    if _compiler_status is not None:
        return _compiler_status

    _compiler_status = (False, False, False)
    if IS_WASM:
        # Can't run compiler from inside WASM.
        return _compiler_status

    # XXX: this is really ugly. But I don't know how to invoke Distutils
    #      in a safer way...
    code = textwrap.dedent(
        f"""\
        import os
        import sys
        sys.path = {repr(sys.path)}

        def configuration(parent_name='',top_path=None):
            global config
            from numpy.distutils.misc_util import Configuration
            config = Configuration('', parent_name, top_path)
            return config

        from numpy.distutils.core import setup
        setup(configuration=configuration)

        config_cmd = config.get_config_cmd()
        have_c = config_cmd.try_compile('void foo() {{}}')
        print('COMPILERS:%%d,%%d,%%d' %% (have_c,
                                          config.have_f77c(),
                                          config.have_f90c()))
        sys.exit(99)
        """
    )
    code = code % dict(syspath=repr(sys.path))

    tmpdir = tempfile.mkdtemp()
    try:
        script = os.path.join(tmpdir, "setup.py")

        with open(script, "w") as f:
            f.write(code)

        cmd = [sys.executable, "setup.py", "config"]
        p = subprocess.Popen(
            cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=tmpdir
        )
        out, err = p.communicate()
    finally:
        shutil.rmtree(tmpdir)

    m = re.search(rb"COMPILERS:(\d+),(\d+),(\d+)", out)
    if m:
        _compiler_status = (
            bool(int(m.group(1))),
            bool(int(m.group(2))),
            bool(int(m.group(3))),
        )
    # Finished
    return _compiler_status


def has_c_compiler():
    return _get_compiler_status()[0]


def has_f77_compiler():
    return _get_compiler_status()[1]


def has_f90_compiler():
    return _get_compiler_status()[2]
Metadata
View Raw File