NumPy-源码解析-四-

41 阅读53分钟

NumPy 源码解析(四)

.\numpy\numpy\distutils\command\config_compiler.py

# 从distutils.core模块中导入Command类
from distutils.core import Command
# 从numpy.distutils模块中导入log函数
from numpy.distutils import log

#XXX: Linker flags

# 展示Fortran编译器
def show_fortran_compilers(_cache=None):
    # 使用缓存来防止无限递归
    if _cache:
        return
    # 如果缓存为None,则初始化为空列表
    elif _cache is None:
        _cache = []
    # 将1添加到缓存列表中
    _cache.append(1)
    # 从numpy.distutils.fcompiler模块中导入show_fcompilers函数
    from numpy.distutils.fcompiler import show_fcompilers
    # 从distutils.core模块中导入_setup_distribution属性
    import distutils.core
    dist = distutils.core._setup_distribution
    # 展示Fortran编译器
    show_fcompilers(dist)

# 继承自Command类的config_fc类
class config_fc(Command):
    """ Distutils command to hold user specified options
    to Fortran compilers.

    config_fc command is used by the FCompiler.customize() method.
    """

    # 描述信息
    description = "specify Fortran 77/Fortran 90 compiler information"

    # 用户选项列表
    user_options = [
        ('fcompiler=', None, "specify Fortran compiler type"),
        ('f77exec=', None, "specify F77 compiler command"),
        ('f90exec=', None, "specify F90 compiler command"),
        ('f77flags=', None, "specify F77 compiler flags"),
        ('f90flags=', None, "specify F90 compiler flags"),
        ('opt=', None, "specify optimization flags"),
        ('arch=', None, "specify architecture specific optimization flags"),
        ('debug', 'g', "compile with debugging information"),
        ('noopt', None, "compile without optimization"),
        ('noarch', None, "compile without arch-dependent optimization"),
        ]

    # 帮助选项列表
    help_options = [
        ('help-fcompiler', None, "list available Fortran compilers",
         show_fortran_compilers),
        ]

    # 布尔选项列表
    boolean_options = ['debug', 'noopt', 'noarch']

    # 初始化选项
    def initialize_options(self):
        self.fcompiler = None
        self.f77exec = None
        self.f90exec = None
        self.f77flags = None
        self.f90flags = None
        self.opt = None
        self.arch = None
        self.debug = None
        self.noopt = None
        self.noarch = None

    # 最终选项
    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)

    # 运行方法
    def run(self):
        # 什么也不做
        return

# 继承自Command类的config_cc类
class config_cc(Command):
    # 用于保存用户指定的 C/C++ 编译器选项的 Distutils 命令
    description = "specify C/C++ compiler information"
    
    # 用户选项列表
    user_options = [
        ('compiler=', None, "specify C/C++ compiler type"),
        ]
    
    # 初始化选项
    def initialize_options(self):
        self.compiler = None
    
    # 最终选项
    def finalize_options(self):
        log.info('unifing config_cc, config, build_clib, build_ext, build commands --compiler 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 ['compiler']:
            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)
        return
    
    # 运行命令
    def run(self):
        # 什么也不做
        return

.\numpy\numpy\distutils\command\develop.py

"""
用于重写 setuptools 中的 develop 命令,以确保我们从 build_src 或 build_scripts 生成的文件被正确转换为真实文件并具有文件名。

"""
# 从 setuptools.command.develop 导入 develop 类
from setuptools.command.develop import develop as old_develop

# 创建一个新的 develop 类,继承自 old_develop
class develop(old_develop):
    # 复制旧 develop 类的文档字符串
    __doc__ = old_develop.__doc__
    # 安装用于开发的命令
    def install_for_development(self):
        # 在原地构建源文件
        self.reinitialize_command('build_src', inplace=1)
        # 确保脚本已构建
        self.run_command('build_scripts')
        # 调用旧的 develop 类的 install_for_development 方法
        old_develop.install_for_development(self)

.\numpy\numpy\distutils\command\egg_info.py

# 导入sys模块
import sys

# 从setuptools.command.egg_info模块中导入egg_info类,重命名为_egg_info
from setuptools.command.egg_info import egg_info as _egg_info

# 定义egg_info类,继承自_egg_info类
class egg_info(_egg_info):
    # 定义run方法
    def run(self):
        # 如果'sdist'在sys.argv中
        if 'sdist' in sys.argv:
            # 导入warnings模块
            import warnings
            # 导入textwrap模块
            import textwrap
            # 定义消息内容
            msg = textwrap.dedent("""
                `build_src` is being run, this may lead to missing
                files in your sdist!  You want to use distutils.sdist
                instead of the setuptools version:

                    from distutils.command.sdist import sdist
                    cmdclass={'sdist': sdist}"

                See numpy's setup.py or gh-7131 for details.""")
            # 发出UserWarning警告,显示消息内容
            warnings.warn(msg, UserWarning, stacklevel=2)

        # 确保build_src已经执行,以便为setuptools的egg_info命令提供真实的文件名,而不是生成文件的函数
        self.run_command("build_src")
        # 调用_egg_info类的run方法
        _egg_info.run(self)

.\numpy\numpy\distutils\command\install.py

# 导入 sys 模块
import sys
# 检查 setuptools 是否在 sys 模块中
if 'setuptools' in sys.modules:
    # 如果是,导入 setuptools.command.install 模块并重命名为 old_install_mod
    import setuptools.command.install as old_install_mod
    # 设置 have_setuptools 为 True
    have_setuptools = True
else:
    # 如果不是,导入 distutils.command.install 模块并重命名为 old_install_mod
    import distutils.command.install as old_install_mod
    # 设置 have_setuptools 为 False
    have_setuptools = False
# 导入 distutils.file_util 模块中的 write_file 方法
from distutils.file_util import write_file

# 将 old_install_mod.install 方法保存到 old_install 变量中
old_install = old_install_mod.install

# 创建名为 install 的类并继承 old_install 类
class install(old_install):

    # 始终运行 install_clib - 这个命令很便宜,所以无需绕过它;
    # 但它不会被 setuptools 运行 - 所以它会在 install_data 中再次运行
    sub_commands = old_install.sub_commands + [
        ('install_clib', lambda x: True)
    ]

    # 完成选项的设置
    def finalize_options (self):
        old_install.finalize_options(self)
        self.install_lib = self.install_libbase

    # setuptools 版本的 .run() 方法
    def setuptools_run(self):
        """ The setuptools version of the .run() method.

    We must pull in the entire code so we can override the level used in the
    _getframe() call since we wrap this call by one more level.
    """
        from distutils.command.install import install as distutils_install

    # 明确请求旧式安装?直接执行
        if self.old_and_unmanageable or self.single_version_externally_managed:
            return distutils_install.run(self)

    # 尝试检测是否被 setup() 或其他命令调用。如果被 setup() 调用,我们的调用者将是 'distutils.dist' 中的 'run_command' 方法,而*其*调用者将是 'run_commands' 方法。如果以其他方式被调用,我们的直接调用者*可能*是 'run_command',但其不是被 'run_commands' 调用。这有点笨拙,但似乎可行。
        caller = sys._getframe(3)
        caller_module = caller.f_globals.get('__name__', '')
        caller_name = caller.f_code.co_name

        if caller_module != 'distutils.dist' or caller_name!='run_commands':
    # 我们不是从命令行或 setup() 被调用,所以我们应该以向后兼容的方式运行,以支持 bdist_* 命令。
    distutils_install.run(self)
        else:
    self.do_egg_install()
    # 定义一个方法,用于运行安装程序
    def run(self):
        # 如果没有安装 setuptools,则调用旧的安装方法
        if not have_setuptools:
            r = old_install.run(self)
        # 如果有安装 setuptools,则调用 setuptools 的运行方法
        else:
            r = self.setuptools_run()
        # 如果记录安装的文件
        if self.record:
            # 当 INSTALLED_FILES 包含带有空格的路径时,bdist_rpm 会失败。
            # 这样的路径必须用双引号括起来。
            with open(self.record) as f:
                lines = []
                need_rewrite = False
                # 遍历记录中的每一行
                for l in f:
                    l = l.rstrip()
                    # 如果该行包含空格,则需要重写记录
                    if ' ' in l:
                        need_rewrite = True
                        l = '"%s"' % (l)
                    lines.append(l)
            # 如果需要重写记录,则执行写文件方法,将记录覆盖写入
            if need_rewrite:
                self.execute(write_file, (self.record, lines), "re-writing list of installed files to '%s'" % self.record)
        # 返回运行结果
        return r

.\numpy\numpy\distutils\command\install_clib.py

import os
from distutils.core import Command
from distutils.ccompiler import new_compiler
from numpy.distutils.misc_util import get_cmd

class install_clib(Command):
    # 定义安装可安装 C 库的命令
    description = "Command to install installable C libraries"

    user_options = []

    def initialize_options(self):
        # 初始化选项
        self.install_dir = None
        self.outfiles = []

    def finalize_options(self):
        # 完成选项设置
        self.set_undefined_options('install', ('install_lib', 'install_dir'))

    def run (self):
        # 运行安装 C 库的命令
        build_clib_cmd = get_cmd("build_clib")
        if not build_clib_cmd.build_clib:
            # 可能出现用户指定 `--skip-build` 的情况
            build_clib_cmd.finalize_options()
        build_dir = build_clib_cmd.build_clib

        # 需要编译器来获取库名-> 文件名的关联
        if not build_clib_cmd.compiler:
            compiler = new_compiler(compiler=None)
            compiler.customize(self.distribution)
        else:
            compiler = build_clib_cmd.compiler

        for l in self.distribution.installed_libraries:
            target_dir = os.path.join(self.install_dir, l.target_dir)
            name = compiler.library_filename(l.name)
            source = os.path.join(build_dir, name)
            self.mkpath(target_dir)
            self.outfiles.append(self.copy_file(source, target_dir)[0])

    def get_outputs(self):
        # 获取输出文件
        return self.outfiles

.\numpy\numpy\distutils\command\install_data.py

# 导入sys模块
import sys
# 检查是否已导入setuptools模块
have_setuptools = ('setuptools' in sys.modules)

# 导入distutils.command.install_data模块的install_data类为old_install_data
from distutils.command.install_data import install_data as old_install_data

# 数据安装程序,比distutils具有更好的智能
# 数据文件被复制到项目目录而不是随意放置
class install_data (old_install_data):

    # 运行安装数据程序
    def run(self):
        # 调用old_install_data的run方法
        old_install_data.run(self)

        # 如果已经导入setuptools模块
        if have_setuptools:
            # 再次运行install_clib,因为setuptools不会自动运行install的子命令
            self.run_command('install_clib')

    # 设置选项的最终方法
    def finalize_options (self):
        # 设置未定义的选项 install_lib, root, force
        self.set_undefined_options('install',
                                   ('install_lib', 'install_dir'),
                                   ('root', 'root'),
                                   ('force', 'force'),
                                  )

.\numpy\numpy\distutils\command\install_headers.py

# 导入 os 模块
import os
# 从 distutils.command.install_headers 模块导入 install_headers 类,用作老的 install_headers
from distutils.command.install_headers import install_headers as old_install_headers

# 创建一个名为 install_headers 的类,继承自 old_install_headers 类
class install_headers (old_install_headers):

    # 定义 run 方法
    def run (self):
        # 获取分发的头文件列表
        headers = self.distribution.headers
        # 如果没有头文件,则返回
        if not headers:
            return

        # 获取安装目录的上一级目录
        prefix = os.path.dirname(self.install_dir)
        # 遍历头文件列表
        for header in headers:
            # 如果头文件是一个元组
            if isinstance(header, tuple):
                # 一种小技巧,但我不知道在哪里修改这个...
                if header[0] == 'numpy._core':
                    # 将头文件的第一个元素修改为 'numpy',保留第二个元素不变
                    header = ('numpy', header[1])
                    # 如果头文件的扩展名为 '.inc',则跳过此头文件
                    if os.path.splitext(header[1])[1] == '.inc':
                        continue
                # 根据头文件的第一个元素创建安装路径
                d = os.path.join(*([prefix]+header[0].split('.')))
                # 获取头文件的第二个元素
                header = header[1]
            else:
                # 如果头文件不是元组,使用默认的安装路径
                d = self.install_dir
            # 创建安装路径
            self.mkpath(d)
            # 复制头文件到安装路径,并将复制的文件名添加到 outfiles 列表
            (out, _) = self.copy_file(header, d)
            self.outfiles.append(out)

.\numpy\numpy\distutils\command\sdist.py

# 导入sys模块
import sys
# 检查是否在sys模块中存在setuptools模块
if 'setuptools' in sys.modules:
    # 如果存在,则导入setuptools.command.sdist模块中的sdist类,并命名为old_sdist
    from setuptools.command.sdist import sdist as old_sdist
else:
    # 如果不存在,则导入distutils.command.sdist模块中的sdist类,并命名为old_sdist
    from distutils.command.sdist import sdist as old_sdist

# 导入numpy.distutils.misc_util模块中的get_data_files函数
from numpy.distutils.misc_util import get_data_files

# 创建一个名为sdist的类,继承自old_sdist类
class sdist(old_sdist):

    # 定义add_defaults方法
    def add_defaults (self):
        # 调用old_sdist类的add_defaults方法
        old_sdist.add_defaults(self)

        # 获取self.distribution,并赋值给dist
        dist = self.distribution

        # 如果dist具有数据文件,则遍历dist.data_files并将文件列表添加到filelist中
        if dist.has_data_files():
            for data in dist.data_files:
                self.filelist.extend(get_data_files(data))

        # 如果dist具有头文件,则遍历dist.headers,如果是字符串则直接添加到filelist中,如果是元组则取索引为1的元素添加到filelist中
        if dist.has_headers():
            headers = []
            for h in dist.headers:
                if isinstance(h, str): headers.append(h)
                else: headers.append(h[1])
            self.filelist.extend(headers)

        return

.\numpy\numpy\distutils\command\__init__.py

# 导入distutils.command模块
"""distutils.command

Package containing implementation of all the standard Distutils
commands.

"""
# 删除测试对象属性不可写
def test_na_writable_attributes_deletion():
    # 创建NA对象
    a = np.NA(2)
    # 待删除的属性列表
    attr =  ['payload', 'dtype']
    # 遍历属性列表
    for s in attr:
        # 断言删除属性时出现属性错误
        assert_raises(AttributeError, delattr, a, s)

# 版本信息
__revision__ = "$Id: __init__.py,v 1.3 2005/05/16 11:08:49 pearu Exp $"

# 所有distutils命令列表
distutils_all = [  #'build_py',
                   'clean',
                   'install_clib',
                   'install_scripts',
                   'bdist',
                   'bdist_dumb',
                   'bdist_wininst',
                ]

# 动态导入distutils.command模块中的指定命令
__import__('distutils.command', globals(), locals(), distutils_all)

# 导出的模块列表
__all__ = ['build',
           'config_compiler',
           'config',
           'build_src',
           'build_py',
           'build_ext',
           'build_clib',
           'build_scripts',
           'install',
           'install_data',
           'install_headers',
           'install_lib',
           'bdist_rpm',
           'sdist',
          ] + distutils_all

.\numpy\numpy\distutils\conv_template.py

# 解析输入字符串中的重复块结构,返回第一级重复块的起始和结束标记
def parse_structure(astr, level):
    """
    The returned line number is from the beginning of the string, starting
    at zero. Returns an empty list if no loops found.

    """
    # 如果是第一级重复块,则使用标准的起始和结束标记
    if level == 0 :
        loopbeg = "/**begin repeat"
        loopend = "/**end repeat**/"
    # 对于嵌套的重复块,使用带有深度编号的起始和结束标记
    else :
        loopbeg = "/**begin repeat%d" % level
        loopend = "/**end repeat%d**/" % level

    ind = 0  # 初始化索引
    line = 0  # 初始化行数
    spanlist = []  # 初始化用于存储重复块位置的列表
    # 循环直到条件不再满足
    while True:
        # 在字符串 astr 中从索引 ind 开始查找字符串 loopbeg 的第一个出现位置
        start = astr.find(loopbeg, ind)
        # 如果未找到,则退出循环
        if start == -1:
            break
        # 继续在字符串 astr 中查找 "*/" 的第一个出现位置,起始索引为 start
        start2 = astr.find("*/", start)
        # 在找到的 "*/" 后查找下一个换行符的位置
        start2 = astr.find("\n", start2)
        # 在字符串 astr 中从 start2 开始查找字符串 loopend 的第一个出现位置
        fini1 = astr.find(loopend, start2)
        # 继续在找到的 loopend 后查找下一个换行符的位置
        fini2 = astr.find("\n", fini1)
        # 计算并累加位于 ind 和 start2+1 之间的换行符数量到 line 中
        line += astr.count("\n", ind, start2+1)
        # 将找到的起始和结束位置以及相关行号信息作为元组添加到 spanlist 中
        spanlist.append((start, start2+1, fini1, fini2+1, line))
        # 计算并累加位于 start2+1 和 fini2 之间的换行符数量到 line 中
        line += astr.count("\n", start2+1, fini2)
        # 更新查找的起始索引 ind 为 fini2
        ind = fini2
    # 对 spanlist 中的元组按照起始位置排序
    spanlist.sort()
    # 返回排序后的 spanlist 列表
    return spanlist
# 为给定的正则表达式模式创建一个编译对象,用于匹配字符串中的 '(a,b,c)*4' 格式
parenrep = re.compile(r"\(([^)]*)\)\*(\d+)")
# 为给定的正则表达式模式创建一个编译对象,用于匹配字符串中的 'xxx*3' 格式
plainrep = re.compile(r"([^*]+)\*(\d+)")

def parse_values(astr):
    """
    替换字符串 astr 中所有的 '(a,b,c)*4' 形式为 'a,b,c,a,b,c,a,b,c,a,b,c'。
    空括号生成空值,例如 '()*4' 返回 ',,,'。结果按 ',' 分割并返回值列表。
    替换字符串 astr 中所有的 'xxx*3' 形式为 'xxx,xxx,xxx'。
    """
    astr = parenrep.sub(paren_repl, astr)
    astr = ','.join([plainrep.sub(paren_repl, x.strip()) for x in astr.split(',')])
    return astr.split(',')

# 为给定的正则表达式模式创建一个编译对象,用于匹配字符串中的 '\n\s*\*?' 格式
stripast = re.compile(r"\n\s*\*?")
# 为给定的正则表达式模式创建一个编译对象,用于匹配字符串中的 '# name = value #' 格式
named_re = re.compile(r"#\s*(\w*)\s*=([^#]*)#")
# 为给定的正则表达式模式创建一个编译对象,用于匹配字符串中的 'var1=value1' 格式
exclude_vars_re = re.compile(r"(\w*)=(\w*)")
# 为给定的正则表达式模式创建一个编译对象,用于匹配字符串中的 ':exclude:' 格式
exclude_re = re.compile(":exclude:")

def parse_loop_header(loophead):
    """
    解析循环头部字符串,查找所有的命名替换和排除变量。

    返回两个部分:
    1. 一个字典列表,每个字典代表一个循环迭代,其中键是要替换的名称,值是替换的字符串。
    2. 一个排除列表,每个条目都是一个字典,包含要排除的变量名和对应的值。
    """
    loophead = stripast.sub("", loophead)
    names = []
    reps = named_re.findall(loophead)
    nsub = None
    for rep in reps:
        name = rep[0]
        vals = parse_values(rep[1])
        size = len(vals)
        if nsub is None:
            nsub = size
        elif nsub != size:
            msg = "Mismatch in number of values, %d != %d\n%s = %s"
            raise ValueError(msg % (nsub, size, name, vals))
        names.append((name, vals))

    excludes = []
    for obj in exclude_re.finditer(loophead):
        span = obj.span()
        endline = loophead.find('\n', span[1])
        substr = loophead[span[1]:endline]
        ex_names = exclude_vars_re.findall(substr)
        excludes.append(dict(ex_names))

    dlist = []
    if nsub is None:
        raise ValueError("No substitution variables found")
    for i in range(nsub):
        tmp = {name: vals[i] for name, vals in names}
        dlist.append(tmp)
    return dlist

# 为给定的正则表达式模式创建一个编译对象,用于匹配字符串中的 '@varname@' 格式
replace_re = re.compile(r"@(\w+)@")

def parse_string(astr, env, level, line):
    """
    解析字符串 astr,替换其中的 '@varname@' 格式为环境变量中对应的值。

    参数:
    - astr: 待解析的字符串
    - env: 环境变量字典,用于替换 '@varname@' 中的 varname
    - level: 解析层级
    - line: 当前处理的行数

    返回替换后的字符串以及包含当前行号信息的字符串
    """
    lineno = "#line %d\n" % line
    # 定义一个函数 replace,用于替换字符串中的变量名为对应的值
    def replace(match):
        # 获取匹配到的变量名
        name = match.group(1)
        try:
            # 尝试从环境变量中获取对应变量名的值
            val = env[name]
        except KeyError:
            # 如果变量名在环境变量中未定义,抛出错误并指明行号和变量名
            msg = 'line %d: no definition of key "%s"' % (line, name)
            raise ValueError(msg) from None
        # 返回变量名对应的值
        return val

    # 初始化代码列表,包含初始行号
    code = [lineno]
    # 解析给定的结构化字符串 astr,得到结构信息 struct
    struct = parse_structure(astr, level)
    if struct:
        # 如果存在结构信息,则递归处理内部循环
        oldend = 0
        newlevel = level + 1
        for sub in struct:
            # 分别获取前缀、头部、文本和结束位置等信息
            pref = astr[oldend:sub[0]]
            head = astr[sub[0]:sub[1]]
            text = astr[sub[1]:sub[2]]
            oldend = sub[3]
            newline = line + sub[4]
            # 将前缀部分中的变量名替换为对应的值
            code.append(replace_re.sub(replace, pref))
            try:
                # 解析循环头部,获取环境变量列表
                envlist = parse_loop_header(head)
            except ValueError as e:
                # 如果解析出错,抛出包含行号和错误信息的新错误
                msg = "line %d: %s" % (newline, e)
                raise ValueError(msg)
            for newenv in envlist:
                # 更新新环境变量列表,并解析文本内容得到新代码,追加到 code 中
                newenv.update(env)
                newcode = parse_string(text, newenv, newlevel, newline)
                code.extend(newcode)
        # 获取剩余的后缀部分并进行变量名替换
        suff = astr[oldend:]
        code.append(replace_re.sub(replace, suff))
    else:
        # 如果不存在结构信息,则直接将整个字符串 astr 中的变量名替换为对应的值
        code.append(replace_re.sub(replace, astr))
    # 将代码列表转换为字符串并返回
    code.append('\n')
    return ''.join(code)
# 处理给定字符串,返回处理后的代码字符串
def process_str(astr):
    # 创建一个空的代码列表,包含头部信息
    code = [header]
    # 将解析字符串后的代码块添加到代码列表中
    code.extend(parse_string(astr, global_names, 0, 1))
    # 将代码列表转换为一个字符串并返回
    return ''.join(code)


# 匹配以#include开头的行,并捕获引号内的文件名
include_src_re = re.compile(r"(\n|\A)#include\s*['\"]"
                            r"(?P<name>[\w\d./\\]+[.]src)['\"]", re.I)

# 解析源文件中的包含文件,并返回解析后的所有行
def resolve_includes(source):
    # 获取源文件的目录路径
    d = os.path.dirname(source)
    # 打开源文件并逐行处理
    with open(source) as fid:
        lines = []
        for line in fid:
            # 匹配当前行是否为#include开头的格式
            m = include_src_re.match(line)
            if m:
                # 提取引号内的文件名
                fn = m.group('name')
                # 如果文件名不是绝对路径,则加上源文件的目录路径
                if not os.path.isabs(fn):
                    fn = os.path.join(d, fn)
                # 如果文件存在,则递归解析该文件的内容,否则直接添加当前行
                if os.path.isfile(fn):
                    lines.extend(resolve_includes(fn))
                else:
                    lines.append(line)
            else:
                lines.append(line)
    # 返回所有处理后的行组成的列表
    return lines


# 处理源文件,返回处理后的代码字符串
def process_file(source):
    # 解析源文件中的包含文件,获取所有处理后的行
    lines = resolve_includes(source)
    # 规范化源文件路径,并将路径中的反斜杠转义为双反斜杠
    sourcefile = os.path.normcase(source).replace("\\", "\\\\")
    try:
        # 调用process_str处理所有行组成的字符串,获取处理后的代码字符串
        code = process_str(''.join(lines))
    except ValueError as e:
        # 如果出现错误,则抛出新的错误,指示出错的源文件及位置
        raise ValueError('In "%s" loop at %s' % (sourcefile, e)) from None
    # 返回带有#line指令的处理后的代码字符串
    return '#line 1 "%s"\n%s' % (sourcefile, code)


# 给定一个字典,生成一个唯一的键
def unique_key(adict):
    # 获取字典中所有的键
    allkeys = list(adict.keys())
    done = False
    n = 1
    # 循环直到生成一个唯一的键
    while not done:
        # 按长度为n的方式生成新的键
        newkey = "".join([x[:n] for x in allkeys])
        # 如果新键已经存在于字典的键中,则增加n的长度
        if newkey in allkeys:
            n += 1
        else:
            done = True
    # 返回生成的唯一键
    return newkey


# 主程序入口
def main():
    try:
        # 尝试从命令行参数中获取文件名
        file = sys.argv[1]
    except IndexError:
        # 如果没有命令行参数,则使用标准输入和标准输出
        fid = sys.stdin
        outfile = sys.stdout
    else:
        # 如果有命令行参数,则打开对应的输入文件和输出文件
        fid = open(file, 'r')
        (base, ext) = os.path.splitext(file)
        newname = base
        outfile = open(newname, 'w')

    # 读取所有输入内容
    allstr = fid.read()
    try:
        # 处理所有输入内容,并获取处理后的字符串
        writestr = process_str(allstr)
    except ValueError as e:
        # 如果处理过程中出错,则抛出新的错误,指示出错的文件及位置
        raise ValueError("In %s loop at %s" % (file, e)) from None

    # 将处理后的字符串写入输出文件
    outfile.write(writestr)


# 如果当前脚本作为主程序运行,则调用main函数
if __name__ == "__main__":
    main()

.\numpy\numpy\distutils\core.py

# 导入 sys 模块,用于系统相关操作
import sys
# 从 distutils.core 模块导入 Distribution 类,用于处理发行版相关任务
from distutils.core import Distribution

# 检查是否已导入 setuptools 模块
if 'setuptools' in sys.modules:
    have_setuptools = True
    # 如果有 setuptools,则从 setuptools 中导入 setup 函数,并重命名为 old_setup
    from setuptools import setup as old_setup
    # 导入 setuptools.command 中的 easy_install 模块,用于安装包
    # 注意:easy_install 还会导入 math 模块,可能从当前工作目录中获取
    from setuptools.command import easy_install
    try:
        # 尝试导入 setuptools.command 中的 bdist_egg 模块,用于创建 egg 包
        from setuptools.command import bdist_egg
    except ImportError:
        # 如果导入失败,表示 setuptools 版本过旧,设置 have_setuptools 为 False
        have_setuptools = False
else:
    # 如果没有导入 setuptools,则从 distutils.core 中导入 setup 函数,并重命名为 old_setup
    from distutils.core import setup as old_setup
    have_setuptools = False

# 导入 warnings 模块,用于处理警告信息
import warnings
# 导入 distutils.core 和 distutils.dist 模块,用于核心任务和发行版任务
import distutils.core
import distutils.dist

# 从 numpy.distutils.extension 模块中导入 Extension 类,用于编译扩展模块
from numpy.distutils.extension import Extension  # noqa: F401
# 从 numpy.distutils.numpy_distribution 模块中导入 NumpyDistribution 类,用于处理 NumPy 发行版
from numpy.distutils.numpy_distribution import NumpyDistribution
# 从 numpy.distutils.command 模块中导入多个命令类,用于编译、构建等任务
from numpy.distutils.command import config, config_compiler, \
     build, build_py, build_ext, build_clib, build_src, build_scripts, \
     sdist, install_data, install_headers, install, bdist_rpm, \
     install_clib
# 从 numpy.distutils.misc_util 模块中导入辅助函数 is_sequence 和 is_string
from numpy.distutils.misc_util import is_sequence, is_string

# 定义一个字典 numpy_cmdclass,存储各个命令类对应的处理类
numpy_cmdclass = {'build':            build.build,
                  'build_src':        build_src.build_src,
                  'build_scripts':    build_scripts.build_scripts,
                  'config_cc':        config_compiler.config_cc,
                  'config_fc':        config_compiler.config_fc,
                  'config':           config.config,
                  'build_ext':        build_ext.build_ext,
                  'build_py':         build_py.build_py,
                  'build_clib':       build_clib.build_clib,
                  'sdist':            sdist.sdist,
                  'install_data':     install_data.install_data,
                  'install_headers':  install_headers.install_headers,
                  'install_clib':     install_clib.install_clib,
                  'install':          install.install,
                  'bdist_rpm':        bdist_rpm.bdist_rpm,
                  }

# 如果有 setuptools 模块,则继续进行以下设置
if have_setuptools:
    # 从 numpy.distutils.command 中导入 develop 和 egg_info 模块
    from numpy.distutils.command import develop, egg_info
    # 向 numpy_cmdclass 字典中添加更多命令类和对应的处理类
    numpy_cmdclass['bdist_egg'] = bdist_egg.bdist_egg
    numpy_cmdclass['develop'] = develop.develop
    numpy_cmdclass['easy_install'] = easy_install.easy_install
    numpy_cmdclass['egg_info'] = egg_info.egg_info

def _dict_append(d, **kws):
    """向字典 d 中的键值对进行追加或更新
    
    Args:
        d (dict): 目标字典
        **kws: 关键字参数,键为要追加或更新的字典键,值为要追加或更新的对应值
    """
    for k, v in kws.items():
        if k not in d:
            d[k] = v
            continue
        dv = d[k]
        if isinstance(dv, tuple):
            d[k] = dv + tuple(v)
        elif isinstance(dv, list):
            d[k] = dv + list(v)
        elif isinstance(dv, dict):
            _dict_append(dv, **v)
        elif is_string(dv):
            d[k] = dv + v
        else:
            raise TypeError(repr(type(dv)))

def _command_line_ok(_cache=None):
    """检查命令行是否不包含任何帮助或显示请求
    
    Args:
        _cache (list, optional): 用于缓存结果的列表
    
    Returns:
        bool: 如果命令行没有包含帮助或显示请求,则返回 True,否则返回 False
    """
    if _cache:
        return _cache[0]
    elif _cache is None:
        _cache = []
    # 初始化一个布尔变量,用于标记参数是否合法,默认为True
    ok = True
    # 根据 Distribution 类的 display_option_names 属性生成展示选项列表
    display_opts = ['--'+n for n in Distribution.display_option_names]
    # 遍历 Distribution 类的 display_options 属性
    for o in Distribution.display_options:
        # 如果选项的第二个元素为真,将其简写形式添加到展示选项列表中
        if o[1]:
            display_opts.append('-'+o[1])
    # 遍历命令行参数列表
    for arg in sys.argv:
        # 如果命令行参数以 '--help' 开头,或者是 '-h',或者在展示选项列表中
        if arg.startswith('--help') or arg=='-h' or arg in display_opts:
            # 将 ok 设置为 False,表示参数不合法
            ok = False
            # 跳出循环,不再检查后续的命令行参数
            break
    # 将检查结果添加到 _cache 列表中
    _cache.append(ok)
    # 返回参数合法性的检查结果
    return ok
def get_distribution(always=False):
    # 获取当前的分发对象
    dist = distutils.core._setup_distribution
    # XXX Hack to get numpy installable with easy_install.
    # The problem is easy_install runs it's own setup(), which
    # sets up distutils.core._setup_distribution. However,
    # when our setup() runs, that gets overwritten and lost.
    # We can't use isinstance, as the DistributionWithoutHelpCommands
    # class is local to a function in setuptools.command.easy_install
    # 这段代码用来处理使用 easy_install 安装 numpy 的问题。
    # easy_install 会运行自己的 setup(),设置了 distutils.core._setup_distribution。
    # 当我们的 setup() 运行时,会覆盖并丢失这个设置。通过这段代码来修复这个问题。
    if dist is not None and \
            'DistributionWithoutHelpCommands' in repr(dist):
        dist = None
    if always and dist is None:
        # 如果指定了 always=True 并且 dist 为 None,则使用 NumpyDistribution 类
        dist = NumpyDistribution()
    return dist

def setup(**attr):

    cmdclass = numpy_cmdclass.copy()

    new_attr = attr.copy()
    if 'cmdclass' in new_attr:
        # 更新 cmdclass,如果在 attr 中指定了 cmdclass
        cmdclass.update(new_attr['cmdclass'])
    new_attr['cmdclass'] = cmdclass

    if 'configuration' in new_attr:
        # To avoid calling configuration if there are any errors
        # or help request in command in the line.
        # 如果命令行中存在错误或者帮助请求,避免调用 configuration 方法。
        configuration = new_attr.pop('configuration')

        old_dist = distutils.core._setup_distribution
        old_stop = distutils.core._setup_stop_after
        distutils.core._setup_distribution = None
        distutils.core._setup_stop_after = "commandline"
        try:
            # 递归调用 setup(),处理新的属性
            dist = setup(**new_attr)
        finally:
            # 恢复原来的 _setup_distribution 和 _setup_stop_after 设置
            distutils.core._setup_distribution = old_dist
            distutils.core._setup_stop_after = old_stop
        if dist.help or not _command_line_ok():
            # 如果显示了帮助信息或者命令行状态不正确,直接返回 dist
            # 跳过运行任何命令
            return dist

        # create setup dictionary and append to new_attr
        # 创建配置字典并添加到 new_attr
        config = configuration()
        if hasattr(config, 'todict'):
            config = config.todict()
        _dict_append(new_attr, **config)

    # Move extension source libraries to libraries
    # 将扩展模块的源代码库移动到 libraries 中
    libraries = []
    for ext in new_attr.get('ext_modules', []):
        new_libraries = []
        for item in ext.libraries:
            if is_sequence(item):
                lib_name, build_info = item
                _check_append_ext_library(libraries, lib_name, build_info)
                new_libraries.append(lib_name)
            elif is_string(item):
                new_libraries.append(item)
            else:
                raise TypeError("invalid description of extension module "
                                "library %r" % (item,))
        ext.libraries = new_libraries
    if libraries:
        if 'libraries' not in new_attr:
            new_attr['libraries'] = []
        for item in libraries:
            _check_append_library(new_attr['libraries'], item)

    # sources in ext_modules or libraries may contain header files
    # ext_modules 或 libraries 中可能包含头文件
    if ('ext_modules' in new_attr or 'libraries' in new_attr) \
       and 'headers' not in new_attr:
        new_attr['headers'] = []

    # Use our custom NumpyDistribution class instead of distutils' one
    # 使用我们自定义的 NumpyDistribution 类,替代 distutils 的类
    new_attr['distclass'] = NumpyDistribution

    return old_setup(**new_attr)
# 检查并向库列表中追加新的库项或更新现有库项的构建信息(如果存在)
def _check_append_library(libraries, item):
    # 遍历库列表中的每一项
    for libitem in libraries:
        # 检查当前库项是否为序列(元组或列表)
        if is_sequence(libitem):
            # 如果待添加的项也是序列
            if is_sequence(item):
                # 如果两个序列的第一个元素相等
                if item[0] == libitem[0]:
                    # 如果第二个元素也相等,则表示已存在相同的库项
                    if item[1] is libitem[1]:
                        return  # 直接返回,无需更新
                    # 如果第二个元素不相等,则发出警告
                    warnings.warn("[0] libraries list contains %r with"
                                  " different build_info" % (item[0],),
                                  stacklevel=2)
                    break
            else:
                # 如果待添加的项不是序列,但与库项的第一个元素相等
                if item == libitem[0]:
                    # 发出相应的警告
                    warnings.warn("[1] libraries list contains %r with"
                                  " no build_info" % (item[0],),
                                  stacklevel=2)
                    break
        else:
            # 如果库项本身不是序列,检查待添加的项是否为序列
            if is_sequence(item):
                # 如果待添加的项的第一个元素与当前库项相等
                if item[0] == libitem:
                    # 发出相应的警告
                    warnings.warn("[2] libraries list contains %r with"
                                  " no build_info" % (item[0],),
                                  stacklevel=2)
                    break
            else:
                # 如果两者相等,则表示已存在相同的库项
                if item == libitem:
                    return  # 直接返回,无需更新

    # 如果未发现相同的库项,则将新的库项添加到列表末尾
    libraries.append(item)

# 检查并向外部库列表中追加新的库项或更新现有库项的构建信息(如果存在)
def _check_append_ext_library(libraries, lib_name, build_info):
    # 遍历库列表中的每一项
    for item in libraries:
        # 检查当前库项是否为序列(元组或列表)
        if is_sequence(item):
            # 如果库项是一个序列,并且序列的第一个元素与指定的库名相等
            if item[0] == lib_name:
                # 如果序列的第二个元素也相等,则表示已存在相同的库项
                if item[1] is build_info:
                    return  # 直接返回,无需更新
                # 如果第二个元素不相等,则发出警告
                warnings.warn("[3] libraries list contains %r with"
                              " different build_info" % (lib_name,),
                              stacklevel=2)
                break
        else:
            # 如果当前库项不是序列,并且与指定的库名相等
            if item == lib_name:
                # 发出相应的警告
                warnings.warn("[4] libraries list contains %r with"
                              " no build_info" % (lib_name,),
                              stacklevel=2)
                break

    # 如果未发现相同的库项,则将新的库名和构建信息添加为元组到列表末尾
    libraries.append((lib_name, build_info))

.\numpy\numpy\distutils\cpuinfo.py

#!/usr/bin/env python3
"""
cpuinfo

Copyright 2002 Pearu Peterson all rights reserved,
Pearu Peterson <pearu@cens.ioc.ee>
Permission to use, modify, and distribute this software is given under the
terms of the NumPy (BSD style) license.  See LICENSE.txt that came with
this distribution for specifics.

NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
Pearu Peterson

"""

# 导入必要的模块和库
import os                    # 操作系统接口
import platform              # 获取平台信息
import re                    # 正则表达式库
import sys                   # 提供对解释器相关功能的访问
import types                 # Python类型相关的操作
import warnings              # 警告控制

from subprocess import getstatusoutput   # 获取命令行输出状态和内容


def getoutput(cmd, successful_status=(0,), stacklevel=1):
    # 尝试执行命令并获取输出和状态
    try:
        status, output = getstatusoutput(cmd)
    except OSError as e:
        # 捕获操作系统异常并发出警告
        warnings.warn(str(e), UserWarning, stacklevel=stacklevel)
        return False, ""
    # 检查状态是否在成功状态列表中,并返回结果和输出内容
    if os.WIFEXITED(status) and os.WEXITSTATUS(status) in successful_status:
        return True, output
    return False, output

def command_info(successful_status=(0,), stacklevel=1, **kw):
    # 执行一组命令并收集输出信息
    info = {}
    for key in kw:
        ok, output = getoutput(kw[key], successful_status=successful_status,
                               stacklevel=stacklevel+1)
        if ok:
            info[key] = output.strip()
    return info

def command_by_line(cmd, successful_status=(0,), stacklevel=1):
    # 执行命令并逐行获取输出内容
    ok, output = getoutput(cmd, successful_status=successful_status,
                           stacklevel=stacklevel+1)
    if not ok:
        return
    for line in output.splitlines():
        yield line.strip()

def key_value_from_command(cmd, sep, successful_status=(0,),
                           stacklevel=1):
    # 从命令输出中获取键值对信息
    d = {}
    for line in command_by_line(cmd, successful_status=successful_status,
                                stacklevel=stacklevel+1):
        l = [s.strip() for s in line.split(sep, 1)]
        if len(l) == 2:
            d[l[0]] = l[1]
    return d

class CPUInfoBase:
    """Holds CPU information and provides methods for requiring
    the availability of various CPU features.
    """

    def _try_call(self, func):
        # 尝试调用给定函数,捕获任何异常
        try:
            return func()
        except Exception:
            pass

    def __getattr__(self, name):
        # 获取未定义的属性时的默认处理方法
        if not name.startswith('_'):
            if hasattr(self, '_'+name):
                attr = getattr(self, '_'+name)
                if isinstance(attr, types.MethodType):
                    return lambda func=self._try_call,attr=attr : func(attr)
            else:
                return lambda : None
        raise AttributeError(name)

    def _getNCPUs(self):
        # 返回 CPU 数量(这里默认为1)
        return 1

    def __get_nbits(self):
        # 获取系统位数(32位或64位)
        abits = platform.architecture()[0]
        nbits = re.compile(r'(\d+)bit').search(abits).group(1)
        return nbits

    def _is_32bit(self):
        # 检查系统是否为32位
        return self.__get_nbits() == '32'

    def _is_64bit(self):
        # 检查系统是否为64位
        return self.__get_nbits() == '64'

class LinuxCPUInfo(CPUInfoBase):
    # Linux 特定的 CPU 信息类
    info = None
    # 初始化方法,用于初始化实例的信息
    def __init__(self):
        # 如果实例的信息已经存在,则直接返回,不执行后续代码
        if self.info is not None:
            return
        # 初始化一个空的信息列表
        info = [ {} ]
        # 获取系统命令 'uname -m' 的输出
        ok, output = getoutput('uname -m')
        # 如果获取成功
        if ok:
            # 将获取的输出去除首尾空白字符,存入info[0]的键 'uname_m' 中
            info[0]['uname_m'] = output.strip()
        try:
            # 尝试打开 '/proc/cpuinfo' 文件
            fo = open('/proc/cpuinfo')
        except OSError as e:
            # 如果打开文件失败,发出警告并抛出异常信息
            warnings.warn(str(e), UserWarning, stacklevel=2)
        else:
            # 如果打开文件成功,遍历文件的每一行
            for line in fo:
                # 分割每行内容,得到键值对列表,去除首尾空白字符
                name_value = [s.strip() for s in line.split(':', 1)]
                # 如果分割后的列表不是长度为2,跳过当前循环
                if len(name_value) != 2:
                    continue
                # 分别取出键和值
                name, value = name_value
                # 如果info为空或者name已经在info[-1]中存在,说明是下一个处理器信息
                if not info or name in info[-1]: # next processor
                    info.append({})
                # 将当前处理器的键值对存入info[-1]中
                info[-1][name] = value
            # 关闭文件流
            fo.close()
        # 将处理后的信息列表赋值给当前实例的类属性info
        self.__class__.info = info

    # 未实现的方法,占位用
    def _not_impl(self): pass

    # 判断当前处理器是否为AMD系列
    def _is_AMD(self):
        return self.info[0]['vendor_id']=='AuthenticAMD'

    # 判断当前处理器是否为AMD Athlon K6-2
    def _is_AthlonK6_2(self):
        return self._is_AMD() and self.info[0]['model'] == '2'

    # 判断当前处理器是否为AMD Athlon K6-3
    def _is_AthlonK6_3(self):
        return self._is_AMD() and self.info[0]['model'] == '3'

    # 判断当前处理器是否为AMD K6系列
    def _is_AthlonK6(self):
        return re.match(r'.*?AMD-K6', self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD K7系列
    def _is_AthlonK7(self):
        return re.match(r'.*?AMD-K7', self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD Athlon MP
    def _is_AthlonMP(self):
        return re.match(r'.*?Athlon\(tm\) MP\b',
                        self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD 64位处理器
    def _is_AMD64(self):
        return self.is_AMD() and self.info[0]['family'] == '15'

    # 判断当前处理器是否为AMD Athlon 64
    def _is_Athlon64(self):
        return re.match(r'.*?Athlon\(tm\) 64\b',
                        self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD Athlon HX
    def _is_AthlonHX(self):
        return re.match(r'.*?Athlon HX\b',
                        self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD Opteron
    def _is_Opteron(self):
        return re.match(r'.*?Opteron\b',
                        self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD Hammer
    def _is_Hammer(self):
        return re.match(r'.*?Hammer\b',
                        self.info[0]['model name']) is not None

    # 判断当前处理器是否为Alpha系列
    def _is_Alpha(self):
        return self.info[0]['cpu']=='Alpha'

    # 判断当前处理器是否为Alpha EV4
    def _is_EV4(self):
        return self.is_Alpha() and self.info[0]['cpu model'] == 'EV4'

    # 判断当前处理器是否为Alpha EV5
    def _is_EV5(self):
        return self.is_Alpha() and self.info[0]['cpu model'] == 'EV5'

    # 判断当前处理器是否为Alpha EV56
    def _is_EV56(self):
        return self.is_Alpha() and self.info[0]['cpu model'] == 'EV56'

    # 判断当前处理器是否为Alpha PCA56
    def _is_PCA56(self):
        return self.is_Alpha() and self.info[0]['cpu model'] == 'PCA56'

    # 判断当前处理器是否为Intel系列
    def _is_Intel(self):
        return self.info[0]['vendor_id']=='GenuineIntel'

    # 判断当前处理器是否为Intel i486
    def _is_i486(self):
        return self.info[0]['cpu']=='i486'

    # 判断当前处理器是否为Intel i586
    def _is_i586(self):
        return self.is_Intel() and self.info[0]['cpu family'] == '5'

    # 判断当前处理器是否为Intel i686
    def _is_i686(self):
        return self.is_Intel() and self.info[0]['cpu family'] == '6'
    # 判断CPU型号是否包含'Celeron'
    def _is_Celeron(self):
        return re.match(r'.*?Celeron',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'
    def _is_Pentium(self):
        return re.match(r'.*?Pentium',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'和'II'
    def _is_PentiumII(self):
        return re.match(r'.*?Pentium.*?II\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否为'PentiumPro'
    def _is_PentiumPro(self):
        return re.match(r'.*?PentiumPro\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'和'MMX'
    def _is_PentiumMMX(self):
        return re.match(r'.*?Pentium.*?MMX\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'和'III'
    def _is_PentiumIII(self):
        return re.match(r'.*?Pentium.*?III\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'和'IV'或者'4'
    def _is_PentiumIV(self):
        return re.match(r'.*?Pentium.*?(IV|4)\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'和'M'
    def _is_PentiumM(self):
        return re.match(r'.*?Pentium.*?M\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否为'Prescott',即为Pentium IV且具有SSE3指令集
    def _is_Prescott(self):
        return (self.is_PentiumIV() and self.has_sse3())
    
    # 判断CPU型号是否为'Nocona',即为Intel系列、特定CPU family、具有SSE3但不具有SSSE3并包含'lm'标志
    def _is_Nocona(self):
        return (self.is_Intel()
                and (self.info[0]['cpu family'] == '6'
                     or self.info[0]['cpu family'] == '15')
                and (self.has_sse3() and not self.has_ssse3())
                and re.match(r'.*?\blm\b', self.info[0]['flags']) is not None)
    
    # 判断CPU型号是否为'Core2',即为64位、Intel系列且包含'Core(TM)2'标志
    def _is_Core2(self):
        return (self.is_64bit() and self.is_Intel() and
                re.match(r'.*?Core\(TM\)2\b',
                         self.info[0]['model name']) is not None)
    
    # 判断CPU型号是否包含'Itanium'
    def _is_Itanium(self):
        return re.match(r'.*?Itanium\b',
                        self.info[0]['family']) is not None
    
    # 判断CPU型号是否包含'XEON'(不区分大小写)
    def _is_XEON(self):
        return re.match(r'.*?XEON\b',
                        self.info[0]['model name'], re.IGNORECASE) is not None
    
    # _is_Xeon 是 _is_XEON 的别名
    
    # 判断是否只有一个CPU
    def _is_singleCPU(self):
        return len(self.info) == 1
    
    # 获取CPU数量
    def _getNCPUs(self):
        return len(self.info)
    
    # 判断CPU是否具有fdiv错误
    def _has_fdiv_bug(self):
        return self.info[0]['fdiv_bug']=='yes'
    
    # 判断CPU是否具有f00f错误
    def _has_f00f_bug(self):
        return self.info[0]['f00f_bug']=='yes'
    
    # 判断CPU是否支持MMX指令集
    def _has_mmx(self):
        return re.match(r'.*?\bmmx\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持SSE指令集
    def _has_sse(self):
        return re.match(r'.*?\bsse\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持SSE2指令集
    def _has_sse2(self):
        return re.match(r'.*?\bsse2\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持SSE3指令集
    def _has_sse3(self):
        return re.match(r'.*?\bpni\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持SSSE3指令集
    def _has_ssse3(self):
        return re.match(r'.*?\bssse3\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持3DNow指令集
    def _has_3dnow(self):
        return re.match(r'.*?\b3dnow\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持3DNowExt指令集
    def _has_3dnowext(self):
        return re.match(r'.*?\b3dnowext\b', self.info[0]['flags']) is not None
class IRIXCPUInfo(CPUInfoBase):
    # IRIXCPUInfo 类,继承自 CPUInfoBase

    info = None
    # 类变量 info,用于存储系统信息,初始值为 None

    def __init__(self):
        # 初始化方法
        if self.info is not None:
            return
        # 如果 info 已经被设置过,则直接返回,避免重复初始化

        # 调用 key_value_from_command 函数获取系统信息,命令为 'sysconf',分隔符为 ' '
        # 只接受状态码为 0 或 1 的执行结果
        info = key_value_from_command('sysconf', sep=' ',
                                      successful_status=(0, 1))
        # 设置类变量 info 为获取到的系统信息
        self.__class__.info = info

    def _not_impl(self): pass
    # 占位方法,未实现的方法,不做任何操作

    def _is_singleCPU(self):
        # 判断是否为单 CPU 系统,根据 info 中的 'NUM_PROCESSORS' 值来判断
        return self.info.get('NUM_PROCESSORS') == '1'

    def _getNCPUs(self):
        # 获取 CPU 数量,如果 'NUM_PROCESSORS' 存在则返回其整数值,否则返回默认值 1
        return int(self.info.get('NUM_PROCESSORS', 1))

    def __cputype(self, n):
        # 辅助方法,用于判断 CPU 类型是否为指定编号 n
        return self.info.get('PROCESSORS').split()[0].lower() == 'r%s' % (n)

    def _is_r2000(self): return self.__cputype(2000)
    def _is_r3000(self): return self.__cputype(3000)
    def _is_r3900(self): return self.__cputype(3900)
    def _is_r4000(self): return self.__cputype(4000)
    def _is_r4100(self): return self.__cputype(4100)
    def _is_r4300(self): return self.__cputype(4300)
    def _is_r4400(self): return self.__cputype(4400)
    def _is_r4600(self): return self.__cputype(4600)
    def _is_r4650(self): return self.__cputype(4650)
    def _is_r5000(self): return self.__cputype(5000)
    def _is_r6000(self): return self.__cputype(6000)
    def _is_r8000(self): return self.__cputype(8000)
    def _is_r10000(self): return self.__cputype(10000)
    def _is_r12000(self): return self.__cputype(12000)
    def _is_rorion(self): return self.__cputype('orion')

    def get_ip(self):
        # 获取主机名(IP),如果出错则忽略异常
        try: return self.info.get('MACHINE')
        except Exception: pass

    def __machine(self, n):
        # 辅助方法,用于判断主机类型是否为指定编号 n
        return self.info.get('MACHINE').lower() == 'ip%s' % (n)

    def _is_IP19(self): return self.__machine(19)
    def _is_IP20(self): return self.__machine(20)
    def _is_IP21(self): return self.__machine(21)
    def _is_IP22(self): return self.__machine(22)
    def _is_IP22_4k(self): return self.__machine(22) and self._is_r4000()
    def _is_IP22_5k(self): return self.__machine(22) and self._is_r5000()
    def _is_IP24(self): return self.__machine(24)
    def _is_IP25(self): return self.__machine(25)
    def _is_IP26(self): return self.__machine(26)
    def _is_IP27(self): return self.__machine(27)
    def _is_IP28(self): return self.__machine(28)
    def _is_IP30(self): return self.__machine(30)
    def _is_IP32(self): return self.__machine(32)
    def _is_IP32_5k(self): return self.__machine(32) and self._is_r5000()
    def _is_IP32_10k(self): return self.__machine(32) and self._is_r10000()


class DarwinCPUInfo(CPUInfoBase):
    # DarwinCPUInfo 类,继承自 CPUInfoBase

    info = None
    # 类变量 info,用于存储系统信息,初始值为 None

    def __init__(self):
        # 初始化方法
        if self.info is not None:
            return
        # 如果 info 已经被设置过,则直接返回,避免重复初始化

        # 调用 command_info 函数获取系统信息,包括 'arch' 和 'machine' 的命令结果
        info = command_info(arch='arch',
                            machine='machine')
        # 使用 sysctl 命令获取更多硬件相关信息,将其存储在 'sysctl_hw' 键下
        info['sysctl_hw'] = key_value_from_command('sysctl hw', sep='=')
        # 设置类变量 info 为获取到的所有系统信息
        self.__class__.info = info

    def _not_impl(self): pass
    # 占位方法,未实现的方法,不做任何操作

    def _getNCPUs(self):
        # 获取 CPU 数量,从 sysctl_hw 字典中获取 'hw.ncpu' 键值,如果不存在则返回默认值 1
        return int(self.info['sysctl_hw'].get('hw.ncpu', 1))

    def _is_Power_Macintosh(self):
        # 判断当前系统是否为 Power Macintosh
        return self.info['sysctl_hw']['hw.machine']=='Power Macintosh'
    # 判断当前系统架构是否为 i386
    def _is_i386(self):
        return self.info['arch']=='i386'
    
    # 判断当前系统架构是否为 ppc
    def _is_ppc(self):
        return self.info['arch']=='ppc'
    
    # 检查当前系统的具体机器型号是否为给定的 PPC 架构类型
    def __machine(self, n):
        return self.info['machine'] == 'ppc%s'%n
    
    # 下面一系列方法用于检查当前系统是否为特定的 PPC 机器型号
    def _is_ppc601(self): return self.__machine(601)
    def _is_ppc602(self): return self.__machine(602)
    def _is_ppc603(self): return self.__machine(603)
    def _is_ppc603e(self): return self.__machine('603e')
    def _is_ppc604(self): return self.__machine(604)
    def _is_ppc604e(self): return self.__machine('604e')
    def _is_ppc620(self): return self.__machine(620)
    def _is_ppc630(self): return self.__machine(630)
    def _is_ppc740(self): return self.__machine(740)
    def _is_ppc7400(self): return self.__machine(7400)
    def _is_ppc7450(self): return self.__machine(7450)
    def _is_ppc750(self): return self.__machine(750)
    def _is_ppc403(self): return self.__machine(403)
    def _is_ppc505(self): return self.__machine(505)
    def _is_ppc801(self): return self.__machine(801)
    def _is_ppc821(self): return self.__machine(821)
    def _is_ppc823(self): return self.__machine(823)
    def _is_ppc860(self): return self.__machine(860)
# 定义一个名为 SunOSCPUInfo 的类,继承自 CPUInfoBase 类
class SunOSCPUInfo(CPUInfoBase):

    # 类变量 info,用于存储系统信息,初始化为 None
    info = None

    # 构造函数,初始化对象实例
    def __init__(self):
        # 如果类变量 info 不为 None,则直接返回,避免重复初始化
        if self.info is not None:
            return
        
        # 调用 command_info 函数获取系统信息,包括架构、机器类型、内核信息等
        info = command_info(arch='arch',
                            mach='mach',
                            uname_i='uname_i',
                            isainfo_b='isainfo -b',
                            isainfo_n='isainfo -n',
                            )
        
        # 调用 key_value_from_command 函数获取并添加额外的 uname -X 命令返回的键值对信息到 info 字典中
        info['uname_X'] = key_value_from_command('uname -X', sep='=')
        
        # 通过迭代 psrinfo -v 0 命令返回的每一行,使用正则表达式匹配处理器信息,并将结果添加到 info 字典中
        for line in command_by_line('psrinfo -v 0'):
            m = re.match(r'\s*The (?P<p>[\w\d]+) processor operates at', line)
            if m:
                info['processor'] = m.group('p')
                break
        
        # 将当前实例的类变量 info 设置为获取到的系统信息
        self.__class__.info = info

    # 以下是一系列用于检测特定硬件或软件特征的方法,每个方法都返回布尔值

    # 检测系统是否为 i386 架构
    def _is_i386(self):
        return self.info['isainfo_n']=='i386'

    # 检测系统是否为 sparc 架构
    def _is_sparc(self):
        return self.info['isainfo_n']=='sparc'

    # 检测系统是否为 sparcv9 架构
    def _is_sparcv9(self):
        return self.info['isainfo_n']=='sparcv9'

    # 获取系统中 CPU 的数量,如果未指定则默认为 1
    def _getNCPUs(self):
        return int(self.info['uname_X'].get('NumCPU', 1))

    # 检测系统是否为 sun4 架构
    def _is_sun4(self):
        return self.info['arch']=='sun4'

    # 检测 uname_i 是否以 SUNW 开头,表示系统是否为 SUNW 类型
    def _is_SUNW(self):
        return re.match(r'SUNW', self.info['uname_i']) is not None

    # 检测 uname_i 是否包含字符串 SPARCstation-5,表示系统是否为 SPARCstation-5 型号
    def _is_sparcstation5(self):
        return re.match(r'.*SPARCstation-5', self.info['uname_i']) is not None

    # 检测 uname_i 是否包含字符串 Ultra-1,表示系统是否为 Ultra-1 型号
    def _is_ultra1(self):
        return re.match(r'.*Ultra-1', self.info['uname_i']) is not None

    # 检测 uname_i 是否包含字符串 Ultra-250,表示系统是否为 Ultra-250 型号
    def _is_ultra250(self):
        return re.match(r'.*Ultra-250', self.info['uname_i']) is not None

    # 以下方法类似,用于检测其他型号
    def _is_ultra2(self):
        return re.match(r'.*Ultra-2', self.info['uname_i']) is not None

    def _is_ultra30(self):
        return re.match(r'.*Ultra-30', self.info['uname_i']) is not None

    def _is_ultra4(self):
        return re.match(r'.*Ultra-4', self.info['uname_i']) is not None

    def _is_ultra5_10(self):
        return re.match(r'.*Ultra-5_10', self.info['uname_i']) is not None

    def _is_ultra5(self):
        return re.match(r'.*Ultra-5', self.info['uname_i']) is not None

    def _is_ultra60(self):
        return re.match(r'.*Ultra-60', self.info['uname_i']) is not None

    def _is_ultra80(self):
        return re.match(r'.*Ultra-80', self.info['uname_i']) is not None

    def _is_ultraenterprice(self):
        return re.match(r'.*Ultra-Enterprise', self.info['uname_i']) is not None

    def _is_ultraenterprice10k(self):
        return re.match(r'.*Ultra-Enterprise-10000', self.info['uname_i']) is not None

    def _is_sunfire(self):
        return re.match(r'.*Sun-Fire', self.info['uname_i']) is not None

    def _is_ultra(self):
        return re.match(r'.*Ultra', self.info['uname_i']) is not None

    # 检测当前处理器是否为 sparcv7 架构
    def _is_cpusparcv7(self):
        return self.info['processor']=='sparcv7'

    # 检测当前处理器是否为 sparcv8 架构
    def _is_cpusparcv8(self):
        return self.info['processor']=='sparcv8'

    # 检测当前处理器是否为 sparcv9 架构
    def _is_cpusparcv9(self):
        return self.info['processor']=='sparcv9'


# 定义一个名为 Win32CPUInfo 的类,继承自 CPUInfoBase 类
class Win32CPUInfo(CPUInfoBase):

    # 类变量 info,用于存储系统信息,初始化为 None
    info = None
    pkey = r"HARDWARE\DESCRIPTION\System\CentralProcessor"
    # 定义注册表路径,指定到处理器信息的位置

    # 构造函数初始化
    def __init__(self):
        if self.info is not None:
            return
        info = []
        try:
            # 尝试导入winreg模块,用于访问Windows注册表
            import winreg

            # 正则表达式匹配处理器标识信息的模式
            prgx = re.compile(r"family\s+(?P<FML>\d+)\s+model\s+(?P<MDL>\d+)"
                              r"\s+stepping\s+(?P<STP>\d+)", re.IGNORECASE)
            # 打开注册表指定路径下的键
            chnd=winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, self.pkey)
            pnum=0
            # 遍历处理器子键
            while True:
                try:
                    proc=winreg.EnumKey(chnd, pnum)
                except winreg.error:
                    break
                else:
                    pnum+=1
                    # 向信息列表添加处理器名称
                    info.append({"Processor":proc})
                    # 打开处理器子键
                    phnd=winreg.OpenKey(chnd, proc)
                    pidx=0
                    # 遍历处理器子键中的值
                    while True:
                        try:
                            name, value, vtpe=winreg.EnumValue(phnd, pidx)
                        except winreg.error:
                            break
                        else:
                            pidx=pidx+1
                            # 将处理器属性及其值添加到信息列表最后一个字典中
                            info[-1][name]=value
                            # 如果属性名为"Identifier",则使用正则表达式解析处理器标识信息
                            if name=="Identifier":
                                srch=prgx.search(value)
                                if srch:
                                    info[-1]["Family"]=int(srch.group("FML"))
                                    info[-1]["Model"]=int(srch.group("MDL"))
                                    info[-1]["Stepping"]=int(srch.group("STP"))
        except Exception as e:
            # 捕获异常并打印错误信息,忽略处理器信息的获取错误
            print(e, '(ignoring)')
        # 将获取的处理器信息赋给类属性info
        self.__class__.info = info

    # 未实现的方法,占位符方法
    def _not_impl(self): pass

    # Athlon处理器判断方法
    def _is_AMD(self):
        return self.info[0]['VendorIdentifier']=='AuthenticAMD'

    # Am486处理器判断方法
    def _is_Am486(self):
        return self.is_AMD() and self.info[0]['Family']==4

    # Am5x86处理器判断方法
    def _is_Am5x86(self):
        return self.is_AMD() and self.info[0]['Family']==4

    # AMDK5处理器判断方法
    def _is_AMDK5(self):
        return self.is_AMD() and self.info[0]['Family']==5 \
               and self.info[0]['Model'] in [0, 1, 2, 3]

    # AMDK6处理器判断方法
    def _is_AMDK6(self):
        return self.is_AMD() and self.info[0]['Family']==5 \
               and self.info[0]['Model'] in [6, 7]

    # AMDK6_2处理器判断方法
    def _is_AMDK6_2(self):
        return self.is_AMD() and self.info[0]['Family']==5 \
               and self.info[0]['Model']==8

    # AMDK6_3处理器判断方法
    def _is_AMDK6_3(self):
        return self.is_AMD() and self.info[0]['Family']==5 \
               and self.info[0]['Model']==9

    # AMDK7处理器判断方法
    def _is_AMDK7(self):
        return self.is_AMD() and self.info[0]['Family'] == 6

    # 要可靠地区分不同类型的AMD64芯片(如Athlon64、Operton、Athlon64 X2、Semperon、Turion 64等)
    # 需要查看cpuid的“brand”信息
    # 判断当前 CPU 是否为 AMD64 架构
    def _is_AMD64(self):
        return self.is_AMD() and self.info[0]['Family'] == 15

    # 判断当前 CPU 是否为 Intel 厂商
    def _is_Intel(self):
        return self.info[0]['VendorIdentifier']=='GenuineIntel'

    # 判断当前 CPU 是否为 Intel 386 系列
    def _is_i386(self):
        return self.info[0]['Family']==3

    # 判断当前 CPU 是否为 Intel 486 系列
    def _is_i486(self):
        return self.info[0]['Family']==4

    # 判断当前 CPU 是否为 Intel 586 系列
    def _is_i586(self):
        return self.is_Intel() and self.info[0]['Family']==5

    # 判断当前 CPU 是否为 Intel 686 系列
    def _is_i686(self):
        return self.is_Intel() and self.info[0]['Family']==6

    # 判断当前 CPU 是否为 Pentium 系列
    def _is_Pentium(self):
        return self.is_Intel() and self.info[0]['Family']==5

    # 判断当前 CPU 是否为 Pentium MMX
    def _is_PentiumMMX(self):
        return self.is_Intel() and self.info[0]['Family']==5 \
               and self.info[0]['Model']==4

    # 判断当前 CPU 是否为 Pentium Pro
    def _is_PentiumPro(self):
        return self.is_Intel() and self.info[0]['Family']==6 \
               and self.info[0]['Model']==1

    # 判断当前 CPU 是否为 Pentium II
    def _is_PentiumII(self):
        return self.is_Intel() and self.info[0]['Family']==6 \
               and self.info[0]['Model'] in [3, 5, 6]

    # 判断当前 CPU 是否为 Pentium III
    def _is_PentiumIII(self):
        return self.is_Intel() and self.info[0]['Family']==6 \
               and self.info[0]['Model'] in [7, 8, 9, 10, 11]

    # 判断当前 CPU 是否为 Pentium IV
    def _is_PentiumIV(self):
        return self.is_Intel() and self.info[0]['Family']==15

    # 判断当前 CPU 是否为 Pentium M
    def _is_PentiumM(self):
        return self.is_Intel() and self.info[0]['Family'] == 6 \
               and self.info[0]['Model'] in [9, 13, 14]

    # 判断当前 CPU 是否为 Core 2
    def _is_Core2(self):
        return self.is_Intel() and self.info[0]['Family'] == 6 \
               and self.info[0]['Model'] in [15, 16, 17]

    # 判断系统是否只有单个 CPU
    def _is_singleCPU(self):
        return len(self.info) == 1

    # 获取系统中 CPU 的数量
    def _getNCPUs(self):
        return len(self.info)

    # 判断当前 CPU 是否支持 MMX 指令集
    def _has_mmx(self):
        if self.is_Intel():
            return (self.info[0]['Family']==5 and self.info[0]['Model']==4) \
                   or (self.info[0]['Family'] in [6, 15])
        elif self.is_AMD():
            return self.info[0]['Family'] in [5, 6, 15]
        else:
            return False

    # 判断当前 CPU 是否支持 SSE 指令集
    def _has_sse(self):
        if self.is_Intel():
            return ((self.info[0]['Family']==6 and
                     self.info[0]['Model'] in [7, 8, 9, 10, 11])
                     or self.info[0]['Family']==15)
        elif self.is_AMD():
            return ((self.info[0]['Family']==6 and
                     self.info[0]['Model'] in [6, 7, 8, 10])
                     or self.info[0]['Family']==15)
        else:
            return False

    # 判断当前 CPU 是否支持 SSE2 指令集
    def _has_sse2(self):
        if self.is_Intel():
            return self.is_Pentium4() or self.is_PentiumM() \
                   or self.is_Core2()
        elif self.is_AMD():
            return self.is_AMD64()
        else:
            return False

    # 判断当前 CPU 是否支持 3DNow 指令集
    def _has_3dnow(self):
        return self.is_AMD() and self.info[0]['Family'] in [5, 6, 15]

    # 判断当前 CPU 是否支持 3DNowExt 指令集
    def _has_3dnowext(self):
        return self.is_AMD() and self.info[0]['Family'] in [6, 15]
# 检查操作系统平台,确定使用哪个 CPU 信息类
if sys.platform.startswith('linux'): # variations: linux2,linux-i386 (any others?)
    # 如果是 Linux 系统,选择 LinuxCPUInfo 类
    cpuinfo = LinuxCPUInfo
elif sys.platform.startswith('irix'):
    # 如果是 IRIX 系统,选择 IRIXCPUInfo 类
    cpuinfo = IRIXCPUInfo
elif sys.platform == 'darwin':
    # 如果是 Darwin(Mac OS X)系统,选择 DarwinCPUInfo 类
    cpuinfo = DarwinCPUInfo
elif sys.platform.startswith('sunos'):
    # 如果是 SunOS 系统,选择 SunOSCPUInfo 类
    cpuinfo = SunOSCPUInfo
elif sys.platform.startswith('win32'):
    # 如果是 Windows 系统,选择 Win32CPUInfo 类
    cpuinfo = Win32CPUInfo
elif sys.platform.startswith('cygwin'):
    # 如果是 Cygwin 系统,选择 LinuxCPUInfo 类(Cygwin 可以通过 LinuxCPUInfo 访问)
    cpuinfo = LinuxCPUInfo
#XXX: other OS's. Eg. use _winreg on Win32. Or os.uname on unices.
else:
    # 如果是其它操作系统,选择 CPUInfoBase 类作为默认
    cpuinfo = CPUInfoBase

# 创建 CPU 信息类的实例
cpu = cpuinfo()

# 下面的代码块不需要注释,因为它们已经被注释掉了,不会执行

.\numpy\numpy\distutils\exec_command.py

"""
exec_command

Implements exec_command function that is (almost) equivalent to
commands.getstatusoutput function but on NT, DOS systems the
returned status is actually correct (though, the returned status
values may be different by a factor). In addition, exec_command
takes keyword arguments for (re-)defining environment variables.

Provides functions:

  exec_command  --- execute command in a specified directory and
                    in the modified environment.
  find_executable --- locate a command using info from environment
                    variable PATH. Equivalent to posix `which`
                    command.

Author: Pearu Peterson <pearu@cens.ioc.ee>
Created: 11 January 2003

Requires: Python 2.x

Successfully tested on:

========  ============  =================================================
os.name   sys.platform  comments
========  ============  =================================================
posix     linux2        Debian (sid) Linux, Python 2.1.3+, 2.2.3+, 2.3.3
                        PyCrust 0.9.3, Idle 1.0.2
posix     linux2        Red Hat 9 Linux, Python 2.1.3, 2.2.2, 2.3.2
posix     sunos5        SunOS 5.9, Python 2.2, 2.3.2
posix     darwin        Darwin 7.2.0, Python 2.3
nt        win32         Windows Me
                        Python 2.3(EE), Idle 1.0, PyCrust 0.7.2
                        Python 2.1.1 Idle 0.8
nt        win32         Windows 98, Python 2.1.1. Idle 0.8
nt        win32         Cygwin 98-4.10, Python 2.1.1(MSC) - echo tests
                        fail i.e. redefining environment variables may
                        not work. FIXED: don't use cygwin echo!
                        Comment: also `cmd /c echo` will not work
                        but redefining environment variables do work.
posix     cygwin        Cygwin 98-4.10, Python 2.3.3(cygming special)
nt        win32         Windows XP, Python 2.3.3
========  ============  =================================================

Known bugs:

* Tests, that send messages to stderr, fail when executed from MSYS prompt
  because the messages are lost at some point.

"""
__all__ = ['exec_command', 'find_executable']

import os  # 导入操作系统相关的功能
import sys  # 导入系统相关的功能
import subprocess  # 导入子进程管理的功能
import locale  # 导入处理本地化的功能
import warnings  # 导入警告处理的功能

from numpy.distutils.misc_util import is_sequence, make_temp_file  # 导入 numpy 相关的功能
from numpy.distutils import log  # 导入 numpy 相关的日志记录功能

def filepath_from_subprocess_output(output):
    """
    Convert `bytes` in the encoding used by a subprocess into a filesystem-appropriate `str`.

    Inherited from `exec_command`, and possibly incorrect.
    """
    mylocale = locale.getpreferredencoding(False)  # 获取首选编码
    if mylocale is None:
        mylocale = 'ascii'
    output = output.decode(mylocale, errors='replace')  # 解码 subprocess 输出为字符串
    output = output.replace('\r\n', '\n')  # 替换换行符格式
    # Another historical oddity
    if output[-1:] == '\n':  # 移除末尾可能存在的多余换行符
        output = output[:-1]
    return output

def forward_bytes_to_stdout(val):
    """
    Forward bytes from a subprocess call to the console, without attempting to
    decode them.
    """
    # 此函数用于将子进程调用的字节流直接输出到控制台,不进行解码操作
    # 假设 subprocess 调用已经返回了适当编码的字节流数据。
    if hasattr(sys.stdout, 'buffer'):
        # 如果 sys.stdout 有 'buffer' 属性,直接使用底层的二进制输出
        sys.stdout.buffer.write(val)
    elif hasattr(sys.stdout, 'encoding'):
        # 如果 sys.stdout 有 'encoding' 属性,尝试使用相同的编码进行解码和再编码
        sys.stdout.write(val.decode(sys.stdout.encoding))
    else:
        # 如果无法确定编码,使用 UTF-8 编码进行解码,替换错误的字符
        sys.stdout.write(val.decode('utf8', errors='replace'))
def temp_file_name():
    # 发出警告,提示 temp_file_name 函数在 NumPy v1.17 版本后已弃用,建议使用 tempfile.mkstemp 替代
    warnings.warn('temp_file_name is deprecated since NumPy v1.17, use '
                  'tempfile.mkstemp instead', DeprecationWarning, stacklevel=1)
    # 调用 make_temp_file 函数创建临时文件,返回文件对象和文件名
    fo, name = make_temp_file()
    # 关闭临时文件对象
    fo.close()
    # 返回临时文件名
    return name

def get_pythonexe():
    # 获取当前 Python 解释器的可执行文件路径
    pythonexe = sys.executable
    # 如果操作系统为 Windows 平台
    if os.name in ['nt', 'dos']:
        # 分离文件路径和文件名
        fdir, fn = os.path.split(pythonexe)
        # 将文件名转换为大写并替换 'PYTHONW' 为 'PYTHON'
        fn = fn.upper().replace('PYTHONW', 'PYTHON')
        # 拼接路径和修改后的文件名
        pythonexe = os.path.join(fdir, fn)
        # 断言文件路径存在且是一个文件
        assert os.path.isfile(pythonexe), '%r is not a file' % (pythonexe,)
    # 返回 Python 解释器的可执行文件路径
    return pythonexe

def find_executable(exe, path=None, _cache={}):
    """Return full path of a executable or None.

    Symbolic links are not followed.
    """
    # 以 (exe, path) 为键从缓存中查找路径
    key = exe, path
    try:
        return _cache[key]
    except KeyError:
        pass
    # 记录调试信息,查找可执行文件
    log.debug('find_executable(%r)' % exe)
    # 保存原始的可执行文件名
    orig_exe = exe

    # 如果路径为空,则使用环境变量 PATH 或者默认路径
    if path is None:
        path = os.environ.get('PATH', os.defpath)
    # 根据操作系统类型选择 realpath 函数
    if os.name=='posix':
        realpath = os.path.realpath
    else:
        realpath = lambda a:a

    # 如果可执行文件名以双引号开头,则去除双引号
    if exe.startswith('"'):
        exe = exe[1:-1]

    # Windows 平台的可执行文件后缀列表
    suffixes = ['']
    if os.name in ['nt', 'dos', 'os2']:
        fn, ext = os.path.splitext(exe)
        extra_suffixes = ['.exe', '.com', '.bat']
        # 如果文件名后缀不在附加后缀列表中,则使用附加后缀
        if ext.lower() not in extra_suffixes:
            suffixes = extra_suffixes

    # 如果可执行文件名是绝对路径
    if os.path.isabs(exe):
        paths = ['']
    else:
        # 将 PATH 分割为绝对路径列表
        paths = [ os.path.abspath(p) for p in path.split(os.pathsep) ]

    # 遍历所有可能的路径和后缀
    for path in paths:
        fn = os.path.join(path, exe)
        for s in suffixes:
            f_ext = fn+s
            # 如果文件不是符号链接,则获取其真实路径
            if not os.path.islink(f_ext):
                f_ext = realpath(f_ext)
            # 如果文件存在且可执行,则返回其路径
            if os.path.isfile(f_ext) and os.access(f_ext, os.X_OK):
                log.info('Found executable %s' % f_ext)
                _cache[key] = f_ext
                return f_ext

    # 记录警告信息,未找到可执行文件
    log.warn('Could not locate executable %s' % orig_exe)
    return None

############################################################

def _preserve_environment( names ):
    # 记录调试信息,保留环境变量
    log.debug('_preserve_environment(%r)' % (names))
    # 创建包含指定环境变量名及其当前值的字典
    env = {name: os.environ.get(name) for name in names}
    # 返回环境变量字典
    return env

def _update_environment( **env ):
    # 记录调试信息,更新环境变量
    log.debug('_update_environment(...)')
    # 遍历环境变量字典,更新当前进程的环境变量
    for name, value in env.items():
        os.environ[name] = value or ''

def exec_command(command, execute_in='', use_shell=None, use_tee=None,
                 _with_python = 1, **env ):
    """
    Return (status,output) of executed command.

    .. deprecated:: 1.17
        Use subprocess.Popen instead

    Parameters
    ----------
    command : str
        A concatenated string of executable and arguments.
    execute_in : str
        Before running command ``cd execute_in`` and after ``cd -``.
    use_shell : {bool, None}, optional
        If True, execute ``sh -c command``. Default None (True)
    use_tee : {bool, None}, optional
        If True use tee. Default None (True)


    Returns
    -------
    """
    res : str
        Both stdout and stderr messages.

    Notes
    -----
    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.

    """
    # 发出警告,提示 exec_command 函数自 NumPy v1.17 起已废弃,请使用 subprocess.Popen 替代
    warnings.warn('exec_command is deprecated since NumPy v1.17, use '
                  'subprocess.Popen instead', DeprecationWarning, stacklevel=1)
    # 记录调试信息,显示执行的命令和环境变量
    log.debug('exec_command(%r,%s)' % (command,
         ','.join(['%s=%r'%kv for kv in env.items()])))

    # 根据操作系统类型决定是否使用 tee 命令
    if use_tee is None:
        use_tee = os.name=='posix'
    # 根据操作系统类型决定是否使用 shell
    if use_shell is None:
        use_shell = os.name=='posix'
    # 将执行路径转换为绝对路径
    execute_in = os.path.abspath(execute_in)
    # 获取当前工作目录的绝对路径
    oldcwd = os.path.abspath(os.getcwd())

    # 根据文件名是否包含 'exec_command' 来决定执行目录的设定
    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( list(env.keys()) )
    _update_environment( **env )

    try:
        # 执行命令,获取执行状态 st
        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)

    # 返回执行状态 st
    return st
# 执行给定命令的内部工作函数,用于 exec_command()。
def _exec_command(command, use_shell=None, use_tee=None, **env):
    # 如果 use_shell 未指定,则根据操作系统确定是否使用 shell
    if use_shell is None:
        use_shell = os.name == 'posix'
    # 如果 use_tee 未指定,则根据操作系统确定是否使用 tee
    if use_tee is None:
        use_tee = os.name == 'posix'

    # 在 POSIX 系统上且需要使用 shell 时,覆盖 subprocess 默认的 /bin/sh
    if os.name == 'posix' and use_shell:
        sh = os.environ.get('SHELL', '/bin/sh')
        # 如果命令是一个序列,则创建一个新的命令序列
        if is_sequence(command):
            command = [sh, '-c', ' '.join(command)]
        else:
            command = [sh, '-c', command]
        use_shell = False

    # 在 Windows 上且命令是一个序列时,手动拼接字符串以用于 CreateProcess()
    elif os.name == 'nt' and is_sequence(command):
        command = ' '.join(_quote_arg(arg) for arg in command)

    # 默认情况下继承环境变量
    env = env or None
    try:
        # 启动子进程执行命令,text 设为 False 以便 communicate() 返回字节流,
        # 我们需要手动解码输出,以避免遇到无效字符时引发 UnicodeDecodeError
        proc = subprocess.Popen(command, shell=use_shell, env=env, text=False,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
    except OSError:
        # 如果启动子进程失败,返回 127,并返回空字符串
        return 127, ''

    # 读取子进程的输出和错误信息
    text, err = proc.communicate()
    
    # 获取系统首选编码,用于解码子进程输出
    mylocale = locale.getpreferredencoding(False)
    if mylocale is None:
        mylocale = 'ascii'
    # 使用替换错误模式解码文本,将 '\r\n' 替换为 '\n'
    text = text.decode(mylocale, errors='replace')
    text = text.replace('\r\n', '\n')

    # 去除末尾的换行符(历史遗留问题)
    if text[-1:] == '\n':
        text = text[:-1]

    # 如果需要使用 tee,并且输出文本不为空,则打印输出文本
    if use_tee and text:
        print(text)

    # 返回子进程的返回码和处理后的输出文本
    return proc.returncode, text


# 将参数 arg 安全地引用为可以在 shell 命令行中使用的形式
def _quote_arg(arg):
    # 如果字符串中不包含双引号且包含空格,则将整个字符串用双引号引起来
    if '"' not in arg and ' ' in arg:
        return '"%s"' % arg
    return arg

.\numpy\numpy\distutils\extension.py

"""
distutils.extension

Provides the Extension class, used to describe C/C++ extension
modules in setup scripts.

Overridden to support f2py.

"""
# 导入正则表达式模块
import re
# 从distutils.extension模块导入Extension类,并起别名为old_Extension
from distutils.extension import Extension as old_Extension

# 定义一个正则表达式,匹配C++源文件的文件名后缀
cxx_ext_re = re.compile(r'.*\.(cpp|cxx|cc)\Z', re.I).match
# 定义一个正则表达式,匹配Fortran和Python语言接口文件的文件名后缀
fortran_pyf_ext_re = re.compile(r'.*\.(f90|f95|f77|for|ftn|f|pyf)\Z', re.I).match


class Extension(old_Extension):
    """
    Parameters
    ----------
    name : str
        Extension name.
    sources : list of str
        List of source file locations relative to the top directory of
        the package.
    extra_compile_args : list of str
        Extra command line arguments to pass to the compiler.
    extra_f77_compile_args : list of str
        Extra command line arguments to pass to the fortran77 compiler.
    extra_f90_compile_args : list of str
        Extra command line arguments to pass to the fortran90 compiler.
    """
    # 初始化函数,用于初始化一个扩展模块对象,设置各种编译和链接选项
    def __init__(
            self, name, sources,
            include_dirs=None,
            define_macros=None,
            undef_macros=None,
            library_dirs=None,
            libraries=None,
            runtime_library_dirs=None,
            extra_objects=None,
            extra_compile_args=None,
            extra_link_args=None,
            export_symbols=None,
            swig_opts=None,
            depends=None,
            language=None,
            f2py_options=None,
            module_dirs=None,
            extra_c_compile_args=None,
            extra_cxx_compile_args=None,
            extra_f77_compile_args=None,
            extra_f90_compile_args=None,):
    
        # 调用旧版本的 Extension 类的初始化函数,初始化基类
        old_Extension.__init__(
                self, name, [],
                include_dirs=include_dirs,
                define_macros=define_macros,
                undef_macros=undef_macros,
                library_dirs=library_dirs,
                libraries=libraries,
                runtime_library_dirs=runtime_library_dirs,
                extra_objects=extra_objects,
                extra_compile_args=extra_compile_args,
                extra_link_args=extra_link_args,
                export_symbols=export_symbols)
    
        # 将传入的 sources 参数赋值给当前对象的 sources 属性
        # 避免 assert 语句检查 sources 是否包含字符串类型
        self.sources = sources
    
        # 设置 swig_opts 属性,如果未指定则为空列表
        self.swig_opts = swig_opts or []
        # 如果 swig_opts 被指定为字符串而非列表,则进行警告,并将其转换为列表
        if isinstance(self.swig_opts, str):
            import warnings
            msg = "swig_opts is specified as a string instead of a list"
            warnings.warn(msg, SyntaxWarning, stacklevel=2)
            self.swig_opts = self.swig_opts.split()
    
        # 设置 depends 属性,默认为空列表
        self.depends = depends or []
        # 设置 language 属性
        self.language = language
    
        # 设置 f2py_options、module_dirs、extra_c_compile_args、extra_cxx_compile_args、
        # extra_f77_compile_args、extra_f90_compile_args 属性,默认均为空列表
        self.f2py_options = f2py_options or []
        self.module_dirs = module_dirs or []
        self.extra_c_compile_args = extra_c_compile_args or []
        self.extra_cxx_compile_args = extra_cxx_compile_args or []
        self.extra_f77_compile_args = extra_f77_compile_args or []
        self.extra_f90_compile_args = extra_f90_compile_args or []
    
        return

    # 判断当前模块是否包含 C++ 源文件
    def has_cxx_sources(self):
        # 遍历 sources 属性,判断是否包含 C++ 源文件的扩展名
        for source in self.sources:
            if cxx_ext_re(str(source)):
                return True
        return False

    # 判断当前模块是否包含用于 f2py 的源文件
    def has_f2py_sources(self):
        # 遍历 sources 属性,判断是否包含用于 f2py 的 Fortran pyf 文件
        for source in self.sources:
            if fortran_pyf_ext_re(source):
                return True
        return False
# 定义一个名为 Extension 的类
class Extension:

.\numpy\numpy\distutils\fcompiler\absoft.py

# 导入操作系统模块
import os

# 从 numpy.distutils.cpuinfo 模块导入 cpu 函数
# 从 numpy.distutils.fcompiler 模块导入 FCompiler 类和 dummy_fortran_file 函数
# 从 numpy.distutils.misc_util 模块导入 cyg2win32 函数
from numpy.distutils.cpuinfo import cpu
from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file
from numpy.distutils.misc_util import cyg2win32

# 定义可用的编译器列表,其中只包含 AbsoftFCompiler
compilers = ['AbsoftFCompiler']

# 定义 AbsoftFCompiler 类,继承自 FCompiler
class AbsoftFCompiler(FCompiler):

    # 定义编译器类型为 'absoft'
    compiler_type = 'absoft'
    # 定义编译器描述
    description = 'Absoft Corp Fortran Compiler'
    # 定义版本模式匹配规则
    version_pattern = r'(f90:.*?(Absoft Pro FORTRAN Version|FORTRAN 77 Compiler|Absoft Fortran Compiler Version|Copyright Absoft Corporation.*?Version))'+\
                       r' (?P<version>[^\s*,]*)(.*?Absoft Corp|)'

    # 定义可执行文件字典
    executables = {
        'version_cmd'  : None,          # set by update_executables
        'compiler_f77' : ["f77"],
        'compiler_fix' : ["f90"],
        'compiler_f90' : ["f90"],
        'linker_so'    : ["<F90>"],
        'archiver'     : ["ar", "-cr"],
        'ranlib'       : ["ranlib"]
        }

    # 如果操作系统为 Windows
    if os.name=='nt':
        # 定义库开关为 '/out:'
        library_switch = '/out:'      #No space after /out:!

    # 定义模块目录开关为空
    module_dir_switch = None
    # 定义模块包含开关为 '-p'
    module_include_switch = '-p'
    
    # 定义更新可执行程序的方法
    def update_executables(self):
        # 调用 cyg2win32 函数,并传入虚拟的 Fortran 文件名,更新版本命令为 ['<F90>', '-V', '-c', f+'.f', '-o', f+'.o']

    # 定义获取链接器选项的方法
    def get_flags_linker_so(self):
        # 如果操作系统为 Windows
        if os.name=='nt':
            # 定义选项为 ['/dll']
        # 如果版本大于等于 9.0
        elif self.get_version() >= '9.0':
            # 定义选项为 ['-shared']
        else:
            # 定义选项为 ["-K", "shared"]
        # 返回选项

    # 定义库目录选项的方法
    def library_dir_option(self, dir):
        # 如果操作系统为 Windows
        if os.name=='nt':
            # 返回 ['-link', '/PATH:%s' % (dir)]
        # 返回 "-L" + dir

    # 定义库选项的方法
    def library_option(self, lib):
        # 如果操作系统为 Windows
        if os.name=='nt':
            # 返回 '%s.lib' % (lib)
        # 返回 "-l" + lib
    def get_library_dirs(self):
        # 调用父类的方法获取库目录列表
        opt = FCompiler.get_library_dirs(self)
        # 获取环境变量ABSOFT的值
        d = os.environ.get('ABSOFT')
        # 如果存在ABSOFT环境变量
        if d:
            # 获取版本号并判断是否大于等于10.0
            if self.get_version() >= '10.0':
                # 使用共享库,静态库未使用-fPIC编译
                prefix = 'sh'
            else:
                prefix = ''
            # 判断CPU是否为64位
            if cpu.is_64bit():
                suffix = '64'
            else:
                suffix = ''
            # 将目录添加到库目录列表
            opt.append(os.path.join(d, '%slib%s' % (prefix, suffix)))
        return opt

    def get_libraries(self):
        # 调用父类的方法获取库列表
        opt = FCompiler.get_libraries(self)
        # 获取版本号并根据版本号添加不同的库
        if self.get_version() >= '11.0':
            opt.extend(['af90math', 'afio', 'af77math', 'amisc'])
        elif self.get_version() >= '10.0':
            opt.extend(['af90math', 'afio', 'af77math', 'U77'])
        elif self.get_version() >= '8.0':
            opt.extend(['f90math', 'fio', 'f77math', 'U77'])
        else:
            opt.extend(['fio', 'f90math', 'fmath', 'U77'])
        # 如果操作系统为Windows,添加COMDLG32库
        if os.name =='nt':
            opt.append('COMDLG32')
        return opt

    def get_flags(self):
        # 调用父类的方法获取编译选项列表
        opt = FCompiler.get_flags(self)
        # 如果操作系统不是Windows,添加'-s'选项,并根据版本号添加不同的选项
        if os.name != 'nt':
            opt.extend(['-s'])
            if self.get_version():
                if self.get_version()>='8.2':
                    opt.append('-fpic')
        return opt

    def get_flags_f77(self):
        # 调用父类的方法获取Fortran 77编译选项列表
        opt = FCompiler.get_flags_f77(self)
        # 添加特定的编译选项
        opt.extend(['-N22', '-N90', '-N110'])
        v = self.get_version()
        # 如果操作系统为Windows,并且版本号大于等于8.0,添加特定的编译选项
        if os.name == 'nt':
            if v and v>='8.0':
                opt.extend(['-f', '-N15'])
        else:
            opt.append('-f')
            # 根据版本号添加不同的编译选项
            if v:
                if v<='4.6':
                    opt.append('-B108')
                else:
                    opt.append('-N15')
        return opt

    def get_flags_f90(self):
        # 调用父类的方法获取Fortran 90编译选项列表
        opt = FCompiler.get_flags_f90(self)
        # 添加特定的编译选项
        opt.extend(["-YCFRL=1", "-YCOM_NAMES=LCS", "-YCOM_PFX", "-YEXT_PFX",
                    "-YCOM_SFX=_", "-YEXT_SFX=_", "-YEXT_NAMES=LCS"])
        # 如果有版本号,根据版本号添加不同的编译选项
        if self.get_version():
            if self.get_version()>'4.6':
                opt.extend(["-YDEALLOC=ALL"])
        return opt

    def get_flags_fix(self):
        # 调用父类的方法获取固定格式编译选项列表
        opt = FCompiler.get_flags_fix(self)
        # 添加特定的编译选项
        opt.extend(["-YCFRL=1", "-YCOM_NAMES=LCS", "-YCOM_PFX", "-YEXT_PFX",
                    "-YCOM_SFX=_", "-YEXT_SFX=_", "-YEXT_NAMES=LCS"])
        opt.extend(["-f", "fixed"])
        return opt

    def get_flags_opt(self):
        # 返回优化编译选项列表
        opt = ['-O']
        return opt
# 如果当前模块作为脚本直接执行
if __name__ == '__main__':
    # 从 distutils 模块导入 log
    from distutils import log
    # 设置日志记录级别为 2
    log.set_verbosity(2)
    # 从 numpy.distutils 模块导入 customized_fcompiler
    from numpy.distutils import customized_fcompiler
    # 打印使用 absoft 编译器的版本信息
    print(customized_fcompiler(compiler='absoft').get_version())

.\numpy\numpy\distutils\fcompiler\arm.py

# 导入所需模块和库
import sys
from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file
from sys import platform
from os.path import join, dirname, normpath

# 定义 ArmFlangCompiler 类,继承自 FCompiler 类
class ArmFlangCompiler(FCompiler):
    # 定义编译器类型和描述
    compiler_type = 'arm'
    description = 'Arm Compiler'
    version_pattern = r'\s*Arm.*version (?P<version>[\d.-]+).*'

    # 定义一些可执行文件和命令
    ar_exe = 'lib.exe'
    possible_executables = ['armflang']
    executables = {
        'version_cmd': ["", "--version"],
        'compiler_f77': ["armflang", "-fPIC"],
        'compiler_fix': ["armflang", "-fPIC", "-ffixed-form"],
        'compiler_f90': ["armflang", "-fPIC"],
        'linker_so': ["armflang", "-fPIC", "-shared"],
        'archiver': ["ar", "-cr"],
        'ranlib':  None
    }
    
    # 定义一些编译器选项和方法
    pic_flags = ["-fPIC", "-DPIC"]
    c_compiler = 'arm'
    module_dir_switch = '-module '  # 不要删除结尾的空格!

    # 定义获取库的方法
    def get_libraries(self):
        opt = FCompiler.get_libraries(self)
        opt.extend(['flang', 'flangrti', 'ompstub'])
        return opt
    
    # 定义获取库目录的方法
    @functools.lru_cache(maxsize=128)
    def get_library_dirs(self):
        """List of compiler library directories."""
        opt = FCompiler.get_library_dirs(self)
        flang_dir = dirname(self.executables['compiler_f77'][0])
        opt.append(normpath(join(flang_dir, '..', 'lib')))
        return opt
    
    # 定义获取编译器标志的方法
    def get_flags(self):
        return []

    # 定义获取自由编译器标志的方法
    def get_flags_free(self):
        return []

    # 定义获取调试编译器标志的方法
    def get_flags_debug(self):
        return ['-g']

    # 定义获取优化编译器标志的方法
    def get_flags_opt(self):
        return ['-O3']

    # 定义获取体系结构编译器标志的方法
    def get_flags_arch(self):
        return []

    # 定义运行时库目录选项的方法
    def runtime_library_dir_option(self, dir):
        return '-Wl,-rpath=%s' % dir

# 如果作为主程序运行,则执行以下代码
if __name__ == '__main__':
    # 导入所需模块和库
    from distutils import log
    log.set_verbosity(2)
    from numpy.distutils import customized_fcompiler
    # 打印定制的编译器版本信息
    print(customized_fcompiler(compiler='armflang').get_version())

.\numpy\numpy\distutils\fcompiler\compaq.py

# 导入操作系统和系统模块
import os
import sys

# 从numpy.distutils.fcompiler模块中导入FCompiler类和DistutilsPlatformError异常
from numpy.distutils.fcompiler import FCompiler
from distutils.errors import DistutilsPlatformError

# 定义编译器列表
compilers = ['CompaqFCompiler']
# 检查操作系统是否为posix,或者sys.platform是否以'cygwin'开头,如果是则添加'CompaqVisualFCompiler'到编译器列表中
if os.name != 'posix' or sys.platform[:6] == 'cygwin' :
    # 否则在类别系统(如darwin)上会出现误报,因为会选择/bin/df
    compilers.append('CompaqVisualFCompiler')

# 定义CompaqFCompiler类,继承自FCompiler类
class CompaqFCompiler(FCompiler):

    # 设置编译器类型和描述
    compiler_type = 'compaq'
    description = 'Compaq Fortran Compiler'
    version_pattern = r'Compaq Fortran (?P<version>[^\s]*).*'

    # 如果操作系统是linux,则设置fc_exe为'fort';否则为'f90'
    if sys.platform[:5]=='linux':
        fc_exe = 'fort'
    else:
        fc_exe = 'f90'

    # 定义各种可执行文件的命令
    executables = {
        'version_cmd'  : ['<F90>', "-version"],
        'compiler_f77' : [fc_exe, "-f77rtl", "-fixed"],
        'compiler_fix' : [fc_exe, "-fixed"],
        'compiler_f90' : [fc_exe],
        'linker_so'    : ['<F90>'],
        'archiver'     : ["ar", "-cr"],
        'ranlib'       : ["ranlib"]
        }

    # 设置模块目录和模块引入开关(未经测试)
    module_dir_switch = '-module ' 
    module_include_switch = '-I'

    # 定义获取编译器标志、调试标志、优化标志和架构标志的方法
    def get_flags(self):
        return ['-assume no2underscore', '-nomixed_str_len_arg']
    def get_flags_debug(self):
        return ['-g', '-check bounds']
    def get_flags_opt(self):
        return ['-O4', '-align dcommons', '-assume bigarrays',
                '-assume nozsize', '-math_library fast']
    def get_flags_arch(self):
        return ['-arch host', '-tune host']
    def get_flags_linker_so(self):
        if sys.platform[:5]=='linux':
            return ['-shared']
        return ['-shared', '-Wl,-expect_unresolved,*']

# 定义CompaqVisualFCompiler类,继承自FCompiler类
class CompaqVisualFCompiler(FCompiler):

    # 设置编译器类型和描述
    compiler_type = 'compaqv'
    description = 'DIGITAL or Compaq Visual Fortran Compiler'
    version_pattern = (r'(DIGITAL|Compaq) Visual Fortran Optimizing Compiler'
                       r' Version (?P<version>[^\s]*).*')

    compile_switch = '/compile_only'
    object_switch = '/object:'
    library_switch = '/OUT:'      #No space after /OUT:!

    static_lib_extension = ".lib"
    static_lib_format = "%s%s"
    module_dir_switch = '/module:'
    module_include_switch = '/I'

    ar_exe = 'lib.exe'
    fc_exe = 'DF'

    # 如果操作系统是'win32',则从numpy.distutils.msvccompiler模块中导入MSVCCompiler类,并尝试获取其lib属性
    if sys.platform=='win32':
        from numpy.distutils.msvccompiler import MSVCCompiler
        try:
            m = MSVCCompiler()
            m.initialize()
            ar_exe = m.lib
        except DistutilsPlatformError:
            pass
        except AttributeError as e:
            if '_MSVCCompiler__root' in str(e):
                print('Ignoring "%s" (I think it is msvccompiler.py bug)' % (e))
            else:
                raise
        except OSError as e:
            if not "vcvarsall.bat" in str(e):
                print("Unexpected OSError in", __file__)
                raise
        except ValueError as e:
            if not "'path'" in str(e):
                print("Unexpected ValueError in", __file__)
                raise
    # 定义包含不同命令和参数的可执行文件的字典
    executables = {
        'version_cmd'  : ['<F90>', "/what"],  # 版本命令,包含<F90>和/what参数
        'compiler_f77' : [fc_exe, "/f77rtl", "/fixed"],  # F77编译器,包含fc_exe、/f77rtl和/fixed参数
        'compiler_fix' : [fc_exe, "/fixed"],  # fix编译器,包含fc_exe和/fixed参数
        'compiler_f90' : [fc_exe],  # F90编译器,包含fc_exe参数
        'linker_so'    : ['<F90>'],  # 共享库链接器,包含<F90>参数
        'archiver'     : [ar_exe, "/OUT:"],  # 静态库创建工具,包含ar_exe和/OUT:参数
        'ranlib'       : None  # ranlib为空
        }

    # 获取编译器的标志列表
    def get_flags(self):
        return ['/nologo', '/MD', '/WX', '/iface=(cref,nomixed_str_len_arg)',  
                '/names:lowercase', '/assume:underscore']
    # 获取优化编译器的标志列表
    def get_flags_opt(self):
        return ['/Ox', '/fast', '/optimize:5', '/unroll:0', '/math_library:fast']
    # 获取架构编译器的标志列表
    def get_flags_arch(self):
        return ['/threads']
    # 获取调试编译器的标志列表
    def get_flags_debug(self):
        return ['/debug']
# 检查当前模块是否是主程序
if __name__ == '__main__':
    # 从 distutils 模块导入 log 功能
    from distutils import log
    # 设置 log 的输出级别为 2
    log.set_verbosity(2)
    # 从 numpy.distutils 模块导入 customized_fcompiler 功能
    from numpy.distutils import customized_fcompiler
    # 输出使用 compaq 编译器的版本信息
    print(customized_fcompiler(compiler='compaq').get_version())

.\numpy\numpy\distutils\fcompiler\environment.py

# 导入 os 模块
import os
# 从 distutils.dist 模块中导入 Distribution 类
from distutils.dist import Distribution

# 设置类的元类为 'type'
__metaclass__ = type

# 定义环境配置类
class EnvironmentConfig:
    def __init__(self, distutils_section='ALL', **kw):
        # 初始化实例变量
        self._distutils_section = distutils_section
        self._conf_keys = kw
        self._conf = None
        self._hook_handler = None

    # 打印单个变量信息
    def dump_variable(self, name):
        # 获取配置信息
        conf_desc = self._conf_keys[name]
        hook, envvar, confvar, convert, append = conf_desc
        # 如果没有指定转换函数,设为默认转换函数
        if not convert:
            convert = lambda x : x
        # 打印变量名称
        print('%s.%s:' % (self._distutils_section, name))
        # 获取变量值并打印
        v = self._hook_handler(name, hook)
        print('  hook   : %s' % (convert(v),))
        # 如果有环境变量,则获取并打印
        if envvar:
            v = os.environ.get(envvar, None)
            print('  environ: %s' % (convert(v),))
        # 如果有配置变量且有配置信息,则获取并打印
        if confvar and self._conf:
            v = self._conf.get(confvar, (None, None))[1]
            print('  config : %s' % (convert(v),))

    # 打印所有变量信息
    def dump_variables(self):
        for name in self._conf_keys:
            self.dump_variable(name)

    # 获取属性值
    def __getattr__(self, name):
        try:
            conf_desc = self._conf_keys[name]
        except KeyError:
            raise AttributeError(
                f"'EnvironmentConfig' object has no attribute '{name}'"
            ) from None

        return self._get_var(name, conf_desc)

    # 获取变量值
    def get(self, name, default=None):
        try:
            conf_desc = self._conf_keys[name]
        except KeyError:
            return default
        var = self._get_var(name, conf_desc)
        if var is None:
            var = default
        return var

    # 根据配置信息获取变量值
    def _get_var(self, name, conf_desc):
        hook, envvar, confvar, convert, append = conf_desc
        if convert is None:
            convert = lambda x: x
        var = self._hook_handler(name, hook)
        if envvar is not None:
            envvar_contents = os.environ.get(envvar)
            if envvar_contents is not None:
                envvar_contents = convert(envvar_contents)
                if var and append:
                    if os.environ.get('NPY_DISTUTILS_APPEND_FLAGS', '1') == '1':
                        var.extend(envvar_contents)
                    else:
                        var = envvar_contents
                else:
                    var = envvar_contents
        if confvar is not None and self._conf:
            if confvar in self._conf:
                source, confvar_contents = self._conf[confvar]
                var = convert(confvar_contents)
        return var

    # 克隆环境配置对象
    def clone(self, hook_handler):
        ec = self.__class__(distutils_section=self._distutils_section,
                            **self._conf_keys)
        ec._hook_handler = hook_handler
        return ec
    # 定义一个方法,用于接收一个分布对象并设置配置选项字典
    def use_distribution(self, dist):
        # 检查传入的 dist 是否属于 Distribution 类的实例
        if isinstance(dist, Distribution):
            # 如果是,通过 dist 对象获取该分布的选项字典,并将其设置为当前对象的配置属性
            self._conf = dist.get_option_dict(self._distutils_section)
        else:
            # 如果传入的不是 Distribution 类的实例,直接将其赋值给当前对象的配置属性
            self._conf = dist

.\numpy\numpy\distutils\fcompiler\fujitsu.py

"""
fujitsu

Supports Fujitsu compiler function.
This compiler is developed by Fujitsu and is used in A64FX on Fugaku.
"""
# 导入必要的模块
from numpy.distutils.fcompiler import FCompiler

# 定义一个名为FujitsuFCompiler的类,继承自FCompiler类
compilers = ['FujitsuFCompiler']

class FujitsuFCompiler(FCompiler):
    # 编译器类型为fujitsu
    compiler_type = 'fujitsu'
    # 描述信息为Fujitsu Fortran Compiler
    description = 'Fujitsu Fortran Compiler'

    # 可能的可执行文件有frt
    possible_executables = ['frt']
    # 版本号的正则表达式
    version_pattern = r'frt \(FRT\) (?P<version>[a-z\d.]+)'
    # $ frt --version
    # frt (FRT) x.x.x yyyymmdd

    # 可执行文件的配置
    executables = {
        'version_cmd'  : ["<F77>", "--version"],
        'compiler_f77' : ["frt", "-Fixed"],
        'compiler_fix' : ["frt", "-Fixed"],
        'compiler_f90' : ["frt"],
        'linker_so'    : ["frt", "-shared"],
        'archiver'     : ["ar", "-cr"],
        'ranlib'       : ["ranlib"]
        }
    # 用于共享对象的标志
    pic_flags = ['-KPIC']
    # 模块目录开关
    module_dir_switch = '-M'
    # 模块包含开关
    module_include_switch = '-I'

    # 获取优化标志
    def get_flags_opt(self):
        return ['-O3']
    # 获取调试标志
    def get_flags_debug(self):
        return ['-g']
    # 运行时库目录选项
    def runtime_library_dir_option(self, dir):
        return f'-Wl,-rpath={dir}'
    # 获取需要的库
    def get_libraries(self):
        return ['fj90f', 'fj90i', 'fjsrcinfo']

# 如果是主程序,则执行以下内容
if __name__ == '__main__':
    # 导入必要的模块
    from distutils import log
    from numpy.distutils import customized_fcompiler
    # 设置日志详细程度
    log.set_verbosity(2)
    # 打印出定制化编译器的版本信息
    print(customized_fcompiler('fujitsu').get_version())

.\numpy\numpy\distutils\fcompiler\g95.py

# 导入FCompiler类
from numpy.distutils.fcompiler import FCompiler

# 定义G95FCompiler类,继承自FCompiler类
compilers = ['G95FCompiler']

class G95FCompiler(FCompiler):
    # 设置编译器类型为'g95'
    compiler_type = 'g95'
    # 描述为'G95 Fortran Compiler'
    description = 'G95 Fortran Compiler'

#    version_pattern = r'G95 \((GCC (?P<gccversion>[\d.]+)|.*?) \(g95!\) (?P<version>.*)\).*'
    # 定义版本信息的正则表达式模式
    # $ g95 --version
    # G95 (GCC 4.0.3 (g95!) May 22 2006)
    version_pattern = r'G95 \((GCC (?P<gccversion>[\d.]+)|.*?) \(g95 (?P<version>.*)!\) (?P<date>.*)\).*'
    # $ g95 --version
    # G95 (GCC 4.0.3 (g95 0.90!) Aug 22 2006)

    executables = {
        'version_cmd'  : ["<F90>", "--version"],
        'compiler_f77' : ["g95", "-ffixed-form"],
        'compiler_fix' : ["g95", "-ffixed-form"],
        'compiler_f90' : ["g95"],
        'linker_so'    : ["<F90>", "-shared"],
        'archiver'     : ["ar", "-cr"],
        'ranlib'       : ["ranlib"]
        }
    # 设置标志为'-fpic'
    pic_flags = ['-fpic']
    # 设置模块目录开关为'-fmod='
    module_dir_switch = '-fmod='
    # 设置模块包含开关为'-I'
    module_include_switch = '-I'

    # 定义获取标志的方法
    def get_flags(self):
        return ['-fno-second-underscore']
    # 定义获取优化标志的方法
    def get_flags_opt(self):
        return ['-O']
    # 定义获取调试标志的方法
    def get_flags_debug(self):
        return ['-g']

# 如果是直接运行该脚本
if __name__ == '__main__':
    # 导入log和customized_fcompiler函数
    from distutils import log
    from numpy.distutils import customized_fcompiler
    # 设置日志输出详细程度为2
    log.set_verbosity(2)
    # 打印自定义Fortran编译器的版本信息
    print(customized_fcompiler('g95').get_version())

.\numpy\numpy\distutils\fcompiler\gnu.py

# 导入正则表达式模块
import re
# 导入操作系统接口模块
import os
# 导入系统-specific 参数和功能模块
import sys
# 导入警告管理器模块
import warnings
# 导入平台相关模块
import platform
# 导入临时文件模块
import tempfile
# 导入哈希模块
import hashlib
# 导入BASE64 模块
import base64
# 导入子进程管理模块
import subprocess
# 从子进程管理模块导入进程和管道类
from subprocess import Popen, PIPE, STDOUT
# 从NumPy.distutils 模块导入文件路径和子进程输出
from numpy.distutils.exec_command import filepath_from_subprocess_output
# 从NumPy.distutils模块导入Fortran 编译器
from numpy.distutils.fcompiler import FCompiler
# 从distutils版本模块导入松散版本
from distutils.version import LooseVersion

# GnuFCompiler类,继承自FCompiler
class GnuFCompiler(FCompiler):
    # 编译器类型为gnu
    compiler_type = 'gnu'
    # 编译器别名为g77
    compiler_aliases = ('g77', )
    # 描述为GNU Fortran 77 编译器
    description = 'GNU Fortran 77 compiler'

    # GNU版本匹配方法
    def gnu_version_match(self, version_string):
        """Handle the different versions of GNU fortran compilers"""
        # 剥离可能被gfortran发出的警告
        while version_string.startswith('gfortran: warning'):
            # 从第一个换行符之后截取版本字符串并去除空格
            version_string =\
                version_string[version_string.find('\n') + 1:].strip()
        
        # 对GNU fortran不同版本进行处理
        if len(version_string) <= 20:
            # 尝试找到有效的版本字符串
            m = re.search(r'([0-9.]+)', version_string)
            if m:
                if version_string.startswith('GNU Fortran'):
                    # g77提供的版本字符串以GNU Fortran开头
                    return ('g77', m.group(1))
                elif m.start() == 0:
                    # gfortran仅输出类似#.#.#的版本字符串,因此检查匹配是否位于字符串的开头
                    return ('gfortran', m.group(1))
        else:
            # 从--version输出的版本信息,尝试更努力地获取版本信息
            m = re.search(r'GNU Fortran\s+95.*?([0-9-.]+)', version_string)
            if m:
                return ('gfortran', m.group(1))
            m = re.search(
                r'GNU Fortran.*?\-?([0-9-.]+\.[0-9-.]+)', version_string)
            if m:
                v = m.group(1)
                if v.startswith('0') or v.startswith('2') or v.startswith('3'):
                    return ('g77', v)
                else:
                    return ('gfortran', v)
        
        # 如果仍然找不到版本信息,引发异常以便找到问题
        err = 'A valid Fortran version was not found in this string:\n'
        raise ValueError(err + version_string)
    # 定义一个方法用于检查版本号是否匹配特定的 GNU 编译器
    def version_match(self, version_string):
        # 调用对象的方法检查是否匹配 GNU 版本
        v = self.gnu_version_match(version_string)
        # 如果版本不匹配或者第一个元素不是 'g77',返回 None
        if not v or v[0] != 'g77':
            return None
        # 返回匹配的版本号
        return v[1]

    # 可能的执行文件列表,包括 'g77' 和 'f77'
    possible_executables = ['g77', 'f77']

    # 编译器和链接器等可执行文件的命令及选项
    executables = {
        'version_cmd'  : [None, "-dumpversion"],  # 获取版本号的命令
        'compiler_f77' : [None, "-g", "-Wall", "-fno-second-underscore"],  # f77 编译器的选项
        'compiler_f90' : None,  # 对于 f90 代码,使用 --fcompiler=gnu95
        'compiler_fix' : None,  # 修正编译器的选项
        'linker_so'    : [None, "-g", "-Wall"],  # 共享对象链接器的选项
        'archiver'     : ["ar", "-cr"],  # 归档工具的命令及选项
        'ranlib'       : ["ranlib"],  # ranlib 命令
        'linker_exe'   : [None, "-g", "-Wall"]  # 可执行文件链接器的选项
    }

    module_dir_switch = None  # 模块目录的开关,目前未设置
    module_include_switch = None  # 模块包含的开关,目前未设置

    # 对于非 Windows 平台且非 Cygwin Python 的情况,处理位置独立代码标志
    if os.name != 'nt' and sys.platform != 'cygwin':
        pic_flags = ['-fPIC']

    # 当 Python 运行在 Win32 平台时,为 g77 相关的几个键添加 -mno-cygwin 标志
    if sys.platform == 'win32':
        for key in ['version_cmd', 'compiler_f77', 'linker_so', 'linker_exe']:
            executables[key].append('-mno-cygwin')

    g2c = 'g2c'  # g2c 编译器的名称设为 'g2c'
    suggested_f90_compiler = 'gnu95'  # 建议使用的 f90 编译器设为 'gnu95'
    # 获取用于链接共享对象的选项
    def get_flags_linker_so(self):
        # 去除链接器选项中的第一个元素(通常是链接器名称)
        opt = self.linker_so[1:]
        # 如果运行在 macOS 上
        if sys.platform == 'darwin':
            # 获取环境变量中的 MACOSX_DEPLOYMENT_TARGET 设置
            target = os.environ.get('MACOSX_DEPLOYMENT_TARGET', None)
            # 如果 MACOSX_DEPLOYMENT_TARGET 已设置,直接使用其值
            # 并且不作任何更改。但是,如果环境中的值与用于构建 Python 的
            # Makefile 中的值不一致,distutils 会报错。我们让 distutils
            # 处理这个错误检查。
            if not target:
                # 如果环境变量中没有设置 MACOSX_DEPLOYMENT_TARGET
                # 首先尝试从 sysconfig 中获取,然后默认设置为 10.9
                # 这是一个合理的默认值,即使使用官方的 Python 发行版
                # 或其衍生版本。
                import sysconfig
                target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
                if not target:
                    target = '10.9'
                    s = f'Env. variable MACOSX_DEPLOYMENT_TARGET set to {target}'
                    # 发出警告,指示 MACOSX_DEPLOYMENT_TARGET 已设置为默认值
                    warnings.warn(s, stacklevel=2)
                # 将 MACOSX_DEPLOYMENT_TARGET 设置为 target
                os.environ['MACOSX_DEPLOYMENT_TARGET'] = str(target)
            # 添加特定于 macOS 的链接选项
            opt.extend(['-undefined', 'dynamic_lookup', '-bundle'])
        else:
            # 对于非 macOS 平台,添加 "-shared" 选项
            opt.append("-shared")
        # 如果运行在 Solaris 平台
        if sys.platform.startswith('sunos'):
            # SunOS 中静态库 libg2c.a 经常定义动态加载的符号
            # 链接器不能很好地处理这个问题。为了忽略这个问题,使用 -mimpure-text 标志。
            # 虽然不是最安全的方法,但似乎可以工作。gcc 的 man 手册说:
            # "相对于使用 -mimpure-text,你应该使用 -fpic 或 -fPIC 编译所有源代码。"
            opt.append('-mimpure-text')
        # 返回最终的链接器选项列表
        return opt

    # 获取 libgcc 库所在的目录
    def get_libgcc_dir(self):
        try:
            # 执行命令获取 libgcc 文件名
            output = subprocess.check_output(self.compiler_f77 +
                                            ['-print-libgcc-file-name'])
        except (OSError, subprocess.CalledProcessError):
            pass
        else:
            # 处理从子进程输出中获取的文件路径
            output = filepath_from_subprocess_output(output)
            # 返回 libgcc 文件所在的目录
            return os.path.dirname(output)
        # 如果出现异常或未能获取到输出,返回 None
        return None
    # 获取 libgfortran 库的路径
    def get_libgfortran_dir(self):
        # 如果运行在 Linux 平台上
        if sys.platform[:5] == 'linux':
            # 设置 libgfortran 库文件名
            libgfortran_name = 'libgfortran.so'
        # 如果运行在 Darwin(macOS)平台上
        elif sys.platform == 'darwin':
            # 设置 libgfortran 库文件名
            libgfortran_name = 'libgfortran.dylib'
        else:
            # 否则,平台不支持 libgfortran
            libgfortran_name = None

        # 初始化 libgfortran_dir 变量为 None
        libgfortran_dir = None
        # 如果找到了 libgfortran 库文件名
        if libgfortran_name:
            # 设置查找库文件的参数
            find_lib_arg = ['-print-file-name={0}'.format(libgfortran_name)]
            try:
                # 调用子进程执行命令查找库文件位置
                output = subprocess.check_output(
                                       self.compiler_f77 + find_lib_arg)
            except (OSError, subprocess.CalledProcessError):
                # 处理异常情况,比如命令执行错误或者子进程调用错误
                pass
            else:
                # 处理子进程输出,获取文件路径
                output = filepath_from_subprocess_output(output)
                # 获取库文件所在目录路径
                libgfortran_dir = os.path.dirname(output)
        # 返回找到的 libgfortran 库的目录路径
        return libgfortran_dir

    # 获取需要链接的库目录列表
    def get_library_dirs(self):
        # 初始化目录列表为空
        opt = []
        # 如果不是运行在 Linux 平台
        if sys.platform[:5] != 'linux':
            # 获取 libgcc 库的目录
            d = self.get_libgcc_dir()
            # 如果成功获取到 libgcc 库目录
            if d:
                # 如果运行在 Windows 平台且不是使用 cygwin
                if sys.platform == 'win32' and not d.startswith('/usr/lib'):
                    # 规范化目录路径
                    d = os.path.normpath(d)
                    # 构造 libg2c 库文件路径
                    path = os.path.join(d, "lib%s.a" % self.g2c)
                    # 如果路径不存在
                    if not os.path.exists(path):
                        # 计算根目录路径
                        root = os.path.join(d, *((os.pardir, ) * 4))
                        # 构造第二个可能的 lib 目录路径
                        d2 = os.path.abspath(os.path.join(root, 'lib'))
                        # 构造 libg2c 库文件路径
                        path = os.path.join(d2, "lib%s.a" % self.g2c)
                        # 如果路径存在
                        if os.path.exists(path):
                            # 将第二个 lib 目录路径添加到选项列表中
                            opt.append(d2)
                # 将 libgcc 库目录路径添加到选项列表中
                opt.append(d)
        # 获取 libgfortran 库的目录路径
        lib_gfortran_dir = self.get_libgfortran_dir()
        # 如果成功获取到 libgfortran 库目录路径
        if lib_gfortran_dir:
            # 将 libgfortran 库目录路径添加到选项列表中
            opt.append(lib_gfortran_dir)
        # 返回最终的选项列表
        return opt

    # 获取需要链接的库列表
    def get_libraries(self):
        # 初始化库列表为空
        opt = []
        # 获取 libgcc 库的目录路径
        d = self.get_libgcc_dir()
        # 如果成功获取到 libgcc 库目录路径
        if d is not None:
            # 设置 libg2c 的版本后缀
            g2c = self.g2c + '-pic'
            # 构造静态库的格式
            f = self.static_lib_format % (g2c, self.static_lib_extension)
            # 如果静态库文件不存在
            if not os.path.isfile(os.path.join(d, f)):
                # 重置 libg2c 的版本后缀
                g2c = self.g2c
        else:
            # 如果未获取到 libgcc 库目录路径,设置 libg2c 的版本
            g2c = self.g2c

        # 如果成功设置了 libg2c 版本
        if g2c is not None:
            # 将 libg2c 库版本添加到选项列表中
            opt.append(g2c)
        # 获取 C 编译器类型
        c_compiler = self.c_compiler
        # 如果运行在 Windows 平台且 C 编译器类型是 MSVC
        if sys.platform == 'win32' and c_compiler and \
                c_compiler.compiler_type == 'msvc':
            # 添加 gcc 到选项列表中
            opt.append('gcc')
        # 如果运行在 Darwin(macOS)平台
        if sys.platform == 'darwin':
            # 添加 cc_dynamic 到选项列表中
            opt.append('cc_dynamic')
        # 返回最终的选项列表
        return opt

    # 获取调试标志列表
    def get_flags_debug(self):
        # 返回调试标志列表 ['-g']
        return ['-g']

    # 获取优化标志列表
    def get_flags_opt(self):
        # 获取当前编译器版本
        v = self.get_version()
        # 如果版本存在且小于等于 '3.3.3'
        if v and v <= '3.3.3':
            # 对于该编译器版本,使用 '-O2' 优化标志
            opt = ['-O2']
        else:
            # 否则,使用 '-O3' 优化标志
            opt = ['-O3']
        # 添加 '-funroll-loops' 优化标志
        opt.append('-funroll-loops')
        # 返回最终的优化标志列表
        return opt
    # 返回从 CFLAGS 中检测到的架构标志
    def _c_arch_flags(self):
        """ Return detected arch flags from CFLAGS """
        import sysconfig
        try:
            # 获取 Python 的编译配置中的 CFLAGS
            cflags = sysconfig.get_config_vars()['CFLAGS']
        except KeyError:
            # 如果找不到 CFLAGS,则返回空列表
            return []
        # 匹配 "-arch" 后面跟随的架构标志,存入 arch_flags 列表
        arch_re = re.compile(r"-arch\s+(\w+)")
        arch_flags = []
        for arch in arch_re.findall(cflags):
            # 将每个架构标志转换为 ['-arch', arch] 的形式,添加到 arch_flags 中
            arch_flags += ['-arch', arch]
        return arch_flags

    # 返回空列表,占位函数,暂无具体实现
    def get_flags_arch(self):
        return []

    # 返回指定目录的运行时库目录选项
    def runtime_library_dir_option(self, dir):
        if sys.platform == 'win32' or sys.platform == 'cygwin':
            # Windows 和 Cygwin 平台不支持 RPATH,抛出未实现错误
            raise NotImplementedError

        # 断言目录字符串中不包含逗号
        assert "," not in dir

        if sys.platform == 'darwin':
            # macOS 平台使用 -Wl,-rpath,dir 作为运行时库目录选项
            return f'-Wl,-rpath,{dir}'
        elif sys.platform.startswith(('aix', 'os400')):
            # AIX 平台和 OS/400 平台使用 -Wl,-blibpath:dir 作为运行时库目录选项
            return f'-Wl,-blibpath:{dir}'
        else:
            # 其他 Unix-like 平台使用 -Wl,-rpath=dir 作为运行时库目录选项
            return f'-Wl,-rpath={dir}'
class Gnu95FCompiler(GnuFCompiler):
    # 指定编译器类型为 gnu95
    compiler_type = 'gnu95'
    # 设置编译器的别名为 gfortran
    compiler_aliases = ('gfortran', )
    # 描述信息为 GNU Fortran 95 编译器
    description = 'GNU Fortran 95 compiler'

    def version_match(self, version_string):
        # 调用父类方法,检查版本字符串是否匹配
        v = self.gnu_version_match(version_string)
        # 如果版本信息不匹配或者不是 gfortran,返回 None
        if not v or v[0] != 'gfortran':
            return None
        v = v[1]
        # 如果版本大于等于 "4"
        if LooseVersion(v) >= "4":
            # 对于 gcc-4 系列的版本不支持 -mno-cygwin 选项
            pass
        else:
            # 当 Python 不是 Cygwin-Python 时,在 win32 平台上添加 -mno-cygwin 标志
            if sys.platform == 'win32':
                for key in [
                        'version_cmd', 'compiler_f77', 'compiler_f90',
                        'compiler_fix', 'linker_so', 'linker_exe'
                ]:
                    self.executables[key].append('-mno-cygwin')
        return v

    # 可能的可执行文件列表
    possible_executables = ['gfortran', 'f95']
    # 不同类型的编译器及其选项
    executables = {
        'version_cmd'  : ["<F90>", "-dumpversion"],
        'compiler_f77' : [None, "-Wall", "-g", "-ffixed-form",
                          "-fno-second-underscore"],
        'compiler_f90' : [None, "-Wall", "-g",
                          "-fno-second-underscore"],
        'compiler_fix' : [None, "-Wall",  "-g","-ffixed-form",
                          "-fno-second-underscore"],
        'linker_so'    : ["<F90>", "-Wall", "-g"],
        'archiver'     : ["ar", "-cr"],
        'ranlib'       : ["ranlib"],
        'linker_exe'   : [None, "-Wall"]
    }

    # 模块目录选项
    module_dir_switch = '-J'
    # 模块包含选项
    module_include_switch = '-I'

    # 如果系统平台以 ('aix', 'os400') 开头
    if sys.platform.startswith(('aix', 'os400')):
        # 向 linker_so 执行文件添加 -lpthread 标志
        executables['linker_so'].append('-lpthread')
        # 如果平台架构是 64 位
        if platform.architecture()[0][:2] == '64':
            # 对于多个关键字,向可执行文件添加 -maix64 标志
            for key in ['compiler_f77', 'compiler_f90','compiler_fix','linker_so', 'linker_exe']:
                executables[key].append('-maix64')

    # g2c 变量设置为 'gfortran'
    g2c = 'gfortran'

    def _universal_flags(self, cmd):
        """Return a list of -arch flags for every supported architecture."""
        # 如果不是在 Darwin 平台上,返回空列表
        if not sys.platform == 'darwin':
            return []
        arch_flags = []
        # 获取 C 编译器支持的架构标志
        c_archs = self._c_arch_flags()
        # 如果 "i386" 在 C 编译器支持的架构中,将其替换为 "i686"
        if "i386" in c_archs:
            c_archs[c_archs.index("i386")] = "i686"
        # 检查 Fortran 编译器支持的架构,并与 C 编译器的进行比较
        for arch in ["ppc", "i686", "x86_64", "ppc64", "s390x"]:
            # 如果 cmd 可以以 arch 作为目标,并且 arch 在 C 编译器的架构中
            if _can_target(cmd, arch) and arch in c_archs:
                # 添加 -arch arch 标志到 arch_flags 列表中
                arch_flags.extend(["-arch", arch])
        return arch_flags

    def get_flags(self):
        # 调用父类方法获取 flags 列表
        flags = GnuFCompiler.get_flags(self)
        # 获取通用的架构标志
        arch_flags = self._universal_flags(self.compiler_f90)
        # 如果有通用的架构标志,将其插入到 flags 列表的开头
        if arch_flags:
            flags[:0] = arch_flags
        return flags

    def get_flags_linker_so(self):
        # 调用父类方法获取 linker_so 的 flags 列表
        flags = GnuFCompiler.get_flags_linker_so(self)
        # 获取通用的架构标志
        arch_flags = self._universal_flags(self.linker_so)
        # 如果有通用的架构标志,将其插入到 flags 列表的开头
        if arch_flags:
            flags[:0] = arch_flags
        return flags
    # 获得编译器库目录的方法
    def get_library_dirs(self):
        # 调用父类方法获取初始选项列表
        opt = GnuFCompiler.get_library_dirs(self)
        # 如果运行平台是 Windows
        if sys.platform == 'win32':
            # 获取 C 编译器
            c_compiler = self.c_compiler
            # 如果存在 C 编译器且编译器类型是 MSVC
            if c_compiler and c_compiler.compiler_type == "msvc":
                # 获取目标平台
                target = self.get_target()
                if target:
                    # 获取 libgcc 目录,并计算 mingw 目录
                    d = os.path.normpath(self.get_libgcc_dir())
                    root = os.path.join(d, *((os.pardir, ) * 4))
                    path = os.path.join(root, "lib")
                    mingwdir = os.path.normpath(path)
                    # 如果 mingw 目录下存在 libmingwex.a 文件,则添加到选项列表中
                    if os.path.exists(os.path.join(mingwdir, "libmingwex.a")):
                        opt.append(mingwdir)
        # 对于 Macports / Linux,libgfortran 和 libgcc 不是共存的
        # 获取 libgfortran 目录,如果存在则添加到选项列表中
        lib_gfortran_dir = self.get_libgfortran_dir()
        if lib_gfortran_dir:
            opt.append(lib_gfortran_dir)
        # 返回最终的选项列表
        return opt

    # 获取链接库的方法
    def get_libraries(self):
        # 调用父类方法获取初始选项列表
        opt = GnuFCompiler.get_libraries(self)
        # 如果运行平台是 Darwin (MacOS)
        if sys.platform == 'darwin':
            # 移除 cc_dynamic 库
            opt.remove('cc_dynamic')
        # 如果运行平台是 Windows
        if sys.platform == 'win32':
            # 获取 C 编译器
            c_compiler = self.c_compiler
            # 如果存在 C 编译器且编译器类型是 MSVC
            if c_compiler and c_compiler.compiler_type == "msvc":
                # 如果 opt 列表中包含 "gcc",则在其后插入 "mingw32" 和 "mingwex"
                if "gcc" in opt:
                    i = opt.index("gcc")
                    opt.insert(i + 1, "mingwex")
                    opt.insert(i + 1, "mingw32")
            # 如果是 MSVC 编译器,返回空列表
            if c_compiler and c_compiler.compiler_type == "msvc":
                return []
            else:
                pass
        # 返回最终的选项列表
        return opt

    # 获取编译目标的方法
    def get_target(self):
        try:
            # 启动子进程执行编译器命令,并捕获输出
            p = subprocess.Popen(
                self.compiler_f77 + ['-v'],
                stdin=subprocess.PIPE,
                stderr=subprocess.PIPE,
            )
            stdout, stderr = p.communicate()
            output = (stdout or b"") + (stderr or b"")
        except (OSError, subprocess.CalledProcessError):
            pass
        else:
            # 处理子进程输出的文件路径,通过正则表达式匹配目标平台信息
            output = filepath_from_subprocess_output(output)
            m = TARGET_R.search(output)
            if m:
                return m.group(1)
        # 如果没有匹配到目标平台信息,则返回空字符串
        return ""

    # 计算文件的哈希值的方法
    def _hash_files(self, filenames):
        # 创建 SHA1 哈希对象
        h = hashlib.sha1()
        # 遍历文件名列表
        for fn in filenames:
            # 以二进制读取文件内容并更新哈希对象
            with open(fn, 'rb') as f:
                while True:
                    block = f.read(131072)
                    if not block:
                        break
                    h.update(block)
        # 将哈希值进行 Base32 编码,并转换为 ASCII 字符串格式
        text = base64.b32encode(h.digest())
        text = text.decode('ascii')
        # 去除编码结果末尾的 '=' 符号并返回
        return text.rstrip('=')
    def _link_wrapper_lib(self, objects, output_dir, extra_dll_dir,
                          chained_dlls, is_archive):
        """Create a wrapper shared library for the given objects

        Return an MSVC-compatible lib
        """

        c_compiler = self.c_compiler
        # 检查编译器类型是否为 MSVC,否则抛出数值错误异常
        if c_compiler.compiler_type != "msvc":
            raise ValueError("This method only supports MSVC")

        # 计算对象文件和链式 DLL 的哈希值
        object_hash = self._hash_files(list(objects) + list(chained_dlls))

        # 根据系统位数确定标签
        if is_win64():
            tag = 'win_amd64'
        else:
            tag = 'win32'

        # 根据对象的基本名称和哈希值构造库文件名、动态链接库名和定义文件名
        basename = 'lib' + os.path.splitext(
            os.path.basename(objects[0]))[0][:8]
        root_name = basename + '.' + object_hash + '.gfortran-' + tag
        dll_name = root_name + '.dll'
        def_name = root_name + '.def'
        lib_name = root_name + '.lib'

        # 构造动态链接库、定义文件和库文件的路径
        dll_path = os.path.join(extra_dll_dir, dll_name)
        def_path = os.path.join(output_dir, def_name)
        lib_path = os.path.join(output_dir, lib_name)

        # 如果库文件已存在,则直接返回路径
        if os.path.isfile(lib_path):
            # Nothing to do
            return lib_path, dll_path

        # 如果需要创建归档文件,则修改对象列表
        if is_archive:
            objects = (["-Wl,--whole-archive"] + list(objects) +
                       ["-Wl,--no-whole-archive"])

        # 调用链接共享对象的方法,传入对象列表和相关参数
        self.link_shared_object(
            objects,
            dll_name,
            output_dir=extra_dll_dir,
            extra_postargs=list(chained_dlls) + [
                '-Wl,--allow-multiple-definition',
                '-Wl,--output-def,' + def_path,
                '-Wl,--export-all-symbols',
                '-Wl,--enable-auto-import',
                '-static',
                '-mlong-double-64',
            ])

        # 如果系统为 Win64,则指定 /MACHINE:X64,否则为 /MACHINE:X86
        if is_win64():
            specifier = '/MACHINE:X64'
        else:
            specifier = '/MACHINE:X86'

        # MSVC 特定的库参数列表
        lib_args = ['/def:' + def_path, '/OUT:' + lib_path, specifier]

        # 如果编译器尚未初始化,则进行初始化
        if not c_compiler.initialized:
            c_compiler.initialize()

        # 使用编译器的 spawn 方法调用 lib 命令来生成库文件
        c_compiler.spawn([c_compiler.lib] + lib_args)

        # 返回生成的库文件和动态链接库的路径
        return lib_path, dll_path

    def can_ccompiler_link(self, compiler):
        # 判断给定的编译器是否为 MSVC,如果是则返回 False,否则返回 True
        # 表示 MSVC 不能链接由 GNU fortran 编译的对象
        return compiler.compiler_type not in ("msvc", )
    # 将不兼容默认链接器的一组对象文件转换为与之兼容的文件。
    def wrap_unlinkable_objects(self, objects, output_dir, extra_dll_dir):
        """
        Convert a set of object files that are not compatible with the default
        linker, to a file that is compatible.
        """
        # 检查编译器类型是否为 MSVC
        if self.c_compiler.compiler_type == "msvc":
            # 编译一个 DLL 并返回 DLL 的 lib 作为对象。
            # 同时跟踪之前编译的 DLL,以便可以链接到它们。

            # 如果有 .a 归档文件,假设它们是独立的静态库,并为每个构建单独的 DLL。
            archives = []
            plain_objects = []
            for obj in objects:
                if obj.lower().endswith('.a'):
                    archives.append(obj)
                else:
                    plain_objects.append(obj)

            chained_libs = []
            chained_dlls = []
            # 反向遍历归档文件,以处理依赖顺序
            for archive in archives[::-1]:
                lib, dll = self._link_wrapper_lib(
                    [archive],
                    output_dir,
                    extra_dll_dir,
                    chained_dlls=chained_dlls,
                    is_archive=True)
                chained_libs.insert(0, lib)  # 在列表开头插入 lib
                chained_dlls.insert(0, dll)  # 在列表开头插入 dll

            if not plain_objects:
                return chained_libs  # 返回链接的库列表

            # 处理普通对象文件,构建相应的 DLL
            lib, dll = self._link_wrapper_lib(
                plain_objects,
                output_dir,
                extra_dll_dir,
                chained_dlls=chained_dlls,
                is_archive=False)
            return [lib] + chained_libs  # 返回链接的库列表,包括当前构建的库
        else:
            raise ValueError("Unsupported C compiler")
# 如果指定的体系结构支持 -arch 标志,则返回 True
def _can_target(cmd, arch):
    # 复制命令列表,避免修改原始命令
    newcmd = cmd[:]
    # 创建一个临时文件以 .f 为后缀
    fid, filename = tempfile.mkstemp(suffix=".f")
    os.close(fid)
    try:
        # 获取临时文件的目录
        d = os.path.dirname(filename)
        # 根据文件名生成输出文件名,将 .f 后缀改为 .o
        output = os.path.splitext(filename)[0] + ".o"
        try:
            # 向命令列表添加 -arch、体系结构、-c 和文件名参数
            newcmd.extend(["-arch", arch, "-c", filename])
            # 在指定目录中启动子进程,将标准错误输出到标准输出,捕获输出
            p = Popen(newcmd, stderr=STDOUT, stdout=PIPE, cwd=d)
            p.communicate()
            # 返回子进程的退出代码是否为 0,即命令执行成功
            return p.returncode == 0
        finally:
            # 如果生成了输出文件,删除它
            if os.path.exists(output):
                os.remove(output)
    finally:
        # 删除临时创建的文件
        os.remove(filename)


if __name__ == '__main__':
    # 导入日志模块
    from distutils import log
    # 导入自定义的 Fortran 编译器
    from numpy.distutils import customized_fcompiler
    # 设置日志的详细程度为 2
    log.set_verbosity(2)

    # 打印 GNU 编译器的版本信息
    print(customized_fcompiler('gnu').get_version())
    try:
        # 尝试打印 g95 编译器的版本信息,捕获可能的异常
        print(customized_fcompiler('g95').get_version())
    except Exception as e:
        # 打印捕获的异常对象
        print(e)

.\numpy\numpy\distutils\fcompiler\hpux.py

# 从 numpy.distutils.fcompiler 模块导入 FCompiler 类
from numpy.distutils.fcompiler import FCompiler

# 定义一个列表,包含单个字符串 'HPUXFCompiler'
compilers = ['HPUXFCompiler']

# 定义 HPUXFCompiler 类,继承自 FCompiler 类
class HPUXFCompiler(FCompiler):

    # 定义类变量 compiler_type,表示编译器类型为 'hpux'
    compiler_type = 'hpux'
    
    # 定义类变量 description,描述为 'HP Fortran 90 Compiler'
    description = 'HP Fortran 90 Compiler'
    
    # 定义类变量 version_pattern,使用正则表达式匹配 HP F90 编译器版本
    version_pattern =  r'HP F90 (?P<version>[^\s*,]*)'

    # 定义 executables 字典,包含各种命令及其参数
    executables = {
        'version_cmd'  : ["f90", "+version"],  # 版本查询命令
        'compiler_f77' : ["f90"],              # Fortran 77 编译器命令
        'compiler_fix' : ["f90"],              # 固定格式 Fortran 编译器命令
        'compiler_f90' : ["f90"],              # Fortran 90 编译器命令
        'linker_so'    : ["ld", "-b"],         # 动态链接器命令
        'archiver'     : ["ar", "-cr"],        # 静态库打包命令
        'ranlib'       : ["ranlib"]            # ranlib 命令
        }

    # 定义 module_dir_switch 和 module_include_switch 变量,暂未实现(XXX: fix me)
    module_dir_switch = None #XXX: fix me
    module_include_switch = None #XXX: fix me
    
    # 定义 pic_flags 列表,包含 '+Z' 标志
    pic_flags = ['+Z']
    
    # 定义 get_flags 方法,返回 pic_flags 列表和额外的编译标志 ['+ppu', '+DD64']
    def get_flags(self):
        return self.pic_flags + ['+ppu', '+DD64']
    
    # 定义 get_flags_opt 方法,返回优化编译标志 ['-O3']
    def get_flags_opt(self):
        return ['-O3']
    
    # 定义 get_libraries 方法,返回需要链接的库列表,包含 'm' 库
    def get_libraries(self):
        return ['m']
    
    # 定义 get_library_dirs 方法,返回库文件搜索路径列表 ['/usr/lib/hpux64']
    def get_library_dirs(self):
        opt = ['/usr/lib/hpux64']
        return opt
    
    # 定义 get_version 方法,获取编译器版本信息,处理状态码为 256 的情况
    def get_version(self, force=0, ok_status=[256, 0, 1]):
        # XXX status==256 可能表示 'unrecognized option' 或 'no input file' 的错误,version_cmd 需要进一步工作。
        return FCompiler.get_version(self, force, ok_status)

# 如果脚本被直接执行
if __name__ == '__main__':
    # 从 distutils 模块中导入 log
    from distutils import log
    
    # 设置日志输出详细程度为 10
    log.set_verbosity(10)
    
    # 从 numpy.distutils 模块中导入 customized_fcompiler 函数
    from numpy.distutils import customized_fcompiler
    
    # 输出使用 'hpux' 编译器的版本信息
    print(customized_fcompiler(compiler='hpux').get_version())

.\numpy\numpy\distutils\fcompiler\ibm.py

import os  # 导入操作系统接口模块
import re  # 导入正则表达式模块
import sys  # 导入系统模块
import subprocess  # 导入子进程管理模块

from numpy.distutils.fcompiler import FCompiler  # 导入 NumPy 的 Fortran 编译器抽象类
from numpy.distutils.exec_command import find_executable  # 导入查找可执行文件的函数
from numpy.distutils.misc_util import make_temp_file  # 导入创建临时文件的函数
from distutils import log  # 导入 distutils 日志模块

compilers = ['IBMFCompiler']  # 定义一个包含单个元素的列表,元素为字符串 'IBMFCompiler'

class IBMFCompiler(FCompiler):
    compiler_type = 'ibm'  # 编译器类型字符串设为 'ibm'
    description = 'IBM XL Fortran Compiler'  # 编译器描述字符串
    version_pattern =  r'(xlf\(1\)\s*|)IBM XL Fortran ((Advanced Edition |)Version |Enterprise Edition V|for AIX, V)(?P<version>[^\s*]*)'
    # 版本号正则表达式模式字符串,匹配 IBM XL Fortran 编译器的版本信息格式

    executables = {
        'version_cmd'  : ["<F77>", "-qversion"],  # 版本命令行的可执行文件及参数列表
        'compiler_f77' : ["xlf"],  # Fortran 77 编译器的可执行文件及参数列表
        'compiler_fix' : ["xlf90", "-qfixed"],  # 固定格式 Fortran 90 编译器的可执行文件及参数列表
        'compiler_f90' : ["xlf90"],  # 自由格式 Fortran 90 编译器的可执行文件及参数列表
        'linker_so'    : ["xlf95"],  # 共享库链接器的可执行文件及参数列表
        'archiver'     : ["ar", "-cr"],  # 静态库创建工具的可执行文件及参数列表
        'ranlib'       : ["ranlib"]  # ranlib 工具的可执行文件及参数列表
        }

    def get_version(self,*args,**kwds):
        version = FCompiler.get_version(self,*args,**kwds)  # 调用父类方法获取版本信息

        if version is None and sys.platform.startswith('aix'):
            # 如果未能获取版本信息并且运行环境为 AIX
            lslpp = find_executable('lslpp')  # 查找 lslpp 可执行文件路径
            xlf = find_executable('xlf')  # 查找 xlf 可执行文件路径
            if os.path.exists(xlf) and os.path.exists(lslpp):
                try:
                    o = subprocess.check_output([lslpp, '-Lc', 'xlfcmp'])  # 执行 lslpp 命令获取 xlfcmp 组件信息
                except (OSError, subprocess.CalledProcessError):
                    pass
                else:
                    m = re.search(r'xlfcmp:(?P<version>\d+([.]\d+)+)', o)  # 使用正则表达式从输出中提取版本号
                    if m: version = m.group('version')

        xlf_dir = '/etc/opt/ibmcmp/xlf'
        if version is None and os.path.isdir(xlf_dir):
            # 如果未能获取版本信息并且 xlf 目录存在
            # 对于 Linux 系统,如果 xlf 输出不包含版本信息(例如 xlf 8.1),则尝试另一种方法
            l = sorted(os.listdir(xlf_dir))  # 列出 xlf 目录下所有文件和目录,并按字母顺序排序
            l.reverse()  # 反转列表顺序
            l = [d for d in l if os.path.isfile(os.path.join(xlf_dir, d, 'xlf.cfg'))]  # 过滤出包含 'xlf.cfg' 文件的目录列表
            if l:
                from distutils.version import LooseVersion
                self.version = version = LooseVersion(l[0])  # 尝试使用第一个目录的版本号作为结果

        return version  # 返回获取的版本号

    def get_flags(self):
        return ['-qextname']  # 返回编译器标志列表,包含参数 '-qextname'

    def get_flags_debug(self):
        return ['-g']  # 返回调试标志列表,包含参数 '-g'
    # 获取链接器选项的函数,根据当前操作系统和编译器版本生成适当的选项列表
    def get_flags_linker_so(self):
        # 初始化选项列表
        opt = []
        # 如果当前操作系统是 macOS
        if sys.platform=='darwin':
            # 添加特定于 macOS 的链接器选项
            opt.append('-Wl,-bundle,-flat_namespace,-undefined,suppress')
        else:
            # 对于其他操作系统,添加通用的共享库链接器选项
            opt.append('-bshared')
        # 获取编译器版本信息
        version = self.get_version(ok_status=[0, 40])
        # 如果获取到了版本信息
        if version is not None:
            # 如果当前操作系统是以 'aix' 开头的系统
            if sys.platform.startswith('aix'):
                # 指定 xlf 配置文件的路径
                xlf_cfg = '/etc/xlf.cfg'
            else:
                # 根据获取的版本信息构建 xlf 配置文件的路径
                xlf_cfg = '/etc/opt/ibmcmp/xlf/%s/xlf.cfg' % version
            # 创建临时文件用于写入新的 xlf 配置信息
            fo, new_cfg = make_temp_file(suffix='_xlf.cfg')
            # 输出日志信息,指示正在创建新的配置文件
            log.info('Creating '+new_cfg)
            # 打开 xlf 配置文件进行读取
            with open(xlf_cfg) as fi:
                # 编译正则表达式,用于匹配 crt1.o 文件路径信息
                crt1_match = re.compile(r'\s*crt\s*=\s*(?P<path>.*)/crt1.o').match
                # 逐行读取 xlf 配置文件内容
                for line in fi:
                    # 尝试匹配 crt1.o 的路径信息
                    m = crt1_match(line)
                    # 如果匹配成功
                    if m:
                        # 在临时文件中写入修改后的 crt 路径信息
                        fo.write('crt = %s/bundle1.o\n' % (m.group('path')))
                    else:
                        # 将未匹配到的行直接写入临时文件
                        fo.write(line)
            # 关闭临时文件
            fo.close()
            # 添加新的链接器选项,指定使用新创建的配置文件
            opt.append('-F'+new_cfg)
        # 返回生成的链接器选项列表
        return opt

    # 获取优化选项的函数,简单地返回一个包含 '-O3' 的列表
    def get_flags_opt(self):
        return ['-O3']
# 如果当前脚本作为主程序运行
if __name__ == '__main__':
    # 从 numpy.distutils 中导入 customized_fcompiler 函数
    from numpy.distutils import customized_fcompiler
    # 设置日志的详细程度为 2(通常表示详细信息)
    log.set_verbosity(2)
    # 打印使用定制化编译器 'ibm' 的版本信息
    print(customized_fcompiler(compiler='ibm').get_version())

.\numpy\numpy\distutils\fcompiler\intel.py

# 导入 sys 模块,用于系统相关操作
import sys

# 从 numpy.distutils.ccompiler 中导入 simple_version_match 函数
from numpy.distutils.ccompiler import simple_version_match
# 从 numpy.distutils.fcompiler 中导入 FCompiler 类和 dummy_fortran_file 函数
from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file

# 定义一组 Intel 编译器的名称列表
compilers = ['IntelFCompiler', 'IntelVisualFCompiler',
             'IntelItaniumFCompiler', 'IntelItaniumVisualFCompiler',
             'IntelEM64VisualFCompiler', 'IntelEM64TFCompiler']


def intel_version_match(type):
    # 匹配版本字符串中重要部分的函数
    return simple_version_match(start=r'Intel.*?Fortran.*?(?:%s).*?Version' % (type,))


class BaseIntelFCompiler(FCompiler):
    def update_executables(self):
        # 创建一个虚拟的 Fortran 文件并更新执行命令字典
        f = dummy_fortran_file()
        self.executables['version_cmd'] = ['<F77>', '-FI', '-V', '-c',
                                           f + '.f', '-o', f + '.o']

    def runtime_library_dir_option(self, dir):
        # 运行时库目录选项函数,生成链接器选项字符串
        # 注意:这里可以使用 -Xlinker,如果支持的话
        assert "," not in dir

        return '-Wl,-rpath=%s' % dir


class IntelFCompiler(BaseIntelFCompiler):
    # IntelFCompiler 类,继承自 BaseIntelFCompiler 类

    compiler_type = 'intel'
    compiler_aliases = ('ifort',)
    description = 'Intel Fortran Compiler for 32-bit apps'
    version_match = intel_version_match('32-bit|IA-32')

    possible_executables = ['ifort', 'ifc']

    executables = {
        'version_cmd'  : None,          # 由 update_executables 设置
        'compiler_f77' : [None, "-72", "-w90", "-w95"],
        'compiler_f90' : [None],
        'compiler_fix' : [None, "-FI"],
        'linker_so'    : ["<F90>", "-shared"],
        'archiver'     : ["ar", "-cr"],
        'ranlib'       : ["ranlib"]
        }

    pic_flags = ['-fPIC']
    module_dir_switch = '-module '  # 不要移除末尾的空格!
    module_include_switch = '-I'

    def get_flags_free(self):
        # 返回自由格式 Fortran 的编译选项列表
        return ['-FR']

    def get_flags(self):
        # 返回默认的编译选项列表
        return ['-fPIC']

    def get_flags_opt(self):  # Scipy test failures with -O2
        # 获取优化编译选项列表
        v = self.get_version()
        mpopt = 'openmp' if v and v < '15' else 'qopenmp'
        return ['-fp-model', 'strict', '-O1',
                '-assume', 'minus0', '-{}'.format(mpopt)]

    def get_flags_arch(self):
        # 返回架构相关的编译选项列表
        return []

    def get_flags_linker_so(self):
        # 获取用于链接共享对象的链接器选项列表
        opt = FCompiler.get_flags_linker_so(self)
        v = self.get_version()
        if v and v >= '8.0':
            opt.append('-nofor_main')
        if sys.platform == 'darwin':
            # 如果是 macOS 系统,则使用 -dynamiclib
            try:
                idx = opt.index('-shared')
                opt.remove('-shared')
            except ValueError:
                idx = 0
            opt[idx:idx] = ['-dynamiclib', '-Wl,-undefined,dynamic_lookup']
        return opt


class IntelItaniumFCompiler(IntelFCompiler):
    # IntelItaniumFCompiler 类,继承自 IntelFCompiler 类

    compiler_type = 'intele'
    compiler_aliases = ()
    description = 'Intel Fortran Compiler for Itanium apps'

    version_match = intel_version_match('Itanium|IA-64')

    possible_executables = ['ifort', 'efort', 'efc']
    # 定义一个包含多个可执行文件配置的字典
    executables = {
        'version_cmd'  : None,            # 版本命令的配置项,暂未指定
        'compiler_f77' : [None, "-FI", "-w90", "-w95"],  # Fortran 77 编译器的配置项列表
        'compiler_fix' : [None, "-FI"],   # 修复编译器的配置项列表
        'compiler_f90' : [None],          # Fortran 90 编译器的配置项列表,只包含一个元素
        'linker_so'    : ['<F90>', "-shared"],  # 共享库链接器的配置项列表
        'archiver'     : ["ar", "-cr"],   # 归档工具的配置项列表
        'ranlib'       : ["ranlib"]       # ranlib 工具的配置项列表
    }
# 定义一个继承自 IntelFCompiler 的类,用于 Intel EM64T 架构的编译器
class IntelEM64TFCompiler(IntelFCompiler):
    # 编译器类型为 'intelem'
    compiler_type = 'intelem'
    # 没有编译器的别名
    compiler_aliases = ()
    # 描述为“Intel Fortran Compiler for 64-bit apps”
    description = 'Intel Fortran Compiler for 64-bit apps'

    # 匹配版本信息的正则表达式,用于识别基于 EM64T 架构的 Intel 编译器
    version_match = intel_version_match('EM64T-based|Intel\\(R\\) 64|64|IA-64|64-bit')

    # 可能的可执行文件列表
    possible_executables = ['ifort', 'efort', 'efc']

    # 定义可执行文件的命令字典
    executables = {
        'version_cmd'  : None,  # 版本命令为空
        'compiler_f77' : [None, "-FI"],  # Fortran 77 编译器命令
        'compiler_fix' : [None, "-FI"],  # 修复格式 Fortran 编译器命令
        'compiler_f90' : [None],  # Fortran 90 编译器命令
        'linker_so'    : ['<F90>', "-shared"],  # 共享库链接器命令
        'archiver'     : ["ar", "-cr"],  # 静态库打包命令
        'ranlib'       : ["ranlib"]  # ranlib 命令
        }

# Is there no difference in the version string between the above compilers
# and the Visual compilers?


# 定义一个继承自 BaseIntelFCompiler 的类,用于 Intel Visual Fortran 编译器
class IntelVisualFCompiler(BaseIntelFCompiler):
    # 编译器类型为 'intelv'
    compiler_type = 'intelv'
    # 描述为“Intel Visual Fortran Compiler for 32-bit apps”
    description = 'Intel Visual Fortran Compiler for 32-bit apps'
    # 使用正则表达式匹配版本信息,用于识别 32 位 Intel Visual Fortran 编译器
    version_match = intel_version_match('32-bit|IA-32')

    # 更新可执行文件的方法
    def update_executables(self):
        # 创建一个虚拟的 Fortran 文件名
        f = dummy_fortran_file()
        # 设置版本命令的值为 Fortran 编译的命令列表
        self.executables['version_cmd'] = ['<F77>', '/FI', '/c',
                                           f + '.f', '/o', f + '.o']

    # ar_exe 表示 lib.exe 可执行文件名
    ar_exe = 'lib.exe'
    # 可能的可执行文件列表
    possible_executables = ['ifort', 'ifl']

    # 定义可执行文件的命令字典
    executables = {
        'version_cmd'  : None,  # 版本命令为空
        'compiler_f77' : [None],  # Fortran 77 编译器命令
        'compiler_fix' : [None],  # 修复格式 Fortran 编译器命令
        'compiler_f90' : [None],  # Fortran 90 编译器命令
        'linker_so'    : [None],  # 共享库链接器命令为空
        'archiver'     : [ar_exe, "/verbose", "/OUT:"],  # 静态库打包命令
        'ranlib'       : None  # ranlib 命令为空
        }

    # 编译开关为 '/c '
    compile_switch = '/c '
    # 对象开关为 '/Fo',后面没有空格!
    object_switch = '/Fo'     # No space after /Fo!
    # 库开关为 '/OUT:',后面没有空格!
    library_switch = '/OUT:'  # No space after /OUT:!
    # 模块目录开关为 '/module:',后面没有空格!
    module_dir_switch = '/module:'  # No space after /module:
    # 模块包含开关为 '/I'
    module_include_switch = '/I'

    # 返回优化标志列表的方法
    def get_flags(self):
        opt = ['/nologo', '/MD', '/nbs', '/names:lowercase', 
               '/assume:underscore', '/fpp']
        return opt

    # 返回自由格式标志列表的方法
    def get_flags_free(self):
        return []

    # 返回调试标志列表的方法
    def get_flags_debug(self):
        return ['/4Yb', '/d2']

    # 返回优化标志列表的方法
    def get_flags_opt(self):
        return ['/O1', '/assume:minus0']  # Scipy test failures with /O2

    # 返回体系结构标志列表的方法
    def get_flags_arch(self):
        return ["/arch:IA32", "/QaxSSE3"]

    # 运行时库目录选项的方法
    def runtime_library_dir_option(self, dir):
        raise NotImplementedError


# 定义一个继承自 IntelVisualFCompiler 的类,用于 Intel Itanium 架构的 Visual Fortran 编译器
class IntelItaniumVisualFCompiler(IntelVisualFCompiler):
    # 编译器类型为 'intelev'
    compiler_type = 'intelev'
    # 描述为“Intel Visual Fortran Compiler for Itanium apps”

    description = 'Intel Visual Fortran Compiler for Itanium apps'

    # 使用正则表达式匹配版本信息,用于识别 Itanium 架构的 Intel Visual Fortran 编译器
    version_match = intel_version_match('Itanium')

    # 可能的可执行文件列表,这里是一个猜测
    possible_executables = ['efl']  # XXX this is a wild guess
    # ar_exe 和父类的相同
    ar_exe = IntelVisualFCompiler.ar_exe

    # 定义可执行文件的命令字典
    executables = {
        'version_cmd'  : None,  # 版本命令为空
        'compiler_f77' : [None, "-FI", "-w90", "-w95"],  # Fortran 77 编译器命令
        'compiler_fix' : [None, "-FI", "-4L72", "-w"],   # 修复格式 Fortran 编译器命令
        'compiler_f90' : [None],  # Fortran 90 编译器命令
        'linker_so'    : ['<F90>', "-shared"],  # 共享库链接器命令
        'archiver'     : [ar_exe, "/verbose", "/OUT:"],  # 静态库打包命令
        'ranlib'       : None  # ranlib 命令为空
        }


# 定义一个继承自 IntelVisualFCompiler 的类,用于 Intel EM64 架构的 Visual Fortran 编译器
class IntelEM64VisualFCompiler(IntelVisualFCompiler):
    # 编译器类型为 'intelvem'
    compiler_type = 'intelvem'
    # 定义变量 description,描述为“Intel Visual Fortran Compiler for 64-bit apps”
    description = 'Intel Visual Fortran Compiler for 64-bit apps'

    # 定义函数 version_match,用于匹配简单的版本信息,起始匹配字符串为'Intel(R).*?64,'
    version_match = simple_version_match(start=r'Intel\(R\).*?64,')

    # 定义方法 get_flags_arch,返回一个空列表,用于获取特定的编译标志(此处为占位符)
    def get_flags_arch(self):
        return []
# 如果当前脚本作为主程序执行
if __name__ == '__main__':
    # 从 distutils 模块导入 log 函数
    from distutils import log
    # 设置日志的详细程度为 2(即详细输出)
    log.set_verbosity(2)
    # 从 numpy.distutils 模块导入 customized_fcompiler 函数
    from numpy.distutils import customized_fcompiler
    # 打印使用 intel 编译器的 customized_fcompiler 函数的版本信息
    print(customized_fcompiler(compiler='intel').get_version())

.\numpy\numpy\distutils\fcompiler\lahey.py

# 导入标准库 os
import os

# 从 numpy.distutils.fcompiler 中导入 FCompiler 类
from numpy.distutils.fcompiler import FCompiler

# 定义一个名为 compilers 的列表,包含字符串 'LaheyFCompiler'
compilers = ['LaheyFCompiler']

# 定义 LaheyFCompiler 类,继承自 FCompiler 类
class LaheyFCompiler(FCompiler):

    # 定义编译器类型为 'lahey'
    compiler_type = 'lahey'

    # 编译器的描述信息
    description = 'Lahey/Fujitsu Fortran 95 Compiler'

    # 版本号的正则表达式模式
    version_pattern =  r'Lahey/Fujitsu Fortran 95 Compiler Release (?P<version>[^\s*]*)'

    # 定义一些可执行命令的字典
    executables = {
        'version_cmd'  : ["<F90>", "--version"],   # 版本命令
        'compiler_f77' : ["lf95", "--fix"],        # Fortran 77 编译器命令
        'compiler_fix' : ["lf95", "--fix"],        # 修正命令
        'compiler_f90' : ["lf95"],                 # Fortran 90 编译器命令
        'linker_so'    : ["lf95", "-shared"],      # 共享库链接命令
        'archiver'     : ["ar", "-cr"],            # 静态库归档命令
        'ranlib'       : ["ranlib"]                # Ranlib 命令
        }

    # 模块目录开关,暂未实现,待修复
    module_dir_switch = None  #XXX Fix me

    # 模块包含开关,暂未实现,待修复
    module_include_switch = None #XXX Fix me

    # 获取优化标志的方法,返回包含 '-O' 的列表
    def get_flags_opt(self):
        return ['-O']

    # 获取调试标志的方法,返回包含 '-g', '--chk', '--chkglobal' 的列表
    def get_flags_debug(self):
        return ['-g', '--chk', '--chkglobal']

    # 获取库目录的方法
    def get_library_dirs(self):
        opt = []
        d = os.environ.get('LAHEY')
        if d:
            opt.append(os.path.join(d, 'lib'))
        return opt

    # 获取库列表的方法
    def get_libraries(self):
        opt = []
        opt.extend(['fj9f6', 'fj9i6', 'fj9ipp', 'fj9e6'])
        return opt

# 如果当前模块是主程序
if __name__ == '__main__':

    # 从 distutils 中导入 log
    from distutils import log

    # 设置日志详细级别为 2
    log.set_verbosity(2)

    # 从 numpy.distutils 中导入 customized_fcompiler
    from numpy.distutils import customized_fcompiler

    # 打印使用 compiler='lahey' 参数调用 customized_fcompiler 的版本信息
    print(customized_fcompiler(compiler='lahey').get_version())

.\numpy\numpy\distutils\fcompiler\mips.py

# 导入必要的模块和类
from numpy.distutils.cpuinfo import cpu
from numpy.distutils.fcompiler import FCompiler

# 定义 MIPSFCompiler 类,继承自 FCompiler 类
class MIPSFCompiler(FCompiler):

    # 编译器类型为 'mips'
    compiler_type = 'mips'
    # 描述为 'MIPSpro Fortran Compiler'
    description = 'MIPSpro Fortran Compiler'
    # 版本号的正则表达式模式,用于提取版本信息
    version_pattern =  r'MIPSpro Compilers: Version (?P<version>[^\s*,]*)'

    # 定义可执行命令的字典
    executables = {
        'version_cmd'  : ["<F90>", "-version"],  # 版本查询命令
        'compiler_f77' : ["f77", "-f77"],        # Fortran 77 编译器命令
        'compiler_fix' : ["f90", "-fixedform"],  # 固定格式 Fortran 90 编译器命令
        'compiler_f90' : ["f90"],                # Fortran 90 编译器命令
        'linker_so'    : ["f90", "-shared"],     # 共享库链接器命令
        'archiver'     : ["ar", "-cr"],          # 归档命令
        'ranlib'       : None                    # 未指定 ranlib 命令
        }

    # 模块目录开关和模块包含开关,当前为待修复状态
    module_dir_switch = None  # XXX: fix me
    module_include_switch = None  # XXX: fix me

    # PIC(位置独立代码)标志
    pic_flags = ['-KPIC']

    # 返回标志列表及编译器的位宽为 32 位
    def get_flags(self):
        return self.pic_flags + ['-n32']

    # 返回优化标志为 '-O3'
    def get_flags_opt(self):
        return ['-O3']

    # 返回特定架构的标志
    def get_flags_arch(self):
        opt = []
        # 遍历不同的 MIPS 架构版本
        for a in '19 20 21 22_4k 22_5k 24 25 26 27 28 30 32_5k 32_10k'.split():
            # 如果当前 CPU 是某个版本的 IP 架构,则添加相应的编译标志
            if getattr(cpu, 'is_IP%s' % a)():
                opt.append('-TARG:platform=IP%s' % a)
                break
        return opt

    # 返回 Fortran 77 的特定架构标志
    def get_flags_arch_f77(self):
        r = None
        # 根据 CPU 类型确定 Fortran 77 的架构标志
        if cpu.is_r10000(): r = 10000
        elif cpu.is_r12000(): r = 12000
        elif cpu.is_r8000(): r = 8000
        elif cpu.is_r5000(): r = 5000
        elif cpu.is_r4000(): r = 4000
        if r is not None:
            return ['r%s' % (r)]
        return []

    # 返回 Fortran 90 的特定架构标志
    def get_flags_arch_f90(self):
        r = self.get_flags_arch_f77()
        if r:
            r[0] = '-' + r[0]
        return r

# 如果作为主程序运行,则输出定制的 MIPS 编译器的版本信息
if __name__ == '__main__':
    from numpy.distutils import customized_fcompiler
    print(customized_fcompiler(compiler='mips').get_version())

.\numpy\numpy\distutils\fcompiler\nag.py

# 导入 sys 模块,用于获取系统相关信息
import sys
# 导入 re 模块,用于正则表达式操作
import re
# 从 numpy.distutils.fcompiler 导入 FCompiler 类
from numpy.distutils.fcompiler import FCompiler

# 定义一个列表,包含两个编译器类名
compilers = ['NAGFCompiler', 'NAGFORCompiler']

# 定义一个名为 BaseNAGFCompiler 的类,继承自 FCompiler 类
class BaseNAGFCompiler(FCompiler):
    # 定义版本号匹配的正则表达式模式
    version_pattern = r'NAG.* Release (?P<version>[^(\s]*)'

    # 方法:匹配版本号
    def version_match(self, version_string):
        # 在版本字符串中搜索匹配版本号的模式
        m = re.search(self.version_pattern, version_string)
        # 如果匹配成功,返回版本号
        if m:
            return m.group('version')
        else:
            return None

    # 方法:获取链接器选项
    def get_flags_linker_so(self):
        return ["-Wl,-shared"]

    # 方法:获取优化选项
    def get_flags_opt(self):
        return ['-O4']

    # 方法:获取架构相关选项
    def get_flags_arch(self):
        return []

# 定义一个名为 NAGFCompiler 的类,继承自 BaseNAGFCompiler 类
class NAGFCompiler(BaseNAGFCompiler):
    # 类属性:编译器类型为 'nag'
    compiler_type = 'nag'
    # 类属性:描述为 'NAGWare Fortran 95 Compiler'
    description = 'NAGWare Fortran 95 Compiler'

    # 类属性:定义不同命令的执行路径
    executables = {
        'version_cmd'  : ["<F90>", "-V"],
        'compiler_f77' : ["f95", "-fixed"],
        'compiler_fix' : ["f95", "-fixed"],
        'compiler_f90' : ["f95"],
        'linker_so'    : ["<F90>"],
        'archiver'     : ["ar", "-cr"],
        'ranlib'       : ["ranlib"]
        }

    # 方法:重写获取链接器选项的方法
    def get_flags_linker_so(self):
        # 如果系统平台是 'darwin'(即 macOS)
        if sys.platform == 'darwin':
            # 返回特定于 macOS 的链接选项
            return ['-unsharedf95', '-Wl,-bundle,-flat_namespace,-undefined,suppress']
        # 否则调用父类的方法获取链接选项
        return BaseNAGFCompiler.get_flags_linker_so(self)

    # 方法:重写获取架构相关选项的方法
    def get_flags_arch(self):
        # 获取当前编译器的版本号
        version = self.get_version()
        # 如果版本号存在且小于 '5.1'
        if version and version < '5.1':
            # 返回特定的目标架构选项
            return ['-target=native']
        else:
            # 否则调用父类的方法获取架构选项
            return BaseNAGFCompiler.get_flags_arch(self)

    # 方法:获取调试选项
    def get_flags_debug(self):
        # 返回调试相关的选项
        return ['-g', '-gline', '-g90', '-nan', '-C']

# 定义一个名为 NAGFORCompiler 的类,继承自 BaseNAGFCompiler 类
class NAGFORCompiler(BaseNAGFCompiler):
    # 类属性:编译器类型为 'nagfor'
    compiler_type = 'nagfor'
    # 类属性:描述为 'NAG Fortran Compiler'
    description = 'NAG Fortran Compiler'

    # 类属性:定义不同命令的执行路径
    executables = {
        'version_cmd'  : ["nagfor", "-V"],
        'compiler_f77' : ["nagfor", "-fixed"],
        'compiler_fix' : ["nagfor", "-fixed"],
        'compiler_f90' : ["nagfor"],
        'linker_so'    : ["nagfor"],
        'archiver'     : ["ar", "-cr"],
        'ranlib'       : ["ranlib"]
        }

    # 方法:重写获取链接器选项的方法
    def get_flags_linker_so(self):
        # 如果系统平台是 'darwin'(即 macOS)
        if sys.platform == 'darwin':
            # 返回特定于 macOS 的链接选项
            return ['-unsharedrts',
                    '-Wl,-bundle,-flat_namespace,-undefined,suppress']
        # 否则调用父类的方法获取链接选项
        return BaseNAGFCompiler.get_flags_linker_so(self)

    # 方法:获取调试选项
    def get_flags_debug(self):
        # 获取当前编译器的版本号
        version = self.get_version()
        # 如果版本号存在且大于 '6.1'
        if version and version > '6.1':
            # 返回特定的调试选项
            return ['-g', '-u', '-nan', '-C=all', '-thread_safe',
                    '-kind=unique', '-Warn=allocation', '-Warn=subnormal']
        else:
            # 否则返回通用的调试选项
            return ['-g', '-nan', '-C=all', '-u', '-thread_safe']

# 如果当前脚本被直接运行
if __name__ == '__main__':
    # 从 distutils 模块中导入 log 对象
    from distutils import log
    # 设置日志的详细程度为 2
    log.set_verbosity(2)
    # 从 numpy.distutils 中导入 customized_fcompiler 函数
    from numpy.distutils import customized_fcompiler
    # 使用 customized_fcompiler 函数创建一个特定编译器的实例,这里是 'nagfor'
    compiler = customized_fcompiler(compiler='nagfor')
    # 打印编译器的版本信息
    print(compiler.get_version())
    # 打印编译器的调试选项
    print(compiler.get_flags_debug())

.\numpy\numpy\distutils\fcompiler\none.py

# 导入 numpy.distutils.fcompiler 模块中的 FCompiler 类
from numpy.distutils.fcompiler import FCompiler
# 导入 numpy.distutils 中的 customized_fcompiler 函数
from numpy.distutils import customized_fcompiler

# 定义一个列表,包含字符串 'NoneFCompiler'
compilers = ['NoneFCompiler']

# 定义一个名为 NoneFCompiler 的类,继承自 FCompiler 类
class NoneFCompiler(FCompiler):

    # 设置编译器类型为 'none'
    compiler_type = 'none'
    # 设置编译器描述为 'Fake Fortran compiler'
    description = 'Fake Fortran compiler'

    # 定义一个字典,包含多个执行文件路径,均设为 None
    executables = {'compiler_f77': None,
                   'compiler_f90': None,
                   'compiler_fix': None,
                   'linker_so': None,
                   'linker_exe': None,
                   'archiver': None,
                   'ranlib': None,
                   'version_cmd': None,
                   }

    # 定义一个方法,用于查找执行文件,但实际上没有实现其功能
    def find_executables(self):
        pass

# 如果作为脚本运行
if __name__ == '__main__':
    # 从 distutils 模块中导入 log 对象
    from distutils import log
    # 设置日志详细程度为 2
    log.set_verbosity(2)
    # 输出 'none' 编译器的版本信息
    print(customized_fcompiler(compiler='none').get_version())

.\numpy\numpy\distutils\fcompiler\nv.py

# 导入 FCompiler 类,用于自定义编译器
from numpy.distutils.fcompiler import FCompiler

# 定义一个列表,包含唯一的编译器类名 'NVHPCFCompiler'
compilers = ['NVHPCFCompiler']

# 创建 NVHPCFCompiler 类,继承自 FCompiler 类,用于 NVIDIA HPC SDK Fortran 编译器
class NVHPCFCompiler(FCompiler):
    """ NVIDIA High Performance Computing (HPC) SDK Fortran Compiler
   
    https://developer.nvidia.com/hpc-sdk
   
    自 2020 年 8 月起,NVIDIA HPC SDK 包含了以前被称为 Portland Group 编译器的编译器,
    https://www.pgroup.com/index.htm.
    参见 `numpy.distutils.fcompiler.pg`。
    """

    # 编译器类型设定为 'nv'
    compiler_type = 'nv'
    # 描述为 'NVIDIA HPC SDK'
    description = 'NVIDIA HPC SDK'
    # 版本模式匹配正则表达式,匹配 'nvfortran' 或者 'xxx (aka nvfortran)' 格式的版本信息
    version_pattern = r'\s*(nvfortran|.+ \(aka nvfortran\)) (?P<version>[\d.-]+).*'

    # 执行命令字典,包含各种编译和链接命令的配置
    executables = {
        'version_cmd': ["<F90>", "-V"],        # 获取版本信息的命令
        'compiler_f77': ["nvfortran"],         # Fortran 77 编译器命令
        'compiler_fix': ["nvfortran", "-Mfixed"],  # 使用固定格式的 Fortran 90 编译器命令
        'compiler_f90': ["nvfortran"],         # Fortran 90 编译器命令
        'linker_so': ["<F90>"],                 # 共享库链接器命令
        'archiver': ["ar", "-cr"],              # 静态库打包命令
        'ranlib': ["ranlib"]                    # ranlib 命令
    }
    
    # 位置无关代码编译选项列表
    pic_flags = ['-fpic']

    # 模块目录开关,用于指定模块输出目录
    module_dir_switch = '-module '
    # 模块包含目录开关,用于指定模块的搜索路径
    module_include_switch = '-I'

    # 获取编译器标志的方法
    def get_flags(self):
        # 优化选项,设置了一些编译选项
        opt = ['-Minform=inform', '-Mnosecond_underscore']
        return self.pic_flags + opt

    # 获取优化标志的方法
    def get_flags_opt(self):
        return ['-fast']

    # 获取调试标志的方法
    def get_flags_debug(self):
        return ['-g']

    # 获取链接共享库标志的方法
    def get_flags_linker_so(self):
        return ["-shared", '-fpic']

    # 运行时库目录选项,返回一个设置了目录的选项字符串
    def runtime_library_dir_option(self, dir):
        return '-R%s' % dir

# 如果脚本作为主程序执行,则执行以下代码块
if __name__ == '__main__':
    # 导入 distutils 中的 log 模块
    from distutils import log
    # 设置日志的详细程度为 2
    log.set_verbosity(2)
    # 导入 numpy.distutils 中的 customized_fcompiler 函数
    from numpy.distutils import customized_fcompiler
    # 输出定制化编译器的版本信息
    print(customized_fcompiler(compiler='nv').get_version())

.\numpy\numpy\distutils\fcompiler\pathf95.py

# 导入 FCompiler 类,该类位于 numpy.distutils.fcompiler 模块中
from numpy.distutils.fcompiler import FCompiler

# 定义一个列表,包含字符串 'PathScaleFCompiler'
compilers = ['PathScaleFCompiler']

# 定义 PathScaleFCompiler 类,继承自 FCompiler 类
class PathScaleFCompiler(FCompiler):

    # 定义编译器类型为 'pathf95'
    compiler_type = 'pathf95'
    # 定义编译器描述为 'PathScale Fortran Compiler'
    description = 'PathScale Fortran Compiler'
    # 定义版本号的正则表达式模式,匹配 'PathScale(TM) Compiler Suite: Version x.x.x' 形式的版本号
    version_pattern = r'PathScale\(TM\) Compiler Suite: Version (?P<version>[\d.]+)'

    # 定义各种执行命令的字典
    executables = {
        'version_cmd'  : ["pathf95", "-version"],  # 获取版本号的命令
        'compiler_f77' : ["pathf95", "-fixedform"],  # Fortran 77 编译器命令
        'compiler_fix' : ["pathf95", "-fixedform"],  # 固定格式 Fortran 编译器命令
        'compiler_f90' : ["pathf95"],  # Fortran 90 编译器命令
        'linker_so'    : ["pathf95", "-shared"],  # 共享库链接器命令
        'archiver'     : ["ar", "-cr"],  # 静态库打包命令
        'ranlib'       : ["ranlib"]  # ranlib 命令
    }
    
    # 定义位置无关代码(Position Independent Code, PIC)的编译选项
    pic_flags = ['-fPIC']
    # 指定模块目录开关选项,结尾有空格不能移除!
    module_dir_switch = '-module ' 
    # 模块包含目录开关选项
    module_include_switch = '-I'

    # 获取优化标志的方法,返回 ['-O3'] 列表
    def get_flags_opt(self):
        return ['-O3']
    
    # 获取调试标志的方法,返回 ['-g'] 列表
    def get_flags_debug(self):
        return ['-g']

# 如果脚本被直接执行
if __name__ == '__main__':
    # 从 distutils 模块中导入 log 对象
    from distutils import log
    # 设置日志详细级别为 2
    log.set_verbosity(2)
    # 从 numpy.distutils 模块中导入 customized_fcompiler 函数,并调用以获取 'pathf95' 编译器的版本
    from numpy.distutils import customized_fcompiler
    print(customized_fcompiler(compiler='pathf95').get_version())  # 打印获取的版本号

.\numpy\numpy\distutils\fcompiler\pg.py

# 导入 sys 模块
import sys

# 从 numpy.distutils.fcompiler 模块导入 FCompiler 类
from numpy.distutils.fcompiler import FCompiler
# 从 sys 模块导入 platform 函数
from sys import platform
# 从 os.path 模块导入 join, dirname, normpath 函数
from os.path import join, dirname, normpath

# 定义 PGroupFCompiler 类,继承自 FCompiler 类
class PGroupFCompiler(FCompiler):

    # 编译器类型
    compiler_type = 'pg'
    # 描述信息
    description = 'Portland Group Fortran Compiler'
    # 版本匹配模式
    version_pattern = r'\s*pg(f77|f90|hpf|fortran) (?P<version>[\d.-]+).*'

    # 根据平台不同选择不同的执行文件配置
    if platform == 'darwin':
        executables = {
            'version_cmd': ["<F77>", "-V"],  # 版本命令
            'compiler_f77': ["pgfortran", "-dynamiclib"],  # Fortran 77 编译器
            'compiler_fix': ["pgfortran", "-Mfixed", "-dynamiclib"],  # 修正格式 Fortran 编译器
            'compiler_f90': ["pgfortran", "-dynamiclib"],  # Fortran 90 编译器
            'linker_so': ["libtool"],  # 共享库链接器
            'archiver': ["ar", "-cr"],  # 静态库打包工具
            'ranlib': ["ranlib"]  # 静态库索引生成工具
        }
        pic_flags = ['']  # 位置无关代码标志
    else:
        executables = {
            'version_cmd': ["<F77>", "-V"],  # 版本命令
            'compiler_f77': ["pgfortran"],  # Fortran 77 编译器
            'compiler_fix': ["pgfortran", "-Mfixed"],  # 修正格式 Fortran 编译器
            'compiler_f90': ["pgfortran"],  # Fortran 90 编译器
            'linker_so': ["<F90>"],  # 共享库链接器
            'archiver': ["ar", "-cr"],  # 静态库打包工具
            'ranlib': ["ranlib"]  # 静态库索引生成工具
        }
        pic_flags = ['-fpic']  # 位置无关代码标志

    module_dir_switch = '-module '  # 模块目录开关
    module_include_switch = '-I'  # 模块包含开关

    # 获取编译器标志
    def get_flags(self):
        opt = ['-Minform=inform', '-Mnosecond_underscore']
        return self.pic_flags + opt  # 返回位置无关代码标志和优化选项

    # 获取优化标志
    def get_flags_opt(self):
        return ['-fast']  # 返回快速优化标志

    # 获取调试标志
    def get_flags_debug(self):
        return ['-g']  # 返回调试标志

    # 根据平台不同获取链接共享库标志
    if platform == 'darwin':
        def get_flags_linker_so(self):
            return ["-dynamic", '-undefined', 'dynamic_lookup']  # 返回动态链接标志
    else:
        def get_flags_linker_so(self):
            return ["-shared", '-fpic']  # 返回共享库和位置无关代码标志

    # 运行时库目录选项
    def runtime_library_dir_option(self, dir):
        return '-R%s' % dir  # 返回运行时库目录选项


# 导入 functools 模块
import functools

# 定义 PGroupFlangCompiler 类,继承自 FCompiler 类
class PGroupFlangCompiler(FCompiler):
    # 编译器类型
    compiler_type = 'flang'
    # 描述信息
    description = 'Portland Group Fortran LLVM Compiler'
    # 版本匹配模式
    version_pattern = r'\s*(flang|clang) version (?P<version>[\d.-]+).*'

    ar_exe = 'lib.exe'  # 静态库打包工具
    possible_executables = ['flang']  # 可能的可执行文件列表

    executables = {
        'version_cmd': ["<F77>", "--version"],  # 版本命令
        'compiler_f77': ["flang"],  # Fortran 77 编译器
        'compiler_fix': ["flang"],  # 修正格式 Fortran 编译器
        'compiler_f90': ["flang"],  # Fortran 90 编译器
        'linker_so': [None],  # 共享库链接器(空值表示无效)
        'archiver': [ar_exe, "/verbose", "/OUT:"],  # 静态库打包工具
        'ranlib': None  # 静态库索引生成工具(空值表示无效)
    }

    library_switch = '/OUT:'  # 库开关
    module_dir_switch = '-module '  # 模块目录开关

    # 获取库列表
    def get_libraries(self):
        opt = FCompiler.get_libraries(self)
        opt.extend(['flang', 'flangrti', 'ompstub'])
        return opt  # 返回扩展后的库列表

    # 获取库目录列表
    @functools.lru_cache(maxsize=128)
    def get_library_dirs(self):
        """List of compiler library directories."""
        opt = FCompiler.get_library_dirs(self)
        flang_dir = dirname(self.executables['compiler_f77'][0])
        opt.append(normpath(join(flang_dir, '..', 'lib')))
        return opt  # 返回库目录列表

    # 获取编译器标志
    def get_flags(self):
        return []  # 返回空列表(无特定编译器标志)
    # 返回一个空列表,表示没有额外的编译选项
    def get_flags_free(self):
        return []
    
    # 返回一个包含编译调试信息的选项列表,这里只包含了 '-g',表示生成调试信息
    def get_flags_debug(self):
        return ['-g']
    
    # 返回一个包含编译优化选项的列表,这里只包含了 '-O3',表示进行高级优化
    def get_flags_opt(self):
        return ['-O3']
    
    # 返回一个空列表,表示没有特定的架构相关的编译选项
    def get_flags_arch(self):
        return []
    
    # 抛出一个未实现的异常,表示该方法在子类中需要被实现
    def runtime_library_dir_option(self, dir):
        raise NotImplementedError
if __name__ == '__main__':
    # 检查是否当前脚本作为主程序运行
    from distutils import log
    # 从 distutils 模块导入 log 功能
    log.set_verbosity(2)
    # 设置日志的详细程度为 2 (详细输出)
    from numpy.distutils import customized_fcompiler
    # 从 numpy.distutils 模块导入 customized_fcompiler 函数
    if 'flang' in sys.argv:
        # 如果 'flang' 存在于命令行参数中
        print(customized_fcompiler(compiler='flang').get_version())
        # 使用 flang 编译器获取其版本并打印
    else:
        # 如果 'flang' 不存在于命令行参数中
        print(customized_fcompiler(compiler='pg').get_version())
        # 使用 pg 编译器获取其版本并打印

.\numpy\numpy\distutils\fcompiler\sun.py

# 从 numpy.distutils.ccompiler 模块中导入 simple_version_match 函数
from numpy.distutils.ccompiler import simple_version_match
# 从 numpy.distutils.fcompiler 模块中导入 FCompiler 类
from numpy.distutils.fcompiler import FCompiler

# 定义一个列表 compilers 包含字符串 'SunFCompiler'
compilers = ['SunFCompiler']

# 定义一个名为 SunFCompiler 的类,继承自 FCompiler 类
class SunFCompiler(FCompiler):

    # 类变量,指定编译器类型为 'sun'
    compiler_type = 'sun'
    # 描述信息,表示这是 Sun 或 Forte Fortran 95 编译器
    description = 'Sun or Forte Fortran 95 Compiler'
    
    # 版本匹配函数,使用 simple_version_match 函数匹配特定的版本字符串
    version_match = simple_version_match(
                      start=r'f9[05]: (Sun|Forte|WorkShop).*Fortran 95')

    # 可执行文件的配置字典,包含不同的命令及其参数
    executables = {
        'version_cmd'  : ["<F90>", "-V"],  # 获取版本信息的命令
        'compiler_f77' : ["f90"],  # Fortran 77 编译器命令
        'compiler_fix' : ["f90", "-fixed"],  # 指定了 -fixed 标志的 Fortran 90 编译器命令
        'compiler_f90' : ["f90"],  # Fortran 90 编译器命令
        'linker_so'    : ["<F90>", "-Bdynamic", "-G"],  # 动态链接器命令
        'archiver'     : ["ar", "-cr"],  # 归档命令
        'ranlib'       : ["ranlib"]  # ranlib 命令
        }
    
    # 模块目录开关的配置项
    module_dir_switch = '-moddir='
    # 模块包含开关的配置项
    module_include_switch = '-M'
    # PIC(Position Independent Code)标志的配置选项
    pic_flags = ['-xcode=pic32']

    # 获取 Fortran 77 编译器标志的方法
    def get_flags_f77(self):
        ret = ["-ftrap=%none"]  # 返回一个包含 '-ftrap=%none' 的列表
        # 如果版本号大于或等于 '7',则添加 '-f77' 到返回列表中
        if (self.get_version() or '') >= '7':
            ret.append("-f77")
        else:
            ret.append("-fixed")  # 否则添加 '-fixed' 到返回列表中
        return ret
    
    # 获取优化标志的方法
    def get_opt(self):
        return ['-fast', '-dalign']  # 返回包含优化标志 '-fast' 和 '-dalign' 的列表
    
    # 获取架构标志的方法
    def get_arch(self):
        return ['-xtarget=generic']  # 返回一个包含 '-xtarget=generic' 的列表
    
    # 获取库文件标志的方法
    def get_libraries(self):
        opt = []
        opt.extend(['fsu', 'sunmath', 'mvec'])  # 将 'fsu', 'sunmath', 'mvec' 添加到 opt 列表中
        return opt
    
    # 返回运行时库目录选项的方法
    def runtime_library_dir_option(self, dir):
        return '-R%s' % dir  # 返回形如 '-R<dir>' 的字符串

# 如果当前模块是主程序入口
if __name__ == '__main__':
    # 从 distutils 模块中导入 log 对象
    from distutils import log
    log.set_verbosity(2)  # 设置 log 的详细程度为 2
    # 从 numpy.distutils 模块中导入 customized_fcompiler 函数
    from numpy.distutils import customized_fcompiler
    # 打印使用 'sun' 编译器的版本信息
    print(customized_fcompiler(compiler='sun').get_version())

.\numpy\numpy\distutils\fcompiler\vast.py

import os  # 导入标准库 os

from numpy.distutils.fcompiler.gnu import GnuFCompiler  # 从 numpy 的 distutils 子模块中导入 GnuFCompiler 类

compilers = ['VastFCompiler']  # 定义一个列表 compilers,包含字符串 'VastFCompiler'

class VastFCompiler(GnuFCompiler):
    compiler_type = 'vast'  # 设置编译器类型为 'vast'
    compiler_aliases = ()  # 定义编译器别名为空元组
    description = 'Pacific-Sierra Research Fortran 90 Compiler'  # 设置编译器描述信息
    version_pattern = (r'\s*Pacific-Sierra Research vf90 '
                       r'(Personal|Professional)\s+(?P<version>[^\s]*)')  # 定义版本号的正则表达式模式

    # VAST f90 不支持 -o 与 -c 一起使用。因此,对象文件先创建在当前目录,然后移动到构建目录
    object_switch = ' && function _mvfile { mv -v `basename $1` $1 ; } && _mvfile '  # 定义用于移动文件的 shell 命令

    executables = {  # 定义编译器和链接器的可执行命令字典
        'version_cmd'  : ["vf90", "-v"],  # 获取版本信息的命令
        'compiler_f77' : ["g77"],  # Fortran 77 编译器命令
        'compiler_fix' : ["f90", "-Wv,-ya"],  # 修复 Fortran 编译器命令
        'compiler_f90' : ["f90"],  # Fortran 90 编译器命令
        'linker_so'    : ["<F90>"],  # 链接器命令
        'archiver'     : ["ar", "-cr"],  # 归档工具命令
        'ranlib'       : ["ranlib"]  # ranlib 命令
        }

    module_dir_switch = None  # 设置模块目录的开关为 None
    module_include_switch = None  # 设置模块包含的开关为 None

    def find_executables(self):
        pass  # 空方法,用于查找可执行文件

    def get_version_cmd(self):
        f90 = self.compiler_f90[0]  # 获取 Fortran 90 编译器路径
        d, b = os.path.split(f90)  # 分离路径和文件名
        vf90 = os.path.join(d, 'v'+b)  # 构建带有 'v' 前缀的路径
        return vf90  # 返回 vf90 的路径

    def get_flags_arch(self):
        vast_version = self.get_version()  # 获取 VAST 编译器的版本
        gnu = GnuFCompiler()  # 创建一个 GnuFCompiler 的实例
        gnu.customize(None)  # 自定义 GnuFCompiler 实例
        self.version = gnu.get_version()  # 设置当前实例的版本为 GnuFCompiler 的版本
        opt = GnuFCompiler.get_flags_arch(self)  # 调用 GnuFCompiler 的 get_flags_arch 方法获取编译选项
        self.version = vast_version  # 恢复原始的 VAST 编译器版本
        return opt  # 返回编译选项

if __name__ == '__main__':
    from distutils import log  # 从 distutils 模块导入 log 对象
    log.set_verbosity(2)  # 设置日志输出详细级别为 2
    from numpy.distutils import customized_fcompiler  # 从 numpy 的 distutils 子模块导入 customized_fcompiler 函数
    print(customized_fcompiler(compiler='vast').get_version())  # 打印使用 'vast' 编译器的版本信息