Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +1 -0
- ACE_plus/Unmodel_training.sh +28 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/distutils-precedence.pth +3 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__init__.py +247 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/__init__.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_entry_points.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_imp.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_importlib.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_itertools.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_path.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_reqs.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/archive_util.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/build_meta.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/dep_util.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/depends.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/discovery.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/dist.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/errors.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/extension.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/glob.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/installer.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/launch.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/logging.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/monkey.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/msvc.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/namespaces.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/package_index.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/py34compat.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/sandbox.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/unicode_utils.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/version.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/wheel.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/windows_support.cpython-310.pyc +0 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_deprecation_warning.py +7 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/__init__.py +24 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/_collections.py +56 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/_macos_compat.py +12 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/_msvccompiler.py +572 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/bcppcompiler.py +408 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/ccompiler.py +1220 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/config.py +139 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/core.py +291 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/cygwinccompiler.py +364 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/debug.py +5 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/dep_util.py +96 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/dist.py +1286 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/errors.py +127 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/extension.py +248 -0
- ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/fancy_getopt.py +470 -0
.gitattributes
CHANGED
|
@@ -100,3 +100,4 @@ Training_Data/TigcPerson_4.jpg filter=lfs diff=lfs merge=lfs -text
|
|
| 100 |
Training_Data/Inperson_3-V1.png filter=lfs diff=lfs merge=lfs -text
|
| 101 |
Training_Data/Venusperson_11-Garment.jpg filter=lfs diff=lfs merge=lfs -text
|
| 102 |
Training_Data/TigcPerson_2.jpg filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 100 |
Training_Data/Inperson_3-V1.png filter=lfs diff=lfs merge=lfs -text
|
| 101 |
Training_Data/Venusperson_11-Garment.jpg filter=lfs diff=lfs merge=lfs -text
|
| 102 |
Training_Data/TigcPerson_2.jpg filter=lfs diff=lfs merge=lfs -text
|
| 103 |
+
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/cli-arm64.exe filter=lfs diff=lfs merge=lfs -text
|
ACE_plus/Unmodel_training.sh
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# Script to clean GPU memory and run training
|
| 3 |
+
|
| 4 |
+
# Kill any existing Python processes
|
| 5 |
+
echo "Stopping any running Python processes..."
|
| 6 |
+
pkill -9 python
|
| 7 |
+
|
| 8 |
+
# Clear GPU cache
|
| 9 |
+
echo "Clearing GPU cache..."
|
| 10 |
+
nvidia-smi --gpu-reset
|
| 11 |
+
|
| 12 |
+
# Wait a moment for cleanup
|
| 13 |
+
sleep 5
|
| 14 |
+
|
| 15 |
+
# Check GPU memory status
|
| 16 |
+
echo "Current GPU memory status:"
|
| 17 |
+
nvidia-smi
|
| 18 |
+
|
| 19 |
+
# Set memory optimization environment variables
|
| 20 |
+
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
|
| 21 |
+
export PYTORCH_NO_CUDA_MEMORY_CACHING=1
|
| 22 |
+
|
| 23 |
+
# Run training with reduced image size (optional)
|
| 24 |
+
echo "Starting training..."
|
| 25 |
+
python run_train.py --cfg train_config/ace_plus_fft_lora.yaml
|
| 26 |
+
|
| 27 |
+
# Or if you have a specific memory-optimized config:
|
| 28 |
+
# python run_train.py --cfg train_config/ace_plus_fft_lora_low_mem.yaml
|
ACE_plus/flashenv/lib/python3.10/site-packages/distutils-precedence.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2638ce9e2500e572a5e0de7faed6661eb569d1b696fcba07b0dd223da5f5d224
|
| 3 |
+
size 151
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__init__.py
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Extensions to the 'distutils' for large or complex distributions"""
|
| 2 |
+
|
| 3 |
+
import functools
|
| 4 |
+
import os
|
| 5 |
+
import re
|
| 6 |
+
import warnings
|
| 7 |
+
|
| 8 |
+
import _distutils_hack.override # noqa: F401
|
| 9 |
+
|
| 10 |
+
import distutils.core
|
| 11 |
+
from distutils.errors import DistutilsOptionError
|
| 12 |
+
from distutils.util import convert_path as _convert_path
|
| 13 |
+
|
| 14 |
+
from ._deprecation_warning import SetuptoolsDeprecationWarning
|
| 15 |
+
|
| 16 |
+
import setuptools.version
|
| 17 |
+
from setuptools.extension import Extension
|
| 18 |
+
from setuptools.dist import Distribution
|
| 19 |
+
from setuptools.depends import Require
|
| 20 |
+
from setuptools.discovery import PackageFinder, PEP420PackageFinder
|
| 21 |
+
from . import monkey
|
| 22 |
+
from . import logging
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
__all__ = [
|
| 26 |
+
'setup',
|
| 27 |
+
'Distribution',
|
| 28 |
+
'Command',
|
| 29 |
+
'Extension',
|
| 30 |
+
'Require',
|
| 31 |
+
'SetuptoolsDeprecationWarning',
|
| 32 |
+
'find_packages',
|
| 33 |
+
'find_namespace_packages',
|
| 34 |
+
]
|
| 35 |
+
|
| 36 |
+
__version__ = setuptools.version.__version__
|
| 37 |
+
|
| 38 |
+
bootstrap_install_from = None
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
find_packages = PackageFinder.find
|
| 42 |
+
find_namespace_packages = PEP420PackageFinder.find
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def _install_setup_requires(attrs):
|
| 46 |
+
# Note: do not use `setuptools.Distribution` directly, as
|
| 47 |
+
# our PEP 517 backend patch `distutils.core.Distribution`.
|
| 48 |
+
class MinimalDistribution(distutils.core.Distribution):
|
| 49 |
+
"""
|
| 50 |
+
A minimal version of a distribution for supporting the
|
| 51 |
+
fetch_build_eggs interface.
|
| 52 |
+
"""
|
| 53 |
+
|
| 54 |
+
def __init__(self, attrs):
|
| 55 |
+
_incl = 'dependency_links', 'setup_requires'
|
| 56 |
+
filtered = {k: attrs[k] for k in set(_incl) & set(attrs)}
|
| 57 |
+
super().__init__(filtered)
|
| 58 |
+
# Prevent accidentally triggering discovery with incomplete set of attrs
|
| 59 |
+
self.set_defaults._disable()
|
| 60 |
+
|
| 61 |
+
def _get_project_config_files(self, filenames=None):
|
| 62 |
+
"""Ignore ``pyproject.toml``, they are not related to setup_requires"""
|
| 63 |
+
try:
|
| 64 |
+
cfg, toml = super()._split_standard_project_metadata(filenames)
|
| 65 |
+
return cfg, ()
|
| 66 |
+
except Exception:
|
| 67 |
+
return filenames, ()
|
| 68 |
+
|
| 69 |
+
def finalize_options(self):
|
| 70 |
+
"""
|
| 71 |
+
Disable finalize_options to avoid building the working set.
|
| 72 |
+
Ref #2158.
|
| 73 |
+
"""
|
| 74 |
+
|
| 75 |
+
dist = MinimalDistribution(attrs)
|
| 76 |
+
|
| 77 |
+
# Honor setup.cfg's options.
|
| 78 |
+
dist.parse_config_files(ignore_option_errors=True)
|
| 79 |
+
if dist.setup_requires:
|
| 80 |
+
dist.fetch_build_eggs(dist.setup_requires)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def setup(**attrs):
|
| 84 |
+
# Make sure we have any requirements needed to interpret 'attrs'.
|
| 85 |
+
logging.configure()
|
| 86 |
+
_install_setup_requires(attrs)
|
| 87 |
+
return distutils.core.setup(**attrs)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
setup.__doc__ = distutils.core.setup.__doc__
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
_Command = monkey.get_unpatched(distutils.core.Command)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
class Command(_Command):
|
| 97 |
+
"""
|
| 98 |
+
Setuptools internal actions are organized using a *command design pattern*.
|
| 99 |
+
This means that each action (or group of closely related actions) executed during
|
| 100 |
+
the build should be implemented as a ``Command`` subclass.
|
| 101 |
+
|
| 102 |
+
These commands are abstractions and do not necessarily correspond to a command that
|
| 103 |
+
can (or should) be executed via a terminal, in a CLI fashion (although historically
|
| 104 |
+
they would).
|
| 105 |
+
|
| 106 |
+
When creating a new command from scratch, custom defined classes **SHOULD** inherit
|
| 107 |
+
from ``setuptools.Command`` and implement a few mandatory methods.
|
| 108 |
+
Between these mandatory methods, are listed:
|
| 109 |
+
|
| 110 |
+
.. method:: initialize_options(self)
|
| 111 |
+
|
| 112 |
+
Set or (reset) all options/attributes/caches used by the command
|
| 113 |
+
to their default values. Note that these values may be overwritten during
|
| 114 |
+
the build.
|
| 115 |
+
|
| 116 |
+
.. method:: finalize_options(self)
|
| 117 |
+
|
| 118 |
+
Set final values for all options/attributes used by the command.
|
| 119 |
+
Most of the time, each option/attribute/cache should only be set if it does not
|
| 120 |
+
have any value yet (e.g. ``if self.attr is None: self.attr = val``).
|
| 121 |
+
|
| 122 |
+
.. method:: run(self)
|
| 123 |
+
|
| 124 |
+
Execute the actions intended by the command.
|
| 125 |
+
(Side effects **SHOULD** only take place when ``run`` is executed,
|
| 126 |
+
for example, creating new files or writing to the terminal output).
|
| 127 |
+
|
| 128 |
+
A useful analogy for command classes is to think of them as subroutines with local
|
| 129 |
+
variables called "options". The options are "declared" in ``initialize_options()``
|
| 130 |
+
and "defined" (given their final values, aka "finalized") in ``finalize_options()``,
|
| 131 |
+
both of which must be defined by every command class. The "body" of the subroutine,
|
| 132 |
+
(where it does all the work) is the ``run()`` method.
|
| 133 |
+
Between ``initialize_options()`` and ``finalize_options()``, ``setuptools`` may set
|
| 134 |
+
the values for options/attributes based on user's input (or circumstance),
|
| 135 |
+
which means that the implementation should be careful to not overwrite values in
|
| 136 |
+
``finalize_options`` unless necessary.
|
| 137 |
+
|
| 138 |
+
Please note that other commands (or other parts of setuptools) may also overwrite
|
| 139 |
+
the values of the command's options/attributes multiple times during the build
|
| 140 |
+
process.
|
| 141 |
+
Therefore it is important to consistently implement ``initialize_options()`` and
|
| 142 |
+
``finalize_options()``. For example, all derived attributes (or attributes that
|
| 143 |
+
depend on the value of other attributes) **SHOULD** be recomputed in
|
| 144 |
+
``finalize_options``.
|
| 145 |
+
|
| 146 |
+
When overwriting existing commands, custom defined classes **MUST** abide by the
|
| 147 |
+
same APIs implemented by the original class. They also **SHOULD** inherit from the
|
| 148 |
+
original class.
|
| 149 |
+
"""
|
| 150 |
+
|
| 151 |
+
command_consumes_arguments = False
|
| 152 |
+
|
| 153 |
+
def __init__(self, dist, **kw):
|
| 154 |
+
"""
|
| 155 |
+
Construct the command for dist, updating
|
| 156 |
+
vars(self) with any keyword parameters.
|
| 157 |
+
"""
|
| 158 |
+
super().__init__(dist)
|
| 159 |
+
vars(self).update(kw)
|
| 160 |
+
|
| 161 |
+
def _ensure_stringlike(self, option, what, default=None):
|
| 162 |
+
val = getattr(self, option)
|
| 163 |
+
if val is None:
|
| 164 |
+
setattr(self, option, default)
|
| 165 |
+
return default
|
| 166 |
+
elif not isinstance(val, str):
|
| 167 |
+
raise DistutilsOptionError(
|
| 168 |
+
"'%s' must be a %s (got `%s`)" % (option, what, val)
|
| 169 |
+
)
|
| 170 |
+
return val
|
| 171 |
+
|
| 172 |
+
def ensure_string_list(self, option):
|
| 173 |
+
r"""Ensure that 'option' is a list of strings. If 'option' is
|
| 174 |
+
currently a string, we split it either on /,\s*/ or /\s+/, so
|
| 175 |
+
"foo bar baz", "foo,bar,baz", and "foo, bar baz" all become
|
| 176 |
+
["foo", "bar", "baz"].
|
| 177 |
+
|
| 178 |
+
..
|
| 179 |
+
TODO: This method seems to be similar to the one in ``distutils.cmd``
|
| 180 |
+
Probably it is just here for backward compatibility with old Python versions?
|
| 181 |
+
|
| 182 |
+
:meta private:
|
| 183 |
+
"""
|
| 184 |
+
val = getattr(self, option)
|
| 185 |
+
if val is None:
|
| 186 |
+
return
|
| 187 |
+
elif isinstance(val, str):
|
| 188 |
+
setattr(self, option, re.split(r',\s*|\s+', val))
|
| 189 |
+
else:
|
| 190 |
+
if isinstance(val, list):
|
| 191 |
+
ok = all(isinstance(v, str) for v in val)
|
| 192 |
+
else:
|
| 193 |
+
ok = False
|
| 194 |
+
if not ok:
|
| 195 |
+
raise DistutilsOptionError(
|
| 196 |
+
"'%s' must be a list of strings (got %r)" % (option, val)
|
| 197 |
+
)
|
| 198 |
+
|
| 199 |
+
def reinitialize_command(self, command, reinit_subcommands=0, **kw):
|
| 200 |
+
cmd = _Command.reinitialize_command(self, command, reinit_subcommands)
|
| 201 |
+
vars(cmd).update(kw)
|
| 202 |
+
return cmd
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
def _find_all_simple(path):
|
| 206 |
+
"""
|
| 207 |
+
Find all files under 'path'
|
| 208 |
+
"""
|
| 209 |
+
results = (
|
| 210 |
+
os.path.join(base, file)
|
| 211 |
+
for base, dirs, files in os.walk(path, followlinks=True)
|
| 212 |
+
for file in files
|
| 213 |
+
)
|
| 214 |
+
return filter(os.path.isfile, results)
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
def findall(dir=os.curdir):
|
| 218 |
+
"""
|
| 219 |
+
Find all files under 'dir' and return the list of full filenames.
|
| 220 |
+
Unless dir is '.', return full filenames with dir prepended.
|
| 221 |
+
"""
|
| 222 |
+
files = _find_all_simple(dir)
|
| 223 |
+
if dir == os.curdir:
|
| 224 |
+
make_rel = functools.partial(os.path.relpath, start=dir)
|
| 225 |
+
files = map(make_rel, files)
|
| 226 |
+
return list(files)
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
@functools.wraps(_convert_path)
|
| 230 |
+
def convert_path(pathname):
|
| 231 |
+
from inspect import cleandoc
|
| 232 |
+
|
| 233 |
+
msg = """
|
| 234 |
+
The function `convert_path` is considered internal and not part of the public API.
|
| 235 |
+
Its direct usage by 3rd-party packages is considered deprecated and the function
|
| 236 |
+
may be removed in the future.
|
| 237 |
+
"""
|
| 238 |
+
warnings.warn(cleandoc(msg), SetuptoolsDeprecationWarning)
|
| 239 |
+
return _convert_path(pathname)
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
class sic(str):
|
| 243 |
+
"""Treat this string as-is (https://en.wikipedia.org/wiki/Sic)"""
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
# Apply monkey patches
|
| 247 |
+
monkey.patch_all()
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/__init__.cpython-310.pyc
ADDED
|
Binary file (9.52 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-310.pyc
ADDED
|
Binary file (565 Bytes). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_entry_points.cpython-310.pyc
ADDED
|
Binary file (3.03 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_imp.cpython-310.pyc
ADDED
|
Binary file (2.09 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_importlib.cpython-310.pyc
ADDED
|
Binary file (1.36 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_itertools.cpython-310.pyc
ADDED
|
Binary file (929 Bytes). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_path.cpython-310.pyc
ADDED
|
Binary file (1.1 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/_reqs.cpython-310.pyc
ADDED
|
Binary file (844 Bytes). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/archive_util.cpython-310.pyc
ADDED
|
Binary file (6.2 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/build_meta.cpython-310.pyc
ADDED
|
Binary file (18.1 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/dep_util.cpython-310.pyc
ADDED
|
Binary file (872 Bytes). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/depends.cpython-310.pyc
ADDED
|
Binary file (5.31 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/discovery.cpython-310.pyc
ADDED
|
Binary file (20.6 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/dist.cpython-310.pyc
ADDED
|
Binary file (38.4 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/errors.cpython-310.pyc
ADDED
|
Binary file (2.5 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/extension.cpython-310.pyc
ADDED
|
Binary file (5.91 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/glob.cpython-310.pyc
ADDED
|
Binary file (3.75 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/installer.cpython-310.pyc
ADDED
|
Binary file (3 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/launch.cpython-310.pyc
ADDED
|
Binary file (922 Bytes). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/logging.cpython-310.pyc
ADDED
|
Binary file (1.26 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/monkey.cpython-310.pyc
ADDED
|
Binary file (4.46 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/msvc.cpython-310.pyc
ADDED
|
Binary file (40.6 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/namespaces.cpython-310.pyc
ADDED
|
Binary file (3.63 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/package_index.cpython-310.pyc
ADDED
|
Binary file (32.7 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/py34compat.cpython-310.pyc
ADDED
|
Binary file (497 Bytes). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/sandbox.cpython-310.pyc
ADDED
|
Binary file (15.8 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/unicode_utils.cpython-310.pyc
ADDED
|
Binary file (1.13 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/version.cpython-310.pyc
ADDED
|
Binary file (339 Bytes). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/wheel.cpython-310.pyc
ADDED
|
Binary file (7.61 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/__pycache__/windows_support.cpython-310.pyc
ADDED
|
Binary file (1.05 kB). View file
|
|
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_deprecation_warning.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class SetuptoolsDeprecationWarning(Warning):
|
| 2 |
+
"""
|
| 3 |
+
Base class for warning deprecations in ``setuptools``
|
| 4 |
+
|
| 5 |
+
This class is not derived from ``DeprecationWarning``, and as such is
|
| 6 |
+
visible by default.
|
| 7 |
+
"""
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/__init__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils
|
| 2 |
+
|
| 3 |
+
The main package for the Python Module Distribution Utilities. Normally
|
| 4 |
+
used from a setup script as
|
| 5 |
+
|
| 6 |
+
from distutils.core import setup
|
| 7 |
+
|
| 8 |
+
setup (...)
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import sys
|
| 12 |
+
import importlib
|
| 13 |
+
|
| 14 |
+
__version__ = sys.version[: sys.version.index(' ')]
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
try:
|
| 18 |
+
# Allow Debian and pkgsrc (only) to customize system
|
| 19 |
+
# behavior. Ref pypa/distutils#2 and pypa/distutils#16.
|
| 20 |
+
# This hook is deprecated and no other environments
|
| 21 |
+
# should use it.
|
| 22 |
+
importlib.import_module('_distutils_system_mod')
|
| 23 |
+
except ImportError:
|
| 24 |
+
pass
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/_collections.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import collections
|
| 2 |
+
import itertools
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
# from jaraco.collections 3.5.1
|
| 6 |
+
class DictStack(list, collections.abc.Mapping):
|
| 7 |
+
"""
|
| 8 |
+
A stack of dictionaries that behaves as a view on those dictionaries,
|
| 9 |
+
giving preference to the last.
|
| 10 |
+
|
| 11 |
+
>>> stack = DictStack([dict(a=1, c=2), dict(b=2, a=2)])
|
| 12 |
+
>>> stack['a']
|
| 13 |
+
2
|
| 14 |
+
>>> stack['b']
|
| 15 |
+
2
|
| 16 |
+
>>> stack['c']
|
| 17 |
+
2
|
| 18 |
+
>>> len(stack)
|
| 19 |
+
3
|
| 20 |
+
>>> stack.push(dict(a=3))
|
| 21 |
+
>>> stack['a']
|
| 22 |
+
3
|
| 23 |
+
>>> set(stack.keys()) == set(['a', 'b', 'c'])
|
| 24 |
+
True
|
| 25 |
+
>>> set(stack.items()) == set([('a', 3), ('b', 2), ('c', 2)])
|
| 26 |
+
True
|
| 27 |
+
>>> dict(**stack) == dict(stack) == dict(a=3, c=2, b=2)
|
| 28 |
+
True
|
| 29 |
+
>>> d = stack.pop()
|
| 30 |
+
>>> stack['a']
|
| 31 |
+
2
|
| 32 |
+
>>> d = stack.pop()
|
| 33 |
+
>>> stack['a']
|
| 34 |
+
1
|
| 35 |
+
>>> stack.get('b', None)
|
| 36 |
+
>>> 'c' in stack
|
| 37 |
+
True
|
| 38 |
+
"""
|
| 39 |
+
|
| 40 |
+
def __iter__(self):
|
| 41 |
+
dicts = list.__iter__(self)
|
| 42 |
+
return iter(set(itertools.chain.from_iterable(c.keys() for c in dicts)))
|
| 43 |
+
|
| 44 |
+
def __getitem__(self, key):
|
| 45 |
+
for scope in reversed(tuple(list.__iter__(self))):
|
| 46 |
+
if key in scope:
|
| 47 |
+
return scope[key]
|
| 48 |
+
raise KeyError(key)
|
| 49 |
+
|
| 50 |
+
push = list.append
|
| 51 |
+
|
| 52 |
+
def __contains__(self, other):
|
| 53 |
+
return collections.abc.Mapping.__contains__(self, other)
|
| 54 |
+
|
| 55 |
+
def __len__(self):
|
| 56 |
+
return len(list(iter(self)))
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/_macos_compat.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
import importlib
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def bypass_compiler_fixup(cmd, args):
|
| 6 |
+
return cmd
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
if sys.platform == 'darwin':
|
| 10 |
+
compiler_fixup = importlib.import_module('_osx_support').compiler_fixup
|
| 11 |
+
else:
|
| 12 |
+
compiler_fixup = bypass_compiler_fixup
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/_msvccompiler.py
ADDED
|
@@ -0,0 +1,572 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils._msvccompiler
|
| 2 |
+
|
| 3 |
+
Contains MSVCCompiler, an implementation of the abstract CCompiler class
|
| 4 |
+
for Microsoft Visual Studio 2015.
|
| 5 |
+
|
| 6 |
+
The module is compatible with VS 2015 and later. You can find legacy support
|
| 7 |
+
for older versions in distutils.msvc9compiler and distutils.msvccompiler.
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
# Written by Perry Stoll
|
| 11 |
+
# hacked by Robin Becker and Thomas Heller to do a better job of
|
| 12 |
+
# finding DevStudio (through the registry)
|
| 13 |
+
# ported to VS 2005 and VS 2008 by Christian Heimes
|
| 14 |
+
# ported to VS 2015 by Steve Dower
|
| 15 |
+
|
| 16 |
+
import os
|
| 17 |
+
import subprocess
|
| 18 |
+
import contextlib
|
| 19 |
+
import warnings
|
| 20 |
+
import unittest.mock as mock
|
| 21 |
+
|
| 22 |
+
with contextlib.suppress(ImportError):
|
| 23 |
+
import winreg
|
| 24 |
+
|
| 25 |
+
from distutils.errors import (
|
| 26 |
+
DistutilsExecError,
|
| 27 |
+
DistutilsPlatformError,
|
| 28 |
+
CompileError,
|
| 29 |
+
LibError,
|
| 30 |
+
LinkError,
|
| 31 |
+
)
|
| 32 |
+
from distutils.ccompiler import CCompiler, gen_lib_options
|
| 33 |
+
from distutils import log
|
| 34 |
+
from distutils.util import get_platform
|
| 35 |
+
|
| 36 |
+
from itertools import count
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def _find_vc2015():
|
| 40 |
+
try:
|
| 41 |
+
key = winreg.OpenKeyEx(
|
| 42 |
+
winreg.HKEY_LOCAL_MACHINE,
|
| 43 |
+
r"Software\Microsoft\VisualStudio\SxS\VC7",
|
| 44 |
+
access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY,
|
| 45 |
+
)
|
| 46 |
+
except OSError:
|
| 47 |
+
log.debug("Visual C++ is not registered")
|
| 48 |
+
return None, None
|
| 49 |
+
|
| 50 |
+
best_version = 0
|
| 51 |
+
best_dir = None
|
| 52 |
+
with key:
|
| 53 |
+
for i in count():
|
| 54 |
+
try:
|
| 55 |
+
v, vc_dir, vt = winreg.EnumValue(key, i)
|
| 56 |
+
except OSError:
|
| 57 |
+
break
|
| 58 |
+
if v and vt == winreg.REG_SZ and os.path.isdir(vc_dir):
|
| 59 |
+
try:
|
| 60 |
+
version = int(float(v))
|
| 61 |
+
except (ValueError, TypeError):
|
| 62 |
+
continue
|
| 63 |
+
if version >= 14 and version > best_version:
|
| 64 |
+
best_version, best_dir = version, vc_dir
|
| 65 |
+
return best_version, best_dir
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def _find_vc2017():
|
| 69 |
+
"""Returns "15, path" based on the result of invoking vswhere.exe
|
| 70 |
+
If no install is found, returns "None, None"
|
| 71 |
+
|
| 72 |
+
The version is returned to avoid unnecessarily changing the function
|
| 73 |
+
result. It may be ignored when the path is not None.
|
| 74 |
+
|
| 75 |
+
If vswhere.exe is not available, by definition, VS 2017 is not
|
| 76 |
+
installed.
|
| 77 |
+
"""
|
| 78 |
+
root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles")
|
| 79 |
+
if not root:
|
| 80 |
+
return None, None
|
| 81 |
+
|
| 82 |
+
try:
|
| 83 |
+
path = subprocess.check_output(
|
| 84 |
+
[
|
| 85 |
+
os.path.join(
|
| 86 |
+
root, "Microsoft Visual Studio", "Installer", "vswhere.exe"
|
| 87 |
+
),
|
| 88 |
+
"-latest",
|
| 89 |
+
"-prerelease",
|
| 90 |
+
"-requires",
|
| 91 |
+
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
| 92 |
+
"-property",
|
| 93 |
+
"installationPath",
|
| 94 |
+
"-products",
|
| 95 |
+
"*",
|
| 96 |
+
],
|
| 97 |
+
encoding="mbcs",
|
| 98 |
+
errors="strict",
|
| 99 |
+
).strip()
|
| 100 |
+
except (subprocess.CalledProcessError, OSError, UnicodeDecodeError):
|
| 101 |
+
return None, None
|
| 102 |
+
|
| 103 |
+
path = os.path.join(path, "VC", "Auxiliary", "Build")
|
| 104 |
+
if os.path.isdir(path):
|
| 105 |
+
return 15, path
|
| 106 |
+
|
| 107 |
+
return None, None
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
PLAT_SPEC_TO_RUNTIME = {
|
| 111 |
+
'x86': 'x86',
|
| 112 |
+
'x86_amd64': 'x64',
|
| 113 |
+
'x86_arm': 'arm',
|
| 114 |
+
'x86_arm64': 'arm64',
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def _find_vcvarsall(plat_spec):
|
| 119 |
+
# bpo-38597: Removed vcruntime return value
|
| 120 |
+
_, best_dir = _find_vc2017()
|
| 121 |
+
|
| 122 |
+
if not best_dir:
|
| 123 |
+
best_version, best_dir = _find_vc2015()
|
| 124 |
+
|
| 125 |
+
if not best_dir:
|
| 126 |
+
log.debug("No suitable Visual C++ version found")
|
| 127 |
+
return None, None
|
| 128 |
+
|
| 129 |
+
vcvarsall = os.path.join(best_dir, "vcvarsall.bat")
|
| 130 |
+
if not os.path.isfile(vcvarsall):
|
| 131 |
+
log.debug("%s cannot be found", vcvarsall)
|
| 132 |
+
return None, None
|
| 133 |
+
|
| 134 |
+
return vcvarsall, None
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def _get_vc_env(plat_spec):
|
| 138 |
+
if os.getenv("DISTUTILS_USE_SDK"):
|
| 139 |
+
return {key.lower(): value for key, value in os.environ.items()}
|
| 140 |
+
|
| 141 |
+
vcvarsall, _ = _find_vcvarsall(plat_spec)
|
| 142 |
+
if not vcvarsall:
|
| 143 |
+
raise DistutilsPlatformError("Unable to find vcvarsall.bat")
|
| 144 |
+
|
| 145 |
+
try:
|
| 146 |
+
out = subprocess.check_output(
|
| 147 |
+
f'cmd /u /c "{vcvarsall}" {plat_spec} && set',
|
| 148 |
+
stderr=subprocess.STDOUT,
|
| 149 |
+
).decode('utf-16le', errors='replace')
|
| 150 |
+
except subprocess.CalledProcessError as exc:
|
| 151 |
+
log.error(exc.output)
|
| 152 |
+
raise DistutilsPlatformError(f"Error executing {exc.cmd}")
|
| 153 |
+
|
| 154 |
+
env = {
|
| 155 |
+
key.lower(): value
|
| 156 |
+
for key, _, value in (line.partition('=') for line in out.splitlines())
|
| 157 |
+
if key and value
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
return env
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
def _find_exe(exe, paths=None):
|
| 164 |
+
"""Return path to an MSVC executable program.
|
| 165 |
+
|
| 166 |
+
Tries to find the program in several places: first, one of the
|
| 167 |
+
MSVC program search paths from the registry; next, the directories
|
| 168 |
+
in the PATH environment variable. If any of those work, return an
|
| 169 |
+
absolute path that is known to exist. If none of them work, just
|
| 170 |
+
return the original program name, 'exe'.
|
| 171 |
+
"""
|
| 172 |
+
if not paths:
|
| 173 |
+
paths = os.getenv('path').split(os.pathsep)
|
| 174 |
+
for p in paths:
|
| 175 |
+
fn = os.path.join(os.path.abspath(p), exe)
|
| 176 |
+
if os.path.isfile(fn):
|
| 177 |
+
return fn
|
| 178 |
+
return exe
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
# A map keyed by get_platform() return values to values accepted by
|
| 182 |
+
# 'vcvarsall.bat'. Always cross-compile from x86 to work with the
|
| 183 |
+
# lighter-weight MSVC installs that do not include native 64-bit tools.
|
| 184 |
+
PLAT_TO_VCVARS = {
|
| 185 |
+
'win32': 'x86',
|
| 186 |
+
'win-amd64': 'x86_amd64',
|
| 187 |
+
'win-arm32': 'x86_arm',
|
| 188 |
+
'win-arm64': 'x86_arm64',
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
class MSVCCompiler(CCompiler):
|
| 193 |
+
"""Concrete class that implements an interface to Microsoft Visual C++,
|
| 194 |
+
as defined by the CCompiler abstract class."""
|
| 195 |
+
|
| 196 |
+
compiler_type = 'msvc'
|
| 197 |
+
|
| 198 |
+
# Just set this so CCompiler's constructor doesn't barf. We currently
|
| 199 |
+
# don't use the 'set_executables()' bureaucracy provided by CCompiler,
|
| 200 |
+
# as it really isn't necessary for this sort of single-compiler class.
|
| 201 |
+
# Would be nice to have a consistent interface with UnixCCompiler,
|
| 202 |
+
# though, so it's worth thinking about.
|
| 203 |
+
executables = {}
|
| 204 |
+
|
| 205 |
+
# Private class data (need to distinguish C from C++ source for compiler)
|
| 206 |
+
_c_extensions = ['.c']
|
| 207 |
+
_cpp_extensions = ['.cc', '.cpp', '.cxx']
|
| 208 |
+
_rc_extensions = ['.rc']
|
| 209 |
+
_mc_extensions = ['.mc']
|
| 210 |
+
|
| 211 |
+
# Needed for the filename generation methods provided by the
|
| 212 |
+
# base class, CCompiler.
|
| 213 |
+
src_extensions = _c_extensions + _cpp_extensions + _rc_extensions + _mc_extensions
|
| 214 |
+
res_extension = '.res'
|
| 215 |
+
obj_extension = '.obj'
|
| 216 |
+
static_lib_extension = '.lib'
|
| 217 |
+
shared_lib_extension = '.dll'
|
| 218 |
+
static_lib_format = shared_lib_format = '%s%s'
|
| 219 |
+
exe_extension = '.exe'
|
| 220 |
+
|
| 221 |
+
def __init__(self, verbose=0, dry_run=0, force=0):
|
| 222 |
+
super().__init__(verbose, dry_run, force)
|
| 223 |
+
# target platform (.plat_name is consistent with 'bdist')
|
| 224 |
+
self.plat_name = None
|
| 225 |
+
self.initialized = False
|
| 226 |
+
|
| 227 |
+
@classmethod
|
| 228 |
+
def _configure(cls, vc_env):
|
| 229 |
+
"""
|
| 230 |
+
Set class-level include/lib dirs.
|
| 231 |
+
"""
|
| 232 |
+
cls.include_dirs = cls._parse_path(vc_env.get('include', ''))
|
| 233 |
+
cls.library_dirs = cls._parse_path(vc_env.get('lib', ''))
|
| 234 |
+
|
| 235 |
+
@staticmethod
|
| 236 |
+
def _parse_path(val):
|
| 237 |
+
return [dir.rstrip(os.sep) for dir in val.split(os.pathsep) if dir]
|
| 238 |
+
|
| 239 |
+
def initialize(self, plat_name=None):
|
| 240 |
+
# multi-init means we would need to check platform same each time...
|
| 241 |
+
assert not self.initialized, "don't init multiple times"
|
| 242 |
+
if plat_name is None:
|
| 243 |
+
plat_name = get_platform()
|
| 244 |
+
# sanity check for platforms to prevent obscure errors later.
|
| 245 |
+
if plat_name not in PLAT_TO_VCVARS:
|
| 246 |
+
raise DistutilsPlatformError(
|
| 247 |
+
f"--plat-name must be one of {tuple(PLAT_TO_VCVARS)}"
|
| 248 |
+
)
|
| 249 |
+
|
| 250 |
+
# Get the vcvarsall.bat spec for the requested platform.
|
| 251 |
+
plat_spec = PLAT_TO_VCVARS[plat_name]
|
| 252 |
+
|
| 253 |
+
vc_env = _get_vc_env(plat_spec)
|
| 254 |
+
if not vc_env:
|
| 255 |
+
raise DistutilsPlatformError(
|
| 256 |
+
"Unable to find a compatible " "Visual Studio installation."
|
| 257 |
+
)
|
| 258 |
+
self._configure(vc_env)
|
| 259 |
+
|
| 260 |
+
self._paths = vc_env.get('path', '')
|
| 261 |
+
paths = self._paths.split(os.pathsep)
|
| 262 |
+
self.cc = _find_exe("cl.exe", paths)
|
| 263 |
+
self.linker = _find_exe("link.exe", paths)
|
| 264 |
+
self.lib = _find_exe("lib.exe", paths)
|
| 265 |
+
self.rc = _find_exe("rc.exe", paths) # resource compiler
|
| 266 |
+
self.mc = _find_exe("mc.exe", paths) # message compiler
|
| 267 |
+
self.mt = _find_exe("mt.exe", paths) # message compiler
|
| 268 |
+
|
| 269 |
+
self.preprocess_options = None
|
| 270 |
+
# bpo-38597: Always compile with dynamic linking
|
| 271 |
+
# Future releases of Python 3.x will include all past
|
| 272 |
+
# versions of vcruntime*.dll for compatibility.
|
| 273 |
+
self.compile_options = ['/nologo', '/O2', '/W3', '/GL', '/DNDEBUG', '/MD']
|
| 274 |
+
|
| 275 |
+
self.compile_options_debug = [
|
| 276 |
+
'/nologo',
|
| 277 |
+
'/Od',
|
| 278 |
+
'/MDd',
|
| 279 |
+
'/Zi',
|
| 280 |
+
'/W3',
|
| 281 |
+
'/D_DEBUG',
|
| 282 |
+
]
|
| 283 |
+
|
| 284 |
+
ldflags = ['/nologo', '/INCREMENTAL:NO', '/LTCG']
|
| 285 |
+
|
| 286 |
+
ldflags_debug = ['/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL']
|
| 287 |
+
|
| 288 |
+
self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1']
|
| 289 |
+
self.ldflags_exe_debug = [*ldflags_debug, '/MANIFEST:EMBED,ID=1']
|
| 290 |
+
self.ldflags_shared = [
|
| 291 |
+
*ldflags,
|
| 292 |
+
'/DLL',
|
| 293 |
+
'/MANIFEST:EMBED,ID=2',
|
| 294 |
+
'/MANIFESTUAC:NO',
|
| 295 |
+
]
|
| 296 |
+
self.ldflags_shared_debug = [
|
| 297 |
+
*ldflags_debug,
|
| 298 |
+
'/DLL',
|
| 299 |
+
'/MANIFEST:EMBED,ID=2',
|
| 300 |
+
'/MANIFESTUAC:NO',
|
| 301 |
+
]
|
| 302 |
+
self.ldflags_static = [*ldflags]
|
| 303 |
+
self.ldflags_static_debug = [*ldflags_debug]
|
| 304 |
+
|
| 305 |
+
self._ldflags = {
|
| 306 |
+
(CCompiler.EXECUTABLE, None): self.ldflags_exe,
|
| 307 |
+
(CCompiler.EXECUTABLE, False): self.ldflags_exe,
|
| 308 |
+
(CCompiler.EXECUTABLE, True): self.ldflags_exe_debug,
|
| 309 |
+
(CCompiler.SHARED_OBJECT, None): self.ldflags_shared,
|
| 310 |
+
(CCompiler.SHARED_OBJECT, False): self.ldflags_shared,
|
| 311 |
+
(CCompiler.SHARED_OBJECT, True): self.ldflags_shared_debug,
|
| 312 |
+
(CCompiler.SHARED_LIBRARY, None): self.ldflags_static,
|
| 313 |
+
(CCompiler.SHARED_LIBRARY, False): self.ldflags_static,
|
| 314 |
+
(CCompiler.SHARED_LIBRARY, True): self.ldflags_static_debug,
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
self.initialized = True
|
| 318 |
+
|
| 319 |
+
# -- Worker methods ------------------------------------------------
|
| 320 |
+
|
| 321 |
+
@property
|
| 322 |
+
def out_extensions(self):
|
| 323 |
+
return {
|
| 324 |
+
**super().out_extensions,
|
| 325 |
+
**{
|
| 326 |
+
ext: self.res_extension
|
| 327 |
+
for ext in self._rc_extensions + self._mc_extensions
|
| 328 |
+
},
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
def compile( # noqa: C901
|
| 332 |
+
self,
|
| 333 |
+
sources,
|
| 334 |
+
output_dir=None,
|
| 335 |
+
macros=None,
|
| 336 |
+
include_dirs=None,
|
| 337 |
+
debug=0,
|
| 338 |
+
extra_preargs=None,
|
| 339 |
+
extra_postargs=None,
|
| 340 |
+
depends=None,
|
| 341 |
+
):
|
| 342 |
+
|
| 343 |
+
if not self.initialized:
|
| 344 |
+
self.initialize()
|
| 345 |
+
compile_info = self._setup_compile(
|
| 346 |
+
output_dir, macros, include_dirs, sources, depends, extra_postargs
|
| 347 |
+
)
|
| 348 |
+
macros, objects, extra_postargs, pp_opts, build = compile_info
|
| 349 |
+
|
| 350 |
+
compile_opts = extra_preargs or []
|
| 351 |
+
compile_opts.append('/c')
|
| 352 |
+
if debug:
|
| 353 |
+
compile_opts.extend(self.compile_options_debug)
|
| 354 |
+
else:
|
| 355 |
+
compile_opts.extend(self.compile_options)
|
| 356 |
+
|
| 357 |
+
add_cpp_opts = False
|
| 358 |
+
|
| 359 |
+
for obj in objects:
|
| 360 |
+
try:
|
| 361 |
+
src, ext = build[obj]
|
| 362 |
+
except KeyError:
|
| 363 |
+
continue
|
| 364 |
+
if debug:
|
| 365 |
+
# pass the full pathname to MSVC in debug mode,
|
| 366 |
+
# this allows the debugger to find the source file
|
| 367 |
+
# without asking the user to browse for it
|
| 368 |
+
src = os.path.abspath(src)
|
| 369 |
+
|
| 370 |
+
if ext in self._c_extensions:
|
| 371 |
+
input_opt = "/Tc" + src
|
| 372 |
+
elif ext in self._cpp_extensions:
|
| 373 |
+
input_opt = "/Tp" + src
|
| 374 |
+
add_cpp_opts = True
|
| 375 |
+
elif ext in self._rc_extensions:
|
| 376 |
+
# compile .RC to .RES file
|
| 377 |
+
input_opt = src
|
| 378 |
+
output_opt = "/fo" + obj
|
| 379 |
+
try:
|
| 380 |
+
self.spawn([self.rc] + pp_opts + [output_opt, input_opt])
|
| 381 |
+
except DistutilsExecError as msg:
|
| 382 |
+
raise CompileError(msg)
|
| 383 |
+
continue
|
| 384 |
+
elif ext in self._mc_extensions:
|
| 385 |
+
# Compile .MC to .RC file to .RES file.
|
| 386 |
+
# * '-h dir' specifies the directory for the
|
| 387 |
+
# generated include file
|
| 388 |
+
# * '-r dir' specifies the target directory of the
|
| 389 |
+
# generated RC file and the binary message resource
|
| 390 |
+
# it includes
|
| 391 |
+
#
|
| 392 |
+
# For now (since there are no options to change this),
|
| 393 |
+
# we use the source-directory for the include file and
|
| 394 |
+
# the build directory for the RC file and message
|
| 395 |
+
# resources. This works at least for win32all.
|
| 396 |
+
h_dir = os.path.dirname(src)
|
| 397 |
+
rc_dir = os.path.dirname(obj)
|
| 398 |
+
try:
|
| 399 |
+
# first compile .MC to .RC and .H file
|
| 400 |
+
self.spawn([self.mc, '-h', h_dir, '-r', rc_dir, src])
|
| 401 |
+
base, _ = os.path.splitext(os.path.basename(src))
|
| 402 |
+
rc_file = os.path.join(rc_dir, base + '.rc')
|
| 403 |
+
# then compile .RC to .RES file
|
| 404 |
+
self.spawn([self.rc, "/fo" + obj, rc_file])
|
| 405 |
+
|
| 406 |
+
except DistutilsExecError as msg:
|
| 407 |
+
raise CompileError(msg)
|
| 408 |
+
continue
|
| 409 |
+
else:
|
| 410 |
+
# how to handle this file?
|
| 411 |
+
raise CompileError(f"Don't know how to compile {src} to {obj}")
|
| 412 |
+
|
| 413 |
+
args = [self.cc] + compile_opts + pp_opts
|
| 414 |
+
if add_cpp_opts:
|
| 415 |
+
args.append('/EHsc')
|
| 416 |
+
args.append(input_opt)
|
| 417 |
+
args.append("/Fo" + obj)
|
| 418 |
+
args.extend(extra_postargs)
|
| 419 |
+
|
| 420 |
+
try:
|
| 421 |
+
self.spawn(args)
|
| 422 |
+
except DistutilsExecError as msg:
|
| 423 |
+
raise CompileError(msg)
|
| 424 |
+
|
| 425 |
+
return objects
|
| 426 |
+
|
| 427 |
+
def create_static_lib(
|
| 428 |
+
self, objects, output_libname, output_dir=None, debug=0, target_lang=None
|
| 429 |
+
):
|
| 430 |
+
|
| 431 |
+
if not self.initialized:
|
| 432 |
+
self.initialize()
|
| 433 |
+
objects, output_dir = self._fix_object_args(objects, output_dir)
|
| 434 |
+
output_filename = self.library_filename(output_libname, output_dir=output_dir)
|
| 435 |
+
|
| 436 |
+
if self._need_link(objects, output_filename):
|
| 437 |
+
lib_args = objects + ['/OUT:' + output_filename]
|
| 438 |
+
if debug:
|
| 439 |
+
pass # XXX what goes here?
|
| 440 |
+
try:
|
| 441 |
+
log.debug('Executing "%s" %s', self.lib, ' '.join(lib_args))
|
| 442 |
+
self.spawn([self.lib] + lib_args)
|
| 443 |
+
except DistutilsExecError as msg:
|
| 444 |
+
raise LibError(msg)
|
| 445 |
+
else:
|
| 446 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 447 |
+
|
| 448 |
+
def link(
|
| 449 |
+
self,
|
| 450 |
+
target_desc,
|
| 451 |
+
objects,
|
| 452 |
+
output_filename,
|
| 453 |
+
output_dir=None,
|
| 454 |
+
libraries=None,
|
| 455 |
+
library_dirs=None,
|
| 456 |
+
runtime_library_dirs=None,
|
| 457 |
+
export_symbols=None,
|
| 458 |
+
debug=0,
|
| 459 |
+
extra_preargs=None,
|
| 460 |
+
extra_postargs=None,
|
| 461 |
+
build_temp=None,
|
| 462 |
+
target_lang=None,
|
| 463 |
+
):
|
| 464 |
+
|
| 465 |
+
if not self.initialized:
|
| 466 |
+
self.initialize()
|
| 467 |
+
objects, output_dir = self._fix_object_args(objects, output_dir)
|
| 468 |
+
fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
|
| 469 |
+
libraries, library_dirs, runtime_library_dirs = fixed_args
|
| 470 |
+
|
| 471 |
+
if runtime_library_dirs:
|
| 472 |
+
self.warn(
|
| 473 |
+
"I don't know what to do with 'runtime_library_dirs': "
|
| 474 |
+
+ str(runtime_library_dirs)
|
| 475 |
+
)
|
| 476 |
+
|
| 477 |
+
lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries)
|
| 478 |
+
if output_dir is not None:
|
| 479 |
+
output_filename = os.path.join(output_dir, output_filename)
|
| 480 |
+
|
| 481 |
+
if self._need_link(objects, output_filename):
|
| 482 |
+
ldflags = self._ldflags[target_desc, debug]
|
| 483 |
+
|
| 484 |
+
export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])]
|
| 485 |
+
|
| 486 |
+
ld_args = (
|
| 487 |
+
ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]
|
| 488 |
+
)
|
| 489 |
+
|
| 490 |
+
# The MSVC linker generates .lib and .exp files, which cannot be
|
| 491 |
+
# suppressed by any linker switches. The .lib files may even be
|
| 492 |
+
# needed! Make sure they are generated in the temporary build
|
| 493 |
+
# directory. Since they have different names for debug and release
|
| 494 |
+
# builds, they can go into the same directory.
|
| 495 |
+
build_temp = os.path.dirname(objects[0])
|
| 496 |
+
if export_symbols is not None:
|
| 497 |
+
(dll_name, dll_ext) = os.path.splitext(
|
| 498 |
+
os.path.basename(output_filename)
|
| 499 |
+
)
|
| 500 |
+
implib_file = os.path.join(build_temp, self.library_filename(dll_name))
|
| 501 |
+
ld_args.append('/IMPLIB:' + implib_file)
|
| 502 |
+
|
| 503 |
+
if extra_preargs:
|
| 504 |
+
ld_args[:0] = extra_preargs
|
| 505 |
+
if extra_postargs:
|
| 506 |
+
ld_args.extend(extra_postargs)
|
| 507 |
+
|
| 508 |
+
output_dir = os.path.dirname(os.path.abspath(output_filename))
|
| 509 |
+
self.mkpath(output_dir)
|
| 510 |
+
try:
|
| 511 |
+
log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args))
|
| 512 |
+
self.spawn([self.linker] + ld_args)
|
| 513 |
+
except DistutilsExecError as msg:
|
| 514 |
+
raise LinkError(msg)
|
| 515 |
+
else:
|
| 516 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 517 |
+
|
| 518 |
+
def spawn(self, cmd):
|
| 519 |
+
env = dict(os.environ, PATH=self._paths)
|
| 520 |
+
with self._fallback_spawn(cmd, env) as fallback:
|
| 521 |
+
return super().spawn(cmd, env=env)
|
| 522 |
+
return fallback.value
|
| 523 |
+
|
| 524 |
+
@contextlib.contextmanager
|
| 525 |
+
def _fallback_spawn(self, cmd, env):
|
| 526 |
+
"""
|
| 527 |
+
Discovered in pypa/distutils#15, some tools monkeypatch the compiler,
|
| 528 |
+
so the 'env' kwarg causes a TypeError. Detect this condition and
|
| 529 |
+
restore the legacy, unsafe behavior.
|
| 530 |
+
"""
|
| 531 |
+
bag = type('Bag', (), {})()
|
| 532 |
+
try:
|
| 533 |
+
yield bag
|
| 534 |
+
except TypeError as exc:
|
| 535 |
+
if "unexpected keyword argument 'env'" not in str(exc):
|
| 536 |
+
raise
|
| 537 |
+
else:
|
| 538 |
+
return
|
| 539 |
+
warnings.warn("Fallback spawn triggered. Please update distutils monkeypatch.")
|
| 540 |
+
with mock.patch.dict('os.environ', env):
|
| 541 |
+
bag.value = super().spawn(cmd)
|
| 542 |
+
|
| 543 |
+
# -- Miscellaneous methods -----------------------------------------
|
| 544 |
+
# These are all used by the 'gen_lib_options() function, in
|
| 545 |
+
# ccompiler.py.
|
| 546 |
+
|
| 547 |
+
def library_dir_option(self, dir):
|
| 548 |
+
return "/LIBPATH:" + dir
|
| 549 |
+
|
| 550 |
+
def runtime_library_dir_option(self, dir):
|
| 551 |
+
raise DistutilsPlatformError(
|
| 552 |
+
"don't know how to set runtime library search path for MSVC"
|
| 553 |
+
)
|
| 554 |
+
|
| 555 |
+
def library_option(self, lib):
|
| 556 |
+
return self.library_filename(lib)
|
| 557 |
+
|
| 558 |
+
def find_library_file(self, dirs, lib, debug=0):
|
| 559 |
+
# Prefer a debugging library if found (and requested), but deal
|
| 560 |
+
# with it if we don't have one.
|
| 561 |
+
if debug:
|
| 562 |
+
try_names = [lib + "_d", lib]
|
| 563 |
+
else:
|
| 564 |
+
try_names = [lib]
|
| 565 |
+
for dir in dirs:
|
| 566 |
+
for name in try_names:
|
| 567 |
+
libfile = os.path.join(dir, self.library_filename(name))
|
| 568 |
+
if os.path.isfile(libfile):
|
| 569 |
+
return libfile
|
| 570 |
+
else:
|
| 571 |
+
# Oops, didn't find it in *any* of 'dirs'
|
| 572 |
+
return None
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/bcppcompiler.py
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.bcppcompiler
|
| 2 |
+
|
| 3 |
+
Contains BorlandCCompiler, an implementation of the abstract CCompiler class
|
| 4 |
+
for the Borland C++ compiler.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
# This implementation by Lyle Johnson, based on the original msvccompiler.py
|
| 8 |
+
# module and using the directions originally published by Gordon Williams.
|
| 9 |
+
|
| 10 |
+
# XXX looks like there's a LOT of overlap between these two classes:
|
| 11 |
+
# someone should sit down and factor out the common code as
|
| 12 |
+
# WindowsCCompiler! --GPW
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
import os
|
| 16 |
+
import warnings
|
| 17 |
+
|
| 18 |
+
from distutils.errors import (
|
| 19 |
+
DistutilsExecError,
|
| 20 |
+
CompileError,
|
| 21 |
+
LibError,
|
| 22 |
+
LinkError,
|
| 23 |
+
UnknownFileError,
|
| 24 |
+
)
|
| 25 |
+
from distutils.ccompiler import CCompiler, gen_preprocess_options
|
| 26 |
+
from distutils.file_util import write_file
|
| 27 |
+
from distutils.dep_util import newer
|
| 28 |
+
from distutils import log
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
warnings.warn(
|
| 32 |
+
"bcppcompiler is deprecated and slated to be removed "
|
| 33 |
+
"in the future. Please discontinue use or file an issue "
|
| 34 |
+
"with pypa/distutils describing your use case.",
|
| 35 |
+
DeprecationWarning,
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
class BCPPCompiler(CCompiler):
|
| 40 |
+
"""Concrete class that implements an interface to the Borland C/C++
|
| 41 |
+
compiler, as defined by the CCompiler abstract class.
|
| 42 |
+
"""
|
| 43 |
+
|
| 44 |
+
compiler_type = 'bcpp'
|
| 45 |
+
|
| 46 |
+
# Just set this so CCompiler's constructor doesn't barf. We currently
|
| 47 |
+
# don't use the 'set_executables()' bureaucracy provided by CCompiler,
|
| 48 |
+
# as it really isn't necessary for this sort of single-compiler class.
|
| 49 |
+
# Would be nice to have a consistent interface with UnixCCompiler,
|
| 50 |
+
# though, so it's worth thinking about.
|
| 51 |
+
executables = {}
|
| 52 |
+
|
| 53 |
+
# Private class data (need to distinguish C from C++ source for compiler)
|
| 54 |
+
_c_extensions = ['.c']
|
| 55 |
+
_cpp_extensions = ['.cc', '.cpp', '.cxx']
|
| 56 |
+
|
| 57 |
+
# Needed for the filename generation methods provided by the
|
| 58 |
+
# base class, CCompiler.
|
| 59 |
+
src_extensions = _c_extensions + _cpp_extensions
|
| 60 |
+
obj_extension = '.obj'
|
| 61 |
+
static_lib_extension = '.lib'
|
| 62 |
+
shared_lib_extension = '.dll'
|
| 63 |
+
static_lib_format = shared_lib_format = '%s%s'
|
| 64 |
+
exe_extension = '.exe'
|
| 65 |
+
|
| 66 |
+
def __init__(self, verbose=0, dry_run=0, force=0):
|
| 67 |
+
|
| 68 |
+
super().__init__(verbose, dry_run, force)
|
| 69 |
+
|
| 70 |
+
# These executables are assumed to all be in the path.
|
| 71 |
+
# Borland doesn't seem to use any special registry settings to
|
| 72 |
+
# indicate their installation locations.
|
| 73 |
+
|
| 74 |
+
self.cc = "bcc32.exe"
|
| 75 |
+
self.linker = "ilink32.exe"
|
| 76 |
+
self.lib = "tlib.exe"
|
| 77 |
+
|
| 78 |
+
self.preprocess_options = None
|
| 79 |
+
self.compile_options = ['/tWM', '/O2', '/q', '/g0']
|
| 80 |
+
self.compile_options_debug = ['/tWM', '/Od', '/q', '/g0']
|
| 81 |
+
|
| 82 |
+
self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x']
|
| 83 |
+
self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x']
|
| 84 |
+
self.ldflags_static = []
|
| 85 |
+
self.ldflags_exe = ['/Gn', '/q', '/x']
|
| 86 |
+
self.ldflags_exe_debug = ['/Gn', '/q', '/x', '/r']
|
| 87 |
+
|
| 88 |
+
# -- Worker methods ------------------------------------------------
|
| 89 |
+
|
| 90 |
+
def compile( # noqa: C901
|
| 91 |
+
self,
|
| 92 |
+
sources,
|
| 93 |
+
output_dir=None,
|
| 94 |
+
macros=None,
|
| 95 |
+
include_dirs=None,
|
| 96 |
+
debug=0,
|
| 97 |
+
extra_preargs=None,
|
| 98 |
+
extra_postargs=None,
|
| 99 |
+
depends=None,
|
| 100 |
+
):
|
| 101 |
+
|
| 102 |
+
macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
|
| 103 |
+
output_dir, macros, include_dirs, sources, depends, extra_postargs
|
| 104 |
+
)
|
| 105 |
+
compile_opts = extra_preargs or []
|
| 106 |
+
compile_opts.append('-c')
|
| 107 |
+
if debug:
|
| 108 |
+
compile_opts.extend(self.compile_options_debug)
|
| 109 |
+
else:
|
| 110 |
+
compile_opts.extend(self.compile_options)
|
| 111 |
+
|
| 112 |
+
for obj in objects:
|
| 113 |
+
try:
|
| 114 |
+
src, ext = build[obj]
|
| 115 |
+
except KeyError:
|
| 116 |
+
continue
|
| 117 |
+
# XXX why do the normpath here?
|
| 118 |
+
src = os.path.normpath(src)
|
| 119 |
+
obj = os.path.normpath(obj)
|
| 120 |
+
# XXX _setup_compile() did a mkpath() too but before the normpath.
|
| 121 |
+
# Is it possible to skip the normpath?
|
| 122 |
+
self.mkpath(os.path.dirname(obj))
|
| 123 |
+
|
| 124 |
+
if ext == '.res':
|
| 125 |
+
# This is already a binary file -- skip it.
|
| 126 |
+
continue # the 'for' loop
|
| 127 |
+
if ext == '.rc':
|
| 128 |
+
# This needs to be compiled to a .res file -- do it now.
|
| 129 |
+
try:
|
| 130 |
+
self.spawn(["brcc32", "-fo", obj, src])
|
| 131 |
+
except DistutilsExecError as msg:
|
| 132 |
+
raise CompileError(msg)
|
| 133 |
+
continue # the 'for' loop
|
| 134 |
+
|
| 135 |
+
# The next two are both for the real compiler.
|
| 136 |
+
if ext in self._c_extensions:
|
| 137 |
+
input_opt = ""
|
| 138 |
+
elif ext in self._cpp_extensions:
|
| 139 |
+
input_opt = "-P"
|
| 140 |
+
else:
|
| 141 |
+
# Unknown file type -- no extra options. The compiler
|
| 142 |
+
# will probably fail, but let it just in case this is a
|
| 143 |
+
# file the compiler recognizes even if we don't.
|
| 144 |
+
input_opt = ""
|
| 145 |
+
|
| 146 |
+
output_opt = "-o" + obj
|
| 147 |
+
|
| 148 |
+
# Compiler command line syntax is: "bcc32 [options] file(s)".
|
| 149 |
+
# Note that the source file names must appear at the end of
|
| 150 |
+
# the command line.
|
| 151 |
+
try:
|
| 152 |
+
self.spawn(
|
| 153 |
+
[self.cc]
|
| 154 |
+
+ compile_opts
|
| 155 |
+
+ pp_opts
|
| 156 |
+
+ [input_opt, output_opt]
|
| 157 |
+
+ extra_postargs
|
| 158 |
+
+ [src]
|
| 159 |
+
)
|
| 160 |
+
except DistutilsExecError as msg:
|
| 161 |
+
raise CompileError(msg)
|
| 162 |
+
|
| 163 |
+
return objects
|
| 164 |
+
|
| 165 |
+
# compile ()
|
| 166 |
+
|
| 167 |
+
def create_static_lib(
|
| 168 |
+
self, objects, output_libname, output_dir=None, debug=0, target_lang=None
|
| 169 |
+
):
|
| 170 |
+
|
| 171 |
+
(objects, output_dir) = self._fix_object_args(objects, output_dir)
|
| 172 |
+
output_filename = self.library_filename(output_libname, output_dir=output_dir)
|
| 173 |
+
|
| 174 |
+
if self._need_link(objects, output_filename):
|
| 175 |
+
lib_args = [output_filename, '/u'] + objects
|
| 176 |
+
if debug:
|
| 177 |
+
pass # XXX what goes here?
|
| 178 |
+
try:
|
| 179 |
+
self.spawn([self.lib] + lib_args)
|
| 180 |
+
except DistutilsExecError as msg:
|
| 181 |
+
raise LibError(msg)
|
| 182 |
+
else:
|
| 183 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 184 |
+
|
| 185 |
+
# create_static_lib ()
|
| 186 |
+
|
| 187 |
+
def link( # noqa: C901
|
| 188 |
+
self,
|
| 189 |
+
target_desc,
|
| 190 |
+
objects,
|
| 191 |
+
output_filename,
|
| 192 |
+
output_dir=None,
|
| 193 |
+
libraries=None,
|
| 194 |
+
library_dirs=None,
|
| 195 |
+
runtime_library_dirs=None,
|
| 196 |
+
export_symbols=None,
|
| 197 |
+
debug=0,
|
| 198 |
+
extra_preargs=None,
|
| 199 |
+
extra_postargs=None,
|
| 200 |
+
build_temp=None,
|
| 201 |
+
target_lang=None,
|
| 202 |
+
):
|
| 203 |
+
|
| 204 |
+
# XXX this ignores 'build_temp'! should follow the lead of
|
| 205 |
+
# msvccompiler.py
|
| 206 |
+
|
| 207 |
+
(objects, output_dir) = self._fix_object_args(objects, output_dir)
|
| 208 |
+
(libraries, library_dirs, runtime_library_dirs) = self._fix_lib_args(
|
| 209 |
+
libraries, library_dirs, runtime_library_dirs
|
| 210 |
+
)
|
| 211 |
+
|
| 212 |
+
if runtime_library_dirs:
|
| 213 |
+
log.warn(
|
| 214 |
+
"I don't know what to do with 'runtime_library_dirs': %s",
|
| 215 |
+
str(runtime_library_dirs),
|
| 216 |
+
)
|
| 217 |
+
|
| 218 |
+
if output_dir is not None:
|
| 219 |
+
output_filename = os.path.join(output_dir, output_filename)
|
| 220 |
+
|
| 221 |
+
if self._need_link(objects, output_filename):
|
| 222 |
+
|
| 223 |
+
# Figure out linker args based on type of target.
|
| 224 |
+
if target_desc == CCompiler.EXECUTABLE:
|
| 225 |
+
startup_obj = 'c0w32'
|
| 226 |
+
if debug:
|
| 227 |
+
ld_args = self.ldflags_exe_debug[:]
|
| 228 |
+
else:
|
| 229 |
+
ld_args = self.ldflags_exe[:]
|
| 230 |
+
else:
|
| 231 |
+
startup_obj = 'c0d32'
|
| 232 |
+
if debug:
|
| 233 |
+
ld_args = self.ldflags_shared_debug[:]
|
| 234 |
+
else:
|
| 235 |
+
ld_args = self.ldflags_shared[:]
|
| 236 |
+
|
| 237 |
+
# Create a temporary exports file for use by the linker
|
| 238 |
+
if export_symbols is None:
|
| 239 |
+
def_file = ''
|
| 240 |
+
else:
|
| 241 |
+
head, tail = os.path.split(output_filename)
|
| 242 |
+
modname, ext = os.path.splitext(tail)
|
| 243 |
+
temp_dir = os.path.dirname(objects[0]) # preserve tree structure
|
| 244 |
+
def_file = os.path.join(temp_dir, '%s.def' % modname)
|
| 245 |
+
contents = ['EXPORTS']
|
| 246 |
+
for sym in export_symbols or []:
|
| 247 |
+
contents.append(' {}=_{}'.format(sym, sym))
|
| 248 |
+
self.execute(write_file, (def_file, contents), "writing %s" % def_file)
|
| 249 |
+
|
| 250 |
+
# Borland C++ has problems with '/' in paths
|
| 251 |
+
objects2 = map(os.path.normpath, objects)
|
| 252 |
+
# split objects in .obj and .res files
|
| 253 |
+
# Borland C++ needs them at different positions in the command line
|
| 254 |
+
objects = [startup_obj]
|
| 255 |
+
resources = []
|
| 256 |
+
for file in objects2:
|
| 257 |
+
(base, ext) = os.path.splitext(os.path.normcase(file))
|
| 258 |
+
if ext == '.res':
|
| 259 |
+
resources.append(file)
|
| 260 |
+
else:
|
| 261 |
+
objects.append(file)
|
| 262 |
+
|
| 263 |
+
for ell in library_dirs:
|
| 264 |
+
ld_args.append("/L%s" % os.path.normpath(ell))
|
| 265 |
+
ld_args.append("/L.") # we sometimes use relative paths
|
| 266 |
+
|
| 267 |
+
# list of object files
|
| 268 |
+
ld_args.extend(objects)
|
| 269 |
+
|
| 270 |
+
# XXX the command-line syntax for Borland C++ is a bit wonky;
|
| 271 |
+
# certain filenames are jammed together in one big string, but
|
| 272 |
+
# comma-delimited. This doesn't mesh too well with the
|
| 273 |
+
# Unix-centric attitude (with a DOS/Windows quoting hack) of
|
| 274 |
+
# 'spawn()', so constructing the argument list is a bit
|
| 275 |
+
# awkward. Note that doing the obvious thing and jamming all
|
| 276 |
+
# the filenames and commas into one argument would be wrong,
|
| 277 |
+
# because 'spawn()' would quote any filenames with spaces in
|
| 278 |
+
# them. Arghghh!. Apparently it works fine as coded...
|
| 279 |
+
|
| 280 |
+
# name of dll/exe file
|
| 281 |
+
ld_args.extend([',', output_filename])
|
| 282 |
+
# no map file and start libraries
|
| 283 |
+
ld_args.append(',,')
|
| 284 |
+
|
| 285 |
+
for lib in libraries:
|
| 286 |
+
# see if we find it and if there is a bcpp specific lib
|
| 287 |
+
# (xxx_bcpp.lib)
|
| 288 |
+
libfile = self.find_library_file(library_dirs, lib, debug)
|
| 289 |
+
if libfile is None:
|
| 290 |
+
ld_args.append(lib)
|
| 291 |
+
# probably a BCPP internal library -- don't warn
|
| 292 |
+
else:
|
| 293 |
+
# full name which prefers bcpp_xxx.lib over xxx.lib
|
| 294 |
+
ld_args.append(libfile)
|
| 295 |
+
|
| 296 |
+
# some default libraries
|
| 297 |
+
ld_args.append('import32')
|
| 298 |
+
ld_args.append('cw32mt')
|
| 299 |
+
|
| 300 |
+
# def file for export symbols
|
| 301 |
+
ld_args.extend([',', def_file])
|
| 302 |
+
# add resource files
|
| 303 |
+
ld_args.append(',')
|
| 304 |
+
ld_args.extend(resources)
|
| 305 |
+
|
| 306 |
+
if extra_preargs:
|
| 307 |
+
ld_args[:0] = extra_preargs
|
| 308 |
+
if extra_postargs:
|
| 309 |
+
ld_args.extend(extra_postargs)
|
| 310 |
+
|
| 311 |
+
self.mkpath(os.path.dirname(output_filename))
|
| 312 |
+
try:
|
| 313 |
+
self.spawn([self.linker] + ld_args)
|
| 314 |
+
except DistutilsExecError as msg:
|
| 315 |
+
raise LinkError(msg)
|
| 316 |
+
|
| 317 |
+
else:
|
| 318 |
+
log.debug("skipping %s (up-to-date)", output_filename)
|
| 319 |
+
|
| 320 |
+
# link ()
|
| 321 |
+
|
| 322 |
+
# -- Miscellaneous methods -----------------------------------------
|
| 323 |
+
|
| 324 |
+
def find_library_file(self, dirs, lib, debug=0):
|
| 325 |
+
# List of effective library names to try, in order of preference:
|
| 326 |
+
# xxx_bcpp.lib is better than xxx.lib
|
| 327 |
+
# and xxx_d.lib is better than xxx.lib if debug is set
|
| 328 |
+
#
|
| 329 |
+
# The "_bcpp" suffix is to handle a Python installation for people
|
| 330 |
+
# with multiple compilers (primarily Distutils hackers, I suspect
|
| 331 |
+
# ;-). The idea is they'd have one static library for each
|
| 332 |
+
# compiler they care about, since (almost?) every Windows compiler
|
| 333 |
+
# seems to have a different format for static libraries.
|
| 334 |
+
if debug:
|
| 335 |
+
dlib = lib + "_d"
|
| 336 |
+
try_names = (dlib + "_bcpp", lib + "_bcpp", dlib, lib)
|
| 337 |
+
else:
|
| 338 |
+
try_names = (lib + "_bcpp", lib)
|
| 339 |
+
|
| 340 |
+
for dir in dirs:
|
| 341 |
+
for name in try_names:
|
| 342 |
+
libfile = os.path.join(dir, self.library_filename(name))
|
| 343 |
+
if os.path.exists(libfile):
|
| 344 |
+
return libfile
|
| 345 |
+
else:
|
| 346 |
+
# Oops, didn't find it in *any* of 'dirs'
|
| 347 |
+
return None
|
| 348 |
+
|
| 349 |
+
# overwrite the one from CCompiler to support rc and res-files
|
| 350 |
+
def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
|
| 351 |
+
if output_dir is None:
|
| 352 |
+
output_dir = ''
|
| 353 |
+
obj_names = []
|
| 354 |
+
for src_name in source_filenames:
|
| 355 |
+
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
|
| 356 |
+
(base, ext) = os.path.splitext(os.path.normcase(src_name))
|
| 357 |
+
if ext not in (self.src_extensions + ['.rc', '.res']):
|
| 358 |
+
raise UnknownFileError(
|
| 359 |
+
"unknown file type '{}' (from '{}')".format(ext, src_name)
|
| 360 |
+
)
|
| 361 |
+
if strip_dir:
|
| 362 |
+
base = os.path.basename(base)
|
| 363 |
+
if ext == '.res':
|
| 364 |
+
# these can go unchanged
|
| 365 |
+
obj_names.append(os.path.join(output_dir, base + ext))
|
| 366 |
+
elif ext == '.rc':
|
| 367 |
+
# these need to be compiled to .res-files
|
| 368 |
+
obj_names.append(os.path.join(output_dir, base + '.res'))
|
| 369 |
+
else:
|
| 370 |
+
obj_names.append(os.path.join(output_dir, base + self.obj_extension))
|
| 371 |
+
return obj_names
|
| 372 |
+
|
| 373 |
+
# object_filenames ()
|
| 374 |
+
|
| 375 |
+
def preprocess(
|
| 376 |
+
self,
|
| 377 |
+
source,
|
| 378 |
+
output_file=None,
|
| 379 |
+
macros=None,
|
| 380 |
+
include_dirs=None,
|
| 381 |
+
extra_preargs=None,
|
| 382 |
+
extra_postargs=None,
|
| 383 |
+
):
|
| 384 |
+
|
| 385 |
+
(_, macros, include_dirs) = self._fix_compile_args(None, macros, include_dirs)
|
| 386 |
+
pp_opts = gen_preprocess_options(macros, include_dirs)
|
| 387 |
+
pp_args = ['cpp32.exe'] + pp_opts
|
| 388 |
+
if output_file is not None:
|
| 389 |
+
pp_args.append('-o' + output_file)
|
| 390 |
+
if extra_preargs:
|
| 391 |
+
pp_args[:0] = extra_preargs
|
| 392 |
+
if extra_postargs:
|
| 393 |
+
pp_args.extend(extra_postargs)
|
| 394 |
+
pp_args.append(source)
|
| 395 |
+
|
| 396 |
+
# We need to preprocess: either we're being forced to, or the
|
| 397 |
+
# source file is newer than the target (or the target doesn't
|
| 398 |
+
# exist).
|
| 399 |
+
if self.force or output_file is None or newer(source, output_file):
|
| 400 |
+
if output_file:
|
| 401 |
+
self.mkpath(os.path.dirname(output_file))
|
| 402 |
+
try:
|
| 403 |
+
self.spawn(pp_args)
|
| 404 |
+
except DistutilsExecError as msg:
|
| 405 |
+
print(msg)
|
| 406 |
+
raise CompileError(msg)
|
| 407 |
+
|
| 408 |
+
# preprocess()
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/ccompiler.py
ADDED
|
@@ -0,0 +1,1220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.ccompiler
|
| 2 |
+
|
| 3 |
+
Contains CCompiler, an abstract base class that defines the interface
|
| 4 |
+
for the Distutils compiler abstraction model."""
|
| 5 |
+
|
| 6 |
+
import sys
|
| 7 |
+
import os
|
| 8 |
+
import re
|
| 9 |
+
|
| 10 |
+
from distutils.errors import (
|
| 11 |
+
CompileError,
|
| 12 |
+
LinkError,
|
| 13 |
+
UnknownFileError,
|
| 14 |
+
DistutilsPlatformError,
|
| 15 |
+
DistutilsModuleError,
|
| 16 |
+
)
|
| 17 |
+
from distutils.spawn import spawn
|
| 18 |
+
from distutils.file_util import move_file
|
| 19 |
+
from distutils.dir_util import mkpath
|
| 20 |
+
from distutils.dep_util import newer_group
|
| 21 |
+
from distutils.util import split_quoted, execute
|
| 22 |
+
from distutils import log
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class CCompiler:
|
| 26 |
+
"""Abstract base class to define the interface that must be implemented
|
| 27 |
+
by real compiler classes. Also has some utility methods used by
|
| 28 |
+
several compiler classes.
|
| 29 |
+
|
| 30 |
+
The basic idea behind a compiler abstraction class is that each
|
| 31 |
+
instance can be used for all the compile/link steps in building a
|
| 32 |
+
single project. Thus, attributes common to all of those compile and
|
| 33 |
+
link steps -- include directories, macros to define, libraries to link
|
| 34 |
+
against, etc. -- are attributes of the compiler instance. To allow for
|
| 35 |
+
variability in how individual files are treated, most of those
|
| 36 |
+
attributes may be varied on a per-compilation or per-link basis.
|
| 37 |
+
"""
|
| 38 |
+
|
| 39 |
+
# 'compiler_type' is a class attribute that identifies this class. It
|
| 40 |
+
# keeps code that wants to know what kind of compiler it's dealing with
|
| 41 |
+
# from having to import all possible compiler classes just to do an
|
| 42 |
+
# 'isinstance'. In concrete CCompiler subclasses, 'compiler_type'
|
| 43 |
+
# should really, really be one of the keys of the 'compiler_class'
|
| 44 |
+
# dictionary (see below -- used by the 'new_compiler()' factory
|
| 45 |
+
# function) -- authors of new compiler interface classes are
|
| 46 |
+
# responsible for updating 'compiler_class'!
|
| 47 |
+
compiler_type = None
|
| 48 |
+
|
| 49 |
+
# XXX things not handled by this compiler abstraction model:
|
| 50 |
+
# * client can't provide additional options for a compiler,
|
| 51 |
+
# e.g. warning, optimization, debugging flags. Perhaps this
|
| 52 |
+
# should be the domain of concrete compiler abstraction classes
|
| 53 |
+
# (UnixCCompiler, MSVCCompiler, etc.) -- or perhaps the base
|
| 54 |
+
# class should have methods for the common ones.
|
| 55 |
+
# * can't completely override the include or library searchg
|
| 56 |
+
# path, ie. no "cc -I -Idir1 -Idir2" or "cc -L -Ldir1 -Ldir2".
|
| 57 |
+
# I'm not sure how widely supported this is even by Unix
|
| 58 |
+
# compilers, much less on other platforms. And I'm even less
|
| 59 |
+
# sure how useful it is; maybe for cross-compiling, but
|
| 60 |
+
# support for that is a ways off. (And anyways, cross
|
| 61 |
+
# compilers probably have a dedicated binary with the
|
| 62 |
+
# right paths compiled in. I hope.)
|
| 63 |
+
# * can't do really freaky things with the library list/library
|
| 64 |
+
# dirs, e.g. "-Ldir1 -lfoo -Ldir2 -lfoo" to link against
|
| 65 |
+
# different versions of libfoo.a in different locations. I
|
| 66 |
+
# think this is useless without the ability to null out the
|
| 67 |
+
# library search path anyways.
|
| 68 |
+
|
| 69 |
+
# Subclasses that rely on the standard filename generation methods
|
| 70 |
+
# implemented below should override these; see the comment near
|
| 71 |
+
# those methods ('object_filenames()' et. al.) for details:
|
| 72 |
+
src_extensions = None # list of strings
|
| 73 |
+
obj_extension = None # string
|
| 74 |
+
static_lib_extension = None
|
| 75 |
+
shared_lib_extension = None # string
|
| 76 |
+
static_lib_format = None # format string
|
| 77 |
+
shared_lib_format = None # prob. same as static_lib_format
|
| 78 |
+
exe_extension = None # string
|
| 79 |
+
|
| 80 |
+
# Default language settings. language_map is used to detect a source
|
| 81 |
+
# file or Extension target language, checking source filenames.
|
| 82 |
+
# language_order is used to detect the language precedence, when deciding
|
| 83 |
+
# what language to use when mixing source types. For example, if some
|
| 84 |
+
# extension has two files with ".c" extension, and one with ".cpp", it
|
| 85 |
+
# is still linked as c++.
|
| 86 |
+
language_map = {
|
| 87 |
+
".c": "c",
|
| 88 |
+
".cc": "c++",
|
| 89 |
+
".cpp": "c++",
|
| 90 |
+
".cxx": "c++",
|
| 91 |
+
".m": "objc",
|
| 92 |
+
}
|
| 93 |
+
language_order = ["c++", "objc", "c"]
|
| 94 |
+
|
| 95 |
+
include_dirs = []
|
| 96 |
+
"""
|
| 97 |
+
include dirs specific to this compiler class
|
| 98 |
+
"""
|
| 99 |
+
|
| 100 |
+
library_dirs = []
|
| 101 |
+
"""
|
| 102 |
+
library dirs specific to this compiler class
|
| 103 |
+
"""
|
| 104 |
+
|
| 105 |
+
def __init__(self, verbose=0, dry_run=0, force=0):
|
| 106 |
+
self.dry_run = dry_run
|
| 107 |
+
self.force = force
|
| 108 |
+
self.verbose = verbose
|
| 109 |
+
|
| 110 |
+
# 'output_dir': a common output directory for object, library,
|
| 111 |
+
# shared object, and shared library files
|
| 112 |
+
self.output_dir = None
|
| 113 |
+
|
| 114 |
+
# 'macros': a list of macro definitions (or undefinitions). A
|
| 115 |
+
# macro definition is a 2-tuple (name, value), where the value is
|
| 116 |
+
# either a string or None (no explicit value). A macro
|
| 117 |
+
# undefinition is a 1-tuple (name,).
|
| 118 |
+
self.macros = []
|
| 119 |
+
|
| 120 |
+
# 'include_dirs': a list of directories to search for include files
|
| 121 |
+
self.include_dirs = []
|
| 122 |
+
|
| 123 |
+
# 'libraries': a list of libraries to include in any link
|
| 124 |
+
# (library names, not filenames: eg. "foo" not "libfoo.a")
|
| 125 |
+
self.libraries = []
|
| 126 |
+
|
| 127 |
+
# 'library_dirs': a list of directories to search for libraries
|
| 128 |
+
self.library_dirs = []
|
| 129 |
+
|
| 130 |
+
# 'runtime_library_dirs': a list of directories to search for
|
| 131 |
+
# shared libraries/objects at runtime
|
| 132 |
+
self.runtime_library_dirs = []
|
| 133 |
+
|
| 134 |
+
# 'objects': a list of object files (or similar, such as explicitly
|
| 135 |
+
# named library files) to include on any link
|
| 136 |
+
self.objects = []
|
| 137 |
+
|
| 138 |
+
for key in self.executables.keys():
|
| 139 |
+
self.set_executable(key, self.executables[key])
|
| 140 |
+
|
| 141 |
+
def set_executables(self, **kwargs):
|
| 142 |
+
"""Define the executables (and options for them) that will be run
|
| 143 |
+
to perform the various stages of compilation. The exact set of
|
| 144 |
+
executables that may be specified here depends on the compiler
|
| 145 |
+
class (via the 'executables' class attribute), but most will have:
|
| 146 |
+
compiler the C/C++ compiler
|
| 147 |
+
linker_so linker used to create shared objects and libraries
|
| 148 |
+
linker_exe linker used to create binary executables
|
| 149 |
+
archiver static library creator
|
| 150 |
+
|
| 151 |
+
On platforms with a command-line (Unix, DOS/Windows), each of these
|
| 152 |
+
is a string that will be split into executable name and (optional)
|
| 153 |
+
list of arguments. (Splitting the string is done similarly to how
|
| 154 |
+
Unix shells operate: words are delimited by spaces, but quotes and
|
| 155 |
+
backslashes can override this. See
|
| 156 |
+
'distutils.util.split_quoted()'.)
|
| 157 |
+
"""
|
| 158 |
+
|
| 159 |
+
# Note that some CCompiler implementation classes will define class
|
| 160 |
+
# attributes 'cpp', 'cc', etc. with hard-coded executable names;
|
| 161 |
+
# this is appropriate when a compiler class is for exactly one
|
| 162 |
+
# compiler/OS combination (eg. MSVCCompiler). Other compiler
|
| 163 |
+
# classes (UnixCCompiler, in particular) are driven by information
|
| 164 |
+
# discovered at run-time, since there are many different ways to do
|
| 165 |
+
# basically the same things with Unix C compilers.
|
| 166 |
+
|
| 167 |
+
for key in kwargs:
|
| 168 |
+
if key not in self.executables:
|
| 169 |
+
raise ValueError(
|
| 170 |
+
"unknown executable '%s' for class %s"
|
| 171 |
+
% (key, self.__class__.__name__)
|
| 172 |
+
)
|
| 173 |
+
self.set_executable(key, kwargs[key])
|
| 174 |
+
|
| 175 |
+
def set_executable(self, key, value):
|
| 176 |
+
if isinstance(value, str):
|
| 177 |
+
setattr(self, key, split_quoted(value))
|
| 178 |
+
else:
|
| 179 |
+
setattr(self, key, value)
|
| 180 |
+
|
| 181 |
+
def _find_macro(self, name):
|
| 182 |
+
i = 0
|
| 183 |
+
for defn in self.macros:
|
| 184 |
+
if defn[0] == name:
|
| 185 |
+
return i
|
| 186 |
+
i += 1
|
| 187 |
+
return None
|
| 188 |
+
|
| 189 |
+
def _check_macro_definitions(self, definitions):
|
| 190 |
+
"""Ensures that every element of 'definitions' is a valid macro
|
| 191 |
+
definition, ie. either (name,value) 2-tuple or a (name,) tuple. Do
|
| 192 |
+
nothing if all definitions are OK, raise TypeError otherwise.
|
| 193 |
+
"""
|
| 194 |
+
for defn in definitions:
|
| 195 |
+
if not (
|
| 196 |
+
isinstance(defn, tuple)
|
| 197 |
+
and (
|
| 198 |
+
len(defn) in (1, 2)
|
| 199 |
+
and (isinstance(defn[1], str) or defn[1] is None)
|
| 200 |
+
)
|
| 201 |
+
and isinstance(defn[0], str)
|
| 202 |
+
):
|
| 203 |
+
raise TypeError(
|
| 204 |
+
("invalid macro definition '%s': " % defn)
|
| 205 |
+
+ "must be tuple (string,), (string, string), or "
|
| 206 |
+
+ "(string, None)"
|
| 207 |
+
)
|
| 208 |
+
|
| 209 |
+
# -- Bookkeeping methods -------------------------------------------
|
| 210 |
+
|
| 211 |
+
def define_macro(self, name, value=None):
|
| 212 |
+
"""Define a preprocessor macro for all compilations driven by this
|
| 213 |
+
compiler object. The optional parameter 'value' should be a
|
| 214 |
+
string; if it is not supplied, then the macro will be defined
|
| 215 |
+
without an explicit value and the exact outcome depends on the
|
| 216 |
+
compiler used (XXX true? does ANSI say anything about this?)
|
| 217 |
+
"""
|
| 218 |
+
# Delete from the list of macro definitions/undefinitions if
|
| 219 |
+
# already there (so that this one will take precedence).
|
| 220 |
+
i = self._find_macro(name)
|
| 221 |
+
if i is not None:
|
| 222 |
+
del self.macros[i]
|
| 223 |
+
|
| 224 |
+
self.macros.append((name, value))
|
| 225 |
+
|
| 226 |
+
def undefine_macro(self, name):
|
| 227 |
+
"""Undefine a preprocessor macro for all compilations driven by
|
| 228 |
+
this compiler object. If the same macro is defined by
|
| 229 |
+
'define_macro()' and undefined by 'undefine_macro()' the last call
|
| 230 |
+
takes precedence (including multiple redefinitions or
|
| 231 |
+
undefinitions). If the macro is redefined/undefined on a
|
| 232 |
+
per-compilation basis (ie. in the call to 'compile()'), then that
|
| 233 |
+
takes precedence.
|
| 234 |
+
"""
|
| 235 |
+
# Delete from the list of macro definitions/undefinitions if
|
| 236 |
+
# already there (so that this one will take precedence).
|
| 237 |
+
i = self._find_macro(name)
|
| 238 |
+
if i is not None:
|
| 239 |
+
del self.macros[i]
|
| 240 |
+
|
| 241 |
+
undefn = (name,)
|
| 242 |
+
self.macros.append(undefn)
|
| 243 |
+
|
| 244 |
+
def add_include_dir(self, dir):
|
| 245 |
+
"""Add 'dir' to the list of directories that will be searched for
|
| 246 |
+
header files. The compiler is instructed to search directories in
|
| 247 |
+
the order in which they are supplied by successive calls to
|
| 248 |
+
'add_include_dir()'.
|
| 249 |
+
"""
|
| 250 |
+
self.include_dirs.append(dir)
|
| 251 |
+
|
| 252 |
+
def set_include_dirs(self, dirs):
|
| 253 |
+
"""Set the list of directories that will be searched to 'dirs' (a
|
| 254 |
+
list of strings). Overrides any preceding calls to
|
| 255 |
+
'add_include_dir()'; subsequence calls to 'add_include_dir()' add
|
| 256 |
+
to the list passed to 'set_include_dirs()'. This does not affect
|
| 257 |
+
any list of standard include directories that the compiler may
|
| 258 |
+
search by default.
|
| 259 |
+
"""
|
| 260 |
+
self.include_dirs = dirs[:]
|
| 261 |
+
|
| 262 |
+
def add_library(self, libname):
|
| 263 |
+
"""Add 'libname' to the list of libraries that will be included in
|
| 264 |
+
all links driven by this compiler object. Note that 'libname'
|
| 265 |
+
should *not* be the name of a file containing a library, but the
|
| 266 |
+
name of the library itself: the actual filename will be inferred by
|
| 267 |
+
the linker, the compiler, or the compiler class (depending on the
|
| 268 |
+
platform).
|
| 269 |
+
|
| 270 |
+
The linker will be instructed to link against libraries in the
|
| 271 |
+
order they were supplied to 'add_library()' and/or
|
| 272 |
+
'set_libraries()'. It is perfectly valid to duplicate library
|
| 273 |
+
names; the linker will be instructed to link against libraries as
|
| 274 |
+
many times as they are mentioned.
|
| 275 |
+
"""
|
| 276 |
+
self.libraries.append(libname)
|
| 277 |
+
|
| 278 |
+
def set_libraries(self, libnames):
|
| 279 |
+
"""Set the list of libraries to be included in all links driven by
|
| 280 |
+
this compiler object to 'libnames' (a list of strings). This does
|
| 281 |
+
not affect any standard system libraries that the linker may
|
| 282 |
+
include by default.
|
| 283 |
+
"""
|
| 284 |
+
self.libraries = libnames[:]
|
| 285 |
+
|
| 286 |
+
def add_library_dir(self, dir):
|
| 287 |
+
"""Add 'dir' to the list of directories that will be searched for
|
| 288 |
+
libraries specified to 'add_library()' and 'set_libraries()'. The
|
| 289 |
+
linker will be instructed to search for libraries in the order they
|
| 290 |
+
are supplied to 'add_library_dir()' and/or 'set_library_dirs()'.
|
| 291 |
+
"""
|
| 292 |
+
self.library_dirs.append(dir)
|
| 293 |
+
|
| 294 |
+
def set_library_dirs(self, dirs):
|
| 295 |
+
"""Set the list of library search directories to 'dirs' (a list of
|
| 296 |
+
strings). This does not affect any standard library search path
|
| 297 |
+
that the linker may search by default.
|
| 298 |
+
"""
|
| 299 |
+
self.library_dirs = dirs[:]
|
| 300 |
+
|
| 301 |
+
def add_runtime_library_dir(self, dir):
|
| 302 |
+
"""Add 'dir' to the list of directories that will be searched for
|
| 303 |
+
shared libraries at runtime.
|
| 304 |
+
"""
|
| 305 |
+
self.runtime_library_dirs.append(dir)
|
| 306 |
+
|
| 307 |
+
def set_runtime_library_dirs(self, dirs):
|
| 308 |
+
"""Set the list of directories to search for shared libraries at
|
| 309 |
+
runtime to 'dirs' (a list of strings). This does not affect any
|
| 310 |
+
standard search path that the runtime linker may search by
|
| 311 |
+
default.
|
| 312 |
+
"""
|
| 313 |
+
self.runtime_library_dirs = dirs[:]
|
| 314 |
+
|
| 315 |
+
def add_link_object(self, object):
|
| 316 |
+
"""Add 'object' to the list of object files (or analogues, such as
|
| 317 |
+
explicitly named library files or the output of "resource
|
| 318 |
+
compilers") to be included in every link driven by this compiler
|
| 319 |
+
object.
|
| 320 |
+
"""
|
| 321 |
+
self.objects.append(object)
|
| 322 |
+
|
| 323 |
+
def set_link_objects(self, objects):
|
| 324 |
+
"""Set the list of object files (or analogues) to be included in
|
| 325 |
+
every link to 'objects'. This does not affect any standard object
|
| 326 |
+
files that the linker may include by default (such as system
|
| 327 |
+
libraries).
|
| 328 |
+
"""
|
| 329 |
+
self.objects = objects[:]
|
| 330 |
+
|
| 331 |
+
# -- Private utility methods --------------------------------------
|
| 332 |
+
# (here for the convenience of subclasses)
|
| 333 |
+
|
| 334 |
+
# Helper method to prep compiler in subclass compile() methods
|
| 335 |
+
|
| 336 |
+
def _setup_compile(self, outdir, macros, incdirs, sources, depends, extra):
|
| 337 |
+
"""Process arguments and decide which source files to compile."""
|
| 338 |
+
outdir, macros, incdirs = self._fix_compile_args(outdir, macros, incdirs)
|
| 339 |
+
|
| 340 |
+
if extra is None:
|
| 341 |
+
extra = []
|
| 342 |
+
|
| 343 |
+
# Get the list of expected output (object) files
|
| 344 |
+
objects = self.object_filenames(sources, strip_dir=0, output_dir=outdir)
|
| 345 |
+
assert len(objects) == len(sources)
|
| 346 |
+
|
| 347 |
+
pp_opts = gen_preprocess_options(macros, incdirs)
|
| 348 |
+
|
| 349 |
+
build = {}
|
| 350 |
+
for i in range(len(sources)):
|
| 351 |
+
src = sources[i]
|
| 352 |
+
obj = objects[i]
|
| 353 |
+
ext = os.path.splitext(src)[1]
|
| 354 |
+
self.mkpath(os.path.dirname(obj))
|
| 355 |
+
build[obj] = (src, ext)
|
| 356 |
+
|
| 357 |
+
return macros, objects, extra, pp_opts, build
|
| 358 |
+
|
| 359 |
+
def _get_cc_args(self, pp_opts, debug, before):
|
| 360 |
+
# works for unixccompiler, cygwinccompiler
|
| 361 |
+
cc_args = pp_opts + ['-c']
|
| 362 |
+
if debug:
|
| 363 |
+
cc_args[:0] = ['-g']
|
| 364 |
+
if before:
|
| 365 |
+
cc_args[:0] = before
|
| 366 |
+
return cc_args
|
| 367 |
+
|
| 368 |
+
def _fix_compile_args(self, output_dir, macros, include_dirs):
|
| 369 |
+
"""Typecheck and fix-up some of the arguments to the 'compile()'
|
| 370 |
+
method, and return fixed-up values. Specifically: if 'output_dir'
|
| 371 |
+
is None, replaces it with 'self.output_dir'; ensures that 'macros'
|
| 372 |
+
is a list, and augments it with 'self.macros'; ensures that
|
| 373 |
+
'include_dirs' is a list, and augments it with 'self.include_dirs'.
|
| 374 |
+
Guarantees that the returned values are of the correct type,
|
| 375 |
+
i.e. for 'output_dir' either string or None, and for 'macros' and
|
| 376 |
+
'include_dirs' either list or None.
|
| 377 |
+
"""
|
| 378 |
+
if output_dir is None:
|
| 379 |
+
output_dir = self.output_dir
|
| 380 |
+
elif not isinstance(output_dir, str):
|
| 381 |
+
raise TypeError("'output_dir' must be a string or None")
|
| 382 |
+
|
| 383 |
+
if macros is None:
|
| 384 |
+
macros = self.macros
|
| 385 |
+
elif isinstance(macros, list):
|
| 386 |
+
macros = macros + (self.macros or [])
|
| 387 |
+
else:
|
| 388 |
+
raise TypeError("'macros' (if supplied) must be a list of tuples")
|
| 389 |
+
|
| 390 |
+
if include_dirs is None:
|
| 391 |
+
include_dirs = self.include_dirs
|
| 392 |
+
elif isinstance(include_dirs, (list, tuple)):
|
| 393 |
+
include_dirs = list(include_dirs) + (self.include_dirs or [])
|
| 394 |
+
else:
|
| 395 |
+
raise TypeError("'include_dirs' (if supplied) must be a list of strings")
|
| 396 |
+
|
| 397 |
+
# add include dirs for class
|
| 398 |
+
include_dirs += self.__class__.include_dirs
|
| 399 |
+
|
| 400 |
+
return output_dir, macros, include_dirs
|
| 401 |
+
|
| 402 |
+
def _prep_compile(self, sources, output_dir, depends=None):
|
| 403 |
+
"""Decide which source files must be recompiled.
|
| 404 |
+
|
| 405 |
+
Determine the list of object files corresponding to 'sources',
|
| 406 |
+
and figure out which ones really need to be recompiled.
|
| 407 |
+
Return a list of all object files and a dictionary telling
|
| 408 |
+
which source files can be skipped.
|
| 409 |
+
"""
|
| 410 |
+
# Get the list of expected output (object) files
|
| 411 |
+
objects = self.object_filenames(sources, output_dir=output_dir)
|
| 412 |
+
assert len(objects) == len(sources)
|
| 413 |
+
|
| 414 |
+
# Return an empty dict for the "which source files can be skipped"
|
| 415 |
+
# return value to preserve API compatibility.
|
| 416 |
+
return objects, {}
|
| 417 |
+
|
| 418 |
+
def _fix_object_args(self, objects, output_dir):
|
| 419 |
+
"""Typecheck and fix up some arguments supplied to various methods.
|
| 420 |
+
Specifically: ensure that 'objects' is a list; if output_dir is
|
| 421 |
+
None, replace with self.output_dir. Return fixed versions of
|
| 422 |
+
'objects' and 'output_dir'.
|
| 423 |
+
"""
|
| 424 |
+
if not isinstance(objects, (list, tuple)):
|
| 425 |
+
raise TypeError("'objects' must be a list or tuple of strings")
|
| 426 |
+
objects = list(objects)
|
| 427 |
+
|
| 428 |
+
if output_dir is None:
|
| 429 |
+
output_dir = self.output_dir
|
| 430 |
+
elif not isinstance(output_dir, str):
|
| 431 |
+
raise TypeError("'output_dir' must be a string or None")
|
| 432 |
+
|
| 433 |
+
return (objects, output_dir)
|
| 434 |
+
|
| 435 |
+
def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs):
|
| 436 |
+
"""Typecheck and fix up some of the arguments supplied to the
|
| 437 |
+
'link_*' methods. Specifically: ensure that all arguments are
|
| 438 |
+
lists, and augment them with their permanent versions
|
| 439 |
+
(eg. 'self.libraries' augments 'libraries'). Return a tuple with
|
| 440 |
+
fixed versions of all arguments.
|
| 441 |
+
"""
|
| 442 |
+
if libraries is None:
|
| 443 |
+
libraries = self.libraries
|
| 444 |
+
elif isinstance(libraries, (list, tuple)):
|
| 445 |
+
libraries = list(libraries) + (self.libraries or [])
|
| 446 |
+
else:
|
| 447 |
+
raise TypeError("'libraries' (if supplied) must be a list of strings")
|
| 448 |
+
|
| 449 |
+
if library_dirs is None:
|
| 450 |
+
library_dirs = self.library_dirs
|
| 451 |
+
elif isinstance(library_dirs, (list, tuple)):
|
| 452 |
+
library_dirs = list(library_dirs) + (self.library_dirs or [])
|
| 453 |
+
else:
|
| 454 |
+
raise TypeError("'library_dirs' (if supplied) must be a list of strings")
|
| 455 |
+
|
| 456 |
+
# add library dirs for class
|
| 457 |
+
library_dirs += self.__class__.library_dirs
|
| 458 |
+
|
| 459 |
+
if runtime_library_dirs is None:
|
| 460 |
+
runtime_library_dirs = self.runtime_library_dirs
|
| 461 |
+
elif isinstance(runtime_library_dirs, (list, tuple)):
|
| 462 |
+
runtime_library_dirs = list(runtime_library_dirs) + (
|
| 463 |
+
self.runtime_library_dirs or []
|
| 464 |
+
)
|
| 465 |
+
else:
|
| 466 |
+
raise TypeError(
|
| 467 |
+
"'runtime_library_dirs' (if supplied) " "must be a list of strings"
|
| 468 |
+
)
|
| 469 |
+
|
| 470 |
+
return (libraries, library_dirs, runtime_library_dirs)
|
| 471 |
+
|
| 472 |
+
def _need_link(self, objects, output_file):
|
| 473 |
+
"""Return true if we need to relink the files listed in 'objects'
|
| 474 |
+
to recreate 'output_file'.
|
| 475 |
+
"""
|
| 476 |
+
if self.force:
|
| 477 |
+
return True
|
| 478 |
+
else:
|
| 479 |
+
if self.dry_run:
|
| 480 |
+
newer = newer_group(objects, output_file, missing='newer')
|
| 481 |
+
else:
|
| 482 |
+
newer = newer_group(objects, output_file)
|
| 483 |
+
return newer
|
| 484 |
+
|
| 485 |
+
def detect_language(self, sources):
|
| 486 |
+
"""Detect the language of a given file, or list of files. Uses
|
| 487 |
+
language_map, and language_order to do the job.
|
| 488 |
+
"""
|
| 489 |
+
if not isinstance(sources, list):
|
| 490 |
+
sources = [sources]
|
| 491 |
+
lang = None
|
| 492 |
+
index = len(self.language_order)
|
| 493 |
+
for source in sources:
|
| 494 |
+
base, ext = os.path.splitext(source)
|
| 495 |
+
extlang = self.language_map.get(ext)
|
| 496 |
+
try:
|
| 497 |
+
extindex = self.language_order.index(extlang)
|
| 498 |
+
if extindex < index:
|
| 499 |
+
lang = extlang
|
| 500 |
+
index = extindex
|
| 501 |
+
except ValueError:
|
| 502 |
+
pass
|
| 503 |
+
return lang
|
| 504 |
+
|
| 505 |
+
# -- Worker methods ------------------------------------------------
|
| 506 |
+
# (must be implemented by subclasses)
|
| 507 |
+
|
| 508 |
+
def preprocess(
|
| 509 |
+
self,
|
| 510 |
+
source,
|
| 511 |
+
output_file=None,
|
| 512 |
+
macros=None,
|
| 513 |
+
include_dirs=None,
|
| 514 |
+
extra_preargs=None,
|
| 515 |
+
extra_postargs=None,
|
| 516 |
+
):
|
| 517 |
+
"""Preprocess a single C/C++ source file, named in 'source'.
|
| 518 |
+
Output will be written to file named 'output_file', or stdout if
|
| 519 |
+
'output_file' not supplied. 'macros' is a list of macro
|
| 520 |
+
definitions as for 'compile()', which will augment the macros set
|
| 521 |
+
with 'define_macro()' and 'undefine_macro()'. 'include_dirs' is a
|
| 522 |
+
list of directory names that will be added to the default list.
|
| 523 |
+
|
| 524 |
+
Raises PreprocessError on failure.
|
| 525 |
+
"""
|
| 526 |
+
pass
|
| 527 |
+
|
| 528 |
+
def compile(
|
| 529 |
+
self,
|
| 530 |
+
sources,
|
| 531 |
+
output_dir=None,
|
| 532 |
+
macros=None,
|
| 533 |
+
include_dirs=None,
|
| 534 |
+
debug=0,
|
| 535 |
+
extra_preargs=None,
|
| 536 |
+
extra_postargs=None,
|
| 537 |
+
depends=None,
|
| 538 |
+
):
|
| 539 |
+
"""Compile one or more source files.
|
| 540 |
+
|
| 541 |
+
'sources' must be a list of filenames, most likely C/C++
|
| 542 |
+
files, but in reality anything that can be handled by a
|
| 543 |
+
particular compiler and compiler class (eg. MSVCCompiler can
|
| 544 |
+
handle resource files in 'sources'). Return a list of object
|
| 545 |
+
filenames, one per source filename in 'sources'. Depending on
|
| 546 |
+
the implementation, not all source files will necessarily be
|
| 547 |
+
compiled, but all corresponding object filenames will be
|
| 548 |
+
returned.
|
| 549 |
+
|
| 550 |
+
If 'output_dir' is given, object files will be put under it, while
|
| 551 |
+
retaining their original path component. That is, "foo/bar.c"
|
| 552 |
+
normally compiles to "foo/bar.o" (for a Unix implementation); if
|
| 553 |
+
'output_dir' is "build", then it would compile to
|
| 554 |
+
"build/foo/bar.o".
|
| 555 |
+
|
| 556 |
+
'macros', if given, must be a list of macro definitions. A macro
|
| 557 |
+
definition is either a (name, value) 2-tuple or a (name,) 1-tuple.
|
| 558 |
+
The former defines a macro; if the value is None, the macro is
|
| 559 |
+
defined without an explicit value. The 1-tuple case undefines a
|
| 560 |
+
macro. Later definitions/redefinitions/ undefinitions take
|
| 561 |
+
precedence.
|
| 562 |
+
|
| 563 |
+
'include_dirs', if given, must be a list of strings, the
|
| 564 |
+
directories to add to the default include file search path for this
|
| 565 |
+
compilation only.
|
| 566 |
+
|
| 567 |
+
'debug' is a boolean; if true, the compiler will be instructed to
|
| 568 |
+
output debug symbols in (or alongside) the object file(s).
|
| 569 |
+
|
| 570 |
+
'extra_preargs' and 'extra_postargs' are implementation- dependent.
|
| 571 |
+
On platforms that have the notion of a command-line (e.g. Unix,
|
| 572 |
+
DOS/Windows), they are most likely lists of strings: extra
|
| 573 |
+
command-line arguments to prepend/append to the compiler command
|
| 574 |
+
line. On other platforms, consult the implementation class
|
| 575 |
+
documentation. In any event, they are intended as an escape hatch
|
| 576 |
+
for those occasions when the abstract compiler framework doesn't
|
| 577 |
+
cut the mustard.
|
| 578 |
+
|
| 579 |
+
'depends', if given, is a list of filenames that all targets
|
| 580 |
+
depend on. If a source file is older than any file in
|
| 581 |
+
depends, then the source file will be recompiled. This
|
| 582 |
+
supports dependency tracking, but only at a coarse
|
| 583 |
+
granularity.
|
| 584 |
+
|
| 585 |
+
Raises CompileError on failure.
|
| 586 |
+
"""
|
| 587 |
+
# A concrete compiler class can either override this method
|
| 588 |
+
# entirely or implement _compile().
|
| 589 |
+
macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
|
| 590 |
+
output_dir, macros, include_dirs, sources, depends, extra_postargs
|
| 591 |
+
)
|
| 592 |
+
cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
|
| 593 |
+
|
| 594 |
+
for obj in objects:
|
| 595 |
+
try:
|
| 596 |
+
src, ext = build[obj]
|
| 597 |
+
except KeyError:
|
| 598 |
+
continue
|
| 599 |
+
self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
|
| 600 |
+
|
| 601 |
+
# Return *all* object filenames, not just the ones we just built.
|
| 602 |
+
return objects
|
| 603 |
+
|
| 604 |
+
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
|
| 605 |
+
"""Compile 'src' to product 'obj'."""
|
| 606 |
+
# A concrete compiler class that does not override compile()
|
| 607 |
+
# should implement _compile().
|
| 608 |
+
pass
|
| 609 |
+
|
| 610 |
+
def create_static_lib(
|
| 611 |
+
self, objects, output_libname, output_dir=None, debug=0, target_lang=None
|
| 612 |
+
):
|
| 613 |
+
"""Link a bunch of stuff together to create a static library file.
|
| 614 |
+
The "bunch of stuff" consists of the list of object files supplied
|
| 615 |
+
as 'objects', the extra object files supplied to
|
| 616 |
+
'add_link_object()' and/or 'set_link_objects()', the libraries
|
| 617 |
+
supplied to 'add_library()' and/or 'set_libraries()', and the
|
| 618 |
+
libraries supplied as 'libraries' (if any).
|
| 619 |
+
|
| 620 |
+
'output_libname' should be a library name, not a filename; the
|
| 621 |
+
filename will be inferred from the library name. 'output_dir' is
|
| 622 |
+
the directory where the library file will be put.
|
| 623 |
+
|
| 624 |
+
'debug' is a boolean; if true, debugging information will be
|
| 625 |
+
included in the library (note that on most platforms, it is the
|
| 626 |
+
compile step where this matters: the 'debug' flag is included here
|
| 627 |
+
just for consistency).
|
| 628 |
+
|
| 629 |
+
'target_lang' is the target language for which the given objects
|
| 630 |
+
are being compiled. This allows specific linkage time treatment of
|
| 631 |
+
certain languages.
|
| 632 |
+
|
| 633 |
+
Raises LibError on failure.
|
| 634 |
+
"""
|
| 635 |
+
pass
|
| 636 |
+
|
| 637 |
+
# values for target_desc parameter in link()
|
| 638 |
+
SHARED_OBJECT = "shared_object"
|
| 639 |
+
SHARED_LIBRARY = "shared_library"
|
| 640 |
+
EXECUTABLE = "executable"
|
| 641 |
+
|
| 642 |
+
def link(
|
| 643 |
+
self,
|
| 644 |
+
target_desc,
|
| 645 |
+
objects,
|
| 646 |
+
output_filename,
|
| 647 |
+
output_dir=None,
|
| 648 |
+
libraries=None,
|
| 649 |
+
library_dirs=None,
|
| 650 |
+
runtime_library_dirs=None,
|
| 651 |
+
export_symbols=None,
|
| 652 |
+
debug=0,
|
| 653 |
+
extra_preargs=None,
|
| 654 |
+
extra_postargs=None,
|
| 655 |
+
build_temp=None,
|
| 656 |
+
target_lang=None,
|
| 657 |
+
):
|
| 658 |
+
"""Link a bunch of stuff together to create an executable or
|
| 659 |
+
shared library file.
|
| 660 |
+
|
| 661 |
+
The "bunch of stuff" consists of the list of object files supplied
|
| 662 |
+
as 'objects'. 'output_filename' should be a filename. If
|
| 663 |
+
'output_dir' is supplied, 'output_filename' is relative to it
|
| 664 |
+
(i.e. 'output_filename' can provide directory components if
|
| 665 |
+
needed).
|
| 666 |
+
|
| 667 |
+
'libraries' is a list of libraries to link against. These are
|
| 668 |
+
library names, not filenames, since they're translated into
|
| 669 |
+
filenames in a platform-specific way (eg. "foo" becomes "libfoo.a"
|
| 670 |
+
on Unix and "foo.lib" on DOS/Windows). However, they can include a
|
| 671 |
+
directory component, which means the linker will look in that
|
| 672 |
+
specific directory rather than searching all the normal locations.
|
| 673 |
+
|
| 674 |
+
'library_dirs', if supplied, should be a list of directories to
|
| 675 |
+
search for libraries that were specified as bare library names
|
| 676 |
+
(ie. no directory component). These are on top of the system
|
| 677 |
+
default and those supplied to 'add_library_dir()' and/or
|
| 678 |
+
'set_library_dirs()'. 'runtime_library_dirs' is a list of
|
| 679 |
+
directories that will be embedded into the shared library and used
|
| 680 |
+
to search for other shared libraries that *it* depends on at
|
| 681 |
+
run-time. (This may only be relevant on Unix.)
|
| 682 |
+
|
| 683 |
+
'export_symbols' is a list of symbols that the shared library will
|
| 684 |
+
export. (This appears to be relevant only on Windows.)
|
| 685 |
+
|
| 686 |
+
'debug' is as for 'compile()' and 'create_static_lib()', with the
|
| 687 |
+
slight distinction that it actually matters on most platforms (as
|
| 688 |
+
opposed to 'create_static_lib()', which includes a 'debug' flag
|
| 689 |
+
mostly for form's sake).
|
| 690 |
+
|
| 691 |
+
'extra_preargs' and 'extra_postargs' are as for 'compile()' (except
|
| 692 |
+
of course that they supply command-line arguments for the
|
| 693 |
+
particular linker being used).
|
| 694 |
+
|
| 695 |
+
'target_lang' is the target language for which the given objects
|
| 696 |
+
are being compiled. This allows specific linkage time treatment of
|
| 697 |
+
certain languages.
|
| 698 |
+
|
| 699 |
+
Raises LinkError on failure.
|
| 700 |
+
"""
|
| 701 |
+
raise NotImplementedError
|
| 702 |
+
|
| 703 |
+
# Old 'link_*()' methods, rewritten to use the new 'link()' method.
|
| 704 |
+
|
| 705 |
+
def link_shared_lib(
|
| 706 |
+
self,
|
| 707 |
+
objects,
|
| 708 |
+
output_libname,
|
| 709 |
+
output_dir=None,
|
| 710 |
+
libraries=None,
|
| 711 |
+
library_dirs=None,
|
| 712 |
+
runtime_library_dirs=None,
|
| 713 |
+
export_symbols=None,
|
| 714 |
+
debug=0,
|
| 715 |
+
extra_preargs=None,
|
| 716 |
+
extra_postargs=None,
|
| 717 |
+
build_temp=None,
|
| 718 |
+
target_lang=None,
|
| 719 |
+
):
|
| 720 |
+
self.link(
|
| 721 |
+
CCompiler.SHARED_LIBRARY,
|
| 722 |
+
objects,
|
| 723 |
+
self.library_filename(output_libname, lib_type='shared'),
|
| 724 |
+
output_dir,
|
| 725 |
+
libraries,
|
| 726 |
+
library_dirs,
|
| 727 |
+
runtime_library_dirs,
|
| 728 |
+
export_symbols,
|
| 729 |
+
debug,
|
| 730 |
+
extra_preargs,
|
| 731 |
+
extra_postargs,
|
| 732 |
+
build_temp,
|
| 733 |
+
target_lang,
|
| 734 |
+
)
|
| 735 |
+
|
| 736 |
+
def link_shared_object(
|
| 737 |
+
self,
|
| 738 |
+
objects,
|
| 739 |
+
output_filename,
|
| 740 |
+
output_dir=None,
|
| 741 |
+
libraries=None,
|
| 742 |
+
library_dirs=None,
|
| 743 |
+
runtime_library_dirs=None,
|
| 744 |
+
export_symbols=None,
|
| 745 |
+
debug=0,
|
| 746 |
+
extra_preargs=None,
|
| 747 |
+
extra_postargs=None,
|
| 748 |
+
build_temp=None,
|
| 749 |
+
target_lang=None,
|
| 750 |
+
):
|
| 751 |
+
self.link(
|
| 752 |
+
CCompiler.SHARED_OBJECT,
|
| 753 |
+
objects,
|
| 754 |
+
output_filename,
|
| 755 |
+
output_dir,
|
| 756 |
+
libraries,
|
| 757 |
+
library_dirs,
|
| 758 |
+
runtime_library_dirs,
|
| 759 |
+
export_symbols,
|
| 760 |
+
debug,
|
| 761 |
+
extra_preargs,
|
| 762 |
+
extra_postargs,
|
| 763 |
+
build_temp,
|
| 764 |
+
target_lang,
|
| 765 |
+
)
|
| 766 |
+
|
| 767 |
+
def link_executable(
|
| 768 |
+
self,
|
| 769 |
+
objects,
|
| 770 |
+
output_progname,
|
| 771 |
+
output_dir=None,
|
| 772 |
+
libraries=None,
|
| 773 |
+
library_dirs=None,
|
| 774 |
+
runtime_library_dirs=None,
|
| 775 |
+
debug=0,
|
| 776 |
+
extra_preargs=None,
|
| 777 |
+
extra_postargs=None,
|
| 778 |
+
target_lang=None,
|
| 779 |
+
):
|
| 780 |
+
self.link(
|
| 781 |
+
CCompiler.EXECUTABLE,
|
| 782 |
+
objects,
|
| 783 |
+
self.executable_filename(output_progname),
|
| 784 |
+
output_dir,
|
| 785 |
+
libraries,
|
| 786 |
+
library_dirs,
|
| 787 |
+
runtime_library_dirs,
|
| 788 |
+
None,
|
| 789 |
+
debug,
|
| 790 |
+
extra_preargs,
|
| 791 |
+
extra_postargs,
|
| 792 |
+
None,
|
| 793 |
+
target_lang,
|
| 794 |
+
)
|
| 795 |
+
|
| 796 |
+
# -- Miscellaneous methods -----------------------------------------
|
| 797 |
+
# These are all used by the 'gen_lib_options() function; there is
|
| 798 |
+
# no appropriate default implementation so subclasses should
|
| 799 |
+
# implement all of these.
|
| 800 |
+
|
| 801 |
+
def library_dir_option(self, dir):
|
| 802 |
+
"""Return the compiler option to add 'dir' to the list of
|
| 803 |
+
directories searched for libraries.
|
| 804 |
+
"""
|
| 805 |
+
raise NotImplementedError
|
| 806 |
+
|
| 807 |
+
def runtime_library_dir_option(self, dir):
|
| 808 |
+
"""Return the compiler option to add 'dir' to the list of
|
| 809 |
+
directories searched for runtime libraries.
|
| 810 |
+
"""
|
| 811 |
+
raise NotImplementedError
|
| 812 |
+
|
| 813 |
+
def library_option(self, lib):
|
| 814 |
+
"""Return the compiler option to add 'lib' to the list of libraries
|
| 815 |
+
linked into the shared library or executable.
|
| 816 |
+
"""
|
| 817 |
+
raise NotImplementedError
|
| 818 |
+
|
| 819 |
+
def has_function( # noqa: C901
|
| 820 |
+
self,
|
| 821 |
+
funcname,
|
| 822 |
+
includes=None,
|
| 823 |
+
include_dirs=None,
|
| 824 |
+
libraries=None,
|
| 825 |
+
library_dirs=None,
|
| 826 |
+
):
|
| 827 |
+
"""Return a boolean indicating whether funcname is supported on
|
| 828 |
+
the current platform. The optional arguments can be used to
|
| 829 |
+
augment the compilation environment.
|
| 830 |
+
"""
|
| 831 |
+
# this can't be included at module scope because it tries to
|
| 832 |
+
# import math which might not be available at that point - maybe
|
| 833 |
+
# the necessary logic should just be inlined?
|
| 834 |
+
import tempfile
|
| 835 |
+
|
| 836 |
+
if includes is None:
|
| 837 |
+
includes = []
|
| 838 |
+
if include_dirs is None:
|
| 839 |
+
include_dirs = []
|
| 840 |
+
if libraries is None:
|
| 841 |
+
libraries = []
|
| 842 |
+
if library_dirs is None:
|
| 843 |
+
library_dirs = []
|
| 844 |
+
fd, fname = tempfile.mkstemp(".c", funcname, text=True)
|
| 845 |
+
f = os.fdopen(fd, "w")
|
| 846 |
+
try:
|
| 847 |
+
for incl in includes:
|
| 848 |
+
f.write("""#include "%s"\n""" % incl)
|
| 849 |
+
f.write(
|
| 850 |
+
"""\
|
| 851 |
+
int main (int argc, char **argv) {
|
| 852 |
+
%s();
|
| 853 |
+
return 0;
|
| 854 |
+
}
|
| 855 |
+
"""
|
| 856 |
+
% funcname
|
| 857 |
+
)
|
| 858 |
+
finally:
|
| 859 |
+
f.close()
|
| 860 |
+
try:
|
| 861 |
+
objects = self.compile([fname], include_dirs=include_dirs)
|
| 862 |
+
except CompileError:
|
| 863 |
+
return False
|
| 864 |
+
finally:
|
| 865 |
+
os.remove(fname)
|
| 866 |
+
|
| 867 |
+
try:
|
| 868 |
+
self.link_executable(
|
| 869 |
+
objects, "a.out", libraries=libraries, library_dirs=library_dirs
|
| 870 |
+
)
|
| 871 |
+
except (LinkError, TypeError):
|
| 872 |
+
return False
|
| 873 |
+
else:
|
| 874 |
+
os.remove(os.path.join(self.output_dir or '', "a.out"))
|
| 875 |
+
finally:
|
| 876 |
+
for fn in objects:
|
| 877 |
+
os.remove(fn)
|
| 878 |
+
return True
|
| 879 |
+
|
| 880 |
+
def find_library_file(self, dirs, lib, debug=0):
|
| 881 |
+
"""Search the specified list of directories for a static or shared
|
| 882 |
+
library file 'lib' and return the full path to that file. If
|
| 883 |
+
'debug' true, look for a debugging version (if that makes sense on
|
| 884 |
+
the current platform). Return None if 'lib' wasn't found in any of
|
| 885 |
+
the specified directories.
|
| 886 |
+
"""
|
| 887 |
+
raise NotImplementedError
|
| 888 |
+
|
| 889 |
+
# -- Filename generation methods -----------------------------------
|
| 890 |
+
|
| 891 |
+
# The default implementation of the filename generating methods are
|
| 892 |
+
# prejudiced towards the Unix/DOS/Windows view of the world:
|
| 893 |
+
# * object files are named by replacing the source file extension
|
| 894 |
+
# (eg. .c/.cpp -> .o/.obj)
|
| 895 |
+
# * library files (shared or static) are named by plugging the
|
| 896 |
+
# library name and extension into a format string, eg.
|
| 897 |
+
# "lib%s.%s" % (lib_name, ".a") for Unix static libraries
|
| 898 |
+
# * executables are named by appending an extension (possibly
|
| 899 |
+
# empty) to the program name: eg. progname + ".exe" for
|
| 900 |
+
# Windows
|
| 901 |
+
#
|
| 902 |
+
# To reduce redundant code, these methods expect to find
|
| 903 |
+
# several attributes in the current object (presumably defined
|
| 904 |
+
# as class attributes):
|
| 905 |
+
# * src_extensions -
|
| 906 |
+
# list of C/C++ source file extensions, eg. ['.c', '.cpp']
|
| 907 |
+
# * obj_extension -
|
| 908 |
+
# object file extension, eg. '.o' or '.obj'
|
| 909 |
+
# * static_lib_extension -
|
| 910 |
+
# extension for static library files, eg. '.a' or '.lib'
|
| 911 |
+
# * shared_lib_extension -
|
| 912 |
+
# extension for shared library/object files, eg. '.so', '.dll'
|
| 913 |
+
# * static_lib_format -
|
| 914 |
+
# format string for generating static library filenames,
|
| 915 |
+
# eg. 'lib%s.%s' or '%s.%s'
|
| 916 |
+
# * shared_lib_format
|
| 917 |
+
# format string for generating shared library filenames
|
| 918 |
+
# (probably same as static_lib_format, since the extension
|
| 919 |
+
# is one of the intended parameters to the format string)
|
| 920 |
+
# * exe_extension -
|
| 921 |
+
# extension for executable files, eg. '' or '.exe'
|
| 922 |
+
|
| 923 |
+
def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
|
| 924 |
+
if output_dir is None:
|
| 925 |
+
output_dir = ''
|
| 926 |
+
return list(
|
| 927 |
+
self._make_out_path(output_dir, strip_dir, src_name)
|
| 928 |
+
for src_name in source_filenames
|
| 929 |
+
)
|
| 930 |
+
|
| 931 |
+
@property
|
| 932 |
+
def out_extensions(self):
|
| 933 |
+
return dict.fromkeys(self.src_extensions, self.obj_extension)
|
| 934 |
+
|
| 935 |
+
def _make_out_path(self, output_dir, strip_dir, src_name):
|
| 936 |
+
base, ext = os.path.splitext(src_name)
|
| 937 |
+
base = self._make_relative(base)
|
| 938 |
+
try:
|
| 939 |
+
new_ext = self.out_extensions[ext]
|
| 940 |
+
except LookupError:
|
| 941 |
+
raise UnknownFileError(
|
| 942 |
+
"unknown file type '{}' (from '{}')".format(ext, src_name)
|
| 943 |
+
)
|
| 944 |
+
if strip_dir:
|
| 945 |
+
base = os.path.basename(base)
|
| 946 |
+
return os.path.join(output_dir, base + new_ext)
|
| 947 |
+
|
| 948 |
+
@staticmethod
|
| 949 |
+
def _make_relative(base):
|
| 950 |
+
"""
|
| 951 |
+
In order to ensure that a filename always honors the
|
| 952 |
+
indicated output_dir, make sure it's relative.
|
| 953 |
+
Ref python/cpython#37775.
|
| 954 |
+
"""
|
| 955 |
+
# Chop off the drive
|
| 956 |
+
no_drive = os.path.splitdrive(base)[1]
|
| 957 |
+
# If abs, chop off leading /
|
| 958 |
+
return no_drive[os.path.isabs(no_drive) :]
|
| 959 |
+
|
| 960 |
+
def shared_object_filename(self, basename, strip_dir=0, output_dir=''):
|
| 961 |
+
assert output_dir is not None
|
| 962 |
+
if strip_dir:
|
| 963 |
+
basename = os.path.basename(basename)
|
| 964 |
+
return os.path.join(output_dir, basename + self.shared_lib_extension)
|
| 965 |
+
|
| 966 |
+
def executable_filename(self, basename, strip_dir=0, output_dir=''):
|
| 967 |
+
assert output_dir is not None
|
| 968 |
+
if strip_dir:
|
| 969 |
+
basename = os.path.basename(basename)
|
| 970 |
+
return os.path.join(output_dir, basename + (self.exe_extension or ''))
|
| 971 |
+
|
| 972 |
+
def library_filename(
|
| 973 |
+
self, libname, lib_type='static', strip_dir=0, output_dir='' # or 'shared'
|
| 974 |
+
):
|
| 975 |
+
assert output_dir is not None
|
| 976 |
+
expected = '"static", "shared", "dylib", "xcode_stub"'
|
| 977 |
+
if lib_type not in eval(expected):
|
| 978 |
+
raise ValueError(f"'lib_type' must be {expected}")
|
| 979 |
+
fmt = getattr(self, lib_type + "_lib_format")
|
| 980 |
+
ext = getattr(self, lib_type + "_lib_extension")
|
| 981 |
+
|
| 982 |
+
dir, base = os.path.split(libname)
|
| 983 |
+
filename = fmt % (base, ext)
|
| 984 |
+
if strip_dir:
|
| 985 |
+
dir = ''
|
| 986 |
+
|
| 987 |
+
return os.path.join(output_dir, dir, filename)
|
| 988 |
+
|
| 989 |
+
# -- Utility methods -----------------------------------------------
|
| 990 |
+
|
| 991 |
+
def announce(self, msg, level=1):
|
| 992 |
+
log.debug(msg)
|
| 993 |
+
|
| 994 |
+
def debug_print(self, msg):
|
| 995 |
+
from distutils.debug import DEBUG
|
| 996 |
+
|
| 997 |
+
if DEBUG:
|
| 998 |
+
print(msg)
|
| 999 |
+
|
| 1000 |
+
def warn(self, msg):
|
| 1001 |
+
sys.stderr.write("warning: %s\n" % msg)
|
| 1002 |
+
|
| 1003 |
+
def execute(self, func, args, msg=None, level=1):
|
| 1004 |
+
execute(func, args, msg, self.dry_run)
|
| 1005 |
+
|
| 1006 |
+
def spawn(self, cmd, **kwargs):
|
| 1007 |
+
spawn(cmd, dry_run=self.dry_run, **kwargs)
|
| 1008 |
+
|
| 1009 |
+
def move_file(self, src, dst):
|
| 1010 |
+
return move_file(src, dst, dry_run=self.dry_run)
|
| 1011 |
+
|
| 1012 |
+
def mkpath(self, name, mode=0o777):
|
| 1013 |
+
mkpath(name, mode, dry_run=self.dry_run)
|
| 1014 |
+
|
| 1015 |
+
|
| 1016 |
+
# Map a sys.platform/os.name ('posix', 'nt') to the default compiler
|
| 1017 |
+
# type for that platform. Keys are interpreted as re match
|
| 1018 |
+
# patterns. Order is important; platform mappings are preferred over
|
| 1019 |
+
# OS names.
|
| 1020 |
+
_default_compilers = (
|
| 1021 |
+
# Platform string mappings
|
| 1022 |
+
# on a cygwin built python we can use gcc like an ordinary UNIXish
|
| 1023 |
+
# compiler
|
| 1024 |
+
('cygwin.*', 'unix'),
|
| 1025 |
+
# OS name mappings
|
| 1026 |
+
('posix', 'unix'),
|
| 1027 |
+
('nt', 'msvc'),
|
| 1028 |
+
)
|
| 1029 |
+
|
| 1030 |
+
|
| 1031 |
+
def get_default_compiler(osname=None, platform=None):
|
| 1032 |
+
"""Determine the default compiler to use for the given platform.
|
| 1033 |
+
|
| 1034 |
+
osname should be one of the standard Python OS names (i.e. the
|
| 1035 |
+
ones returned by os.name) and platform the common value
|
| 1036 |
+
returned by sys.platform for the platform in question.
|
| 1037 |
+
|
| 1038 |
+
The default values are os.name and sys.platform in case the
|
| 1039 |
+
parameters are not given.
|
| 1040 |
+
"""
|
| 1041 |
+
if osname is None:
|
| 1042 |
+
osname = os.name
|
| 1043 |
+
if platform is None:
|
| 1044 |
+
platform = sys.platform
|
| 1045 |
+
for pattern, compiler in _default_compilers:
|
| 1046 |
+
if (
|
| 1047 |
+
re.match(pattern, platform) is not None
|
| 1048 |
+
or re.match(pattern, osname) is not None
|
| 1049 |
+
):
|
| 1050 |
+
return compiler
|
| 1051 |
+
# Default to Unix compiler
|
| 1052 |
+
return 'unix'
|
| 1053 |
+
|
| 1054 |
+
|
| 1055 |
+
# Map compiler types to (module_name, class_name) pairs -- ie. where to
|
| 1056 |
+
# find the code that implements an interface to this compiler. (The module
|
| 1057 |
+
# is assumed to be in the 'distutils' package.)
|
| 1058 |
+
compiler_class = {
|
| 1059 |
+
'unix': ('unixccompiler', 'UnixCCompiler', "standard UNIX-style compiler"),
|
| 1060 |
+
'msvc': ('_msvccompiler', 'MSVCCompiler', "Microsoft Visual C++"),
|
| 1061 |
+
'cygwin': (
|
| 1062 |
+
'cygwinccompiler',
|
| 1063 |
+
'CygwinCCompiler',
|
| 1064 |
+
"Cygwin port of GNU C Compiler for Win32",
|
| 1065 |
+
),
|
| 1066 |
+
'mingw32': (
|
| 1067 |
+
'cygwinccompiler',
|
| 1068 |
+
'Mingw32CCompiler',
|
| 1069 |
+
"Mingw32 port of GNU C Compiler for Win32",
|
| 1070 |
+
),
|
| 1071 |
+
'bcpp': ('bcppcompiler', 'BCPPCompiler', "Borland C++ Compiler"),
|
| 1072 |
+
}
|
| 1073 |
+
|
| 1074 |
+
|
| 1075 |
+
def show_compilers():
|
| 1076 |
+
"""Print list of available compilers (used by the "--help-compiler"
|
| 1077 |
+
options to "build", "build_ext", "build_clib").
|
| 1078 |
+
"""
|
| 1079 |
+
# XXX this "knows" that the compiler option it's describing is
|
| 1080 |
+
# "--compiler", which just happens to be the case for the three
|
| 1081 |
+
# commands that use it.
|
| 1082 |
+
from distutils.fancy_getopt import FancyGetopt
|
| 1083 |
+
|
| 1084 |
+
compilers = []
|
| 1085 |
+
for compiler in compiler_class.keys():
|
| 1086 |
+
compilers.append(("compiler=" + compiler, None, compiler_class[compiler][2]))
|
| 1087 |
+
compilers.sort()
|
| 1088 |
+
pretty_printer = FancyGetopt(compilers)
|
| 1089 |
+
pretty_printer.print_help("List of available compilers:")
|
| 1090 |
+
|
| 1091 |
+
|
| 1092 |
+
def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):
|
| 1093 |
+
"""Generate an instance of some CCompiler subclass for the supplied
|
| 1094 |
+
platform/compiler combination. 'plat' defaults to 'os.name'
|
| 1095 |
+
(eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler
|
| 1096 |
+
for that platform. Currently only 'posix' and 'nt' are supported, and
|
| 1097 |
+
the default compilers are "traditional Unix interface" (UnixCCompiler
|
| 1098 |
+
class) and Visual C++ (MSVCCompiler class). Note that it's perfectly
|
| 1099 |
+
possible to ask for a Unix compiler object under Windows, and a
|
| 1100 |
+
Microsoft compiler object under Unix -- if you supply a value for
|
| 1101 |
+
'compiler', 'plat' is ignored.
|
| 1102 |
+
"""
|
| 1103 |
+
if plat is None:
|
| 1104 |
+
plat = os.name
|
| 1105 |
+
|
| 1106 |
+
try:
|
| 1107 |
+
if compiler is None:
|
| 1108 |
+
compiler = get_default_compiler(plat)
|
| 1109 |
+
|
| 1110 |
+
(module_name, class_name, long_description) = compiler_class[compiler]
|
| 1111 |
+
except KeyError:
|
| 1112 |
+
msg = "don't know how to compile C/C++ code on platform '%s'" % plat
|
| 1113 |
+
if compiler is not None:
|
| 1114 |
+
msg = msg + " with '%s' compiler" % compiler
|
| 1115 |
+
raise DistutilsPlatformError(msg)
|
| 1116 |
+
|
| 1117 |
+
try:
|
| 1118 |
+
module_name = "distutils." + module_name
|
| 1119 |
+
__import__(module_name)
|
| 1120 |
+
module = sys.modules[module_name]
|
| 1121 |
+
klass = vars(module)[class_name]
|
| 1122 |
+
except ImportError:
|
| 1123 |
+
raise DistutilsModuleError(
|
| 1124 |
+
"can't compile C/C++ code: unable to load module '%s'" % module_name
|
| 1125 |
+
)
|
| 1126 |
+
except KeyError:
|
| 1127 |
+
raise DistutilsModuleError(
|
| 1128 |
+
"can't compile C/C++ code: unable to find class '%s' "
|
| 1129 |
+
"in module '%s'" % (class_name, module_name)
|
| 1130 |
+
)
|
| 1131 |
+
|
| 1132 |
+
# XXX The None is necessary to preserve backwards compatibility
|
| 1133 |
+
# with classes that expect verbose to be the first positional
|
| 1134 |
+
# argument.
|
| 1135 |
+
return klass(None, dry_run, force)
|
| 1136 |
+
|
| 1137 |
+
|
| 1138 |
+
def gen_preprocess_options(macros, include_dirs):
|
| 1139 |
+
"""Generate C pre-processor options (-D, -U, -I) as used by at least
|
| 1140 |
+
two types of compilers: the typical Unix compiler and Visual C++.
|
| 1141 |
+
'macros' is the usual thing, a list of 1- or 2-tuples, where (name,)
|
| 1142 |
+
means undefine (-U) macro 'name', and (name,value) means define (-D)
|
| 1143 |
+
macro 'name' to 'value'. 'include_dirs' is just a list of directory
|
| 1144 |
+
names to be added to the header file search path (-I). Returns a list
|
| 1145 |
+
of command-line options suitable for either Unix compilers or Visual
|
| 1146 |
+
C++.
|
| 1147 |
+
"""
|
| 1148 |
+
# XXX it would be nice (mainly aesthetic, and so we don't generate
|
| 1149 |
+
# stupid-looking command lines) to go over 'macros' and eliminate
|
| 1150 |
+
# redundant definitions/undefinitions (ie. ensure that only the
|
| 1151 |
+
# latest mention of a particular macro winds up on the command
|
| 1152 |
+
# line). I don't think it's essential, though, since most (all?)
|
| 1153 |
+
# Unix C compilers only pay attention to the latest -D or -U
|
| 1154 |
+
# mention of a macro on their command line. Similar situation for
|
| 1155 |
+
# 'include_dirs'. I'm punting on both for now. Anyways, weeding out
|
| 1156 |
+
# redundancies like this should probably be the province of
|
| 1157 |
+
# CCompiler, since the data structures used are inherited from it
|
| 1158 |
+
# and therefore common to all CCompiler classes.
|
| 1159 |
+
pp_opts = []
|
| 1160 |
+
for macro in macros:
|
| 1161 |
+
if not (isinstance(macro, tuple) and 1 <= len(macro) <= 2):
|
| 1162 |
+
raise TypeError(
|
| 1163 |
+
"bad macro definition '%s': "
|
| 1164 |
+
"each element of 'macros' list must be a 1- or 2-tuple" % macro
|
| 1165 |
+
)
|
| 1166 |
+
|
| 1167 |
+
if len(macro) == 1: # undefine this macro
|
| 1168 |
+
pp_opts.append("-U%s" % macro[0])
|
| 1169 |
+
elif len(macro) == 2:
|
| 1170 |
+
if macro[1] is None: # define with no explicit value
|
| 1171 |
+
pp_opts.append("-D%s" % macro[0])
|
| 1172 |
+
else:
|
| 1173 |
+
# XXX *don't* need to be clever about quoting the
|
| 1174 |
+
# macro value here, because we're going to avoid the
|
| 1175 |
+
# shell at all costs when we spawn the command!
|
| 1176 |
+
pp_opts.append("-D%s=%s" % macro)
|
| 1177 |
+
|
| 1178 |
+
for dir in include_dirs:
|
| 1179 |
+
pp_opts.append("-I%s" % dir)
|
| 1180 |
+
return pp_opts
|
| 1181 |
+
|
| 1182 |
+
|
| 1183 |
+
def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
|
| 1184 |
+
"""Generate linker options for searching library directories and
|
| 1185 |
+
linking with specific libraries. 'libraries' and 'library_dirs' are,
|
| 1186 |
+
respectively, lists of library names (not filenames!) and search
|
| 1187 |
+
directories. Returns a list of command-line options suitable for use
|
| 1188 |
+
with some compiler (depending on the two format strings passed in).
|
| 1189 |
+
"""
|
| 1190 |
+
lib_opts = []
|
| 1191 |
+
|
| 1192 |
+
for dir in library_dirs:
|
| 1193 |
+
lib_opts.append(compiler.library_dir_option(dir))
|
| 1194 |
+
|
| 1195 |
+
for dir in runtime_library_dirs:
|
| 1196 |
+
opt = compiler.runtime_library_dir_option(dir)
|
| 1197 |
+
if isinstance(opt, list):
|
| 1198 |
+
lib_opts = lib_opts + opt
|
| 1199 |
+
else:
|
| 1200 |
+
lib_opts.append(opt)
|
| 1201 |
+
|
| 1202 |
+
# XXX it's important that we *not* remove redundant library mentions!
|
| 1203 |
+
# sometimes you really do have to say "-lfoo -lbar -lfoo" in order to
|
| 1204 |
+
# resolve all symbols. I just hope we never have to say "-lfoo obj.o
|
| 1205 |
+
# -lbar" to get things to work -- that's certainly a possibility, but a
|
| 1206 |
+
# pretty nasty way to arrange your C code.
|
| 1207 |
+
|
| 1208 |
+
for lib in libraries:
|
| 1209 |
+
(lib_dir, lib_name) = os.path.split(lib)
|
| 1210 |
+
if lib_dir:
|
| 1211 |
+
lib_file = compiler.find_library_file([lib_dir], lib_name)
|
| 1212 |
+
if lib_file:
|
| 1213 |
+
lib_opts.append(lib_file)
|
| 1214 |
+
else:
|
| 1215 |
+
compiler.warn(
|
| 1216 |
+
"no library file corresponding to " "'%s' found (skipping)" % lib
|
| 1217 |
+
)
|
| 1218 |
+
else:
|
| 1219 |
+
lib_opts.append(compiler.library_option(lib))
|
| 1220 |
+
return lib_opts
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/config.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.pypirc
|
| 2 |
+
|
| 3 |
+
Provides the PyPIRCCommand class, the base class for the command classes
|
| 4 |
+
that uses .pypirc in the distutils.command package.
|
| 5 |
+
"""
|
| 6 |
+
import os
|
| 7 |
+
from configparser import RawConfigParser
|
| 8 |
+
|
| 9 |
+
from distutils.cmd import Command
|
| 10 |
+
|
| 11 |
+
DEFAULT_PYPIRC = """\
|
| 12 |
+
[distutils]
|
| 13 |
+
index-servers =
|
| 14 |
+
pypi
|
| 15 |
+
|
| 16 |
+
[pypi]
|
| 17 |
+
username:%s
|
| 18 |
+
password:%s
|
| 19 |
+
"""
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class PyPIRCCommand(Command):
|
| 23 |
+
"""Base command that knows how to handle the .pypirc file"""
|
| 24 |
+
|
| 25 |
+
DEFAULT_REPOSITORY = 'https://upload.pypi.org/legacy/'
|
| 26 |
+
DEFAULT_REALM = 'pypi'
|
| 27 |
+
repository = None
|
| 28 |
+
realm = None
|
| 29 |
+
|
| 30 |
+
user_options = [
|
| 31 |
+
('repository=', 'r', "url of repository [default: %s]" % DEFAULT_REPOSITORY),
|
| 32 |
+
('show-response', None, 'display full response text from server'),
|
| 33 |
+
]
|
| 34 |
+
|
| 35 |
+
boolean_options = ['show-response']
|
| 36 |
+
|
| 37 |
+
def _get_rc_file(self):
|
| 38 |
+
"""Returns rc file path."""
|
| 39 |
+
return os.path.join(os.path.expanduser('~'), '.pypirc')
|
| 40 |
+
|
| 41 |
+
def _store_pypirc(self, username, password):
|
| 42 |
+
"""Creates a default .pypirc file."""
|
| 43 |
+
rc = self._get_rc_file()
|
| 44 |
+
with os.fdopen(os.open(rc, os.O_CREAT | os.O_WRONLY, 0o600), 'w') as f:
|
| 45 |
+
f.write(DEFAULT_PYPIRC % (username, password))
|
| 46 |
+
|
| 47 |
+
def _read_pypirc(self): # noqa: C901
|
| 48 |
+
"""Reads the .pypirc file."""
|
| 49 |
+
rc = self._get_rc_file()
|
| 50 |
+
if os.path.exists(rc):
|
| 51 |
+
self.announce('Using PyPI login from %s' % rc)
|
| 52 |
+
repository = self.repository or self.DEFAULT_REPOSITORY
|
| 53 |
+
|
| 54 |
+
config = RawConfigParser()
|
| 55 |
+
config.read(rc)
|
| 56 |
+
sections = config.sections()
|
| 57 |
+
if 'distutils' in sections:
|
| 58 |
+
# let's get the list of servers
|
| 59 |
+
index_servers = config.get('distutils', 'index-servers')
|
| 60 |
+
_servers = [
|
| 61 |
+
server.strip()
|
| 62 |
+
for server in index_servers.split('\n')
|
| 63 |
+
if server.strip() != ''
|
| 64 |
+
]
|
| 65 |
+
if _servers == []:
|
| 66 |
+
# nothing set, let's try to get the default pypi
|
| 67 |
+
if 'pypi' in sections:
|
| 68 |
+
_servers = ['pypi']
|
| 69 |
+
else:
|
| 70 |
+
# the file is not properly defined, returning
|
| 71 |
+
# an empty dict
|
| 72 |
+
return {}
|
| 73 |
+
for server in _servers:
|
| 74 |
+
current = {'server': server}
|
| 75 |
+
current['username'] = config.get(server, 'username')
|
| 76 |
+
|
| 77 |
+
# optional params
|
| 78 |
+
for key, default in (
|
| 79 |
+
('repository', self.DEFAULT_REPOSITORY),
|
| 80 |
+
('realm', self.DEFAULT_REALM),
|
| 81 |
+
('password', None),
|
| 82 |
+
):
|
| 83 |
+
if config.has_option(server, key):
|
| 84 |
+
current[key] = config.get(server, key)
|
| 85 |
+
else:
|
| 86 |
+
current[key] = default
|
| 87 |
+
|
| 88 |
+
# work around people having "repository" for the "pypi"
|
| 89 |
+
# section of their config set to the HTTP (rather than
|
| 90 |
+
# HTTPS) URL
|
| 91 |
+
if server == 'pypi' and repository in (
|
| 92 |
+
self.DEFAULT_REPOSITORY,
|
| 93 |
+
'pypi',
|
| 94 |
+
):
|
| 95 |
+
current['repository'] = self.DEFAULT_REPOSITORY
|
| 96 |
+
return current
|
| 97 |
+
|
| 98 |
+
if (
|
| 99 |
+
current['server'] == repository
|
| 100 |
+
or current['repository'] == repository
|
| 101 |
+
):
|
| 102 |
+
return current
|
| 103 |
+
elif 'server-login' in sections:
|
| 104 |
+
# old format
|
| 105 |
+
server = 'server-login'
|
| 106 |
+
if config.has_option(server, 'repository'):
|
| 107 |
+
repository = config.get(server, 'repository')
|
| 108 |
+
else:
|
| 109 |
+
repository = self.DEFAULT_REPOSITORY
|
| 110 |
+
return {
|
| 111 |
+
'username': config.get(server, 'username'),
|
| 112 |
+
'password': config.get(server, 'password'),
|
| 113 |
+
'repository': repository,
|
| 114 |
+
'server': server,
|
| 115 |
+
'realm': self.DEFAULT_REALM,
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
return {}
|
| 119 |
+
|
| 120 |
+
def _read_pypi_response(self, response):
|
| 121 |
+
"""Read and decode a PyPI HTTP response."""
|
| 122 |
+
import cgi
|
| 123 |
+
|
| 124 |
+
content_type = response.getheader('content-type', 'text/plain')
|
| 125 |
+
encoding = cgi.parse_header(content_type)[1].get('charset', 'ascii')
|
| 126 |
+
return response.read().decode(encoding)
|
| 127 |
+
|
| 128 |
+
def initialize_options(self):
|
| 129 |
+
"""Initialize options."""
|
| 130 |
+
self.repository = None
|
| 131 |
+
self.realm = None
|
| 132 |
+
self.show_response = 0
|
| 133 |
+
|
| 134 |
+
def finalize_options(self):
|
| 135 |
+
"""Finalizes options."""
|
| 136 |
+
if self.repository is None:
|
| 137 |
+
self.repository = self.DEFAULT_REPOSITORY
|
| 138 |
+
if self.realm is None:
|
| 139 |
+
self.realm = self.DEFAULT_REALM
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/core.py
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.core
|
| 2 |
+
|
| 3 |
+
The only module that needs to be imported to use the Distutils; provides
|
| 4 |
+
the 'setup' function (which is to be called from the setup script). Also
|
| 5 |
+
indirectly provides the Distribution and Command classes, although they are
|
| 6 |
+
really defined in distutils.dist and distutils.cmd.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
import os
|
| 10 |
+
import sys
|
| 11 |
+
import tokenize
|
| 12 |
+
|
| 13 |
+
from distutils.debug import DEBUG
|
| 14 |
+
from distutils.errors import (
|
| 15 |
+
DistutilsSetupError,
|
| 16 |
+
DistutilsError,
|
| 17 |
+
CCompilerError,
|
| 18 |
+
DistutilsArgError,
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
# Mainly import these so setup scripts can "from distutils.core import" them.
|
| 22 |
+
from distutils.dist import Distribution
|
| 23 |
+
from distutils.cmd import Command
|
| 24 |
+
from distutils.config import PyPIRCCommand
|
| 25 |
+
from distutils.extension import Extension
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
__all__ = ['Distribution', 'Command', 'PyPIRCCommand', 'Extension', 'setup']
|
| 29 |
+
|
| 30 |
+
# This is a barebones help message generated displayed when the user
|
| 31 |
+
# runs the setup script with no arguments at all. More useful help
|
| 32 |
+
# is generated with various --help options: global help, list commands,
|
| 33 |
+
# and per-command help.
|
| 34 |
+
USAGE = """\
|
| 35 |
+
usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
|
| 36 |
+
or: %(script)s --help [cmd1 cmd2 ...]
|
| 37 |
+
or: %(script)s --help-commands
|
| 38 |
+
or: %(script)s cmd --help
|
| 39 |
+
"""
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def gen_usage(script_name):
|
| 43 |
+
script = os.path.basename(script_name)
|
| 44 |
+
return USAGE % locals()
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'.
|
| 48 |
+
_setup_stop_after = None
|
| 49 |
+
_setup_distribution = None
|
| 50 |
+
|
| 51 |
+
# Legal keyword arguments for the setup() function
|
| 52 |
+
setup_keywords = (
|
| 53 |
+
'distclass',
|
| 54 |
+
'script_name',
|
| 55 |
+
'script_args',
|
| 56 |
+
'options',
|
| 57 |
+
'name',
|
| 58 |
+
'version',
|
| 59 |
+
'author',
|
| 60 |
+
'author_email',
|
| 61 |
+
'maintainer',
|
| 62 |
+
'maintainer_email',
|
| 63 |
+
'url',
|
| 64 |
+
'license',
|
| 65 |
+
'description',
|
| 66 |
+
'long_description',
|
| 67 |
+
'keywords',
|
| 68 |
+
'platforms',
|
| 69 |
+
'classifiers',
|
| 70 |
+
'download_url',
|
| 71 |
+
'requires',
|
| 72 |
+
'provides',
|
| 73 |
+
'obsoletes',
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
# Legal keyword arguments for the Extension constructor
|
| 77 |
+
extension_keywords = (
|
| 78 |
+
'name',
|
| 79 |
+
'sources',
|
| 80 |
+
'include_dirs',
|
| 81 |
+
'define_macros',
|
| 82 |
+
'undef_macros',
|
| 83 |
+
'library_dirs',
|
| 84 |
+
'libraries',
|
| 85 |
+
'runtime_library_dirs',
|
| 86 |
+
'extra_objects',
|
| 87 |
+
'extra_compile_args',
|
| 88 |
+
'extra_link_args',
|
| 89 |
+
'swig_opts',
|
| 90 |
+
'export_symbols',
|
| 91 |
+
'depends',
|
| 92 |
+
'language',
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def setup(**attrs): # noqa: C901
|
| 97 |
+
"""The gateway to the Distutils: do everything your setup script needs
|
| 98 |
+
to do, in a highly flexible and user-driven way. Briefly: create a
|
| 99 |
+
Distribution instance; find and parse config files; parse the command
|
| 100 |
+
line; run each Distutils command found there, customized by the options
|
| 101 |
+
supplied to 'setup()' (as keyword arguments), in config files, and on
|
| 102 |
+
the command line.
|
| 103 |
+
|
| 104 |
+
The Distribution instance might be an instance of a class supplied via
|
| 105 |
+
the 'distclass' keyword argument to 'setup'; if no such class is
|
| 106 |
+
supplied, then the Distribution class (in dist.py) is instantiated.
|
| 107 |
+
All other arguments to 'setup' (except for 'cmdclass') are used to set
|
| 108 |
+
attributes of the Distribution instance.
|
| 109 |
+
|
| 110 |
+
The 'cmdclass' argument, if supplied, is a dictionary mapping command
|
| 111 |
+
names to command classes. Each command encountered on the command line
|
| 112 |
+
will be turned into a command class, which is in turn instantiated; any
|
| 113 |
+
class found in 'cmdclass' is used in place of the default, which is
|
| 114 |
+
(for command 'foo_bar') class 'foo_bar' in module
|
| 115 |
+
'distutils.command.foo_bar'. The command class must provide a
|
| 116 |
+
'user_options' attribute which is a list of option specifiers for
|
| 117 |
+
'distutils.fancy_getopt'. Any command-line options between the current
|
| 118 |
+
and the next command are used to set attributes of the current command
|
| 119 |
+
object.
|
| 120 |
+
|
| 121 |
+
When the entire command-line has been successfully parsed, calls the
|
| 122 |
+
'run()' method on each command object in turn. This method will be
|
| 123 |
+
driven entirely by the Distribution object (which each command object
|
| 124 |
+
has a reference to, thanks to its constructor), and the
|
| 125 |
+
command-specific options that became attributes of each command
|
| 126 |
+
object.
|
| 127 |
+
"""
|
| 128 |
+
|
| 129 |
+
global _setup_stop_after, _setup_distribution
|
| 130 |
+
|
| 131 |
+
# Determine the distribution class -- either caller-supplied or
|
| 132 |
+
# our Distribution (see below).
|
| 133 |
+
klass = attrs.get('distclass')
|
| 134 |
+
if klass:
|
| 135 |
+
del attrs['distclass']
|
| 136 |
+
else:
|
| 137 |
+
klass = Distribution
|
| 138 |
+
|
| 139 |
+
if 'script_name' not in attrs:
|
| 140 |
+
attrs['script_name'] = os.path.basename(sys.argv[0])
|
| 141 |
+
if 'script_args' not in attrs:
|
| 142 |
+
attrs['script_args'] = sys.argv[1:]
|
| 143 |
+
|
| 144 |
+
# Create the Distribution instance, using the remaining arguments
|
| 145 |
+
# (ie. everything except distclass) to initialize it
|
| 146 |
+
try:
|
| 147 |
+
_setup_distribution = dist = klass(attrs)
|
| 148 |
+
except DistutilsSetupError as msg:
|
| 149 |
+
if 'name' not in attrs:
|
| 150 |
+
raise SystemExit("error in setup command: %s" % msg)
|
| 151 |
+
else:
|
| 152 |
+
raise SystemExit("error in {} setup command: {}".format(attrs['name'], msg))
|
| 153 |
+
|
| 154 |
+
if _setup_stop_after == "init":
|
| 155 |
+
return dist
|
| 156 |
+
|
| 157 |
+
# Find and parse the config file(s): they will override options from
|
| 158 |
+
# the setup script, but be overridden by the command line.
|
| 159 |
+
dist.parse_config_files()
|
| 160 |
+
|
| 161 |
+
if DEBUG:
|
| 162 |
+
print("options (after parsing config files):")
|
| 163 |
+
dist.dump_option_dicts()
|
| 164 |
+
|
| 165 |
+
if _setup_stop_after == "config":
|
| 166 |
+
return dist
|
| 167 |
+
|
| 168 |
+
# Parse the command line and override config files; any
|
| 169 |
+
# command-line errors are the end user's fault, so turn them into
|
| 170 |
+
# SystemExit to suppress tracebacks.
|
| 171 |
+
try:
|
| 172 |
+
ok = dist.parse_command_line()
|
| 173 |
+
except DistutilsArgError as msg:
|
| 174 |
+
raise SystemExit(gen_usage(dist.script_name) + "\nerror: %s" % msg)
|
| 175 |
+
|
| 176 |
+
if DEBUG:
|
| 177 |
+
print("options (after parsing command line):")
|
| 178 |
+
dist.dump_option_dicts()
|
| 179 |
+
|
| 180 |
+
if _setup_stop_after == "commandline":
|
| 181 |
+
return dist
|
| 182 |
+
|
| 183 |
+
# And finally, run all the commands found on the command line.
|
| 184 |
+
if ok:
|
| 185 |
+
return run_commands(dist)
|
| 186 |
+
|
| 187 |
+
return dist
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
# setup ()
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
def run_commands(dist):
|
| 194 |
+
"""Given a Distribution object run all the commands,
|
| 195 |
+
raising ``SystemExit`` errors in the case of failure.
|
| 196 |
+
|
| 197 |
+
This function assumes that either ``sys.argv`` or ``dist.script_args``
|
| 198 |
+
is already set accordingly.
|
| 199 |
+
"""
|
| 200 |
+
try:
|
| 201 |
+
dist.run_commands()
|
| 202 |
+
except KeyboardInterrupt:
|
| 203 |
+
raise SystemExit("interrupted")
|
| 204 |
+
except OSError as exc:
|
| 205 |
+
if DEBUG:
|
| 206 |
+
sys.stderr.write("error: {}\n".format(exc))
|
| 207 |
+
raise
|
| 208 |
+
else:
|
| 209 |
+
raise SystemExit("error: {}".format(exc))
|
| 210 |
+
|
| 211 |
+
except (DistutilsError, CCompilerError) as msg:
|
| 212 |
+
if DEBUG:
|
| 213 |
+
raise
|
| 214 |
+
else:
|
| 215 |
+
raise SystemExit("error: " + str(msg))
|
| 216 |
+
|
| 217 |
+
return dist
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def run_setup(script_name, script_args=None, stop_after="run"):
|
| 221 |
+
"""Run a setup script in a somewhat controlled environment, and
|
| 222 |
+
return the Distribution instance that drives things. This is useful
|
| 223 |
+
if you need to find out the distribution meta-data (passed as
|
| 224 |
+
keyword args from 'script' to 'setup()', or the contents of the
|
| 225 |
+
config files or command-line.
|
| 226 |
+
|
| 227 |
+
'script_name' is a file that will be read and run with 'exec()';
|
| 228 |
+
'sys.argv[0]' will be replaced with 'script' for the duration of the
|
| 229 |
+
call. 'script_args' is a list of strings; if supplied,
|
| 230 |
+
'sys.argv[1:]' will be replaced by 'script_args' for the duration of
|
| 231 |
+
the call.
|
| 232 |
+
|
| 233 |
+
'stop_after' tells 'setup()' when to stop processing; possible
|
| 234 |
+
values:
|
| 235 |
+
init
|
| 236 |
+
stop after the Distribution instance has been created and
|
| 237 |
+
populated with the keyword arguments to 'setup()'
|
| 238 |
+
config
|
| 239 |
+
stop after config files have been parsed (and their data
|
| 240 |
+
stored in the Distribution instance)
|
| 241 |
+
commandline
|
| 242 |
+
stop after the command-line ('sys.argv[1:]' or 'script_args')
|
| 243 |
+
have been parsed (and the data stored in the Distribution)
|
| 244 |
+
run [default]
|
| 245 |
+
stop after all commands have been run (the same as if 'setup()'
|
| 246 |
+
had been called in the usual way
|
| 247 |
+
|
| 248 |
+
Returns the Distribution instance, which provides all information
|
| 249 |
+
used to drive the Distutils.
|
| 250 |
+
"""
|
| 251 |
+
if stop_after not in ('init', 'config', 'commandline', 'run'):
|
| 252 |
+
raise ValueError("invalid value for 'stop_after': {!r}".format(stop_after))
|
| 253 |
+
|
| 254 |
+
global _setup_stop_after, _setup_distribution
|
| 255 |
+
_setup_stop_after = stop_after
|
| 256 |
+
|
| 257 |
+
save_argv = sys.argv.copy()
|
| 258 |
+
g = {'__file__': script_name, '__name__': '__main__'}
|
| 259 |
+
try:
|
| 260 |
+
try:
|
| 261 |
+
sys.argv[0] = script_name
|
| 262 |
+
if script_args is not None:
|
| 263 |
+
sys.argv[1:] = script_args
|
| 264 |
+
# tokenize.open supports automatic encoding detection
|
| 265 |
+
with tokenize.open(script_name) as f:
|
| 266 |
+
code = f.read().replace(r'\r\n', r'\n')
|
| 267 |
+
exec(code, g)
|
| 268 |
+
finally:
|
| 269 |
+
sys.argv = save_argv
|
| 270 |
+
_setup_stop_after = None
|
| 271 |
+
except SystemExit:
|
| 272 |
+
# Hmm, should we do something if exiting with a non-zero code
|
| 273 |
+
# (ie. error)?
|
| 274 |
+
pass
|
| 275 |
+
|
| 276 |
+
if _setup_distribution is None:
|
| 277 |
+
raise RuntimeError(
|
| 278 |
+
(
|
| 279 |
+
"'distutils.core.setup()' was never called -- "
|
| 280 |
+
"perhaps '%s' is not a Distutils setup script?"
|
| 281 |
+
)
|
| 282 |
+
% script_name
|
| 283 |
+
)
|
| 284 |
+
|
| 285 |
+
# I wonder if the setup script's namespace -- g and l -- would be of
|
| 286 |
+
# any interest to callers?
|
| 287 |
+
# print "_setup_distribution:", _setup_distribution
|
| 288 |
+
return _setup_distribution
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
# run_setup ()
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/cygwinccompiler.py
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.cygwinccompiler
|
| 2 |
+
|
| 3 |
+
Provides the CygwinCCompiler class, a subclass of UnixCCompiler that
|
| 4 |
+
handles the Cygwin port of the GNU C compiler to Windows. It also contains
|
| 5 |
+
the Mingw32CCompiler class which handles the mingw32 port of GCC (same as
|
| 6 |
+
cygwin in no-cygwin mode).
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
import os
|
| 10 |
+
import sys
|
| 11 |
+
import copy
|
| 12 |
+
import shlex
|
| 13 |
+
import warnings
|
| 14 |
+
from subprocess import check_output
|
| 15 |
+
|
| 16 |
+
from distutils.unixccompiler import UnixCCompiler
|
| 17 |
+
from distutils.file_util import write_file
|
| 18 |
+
from distutils.errors import (
|
| 19 |
+
DistutilsExecError,
|
| 20 |
+
DistutilsPlatformError,
|
| 21 |
+
CCompilerError,
|
| 22 |
+
CompileError,
|
| 23 |
+
)
|
| 24 |
+
from distutils.version import LooseVersion, suppress_known_deprecation
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def get_msvcr():
|
| 28 |
+
"""Include the appropriate MSVC runtime library if Python was built
|
| 29 |
+
with MSVC 7.0 or later.
|
| 30 |
+
"""
|
| 31 |
+
msc_pos = sys.version.find('MSC v.')
|
| 32 |
+
if msc_pos != -1:
|
| 33 |
+
msc_ver = sys.version[msc_pos + 6 : msc_pos + 10]
|
| 34 |
+
if msc_ver == '1300':
|
| 35 |
+
# MSVC 7.0
|
| 36 |
+
return ['msvcr70']
|
| 37 |
+
elif msc_ver == '1310':
|
| 38 |
+
# MSVC 7.1
|
| 39 |
+
return ['msvcr71']
|
| 40 |
+
elif msc_ver == '1400':
|
| 41 |
+
# VS2005 / MSVC 8.0
|
| 42 |
+
return ['msvcr80']
|
| 43 |
+
elif msc_ver == '1500':
|
| 44 |
+
# VS2008 / MSVC 9.0
|
| 45 |
+
return ['msvcr90']
|
| 46 |
+
elif msc_ver == '1600':
|
| 47 |
+
# VS2010 / MSVC 10.0
|
| 48 |
+
return ['msvcr100']
|
| 49 |
+
elif msc_ver == '1700':
|
| 50 |
+
# VS2012 / MSVC 11.0
|
| 51 |
+
return ['msvcr110']
|
| 52 |
+
elif msc_ver == '1800':
|
| 53 |
+
# VS2013 / MSVC 12.0
|
| 54 |
+
return ['msvcr120']
|
| 55 |
+
elif 1900 <= int(msc_ver) < 2000:
|
| 56 |
+
# VS2015 / MSVC 14.0
|
| 57 |
+
return ['ucrt', 'vcruntime140']
|
| 58 |
+
else:
|
| 59 |
+
raise ValueError("Unknown MS Compiler version %s " % msc_ver)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
_runtime_library_dirs_msg = (
|
| 63 |
+
"Unable to set runtime library search path on Windows, "
|
| 64 |
+
"usually indicated by `runtime_library_dirs` parameter to Extension"
|
| 65 |
+
)
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
class CygwinCCompiler(UnixCCompiler):
|
| 69 |
+
"""Handles the Cygwin port of the GNU C compiler to Windows."""
|
| 70 |
+
|
| 71 |
+
compiler_type = 'cygwin'
|
| 72 |
+
obj_extension = ".o"
|
| 73 |
+
static_lib_extension = ".a"
|
| 74 |
+
shared_lib_extension = ".dll.a"
|
| 75 |
+
dylib_lib_extension = ".dll"
|
| 76 |
+
static_lib_format = "lib%s%s"
|
| 77 |
+
shared_lib_format = "lib%s%s"
|
| 78 |
+
dylib_lib_format = "cyg%s%s"
|
| 79 |
+
exe_extension = ".exe"
|
| 80 |
+
|
| 81 |
+
def __init__(self, verbose=0, dry_run=0, force=0):
|
| 82 |
+
|
| 83 |
+
super().__init__(verbose, dry_run, force)
|
| 84 |
+
|
| 85 |
+
status, details = check_config_h()
|
| 86 |
+
self.debug_print(
|
| 87 |
+
"Python's GCC status: {} (details: {})".format(status, details)
|
| 88 |
+
)
|
| 89 |
+
if status is not CONFIG_H_OK:
|
| 90 |
+
self.warn(
|
| 91 |
+
"Python's pyconfig.h doesn't seem to support your compiler. "
|
| 92 |
+
"Reason: %s. "
|
| 93 |
+
"Compiling may fail because of undefined preprocessor macros." % details
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
self.cc = os.environ.get('CC', 'gcc')
|
| 97 |
+
self.cxx = os.environ.get('CXX', 'g++')
|
| 98 |
+
|
| 99 |
+
self.linker_dll = self.cc
|
| 100 |
+
shared_option = "-shared"
|
| 101 |
+
|
| 102 |
+
self.set_executables(
|
| 103 |
+
compiler='%s -mcygwin -O -Wall' % self.cc,
|
| 104 |
+
compiler_so='%s -mcygwin -mdll -O -Wall' % self.cc,
|
| 105 |
+
compiler_cxx='%s -mcygwin -O -Wall' % self.cxx,
|
| 106 |
+
linker_exe='%s -mcygwin' % self.cc,
|
| 107 |
+
linker_so=('{} -mcygwin {}'.format(self.linker_dll, shared_option)),
|
| 108 |
+
)
|
| 109 |
+
|
| 110 |
+
# Include the appropriate MSVC runtime library if Python was built
|
| 111 |
+
# with MSVC 7.0 or later.
|
| 112 |
+
self.dll_libraries = get_msvcr()
|
| 113 |
+
|
| 114 |
+
@property
|
| 115 |
+
def gcc_version(self):
|
| 116 |
+
# Older numpy dependend on this existing to check for ancient
|
| 117 |
+
# gcc versions. This doesn't make much sense with clang etc so
|
| 118 |
+
# just hardcode to something recent.
|
| 119 |
+
# https://github.com/numpy/numpy/pull/20333
|
| 120 |
+
warnings.warn(
|
| 121 |
+
"gcc_version attribute of CygwinCCompiler is deprecated. "
|
| 122 |
+
"Instead of returning actual gcc version a fixed value 11.2.0 is returned.",
|
| 123 |
+
DeprecationWarning,
|
| 124 |
+
stacklevel=2,
|
| 125 |
+
)
|
| 126 |
+
with suppress_known_deprecation():
|
| 127 |
+
return LooseVersion("11.2.0")
|
| 128 |
+
|
| 129 |
+
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
|
| 130 |
+
"""Compiles the source by spawning GCC and windres if needed."""
|
| 131 |
+
if ext == '.rc' or ext == '.res':
|
| 132 |
+
# gcc needs '.res' and '.rc' compiled to object files !!!
|
| 133 |
+
try:
|
| 134 |
+
self.spawn(["windres", "-i", src, "-o", obj])
|
| 135 |
+
except DistutilsExecError as msg:
|
| 136 |
+
raise CompileError(msg)
|
| 137 |
+
else: # for other files use the C-compiler
|
| 138 |
+
try:
|
| 139 |
+
self.spawn(
|
| 140 |
+
self.compiler_so + cc_args + [src, '-o', obj] + extra_postargs
|
| 141 |
+
)
|
| 142 |
+
except DistutilsExecError as msg:
|
| 143 |
+
raise CompileError(msg)
|
| 144 |
+
|
| 145 |
+
def link(
|
| 146 |
+
self,
|
| 147 |
+
target_desc,
|
| 148 |
+
objects,
|
| 149 |
+
output_filename,
|
| 150 |
+
output_dir=None,
|
| 151 |
+
libraries=None,
|
| 152 |
+
library_dirs=None,
|
| 153 |
+
runtime_library_dirs=None,
|
| 154 |
+
export_symbols=None,
|
| 155 |
+
debug=0,
|
| 156 |
+
extra_preargs=None,
|
| 157 |
+
extra_postargs=None,
|
| 158 |
+
build_temp=None,
|
| 159 |
+
target_lang=None,
|
| 160 |
+
):
|
| 161 |
+
"""Link the objects."""
|
| 162 |
+
# use separate copies, so we can modify the lists
|
| 163 |
+
extra_preargs = copy.copy(extra_preargs or [])
|
| 164 |
+
libraries = copy.copy(libraries or [])
|
| 165 |
+
objects = copy.copy(objects or [])
|
| 166 |
+
|
| 167 |
+
if runtime_library_dirs:
|
| 168 |
+
self.warn(_runtime_library_dirs_msg)
|
| 169 |
+
|
| 170 |
+
# Additional libraries
|
| 171 |
+
libraries.extend(self.dll_libraries)
|
| 172 |
+
|
| 173 |
+
# handle export symbols by creating a def-file
|
| 174 |
+
# with executables this only works with gcc/ld as linker
|
| 175 |
+
if (export_symbols is not None) and (
|
| 176 |
+
target_desc != self.EXECUTABLE or self.linker_dll == "gcc"
|
| 177 |
+
):
|
| 178 |
+
# (The linker doesn't do anything if output is up-to-date.
|
| 179 |
+
# So it would probably better to check if we really need this,
|
| 180 |
+
# but for this we had to insert some unchanged parts of
|
| 181 |
+
# UnixCCompiler, and this is not what we want.)
|
| 182 |
+
|
| 183 |
+
# we want to put some files in the same directory as the
|
| 184 |
+
# object files are, build_temp doesn't help much
|
| 185 |
+
# where are the object files
|
| 186 |
+
temp_dir = os.path.dirname(objects[0])
|
| 187 |
+
# name of dll to give the helper files the same base name
|
| 188 |
+
(dll_name, dll_extension) = os.path.splitext(
|
| 189 |
+
os.path.basename(output_filename)
|
| 190 |
+
)
|
| 191 |
+
|
| 192 |
+
# generate the filenames for these files
|
| 193 |
+
def_file = os.path.join(temp_dir, dll_name + ".def")
|
| 194 |
+
|
| 195 |
+
# Generate .def file
|
| 196 |
+
contents = ["LIBRARY %s" % os.path.basename(output_filename), "EXPORTS"]
|
| 197 |
+
for sym in export_symbols:
|
| 198 |
+
contents.append(sym)
|
| 199 |
+
self.execute(write_file, (def_file, contents), "writing %s" % def_file)
|
| 200 |
+
|
| 201 |
+
# next add options for def-file
|
| 202 |
+
|
| 203 |
+
# for gcc/ld the def-file is specified as any object files
|
| 204 |
+
objects.append(def_file)
|
| 205 |
+
|
| 206 |
+
# end: if ((export_symbols is not None) and
|
| 207 |
+
# (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
|
| 208 |
+
|
| 209 |
+
# who wants symbols and a many times larger output file
|
| 210 |
+
# should explicitly switch the debug mode on
|
| 211 |
+
# otherwise we let ld strip the output file
|
| 212 |
+
# (On my machine: 10KiB < stripped_file < ??100KiB
|
| 213 |
+
# unstripped_file = stripped_file + XXX KiB
|
| 214 |
+
# ( XXX=254 for a typical python extension))
|
| 215 |
+
if not debug:
|
| 216 |
+
extra_preargs.append("-s")
|
| 217 |
+
|
| 218 |
+
UnixCCompiler.link(
|
| 219 |
+
self,
|
| 220 |
+
target_desc,
|
| 221 |
+
objects,
|
| 222 |
+
output_filename,
|
| 223 |
+
output_dir,
|
| 224 |
+
libraries,
|
| 225 |
+
library_dirs,
|
| 226 |
+
runtime_library_dirs,
|
| 227 |
+
None, # export_symbols, we do this in our def-file
|
| 228 |
+
debug,
|
| 229 |
+
extra_preargs,
|
| 230 |
+
extra_postargs,
|
| 231 |
+
build_temp,
|
| 232 |
+
target_lang,
|
| 233 |
+
)
|
| 234 |
+
|
| 235 |
+
def runtime_library_dir_option(self, dir):
|
| 236 |
+
# cygwin doesn't support rpath. While in theory we could error
|
| 237 |
+
# out like MSVC does, code might expect it to work like on Unix, so
|
| 238 |
+
# just warn and hope for the best.
|
| 239 |
+
self.warn(_runtime_library_dirs_msg)
|
| 240 |
+
return []
|
| 241 |
+
|
| 242 |
+
# -- Miscellaneous methods -----------------------------------------
|
| 243 |
+
|
| 244 |
+
def _make_out_path(self, output_dir, strip_dir, src_name):
|
| 245 |
+
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
|
| 246 |
+
norm_src_name = os.path.normcase(src_name)
|
| 247 |
+
return super()._make_out_path(output_dir, strip_dir, norm_src_name)
|
| 248 |
+
|
| 249 |
+
@property
|
| 250 |
+
def out_extensions(self):
|
| 251 |
+
"""
|
| 252 |
+
Add support for rc and res files.
|
| 253 |
+
"""
|
| 254 |
+
return {
|
| 255 |
+
**super().out_extensions,
|
| 256 |
+
**{ext: ext + self.obj_extension for ext in ('.res', '.rc')},
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
|
| 260 |
+
# the same as cygwin plus some additional parameters
|
| 261 |
+
class Mingw32CCompiler(CygwinCCompiler):
|
| 262 |
+
"""Handles the Mingw32 port of the GNU C compiler to Windows."""
|
| 263 |
+
|
| 264 |
+
compiler_type = 'mingw32'
|
| 265 |
+
|
| 266 |
+
def __init__(self, verbose=0, dry_run=0, force=0):
|
| 267 |
+
|
| 268 |
+
super().__init__(verbose, dry_run, force)
|
| 269 |
+
|
| 270 |
+
shared_option = "-shared"
|
| 271 |
+
|
| 272 |
+
if is_cygwincc(self.cc):
|
| 273 |
+
raise CCompilerError('Cygwin gcc cannot be used with --compiler=mingw32')
|
| 274 |
+
|
| 275 |
+
self.set_executables(
|
| 276 |
+
compiler='%s -O -Wall' % self.cc,
|
| 277 |
+
compiler_so='%s -mdll -O -Wall' % self.cc,
|
| 278 |
+
compiler_cxx='%s -O -Wall' % self.cxx,
|
| 279 |
+
linker_exe='%s' % self.cc,
|
| 280 |
+
linker_so='{} {}'.format(self.linker_dll, shared_option),
|
| 281 |
+
)
|
| 282 |
+
|
| 283 |
+
# Maybe we should also append -mthreads, but then the finished
|
| 284 |
+
# dlls need another dll (mingwm10.dll see Mingw32 docs)
|
| 285 |
+
# (-mthreads: Support thread-safe exception handling on `Mingw32')
|
| 286 |
+
|
| 287 |
+
# no additional libraries needed
|
| 288 |
+
self.dll_libraries = []
|
| 289 |
+
|
| 290 |
+
# Include the appropriate MSVC runtime library if Python was built
|
| 291 |
+
# with MSVC 7.0 or later.
|
| 292 |
+
self.dll_libraries = get_msvcr()
|
| 293 |
+
|
| 294 |
+
def runtime_library_dir_option(self, dir):
|
| 295 |
+
raise DistutilsPlatformError(_runtime_library_dirs_msg)
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
# Because these compilers aren't configured in Python's pyconfig.h file by
|
| 299 |
+
# default, we should at least warn the user if he is using an unmodified
|
| 300 |
+
# version.
|
| 301 |
+
|
| 302 |
+
CONFIG_H_OK = "ok"
|
| 303 |
+
CONFIG_H_NOTOK = "not ok"
|
| 304 |
+
CONFIG_H_UNCERTAIN = "uncertain"
|
| 305 |
+
|
| 306 |
+
|
| 307 |
+
def check_config_h():
|
| 308 |
+
"""Check if the current Python installation appears amenable to building
|
| 309 |
+
extensions with GCC.
|
| 310 |
+
|
| 311 |
+
Returns a tuple (status, details), where 'status' is one of the following
|
| 312 |
+
constants:
|
| 313 |
+
|
| 314 |
+
- CONFIG_H_OK: all is well, go ahead and compile
|
| 315 |
+
- CONFIG_H_NOTOK: doesn't look good
|
| 316 |
+
- CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h
|
| 317 |
+
|
| 318 |
+
'details' is a human-readable string explaining the situation.
|
| 319 |
+
|
| 320 |
+
Note there are two ways to conclude "OK": either 'sys.version' contains
|
| 321 |
+
the string "GCC" (implying that this Python was built with GCC), or the
|
| 322 |
+
installed "pyconfig.h" contains the string "__GNUC__".
|
| 323 |
+
"""
|
| 324 |
+
|
| 325 |
+
# XXX since this function also checks sys.version, it's not strictly a
|
| 326 |
+
# "pyconfig.h" check -- should probably be renamed...
|
| 327 |
+
|
| 328 |
+
from distutils import sysconfig
|
| 329 |
+
|
| 330 |
+
# if sys.version contains GCC then python was compiled with GCC, and the
|
| 331 |
+
# pyconfig.h file should be OK
|
| 332 |
+
if "GCC" in sys.version:
|
| 333 |
+
return CONFIG_H_OK, "sys.version mentions 'GCC'"
|
| 334 |
+
|
| 335 |
+
# Clang would also work
|
| 336 |
+
if "Clang" in sys.version:
|
| 337 |
+
return CONFIG_H_OK, "sys.version mentions 'Clang'"
|
| 338 |
+
|
| 339 |
+
# let's see if __GNUC__ is mentioned in python.h
|
| 340 |
+
fn = sysconfig.get_config_h_filename()
|
| 341 |
+
try:
|
| 342 |
+
config_h = open(fn)
|
| 343 |
+
try:
|
| 344 |
+
if "__GNUC__" in config_h.read():
|
| 345 |
+
return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn
|
| 346 |
+
else:
|
| 347 |
+
return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn
|
| 348 |
+
finally:
|
| 349 |
+
config_h.close()
|
| 350 |
+
except OSError as exc:
|
| 351 |
+
return (CONFIG_H_UNCERTAIN, "couldn't read '{}': {}".format(fn, exc.strerror))
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
def is_cygwincc(cc):
|
| 355 |
+
'''Try to determine if the compiler that would be used is from cygwin.'''
|
| 356 |
+
out_string = check_output(shlex.split(cc) + ['-dumpmachine'])
|
| 357 |
+
return out_string.strip().endswith(b'cygwin')
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
get_versions = None
|
| 361 |
+
"""
|
| 362 |
+
A stand-in for the previous get_versions() function to prevent failures
|
| 363 |
+
when monkeypatched. See pypa/setuptools#2969.
|
| 364 |
+
"""
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/debug.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
# If DISTUTILS_DEBUG is anything other than the empty string, we run in
|
| 4 |
+
# debug mode.
|
| 5 |
+
DEBUG = os.environ.get('DISTUTILS_DEBUG')
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/dep_util.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.dep_util
|
| 2 |
+
|
| 3 |
+
Utility functions for simple, timestamp-based dependency of files
|
| 4 |
+
and groups of files; also, function based entirely on such
|
| 5 |
+
timestamp dependency analysis."""
|
| 6 |
+
|
| 7 |
+
import os
|
| 8 |
+
from distutils.errors import DistutilsFileError
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def newer(source, target):
|
| 12 |
+
"""Return true if 'source' exists and is more recently modified than
|
| 13 |
+
'target', or if 'source' exists and 'target' doesn't. Return false if
|
| 14 |
+
both exist and 'target' is the same age or younger than 'source'.
|
| 15 |
+
Raise DistutilsFileError if 'source' does not exist.
|
| 16 |
+
"""
|
| 17 |
+
if not os.path.exists(source):
|
| 18 |
+
raise DistutilsFileError("file '%s' does not exist" % os.path.abspath(source))
|
| 19 |
+
if not os.path.exists(target):
|
| 20 |
+
return 1
|
| 21 |
+
|
| 22 |
+
from stat import ST_MTIME
|
| 23 |
+
|
| 24 |
+
mtime1 = os.stat(source)[ST_MTIME]
|
| 25 |
+
mtime2 = os.stat(target)[ST_MTIME]
|
| 26 |
+
|
| 27 |
+
return mtime1 > mtime2
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
# newer ()
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def newer_pairwise(sources, targets):
|
| 34 |
+
"""Walk two filename lists in parallel, testing if each source is newer
|
| 35 |
+
than its corresponding target. Return a pair of lists (sources,
|
| 36 |
+
targets) where source is newer than target, according to the semantics
|
| 37 |
+
of 'newer()'.
|
| 38 |
+
"""
|
| 39 |
+
if len(sources) != len(targets):
|
| 40 |
+
raise ValueError("'sources' and 'targets' must be same length")
|
| 41 |
+
|
| 42 |
+
# build a pair of lists (sources, targets) where source is newer
|
| 43 |
+
n_sources = []
|
| 44 |
+
n_targets = []
|
| 45 |
+
for i in range(len(sources)):
|
| 46 |
+
if newer(sources[i], targets[i]):
|
| 47 |
+
n_sources.append(sources[i])
|
| 48 |
+
n_targets.append(targets[i])
|
| 49 |
+
|
| 50 |
+
return (n_sources, n_targets)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
# newer_pairwise ()
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def newer_group(sources, target, missing='error'):
|
| 57 |
+
"""Return true if 'target' is out-of-date with respect to any file
|
| 58 |
+
listed in 'sources'. In other words, if 'target' exists and is newer
|
| 59 |
+
than every file in 'sources', return false; otherwise return true.
|
| 60 |
+
'missing' controls what we do when a source file is missing; the
|
| 61 |
+
default ("error") is to blow up with an OSError from inside 'stat()';
|
| 62 |
+
if it is "ignore", we silently drop any missing source files; if it is
|
| 63 |
+
"newer", any missing source files make us assume that 'target' is
|
| 64 |
+
out-of-date (this is handy in "dry-run" mode: it'll make you pretend to
|
| 65 |
+
carry out commands that wouldn't work because inputs are missing, but
|
| 66 |
+
that doesn't matter because you're not actually going to run the
|
| 67 |
+
commands).
|
| 68 |
+
"""
|
| 69 |
+
# If the target doesn't even exist, then it's definitely out-of-date.
|
| 70 |
+
if not os.path.exists(target):
|
| 71 |
+
return 1
|
| 72 |
+
|
| 73 |
+
# Otherwise we have to find out the hard way: if *any* source file
|
| 74 |
+
# is more recent than 'target', then 'target' is out-of-date and
|
| 75 |
+
# we can immediately return true. If we fall through to the end
|
| 76 |
+
# of the loop, then 'target' is up-to-date and we return false.
|
| 77 |
+
from stat import ST_MTIME
|
| 78 |
+
|
| 79 |
+
target_mtime = os.stat(target)[ST_MTIME]
|
| 80 |
+
for source in sources:
|
| 81 |
+
if not os.path.exists(source):
|
| 82 |
+
if missing == 'error': # blow up when we stat() the file
|
| 83 |
+
pass
|
| 84 |
+
elif missing == 'ignore': # missing source dropped from
|
| 85 |
+
continue # target's dependency list
|
| 86 |
+
elif missing == 'newer': # missing source means target is
|
| 87 |
+
return 1 # out-of-date
|
| 88 |
+
|
| 89 |
+
source_mtime = os.stat(source)[ST_MTIME]
|
| 90 |
+
if source_mtime > target_mtime:
|
| 91 |
+
return 1
|
| 92 |
+
else:
|
| 93 |
+
return 0
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
# newer_group ()
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/dist.py
ADDED
|
@@ -0,0 +1,1286 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.dist
|
| 2 |
+
|
| 3 |
+
Provides the Distribution class, which represents the module distribution
|
| 4 |
+
being built/installed/distributed.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import sys
|
| 8 |
+
import os
|
| 9 |
+
import re
|
| 10 |
+
import pathlib
|
| 11 |
+
import contextlib
|
| 12 |
+
from email import message_from_file
|
| 13 |
+
|
| 14 |
+
try:
|
| 15 |
+
import warnings
|
| 16 |
+
except ImportError:
|
| 17 |
+
warnings = None
|
| 18 |
+
|
| 19 |
+
from distutils.errors import (
|
| 20 |
+
DistutilsOptionError,
|
| 21 |
+
DistutilsModuleError,
|
| 22 |
+
DistutilsArgError,
|
| 23 |
+
DistutilsClassError,
|
| 24 |
+
)
|
| 25 |
+
from distutils.fancy_getopt import FancyGetopt, translate_longopt
|
| 26 |
+
from distutils.util import check_environ, strtobool, rfc822_escape
|
| 27 |
+
from distutils import log
|
| 28 |
+
from distutils.debug import DEBUG
|
| 29 |
+
|
| 30 |
+
# Regex to define acceptable Distutils command names. This is not *quite*
|
| 31 |
+
# the same as a Python NAME -- I don't allow leading underscores. The fact
|
| 32 |
+
# that they're very similar is no coincidence; the default naming scheme is
|
| 33 |
+
# to look for a Python module named after the command.
|
| 34 |
+
command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$')
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def _ensure_list(value, fieldname):
|
| 38 |
+
if isinstance(value, str):
|
| 39 |
+
# a string containing comma separated values is okay. It will
|
| 40 |
+
# be converted to a list by Distribution.finalize_options().
|
| 41 |
+
pass
|
| 42 |
+
elif not isinstance(value, list):
|
| 43 |
+
# passing a tuple or an iterator perhaps, warn and convert
|
| 44 |
+
typename = type(value).__name__
|
| 45 |
+
msg = "Warning: '{fieldname}' should be a list, got type '{typename}'"
|
| 46 |
+
msg = msg.format(**locals())
|
| 47 |
+
log.log(log.WARN, msg)
|
| 48 |
+
value = list(value)
|
| 49 |
+
return value
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
class Distribution:
|
| 53 |
+
"""The core of the Distutils. Most of the work hiding behind 'setup'
|
| 54 |
+
is really done within a Distribution instance, which farms the work out
|
| 55 |
+
to the Distutils commands specified on the command line.
|
| 56 |
+
|
| 57 |
+
Setup scripts will almost never instantiate Distribution directly,
|
| 58 |
+
unless the 'setup()' function is totally inadequate to their needs.
|
| 59 |
+
However, it is conceivable that a setup script might wish to subclass
|
| 60 |
+
Distribution for some specialized purpose, and then pass the subclass
|
| 61 |
+
to 'setup()' as the 'distclass' keyword argument. If so, it is
|
| 62 |
+
necessary to respect the expectations that 'setup' has of Distribution.
|
| 63 |
+
See the code for 'setup()', in core.py, for details.
|
| 64 |
+
"""
|
| 65 |
+
|
| 66 |
+
# 'global_options' describes the command-line options that may be
|
| 67 |
+
# supplied to the setup script prior to any actual commands.
|
| 68 |
+
# Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of
|
| 69 |
+
# these global options. This list should be kept to a bare minimum,
|
| 70 |
+
# since every global option is also valid as a command option -- and we
|
| 71 |
+
# don't want to pollute the commands with too many options that they
|
| 72 |
+
# have minimal control over.
|
| 73 |
+
# The fourth entry for verbose means that it can be repeated.
|
| 74 |
+
global_options = [
|
| 75 |
+
('verbose', 'v', "run verbosely (default)", 1),
|
| 76 |
+
('quiet', 'q', "run quietly (turns verbosity off)"),
|
| 77 |
+
('dry-run', 'n', "don't actually do anything"),
|
| 78 |
+
('help', 'h', "show detailed help message"),
|
| 79 |
+
('no-user-cfg', None, 'ignore pydistutils.cfg in your home directory'),
|
| 80 |
+
]
|
| 81 |
+
|
| 82 |
+
# 'common_usage' is a short (2-3 line) string describing the common
|
| 83 |
+
# usage of the setup script.
|
| 84 |
+
common_usage = """\
|
| 85 |
+
Common commands: (see '--help-commands' for more)
|
| 86 |
+
|
| 87 |
+
setup.py build will build the package underneath 'build/'
|
| 88 |
+
setup.py install will install the package
|
| 89 |
+
"""
|
| 90 |
+
|
| 91 |
+
# options that are not propagated to the commands
|
| 92 |
+
display_options = [
|
| 93 |
+
('help-commands', None, "list all available commands"),
|
| 94 |
+
('name', None, "print package name"),
|
| 95 |
+
('version', 'V', "print package version"),
|
| 96 |
+
('fullname', None, "print <package name>-<version>"),
|
| 97 |
+
('author', None, "print the author's name"),
|
| 98 |
+
('author-email', None, "print the author's email address"),
|
| 99 |
+
('maintainer', None, "print the maintainer's name"),
|
| 100 |
+
('maintainer-email', None, "print the maintainer's email address"),
|
| 101 |
+
('contact', None, "print the maintainer's name if known, else the author's"),
|
| 102 |
+
(
|
| 103 |
+
'contact-email',
|
| 104 |
+
None,
|
| 105 |
+
"print the maintainer's email address if known, else the author's",
|
| 106 |
+
),
|
| 107 |
+
('url', None, "print the URL for this package"),
|
| 108 |
+
('license', None, "print the license of the package"),
|
| 109 |
+
('licence', None, "alias for --license"),
|
| 110 |
+
('description', None, "print the package description"),
|
| 111 |
+
('long-description', None, "print the long package description"),
|
| 112 |
+
('platforms', None, "print the list of platforms"),
|
| 113 |
+
('classifiers', None, "print the list of classifiers"),
|
| 114 |
+
('keywords', None, "print the list of keywords"),
|
| 115 |
+
('provides', None, "print the list of packages/modules provided"),
|
| 116 |
+
('requires', None, "print the list of packages/modules required"),
|
| 117 |
+
('obsoletes', None, "print the list of packages/modules made obsolete"),
|
| 118 |
+
]
|
| 119 |
+
display_option_names = [translate_longopt(x[0]) for x in display_options]
|
| 120 |
+
|
| 121 |
+
# negative options are options that exclude other options
|
| 122 |
+
negative_opt = {'quiet': 'verbose'}
|
| 123 |
+
|
| 124 |
+
# -- Creation/initialization methods -------------------------------
|
| 125 |
+
|
| 126 |
+
def __init__(self, attrs=None): # noqa: C901
|
| 127 |
+
"""Construct a new Distribution instance: initialize all the
|
| 128 |
+
attributes of a Distribution, and then use 'attrs' (a dictionary
|
| 129 |
+
mapping attribute names to values) to assign some of those
|
| 130 |
+
attributes their "real" values. (Any attributes not mentioned in
|
| 131 |
+
'attrs' will be assigned to some null value: 0, None, an empty list
|
| 132 |
+
or dictionary, etc.) Most importantly, initialize the
|
| 133 |
+
'command_obj' attribute to the empty dictionary; this will be
|
| 134 |
+
filled in with real command objects by 'parse_command_line()'.
|
| 135 |
+
"""
|
| 136 |
+
|
| 137 |
+
# Default values for our command-line options
|
| 138 |
+
self.verbose = 1
|
| 139 |
+
self.dry_run = 0
|
| 140 |
+
self.help = 0
|
| 141 |
+
for attr in self.display_option_names:
|
| 142 |
+
setattr(self, attr, 0)
|
| 143 |
+
|
| 144 |
+
# Store the distribution meta-data (name, version, author, and so
|
| 145 |
+
# forth) in a separate object -- we're getting to have enough
|
| 146 |
+
# information here (and enough command-line options) that it's
|
| 147 |
+
# worth it. Also delegate 'get_XXX()' methods to the 'metadata'
|
| 148 |
+
# object in a sneaky and underhanded (but efficient!) way.
|
| 149 |
+
self.metadata = DistributionMetadata()
|
| 150 |
+
for basename in self.metadata._METHOD_BASENAMES:
|
| 151 |
+
method_name = "get_" + basename
|
| 152 |
+
setattr(self, method_name, getattr(self.metadata, method_name))
|
| 153 |
+
|
| 154 |
+
# 'cmdclass' maps command names to class objects, so we
|
| 155 |
+
# can 1) quickly figure out which class to instantiate when
|
| 156 |
+
# we need to create a new command object, and 2) have a way
|
| 157 |
+
# for the setup script to override command classes
|
| 158 |
+
self.cmdclass = {}
|
| 159 |
+
|
| 160 |
+
# 'command_packages' is a list of packages in which commands
|
| 161 |
+
# are searched for. The factory for command 'foo' is expected
|
| 162 |
+
# to be named 'foo' in the module 'foo' in one of the packages
|
| 163 |
+
# named here. This list is searched from the left; an error
|
| 164 |
+
# is raised if no named package provides the command being
|
| 165 |
+
# searched for. (Always access using get_command_packages().)
|
| 166 |
+
self.command_packages = None
|
| 167 |
+
|
| 168 |
+
# 'script_name' and 'script_args' are usually set to sys.argv[0]
|
| 169 |
+
# and sys.argv[1:], but they can be overridden when the caller is
|
| 170 |
+
# not necessarily a setup script run from the command-line.
|
| 171 |
+
self.script_name = None
|
| 172 |
+
self.script_args = None
|
| 173 |
+
|
| 174 |
+
# 'command_options' is where we store command options between
|
| 175 |
+
# parsing them (from config files, the command-line, etc.) and when
|
| 176 |
+
# they are actually needed -- ie. when the command in question is
|
| 177 |
+
# instantiated. It is a dictionary of dictionaries of 2-tuples:
|
| 178 |
+
# command_options = { command_name : { option : (source, value) } }
|
| 179 |
+
self.command_options = {}
|
| 180 |
+
|
| 181 |
+
# 'dist_files' is the list of (command, pyversion, file) that
|
| 182 |
+
# have been created by any dist commands run so far. This is
|
| 183 |
+
# filled regardless of whether the run is dry or not. pyversion
|
| 184 |
+
# gives sysconfig.get_python_version() if the dist file is
|
| 185 |
+
# specific to a Python version, 'any' if it is good for all
|
| 186 |
+
# Python versions on the target platform, and '' for a source
|
| 187 |
+
# file. pyversion should not be used to specify minimum or
|
| 188 |
+
# maximum required Python versions; use the metainfo for that
|
| 189 |
+
# instead.
|
| 190 |
+
self.dist_files = []
|
| 191 |
+
|
| 192 |
+
# These options are really the business of various commands, rather
|
| 193 |
+
# than of the Distribution itself. We provide aliases for them in
|
| 194 |
+
# Distribution as a convenience to the developer.
|
| 195 |
+
self.packages = None
|
| 196 |
+
self.package_data = {}
|
| 197 |
+
self.package_dir = None
|
| 198 |
+
self.py_modules = None
|
| 199 |
+
self.libraries = None
|
| 200 |
+
self.headers = None
|
| 201 |
+
self.ext_modules = None
|
| 202 |
+
self.ext_package = None
|
| 203 |
+
self.include_dirs = None
|
| 204 |
+
self.extra_path = None
|
| 205 |
+
self.scripts = None
|
| 206 |
+
self.data_files = None
|
| 207 |
+
self.password = ''
|
| 208 |
+
|
| 209 |
+
# And now initialize bookkeeping stuff that can't be supplied by
|
| 210 |
+
# the caller at all. 'command_obj' maps command names to
|
| 211 |
+
# Command instances -- that's how we enforce that every command
|
| 212 |
+
# class is a singleton.
|
| 213 |
+
self.command_obj = {}
|
| 214 |
+
|
| 215 |
+
# 'have_run' maps command names to boolean values; it keeps track
|
| 216 |
+
# of whether we have actually run a particular command, to make it
|
| 217 |
+
# cheap to "run" a command whenever we think we might need to -- if
|
| 218 |
+
# it's already been done, no need for expensive filesystem
|
| 219 |
+
# operations, we just check the 'have_run' dictionary and carry on.
|
| 220 |
+
# It's only safe to query 'have_run' for a command class that has
|
| 221 |
+
# been instantiated -- a false value will be inserted when the
|
| 222 |
+
# command object is created, and replaced with a true value when
|
| 223 |
+
# the command is successfully run. Thus it's probably best to use
|
| 224 |
+
# '.get()' rather than a straight lookup.
|
| 225 |
+
self.have_run = {}
|
| 226 |
+
|
| 227 |
+
# Now we'll use the attrs dictionary (ultimately, keyword args from
|
| 228 |
+
# the setup script) to possibly override any or all of these
|
| 229 |
+
# distribution options.
|
| 230 |
+
|
| 231 |
+
if attrs:
|
| 232 |
+
# Pull out the set of command options and work on them
|
| 233 |
+
# specifically. Note that this order guarantees that aliased
|
| 234 |
+
# command options will override any supplied redundantly
|
| 235 |
+
# through the general options dictionary.
|
| 236 |
+
options = attrs.get('options')
|
| 237 |
+
if options is not None:
|
| 238 |
+
del attrs['options']
|
| 239 |
+
for (command, cmd_options) in options.items():
|
| 240 |
+
opt_dict = self.get_option_dict(command)
|
| 241 |
+
for (opt, val) in cmd_options.items():
|
| 242 |
+
opt_dict[opt] = ("setup script", val)
|
| 243 |
+
|
| 244 |
+
if 'licence' in attrs:
|
| 245 |
+
attrs['license'] = attrs['licence']
|
| 246 |
+
del attrs['licence']
|
| 247 |
+
msg = "'licence' distribution option is deprecated; use 'license'"
|
| 248 |
+
if warnings is not None:
|
| 249 |
+
warnings.warn(msg)
|
| 250 |
+
else:
|
| 251 |
+
sys.stderr.write(msg + "\n")
|
| 252 |
+
|
| 253 |
+
# Now work on the rest of the attributes. Any attribute that's
|
| 254 |
+
# not already defined is invalid!
|
| 255 |
+
for (key, val) in attrs.items():
|
| 256 |
+
if hasattr(self.metadata, "set_" + key):
|
| 257 |
+
getattr(self.metadata, "set_" + key)(val)
|
| 258 |
+
elif hasattr(self.metadata, key):
|
| 259 |
+
setattr(self.metadata, key, val)
|
| 260 |
+
elif hasattr(self, key):
|
| 261 |
+
setattr(self, key, val)
|
| 262 |
+
else:
|
| 263 |
+
msg = "Unknown distribution option: %s" % repr(key)
|
| 264 |
+
warnings.warn(msg)
|
| 265 |
+
|
| 266 |
+
# no-user-cfg is handled before other command line args
|
| 267 |
+
# because other args override the config files, and this
|
| 268 |
+
# one is needed before we can load the config files.
|
| 269 |
+
# If attrs['script_args'] wasn't passed, assume false.
|
| 270 |
+
#
|
| 271 |
+
# This also make sure we just look at the global options
|
| 272 |
+
self.want_user_cfg = True
|
| 273 |
+
|
| 274 |
+
if self.script_args is not None:
|
| 275 |
+
for arg in self.script_args:
|
| 276 |
+
if not arg.startswith('-'):
|
| 277 |
+
break
|
| 278 |
+
if arg == '--no-user-cfg':
|
| 279 |
+
self.want_user_cfg = False
|
| 280 |
+
break
|
| 281 |
+
|
| 282 |
+
self.finalize_options()
|
| 283 |
+
|
| 284 |
+
def get_option_dict(self, command):
|
| 285 |
+
"""Get the option dictionary for a given command. If that
|
| 286 |
+
command's option dictionary hasn't been created yet, then create it
|
| 287 |
+
and return the new dictionary; otherwise, return the existing
|
| 288 |
+
option dictionary.
|
| 289 |
+
"""
|
| 290 |
+
dict = self.command_options.get(command)
|
| 291 |
+
if dict is None:
|
| 292 |
+
dict = self.command_options[command] = {}
|
| 293 |
+
return dict
|
| 294 |
+
|
| 295 |
+
def dump_option_dicts(self, header=None, commands=None, indent=""):
|
| 296 |
+
from pprint import pformat
|
| 297 |
+
|
| 298 |
+
if commands is None: # dump all command option dicts
|
| 299 |
+
commands = sorted(self.command_options.keys())
|
| 300 |
+
|
| 301 |
+
if header is not None:
|
| 302 |
+
self.announce(indent + header)
|
| 303 |
+
indent = indent + " "
|
| 304 |
+
|
| 305 |
+
if not commands:
|
| 306 |
+
self.announce(indent + "no commands known yet")
|
| 307 |
+
return
|
| 308 |
+
|
| 309 |
+
for cmd_name in commands:
|
| 310 |
+
opt_dict = self.command_options.get(cmd_name)
|
| 311 |
+
if opt_dict is None:
|
| 312 |
+
self.announce(indent + "no option dict for '%s' command" % cmd_name)
|
| 313 |
+
else:
|
| 314 |
+
self.announce(indent + "option dict for '%s' command:" % cmd_name)
|
| 315 |
+
out = pformat(opt_dict)
|
| 316 |
+
for line in out.split('\n'):
|
| 317 |
+
self.announce(indent + " " + line)
|
| 318 |
+
|
| 319 |
+
# -- Config file finding/parsing methods ---------------------------
|
| 320 |
+
|
| 321 |
+
def find_config_files(self):
|
| 322 |
+
"""Find as many configuration files as should be processed for this
|
| 323 |
+
platform, and return a list of filenames in the order in which they
|
| 324 |
+
should be parsed. The filenames returned are guaranteed to exist
|
| 325 |
+
(modulo nasty race conditions).
|
| 326 |
+
|
| 327 |
+
There are multiple possible config files:
|
| 328 |
+
- distutils.cfg in the Distutils installation directory (i.e.
|
| 329 |
+
where the top-level Distutils __inst__.py file lives)
|
| 330 |
+
- a file in the user's home directory named .pydistutils.cfg
|
| 331 |
+
on Unix and pydistutils.cfg on Windows/Mac; may be disabled
|
| 332 |
+
with the ``--no-user-cfg`` option
|
| 333 |
+
- setup.cfg in the current directory
|
| 334 |
+
- a file named by an environment variable
|
| 335 |
+
"""
|
| 336 |
+
check_environ()
|
| 337 |
+
files = [str(path) for path in self._gen_paths() if os.path.isfile(path)]
|
| 338 |
+
|
| 339 |
+
if DEBUG:
|
| 340 |
+
self.announce("using config files: %s" % ', '.join(files))
|
| 341 |
+
|
| 342 |
+
return files
|
| 343 |
+
|
| 344 |
+
def _gen_paths(self):
|
| 345 |
+
# The system-wide Distutils config file
|
| 346 |
+
sys_dir = pathlib.Path(sys.modules['distutils'].__file__).parent
|
| 347 |
+
yield sys_dir / "distutils.cfg"
|
| 348 |
+
|
| 349 |
+
# The per-user config file
|
| 350 |
+
prefix = '.' * (os.name == 'posix')
|
| 351 |
+
filename = prefix + 'pydistutils.cfg'
|
| 352 |
+
if self.want_user_cfg:
|
| 353 |
+
yield pathlib.Path('~').expanduser() / filename
|
| 354 |
+
|
| 355 |
+
# All platforms support local setup.cfg
|
| 356 |
+
yield pathlib.Path('setup.cfg')
|
| 357 |
+
|
| 358 |
+
# Additional config indicated in the environment
|
| 359 |
+
with contextlib.suppress(TypeError):
|
| 360 |
+
yield pathlib.Path(os.getenv("DIST_EXTRA_CONFIG"))
|
| 361 |
+
|
| 362 |
+
def parse_config_files(self, filenames=None): # noqa: C901
|
| 363 |
+
from configparser import ConfigParser
|
| 364 |
+
|
| 365 |
+
# Ignore install directory options if we have a venv
|
| 366 |
+
if sys.prefix != sys.base_prefix:
|
| 367 |
+
ignore_options = [
|
| 368 |
+
'install-base',
|
| 369 |
+
'install-platbase',
|
| 370 |
+
'install-lib',
|
| 371 |
+
'install-platlib',
|
| 372 |
+
'install-purelib',
|
| 373 |
+
'install-headers',
|
| 374 |
+
'install-scripts',
|
| 375 |
+
'install-data',
|
| 376 |
+
'prefix',
|
| 377 |
+
'exec-prefix',
|
| 378 |
+
'home',
|
| 379 |
+
'user',
|
| 380 |
+
'root',
|
| 381 |
+
]
|
| 382 |
+
else:
|
| 383 |
+
ignore_options = []
|
| 384 |
+
|
| 385 |
+
ignore_options = frozenset(ignore_options)
|
| 386 |
+
|
| 387 |
+
if filenames is None:
|
| 388 |
+
filenames = self.find_config_files()
|
| 389 |
+
|
| 390 |
+
if DEBUG:
|
| 391 |
+
self.announce("Distribution.parse_config_files():")
|
| 392 |
+
|
| 393 |
+
parser = ConfigParser()
|
| 394 |
+
for filename in filenames:
|
| 395 |
+
if DEBUG:
|
| 396 |
+
self.announce(" reading %s" % filename)
|
| 397 |
+
parser.read(filename)
|
| 398 |
+
for section in parser.sections():
|
| 399 |
+
options = parser.options(section)
|
| 400 |
+
opt_dict = self.get_option_dict(section)
|
| 401 |
+
|
| 402 |
+
for opt in options:
|
| 403 |
+
if opt != '__name__' and opt not in ignore_options:
|
| 404 |
+
val = parser.get(section, opt)
|
| 405 |
+
opt = opt.replace('-', '_')
|
| 406 |
+
opt_dict[opt] = (filename, val)
|
| 407 |
+
|
| 408 |
+
# Make the ConfigParser forget everything (so we retain
|
| 409 |
+
# the original filenames that options come from)
|
| 410 |
+
parser.__init__()
|
| 411 |
+
|
| 412 |
+
# If there was a "global" section in the config file, use it
|
| 413 |
+
# to set Distribution options.
|
| 414 |
+
|
| 415 |
+
if 'global' in self.command_options:
|
| 416 |
+
for (opt, (src, val)) in self.command_options['global'].items():
|
| 417 |
+
alias = self.negative_opt.get(opt)
|
| 418 |
+
try:
|
| 419 |
+
if alias:
|
| 420 |
+
setattr(self, alias, not strtobool(val))
|
| 421 |
+
elif opt in ('verbose', 'dry_run'): # ugh!
|
| 422 |
+
setattr(self, opt, strtobool(val))
|
| 423 |
+
else:
|
| 424 |
+
setattr(self, opt, val)
|
| 425 |
+
except ValueError as msg:
|
| 426 |
+
raise DistutilsOptionError(msg)
|
| 427 |
+
|
| 428 |
+
# -- Command-line parsing methods ----------------------------------
|
| 429 |
+
|
| 430 |
+
def parse_command_line(self):
|
| 431 |
+
"""Parse the setup script's command line, taken from the
|
| 432 |
+
'script_args' instance attribute (which defaults to 'sys.argv[1:]'
|
| 433 |
+
-- see 'setup()' in core.py). This list is first processed for
|
| 434 |
+
"global options" -- options that set attributes of the Distribution
|
| 435 |
+
instance. Then, it is alternately scanned for Distutils commands
|
| 436 |
+
and options for that command. Each new command terminates the
|
| 437 |
+
options for the previous command. The allowed options for a
|
| 438 |
+
command are determined by the 'user_options' attribute of the
|
| 439 |
+
command class -- thus, we have to be able to load command classes
|
| 440 |
+
in order to parse the command line. Any error in that 'options'
|
| 441 |
+
attribute raises DistutilsGetoptError; any error on the
|
| 442 |
+
command-line raises DistutilsArgError. If no Distutils commands
|
| 443 |
+
were found on the command line, raises DistutilsArgError. Return
|
| 444 |
+
true if command-line was successfully parsed and we should carry
|
| 445 |
+
on with executing commands; false if no errors but we shouldn't
|
| 446 |
+
execute commands (currently, this only happens if user asks for
|
| 447 |
+
help).
|
| 448 |
+
"""
|
| 449 |
+
#
|
| 450 |
+
# We now have enough information to show the Macintosh dialog
|
| 451 |
+
# that allows the user to interactively specify the "command line".
|
| 452 |
+
#
|
| 453 |
+
toplevel_options = self._get_toplevel_options()
|
| 454 |
+
|
| 455 |
+
# We have to parse the command line a bit at a time -- global
|
| 456 |
+
# options, then the first command, then its options, and so on --
|
| 457 |
+
# because each command will be handled by a different class, and
|
| 458 |
+
# the options that are valid for a particular class aren't known
|
| 459 |
+
# until we have loaded the command class, which doesn't happen
|
| 460 |
+
# until we know what the command is.
|
| 461 |
+
|
| 462 |
+
self.commands = []
|
| 463 |
+
parser = FancyGetopt(toplevel_options + self.display_options)
|
| 464 |
+
parser.set_negative_aliases(self.negative_opt)
|
| 465 |
+
parser.set_aliases({'licence': 'license'})
|
| 466 |
+
args = parser.getopt(args=self.script_args, object=self)
|
| 467 |
+
option_order = parser.get_option_order()
|
| 468 |
+
log.set_verbosity(self.verbose)
|
| 469 |
+
|
| 470 |
+
# for display options we return immediately
|
| 471 |
+
if self.handle_display_options(option_order):
|
| 472 |
+
return
|
| 473 |
+
while args:
|
| 474 |
+
args = self._parse_command_opts(parser, args)
|
| 475 |
+
if args is None: # user asked for help (and got it)
|
| 476 |
+
return
|
| 477 |
+
|
| 478 |
+
# Handle the cases of --help as a "global" option, ie.
|
| 479 |
+
# "setup.py --help" and "setup.py --help command ...". For the
|
| 480 |
+
# former, we show global options (--verbose, --dry-run, etc.)
|
| 481 |
+
# and display-only options (--name, --version, etc.); for the
|
| 482 |
+
# latter, we omit the display-only options and show help for
|
| 483 |
+
# each command listed on the command line.
|
| 484 |
+
if self.help:
|
| 485 |
+
self._show_help(
|
| 486 |
+
parser, display_options=len(self.commands) == 0, commands=self.commands
|
| 487 |
+
)
|
| 488 |
+
return
|
| 489 |
+
|
| 490 |
+
# Oops, no commands found -- an end-user error
|
| 491 |
+
if not self.commands:
|
| 492 |
+
raise DistutilsArgError("no commands supplied")
|
| 493 |
+
|
| 494 |
+
# All is well: return true
|
| 495 |
+
return True
|
| 496 |
+
|
| 497 |
+
def _get_toplevel_options(self):
|
| 498 |
+
"""Return the non-display options recognized at the top level.
|
| 499 |
+
|
| 500 |
+
This includes options that are recognized *only* at the top
|
| 501 |
+
level as well as options recognized for commands.
|
| 502 |
+
"""
|
| 503 |
+
return self.global_options + [
|
| 504 |
+
(
|
| 505 |
+
"command-packages=",
|
| 506 |
+
None,
|
| 507 |
+
"list of packages that provide distutils commands",
|
| 508 |
+
),
|
| 509 |
+
]
|
| 510 |
+
|
| 511 |
+
def _parse_command_opts(self, parser, args): # noqa: C901
|
| 512 |
+
"""Parse the command-line options for a single command.
|
| 513 |
+
'parser' must be a FancyGetopt instance; 'args' must be the list
|
| 514 |
+
of arguments, starting with the current command (whose options
|
| 515 |
+
we are about to parse). Returns a new version of 'args' with
|
| 516 |
+
the next command at the front of the list; will be the empty
|
| 517 |
+
list if there are no more commands on the command line. Returns
|
| 518 |
+
None if the user asked for help on this command.
|
| 519 |
+
"""
|
| 520 |
+
# late import because of mutual dependence between these modules
|
| 521 |
+
from distutils.cmd import Command
|
| 522 |
+
|
| 523 |
+
# Pull the current command from the head of the command line
|
| 524 |
+
command = args[0]
|
| 525 |
+
if not command_re.match(command):
|
| 526 |
+
raise SystemExit("invalid command name '%s'" % command)
|
| 527 |
+
self.commands.append(command)
|
| 528 |
+
|
| 529 |
+
# Dig up the command class that implements this command, so we
|
| 530 |
+
# 1) know that it's a valid command, and 2) know which options
|
| 531 |
+
# it takes.
|
| 532 |
+
try:
|
| 533 |
+
cmd_class = self.get_command_class(command)
|
| 534 |
+
except DistutilsModuleError as msg:
|
| 535 |
+
raise DistutilsArgError(msg)
|
| 536 |
+
|
| 537 |
+
# Require that the command class be derived from Command -- want
|
| 538 |
+
# to be sure that the basic "command" interface is implemented.
|
| 539 |
+
if not issubclass(cmd_class, Command):
|
| 540 |
+
raise DistutilsClassError(
|
| 541 |
+
"command class %s must subclass Command" % cmd_class
|
| 542 |
+
)
|
| 543 |
+
|
| 544 |
+
# Also make sure that the command object provides a list of its
|
| 545 |
+
# known options.
|
| 546 |
+
if not (
|
| 547 |
+
hasattr(cmd_class, 'user_options')
|
| 548 |
+
and isinstance(cmd_class.user_options, list)
|
| 549 |
+
):
|
| 550 |
+
msg = (
|
| 551 |
+
"command class %s must provide "
|
| 552 |
+
"'user_options' attribute (a list of tuples)"
|
| 553 |
+
)
|
| 554 |
+
raise DistutilsClassError(msg % cmd_class)
|
| 555 |
+
|
| 556 |
+
# If the command class has a list of negative alias options,
|
| 557 |
+
# merge it in with the global negative aliases.
|
| 558 |
+
negative_opt = self.negative_opt
|
| 559 |
+
if hasattr(cmd_class, 'negative_opt'):
|
| 560 |
+
negative_opt = negative_opt.copy()
|
| 561 |
+
negative_opt.update(cmd_class.negative_opt)
|
| 562 |
+
|
| 563 |
+
# Check for help_options in command class. They have a different
|
| 564 |
+
# format (tuple of four) so we need to preprocess them here.
|
| 565 |
+
if hasattr(cmd_class, 'help_options') and isinstance(
|
| 566 |
+
cmd_class.help_options, list
|
| 567 |
+
):
|
| 568 |
+
help_options = fix_help_options(cmd_class.help_options)
|
| 569 |
+
else:
|
| 570 |
+
help_options = []
|
| 571 |
+
|
| 572 |
+
# All commands support the global options too, just by adding
|
| 573 |
+
# in 'global_options'.
|
| 574 |
+
parser.set_option_table(
|
| 575 |
+
self.global_options + cmd_class.user_options + help_options
|
| 576 |
+
)
|
| 577 |
+
parser.set_negative_aliases(negative_opt)
|
| 578 |
+
(args, opts) = parser.getopt(args[1:])
|
| 579 |
+
if hasattr(opts, 'help') and opts.help:
|
| 580 |
+
self._show_help(parser, display_options=0, commands=[cmd_class])
|
| 581 |
+
return
|
| 582 |
+
|
| 583 |
+
if hasattr(cmd_class, 'help_options') and isinstance(
|
| 584 |
+
cmd_class.help_options, list
|
| 585 |
+
):
|
| 586 |
+
help_option_found = 0
|
| 587 |
+
for (help_option, short, desc, func) in cmd_class.help_options:
|
| 588 |
+
if hasattr(opts, parser.get_attr_name(help_option)):
|
| 589 |
+
help_option_found = 1
|
| 590 |
+
if callable(func):
|
| 591 |
+
func()
|
| 592 |
+
else:
|
| 593 |
+
raise DistutilsClassError(
|
| 594 |
+
"invalid help function %r for help option '%s': "
|
| 595 |
+
"must be a callable object (function, etc.)"
|
| 596 |
+
% (func, help_option)
|
| 597 |
+
)
|
| 598 |
+
|
| 599 |
+
if help_option_found:
|
| 600 |
+
return
|
| 601 |
+
|
| 602 |
+
# Put the options from the command-line into their official
|
| 603 |
+
# holding pen, the 'command_options' dictionary.
|
| 604 |
+
opt_dict = self.get_option_dict(command)
|
| 605 |
+
for (name, value) in vars(opts).items():
|
| 606 |
+
opt_dict[name] = ("command line", value)
|
| 607 |
+
|
| 608 |
+
return args
|
| 609 |
+
|
| 610 |
+
def finalize_options(self):
|
| 611 |
+
"""Set final values for all the options on the Distribution
|
| 612 |
+
instance, analogous to the .finalize_options() method of Command
|
| 613 |
+
objects.
|
| 614 |
+
"""
|
| 615 |
+
for attr in ('keywords', 'platforms'):
|
| 616 |
+
value = getattr(self.metadata, attr)
|
| 617 |
+
if value is None:
|
| 618 |
+
continue
|
| 619 |
+
if isinstance(value, str):
|
| 620 |
+
value = [elm.strip() for elm in value.split(',')]
|
| 621 |
+
setattr(self.metadata, attr, value)
|
| 622 |
+
|
| 623 |
+
def _show_help(self, parser, global_options=1, display_options=1, commands=[]):
|
| 624 |
+
"""Show help for the setup script command-line in the form of
|
| 625 |
+
several lists of command-line options. 'parser' should be a
|
| 626 |
+
FancyGetopt instance; do not expect it to be returned in the
|
| 627 |
+
same state, as its option table will be reset to make it
|
| 628 |
+
generate the correct help text.
|
| 629 |
+
|
| 630 |
+
If 'global_options' is true, lists the global options:
|
| 631 |
+
--verbose, --dry-run, etc. If 'display_options' is true, lists
|
| 632 |
+
the "display-only" options: --name, --version, etc. Finally,
|
| 633 |
+
lists per-command help for every command name or command class
|
| 634 |
+
in 'commands'.
|
| 635 |
+
"""
|
| 636 |
+
# late import because of mutual dependence between these modules
|
| 637 |
+
from distutils.core import gen_usage
|
| 638 |
+
from distutils.cmd import Command
|
| 639 |
+
|
| 640 |
+
if global_options:
|
| 641 |
+
if display_options:
|
| 642 |
+
options = self._get_toplevel_options()
|
| 643 |
+
else:
|
| 644 |
+
options = self.global_options
|
| 645 |
+
parser.set_option_table(options)
|
| 646 |
+
parser.print_help(self.common_usage + "\nGlobal options:")
|
| 647 |
+
print('')
|
| 648 |
+
|
| 649 |
+
if display_options:
|
| 650 |
+
parser.set_option_table(self.display_options)
|
| 651 |
+
parser.print_help(
|
| 652 |
+
"Information display options (just display "
|
| 653 |
+
+ "information, ignore any commands)"
|
| 654 |
+
)
|
| 655 |
+
print('')
|
| 656 |
+
|
| 657 |
+
for command in self.commands:
|
| 658 |
+
if isinstance(command, type) and issubclass(command, Command):
|
| 659 |
+
klass = command
|
| 660 |
+
else:
|
| 661 |
+
klass = self.get_command_class(command)
|
| 662 |
+
if hasattr(klass, 'help_options') and isinstance(klass.help_options, list):
|
| 663 |
+
parser.set_option_table(
|
| 664 |
+
klass.user_options + fix_help_options(klass.help_options)
|
| 665 |
+
)
|
| 666 |
+
else:
|
| 667 |
+
parser.set_option_table(klass.user_options)
|
| 668 |
+
parser.print_help("Options for '%s' command:" % klass.__name__)
|
| 669 |
+
print('')
|
| 670 |
+
|
| 671 |
+
print(gen_usage(self.script_name))
|
| 672 |
+
|
| 673 |
+
def handle_display_options(self, option_order):
|
| 674 |
+
"""If there were any non-global "display-only" options
|
| 675 |
+
(--help-commands or the metadata display options) on the command
|
| 676 |
+
line, display the requested info and return true; else return
|
| 677 |
+
false.
|
| 678 |
+
"""
|
| 679 |
+
from distutils.core import gen_usage
|
| 680 |
+
|
| 681 |
+
# User just wants a list of commands -- we'll print it out and stop
|
| 682 |
+
# processing now (ie. if they ran "setup --help-commands foo bar",
|
| 683 |
+
# we ignore "foo bar").
|
| 684 |
+
if self.help_commands:
|
| 685 |
+
self.print_commands()
|
| 686 |
+
print('')
|
| 687 |
+
print(gen_usage(self.script_name))
|
| 688 |
+
return 1
|
| 689 |
+
|
| 690 |
+
# If user supplied any of the "display metadata" options, then
|
| 691 |
+
# display that metadata in the order in which the user supplied the
|
| 692 |
+
# metadata options.
|
| 693 |
+
any_display_options = 0
|
| 694 |
+
is_display_option = {}
|
| 695 |
+
for option in self.display_options:
|
| 696 |
+
is_display_option[option[0]] = 1
|
| 697 |
+
|
| 698 |
+
for (opt, val) in option_order:
|
| 699 |
+
if val and is_display_option.get(opt):
|
| 700 |
+
opt = translate_longopt(opt)
|
| 701 |
+
value = getattr(self.metadata, "get_" + opt)()
|
| 702 |
+
if opt in ['keywords', 'platforms']:
|
| 703 |
+
print(','.join(value))
|
| 704 |
+
elif opt in ('classifiers', 'provides', 'requires', 'obsoletes'):
|
| 705 |
+
print('\n'.join(value))
|
| 706 |
+
else:
|
| 707 |
+
print(value)
|
| 708 |
+
any_display_options = 1
|
| 709 |
+
|
| 710 |
+
return any_display_options
|
| 711 |
+
|
| 712 |
+
def print_command_list(self, commands, header, max_length):
|
| 713 |
+
"""Print a subset of the list of all commands -- used by
|
| 714 |
+
'print_commands()'.
|
| 715 |
+
"""
|
| 716 |
+
print(header + ":")
|
| 717 |
+
|
| 718 |
+
for cmd in commands:
|
| 719 |
+
klass = self.cmdclass.get(cmd)
|
| 720 |
+
if not klass:
|
| 721 |
+
klass = self.get_command_class(cmd)
|
| 722 |
+
try:
|
| 723 |
+
description = klass.description
|
| 724 |
+
except AttributeError:
|
| 725 |
+
description = "(no description available)"
|
| 726 |
+
|
| 727 |
+
print(" %-*s %s" % (max_length, cmd, description))
|
| 728 |
+
|
| 729 |
+
def print_commands(self):
|
| 730 |
+
"""Print out a help message listing all available commands with a
|
| 731 |
+
description of each. The list is divided into "standard commands"
|
| 732 |
+
(listed in distutils.command.__all__) and "extra commands"
|
| 733 |
+
(mentioned in self.cmdclass, but not a standard command). The
|
| 734 |
+
descriptions come from the command class attribute
|
| 735 |
+
'description'.
|
| 736 |
+
"""
|
| 737 |
+
import distutils.command
|
| 738 |
+
|
| 739 |
+
std_commands = distutils.command.__all__
|
| 740 |
+
is_std = {}
|
| 741 |
+
for cmd in std_commands:
|
| 742 |
+
is_std[cmd] = 1
|
| 743 |
+
|
| 744 |
+
extra_commands = []
|
| 745 |
+
for cmd in self.cmdclass.keys():
|
| 746 |
+
if not is_std.get(cmd):
|
| 747 |
+
extra_commands.append(cmd)
|
| 748 |
+
|
| 749 |
+
max_length = 0
|
| 750 |
+
for cmd in std_commands + extra_commands:
|
| 751 |
+
if len(cmd) > max_length:
|
| 752 |
+
max_length = len(cmd)
|
| 753 |
+
|
| 754 |
+
self.print_command_list(std_commands, "Standard commands", max_length)
|
| 755 |
+
if extra_commands:
|
| 756 |
+
print()
|
| 757 |
+
self.print_command_list(extra_commands, "Extra commands", max_length)
|
| 758 |
+
|
| 759 |
+
def get_command_list(self):
|
| 760 |
+
"""Get a list of (command, description) tuples.
|
| 761 |
+
The list is divided into "standard commands" (listed in
|
| 762 |
+
distutils.command.__all__) and "extra commands" (mentioned in
|
| 763 |
+
self.cmdclass, but not a standard command). The descriptions come
|
| 764 |
+
from the command class attribute 'description'.
|
| 765 |
+
"""
|
| 766 |
+
# Currently this is only used on Mac OS, for the Mac-only GUI
|
| 767 |
+
# Distutils interface (by Jack Jansen)
|
| 768 |
+
import distutils.command
|
| 769 |
+
|
| 770 |
+
std_commands = distutils.command.__all__
|
| 771 |
+
is_std = {}
|
| 772 |
+
for cmd in std_commands:
|
| 773 |
+
is_std[cmd] = 1
|
| 774 |
+
|
| 775 |
+
extra_commands = []
|
| 776 |
+
for cmd in self.cmdclass.keys():
|
| 777 |
+
if not is_std.get(cmd):
|
| 778 |
+
extra_commands.append(cmd)
|
| 779 |
+
|
| 780 |
+
rv = []
|
| 781 |
+
for cmd in std_commands + extra_commands:
|
| 782 |
+
klass = self.cmdclass.get(cmd)
|
| 783 |
+
if not klass:
|
| 784 |
+
klass = self.get_command_class(cmd)
|
| 785 |
+
try:
|
| 786 |
+
description = klass.description
|
| 787 |
+
except AttributeError:
|
| 788 |
+
description = "(no description available)"
|
| 789 |
+
rv.append((cmd, description))
|
| 790 |
+
return rv
|
| 791 |
+
|
| 792 |
+
# -- Command class/object methods ----------------------------------
|
| 793 |
+
|
| 794 |
+
def get_command_packages(self):
|
| 795 |
+
"""Return a list of packages from which commands are loaded."""
|
| 796 |
+
pkgs = self.command_packages
|
| 797 |
+
if not isinstance(pkgs, list):
|
| 798 |
+
if pkgs is None:
|
| 799 |
+
pkgs = ''
|
| 800 |
+
pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != '']
|
| 801 |
+
if "distutils.command" not in pkgs:
|
| 802 |
+
pkgs.insert(0, "distutils.command")
|
| 803 |
+
self.command_packages = pkgs
|
| 804 |
+
return pkgs
|
| 805 |
+
|
| 806 |
+
def get_command_class(self, command):
|
| 807 |
+
"""Return the class that implements the Distutils command named by
|
| 808 |
+
'command'. First we check the 'cmdclass' dictionary; if the
|
| 809 |
+
command is mentioned there, we fetch the class object from the
|
| 810 |
+
dictionary and return it. Otherwise we load the command module
|
| 811 |
+
("distutils.command." + command) and fetch the command class from
|
| 812 |
+
the module. The loaded class is also stored in 'cmdclass'
|
| 813 |
+
to speed future calls to 'get_command_class()'.
|
| 814 |
+
|
| 815 |
+
Raises DistutilsModuleError if the expected module could not be
|
| 816 |
+
found, or if that module does not define the expected class.
|
| 817 |
+
"""
|
| 818 |
+
klass = self.cmdclass.get(command)
|
| 819 |
+
if klass:
|
| 820 |
+
return klass
|
| 821 |
+
|
| 822 |
+
for pkgname in self.get_command_packages():
|
| 823 |
+
module_name = "{}.{}".format(pkgname, command)
|
| 824 |
+
klass_name = command
|
| 825 |
+
|
| 826 |
+
try:
|
| 827 |
+
__import__(module_name)
|
| 828 |
+
module = sys.modules[module_name]
|
| 829 |
+
except ImportError:
|
| 830 |
+
continue
|
| 831 |
+
|
| 832 |
+
try:
|
| 833 |
+
klass = getattr(module, klass_name)
|
| 834 |
+
except AttributeError:
|
| 835 |
+
raise DistutilsModuleError(
|
| 836 |
+
"invalid command '%s' (no class '%s' in module '%s')"
|
| 837 |
+
% (command, klass_name, module_name)
|
| 838 |
+
)
|
| 839 |
+
|
| 840 |
+
self.cmdclass[command] = klass
|
| 841 |
+
return klass
|
| 842 |
+
|
| 843 |
+
raise DistutilsModuleError("invalid command '%s'" % command)
|
| 844 |
+
|
| 845 |
+
def get_command_obj(self, command, create=1):
|
| 846 |
+
"""Return the command object for 'command'. Normally this object
|
| 847 |
+
is cached on a previous call to 'get_command_obj()'; if no command
|
| 848 |
+
object for 'command' is in the cache, then we either create and
|
| 849 |
+
return it (if 'create' is true) or return None.
|
| 850 |
+
"""
|
| 851 |
+
cmd_obj = self.command_obj.get(command)
|
| 852 |
+
if not cmd_obj and create:
|
| 853 |
+
if DEBUG:
|
| 854 |
+
self.announce(
|
| 855 |
+
"Distribution.get_command_obj(): "
|
| 856 |
+
"creating '%s' command object" % command
|
| 857 |
+
)
|
| 858 |
+
|
| 859 |
+
klass = self.get_command_class(command)
|
| 860 |
+
cmd_obj = self.command_obj[command] = klass(self)
|
| 861 |
+
self.have_run[command] = 0
|
| 862 |
+
|
| 863 |
+
# Set any options that were supplied in config files
|
| 864 |
+
# or on the command line. (NB. support for error
|
| 865 |
+
# reporting is lame here: any errors aren't reported
|
| 866 |
+
# until 'finalize_options()' is called, which means
|
| 867 |
+
# we won't report the source of the error.)
|
| 868 |
+
options = self.command_options.get(command)
|
| 869 |
+
if options:
|
| 870 |
+
self._set_command_options(cmd_obj, options)
|
| 871 |
+
|
| 872 |
+
return cmd_obj
|
| 873 |
+
|
| 874 |
+
def _set_command_options(self, command_obj, option_dict=None): # noqa: C901
|
| 875 |
+
"""Set the options for 'command_obj' from 'option_dict'. Basically
|
| 876 |
+
this means copying elements of a dictionary ('option_dict') to
|
| 877 |
+
attributes of an instance ('command').
|
| 878 |
+
|
| 879 |
+
'command_obj' must be a Command instance. If 'option_dict' is not
|
| 880 |
+
supplied, uses the standard option dictionary for this command
|
| 881 |
+
(from 'self.command_options').
|
| 882 |
+
"""
|
| 883 |
+
command_name = command_obj.get_command_name()
|
| 884 |
+
if option_dict is None:
|
| 885 |
+
option_dict = self.get_option_dict(command_name)
|
| 886 |
+
|
| 887 |
+
if DEBUG:
|
| 888 |
+
self.announce(" setting options for '%s' command:" % command_name)
|
| 889 |
+
for (option, (source, value)) in option_dict.items():
|
| 890 |
+
if DEBUG:
|
| 891 |
+
self.announce(" {} = {} (from {})".format(option, value, source))
|
| 892 |
+
try:
|
| 893 |
+
bool_opts = [translate_longopt(o) for o in command_obj.boolean_options]
|
| 894 |
+
except AttributeError:
|
| 895 |
+
bool_opts = []
|
| 896 |
+
try:
|
| 897 |
+
neg_opt = command_obj.negative_opt
|
| 898 |
+
except AttributeError:
|
| 899 |
+
neg_opt = {}
|
| 900 |
+
|
| 901 |
+
try:
|
| 902 |
+
is_string = isinstance(value, str)
|
| 903 |
+
if option in neg_opt and is_string:
|
| 904 |
+
setattr(command_obj, neg_opt[option], not strtobool(value))
|
| 905 |
+
elif option in bool_opts and is_string:
|
| 906 |
+
setattr(command_obj, option, strtobool(value))
|
| 907 |
+
elif hasattr(command_obj, option):
|
| 908 |
+
setattr(command_obj, option, value)
|
| 909 |
+
else:
|
| 910 |
+
raise DistutilsOptionError(
|
| 911 |
+
"error in %s: command '%s' has no such option '%s'"
|
| 912 |
+
% (source, command_name, option)
|
| 913 |
+
)
|
| 914 |
+
except ValueError as msg:
|
| 915 |
+
raise DistutilsOptionError(msg)
|
| 916 |
+
|
| 917 |
+
def reinitialize_command(self, command, reinit_subcommands=0):
|
| 918 |
+
"""Reinitializes a command to the state it was in when first
|
| 919 |
+
returned by 'get_command_obj()': ie., initialized but not yet
|
| 920 |
+
finalized. This provides the opportunity to sneak option
|
| 921 |
+
values in programmatically, overriding or supplementing
|
| 922 |
+
user-supplied values from the config files and command line.
|
| 923 |
+
You'll have to re-finalize the command object (by calling
|
| 924 |
+
'finalize_options()' or 'ensure_finalized()') before using it for
|
| 925 |
+
real.
|
| 926 |
+
|
| 927 |
+
'command' should be a command name (string) or command object. If
|
| 928 |
+
'reinit_subcommands' is true, also reinitializes the command's
|
| 929 |
+
sub-commands, as declared by the 'sub_commands' class attribute (if
|
| 930 |
+
it has one). See the "install" command for an example. Only
|
| 931 |
+
reinitializes the sub-commands that actually matter, ie. those
|
| 932 |
+
whose test predicates return true.
|
| 933 |
+
|
| 934 |
+
Returns the reinitialized command object.
|
| 935 |
+
"""
|
| 936 |
+
from distutils.cmd import Command
|
| 937 |
+
|
| 938 |
+
if not isinstance(command, Command):
|
| 939 |
+
command_name = command
|
| 940 |
+
command = self.get_command_obj(command_name)
|
| 941 |
+
else:
|
| 942 |
+
command_name = command.get_command_name()
|
| 943 |
+
|
| 944 |
+
if not command.finalized:
|
| 945 |
+
return command
|
| 946 |
+
command.initialize_options()
|
| 947 |
+
command.finalized = 0
|
| 948 |
+
self.have_run[command_name] = 0
|
| 949 |
+
self._set_command_options(command)
|
| 950 |
+
|
| 951 |
+
if reinit_subcommands:
|
| 952 |
+
for sub in command.get_sub_commands():
|
| 953 |
+
self.reinitialize_command(sub, reinit_subcommands)
|
| 954 |
+
|
| 955 |
+
return command
|
| 956 |
+
|
| 957 |
+
# -- Methods that operate on the Distribution ----------------------
|
| 958 |
+
|
| 959 |
+
def announce(self, msg, level=log.INFO):
|
| 960 |
+
log.log(level, msg)
|
| 961 |
+
|
| 962 |
+
def run_commands(self):
|
| 963 |
+
"""Run each command that was seen on the setup script command line.
|
| 964 |
+
Uses the list of commands found and cache of command objects
|
| 965 |
+
created by 'get_command_obj()'.
|
| 966 |
+
"""
|
| 967 |
+
for cmd in self.commands:
|
| 968 |
+
self.run_command(cmd)
|
| 969 |
+
|
| 970 |
+
# -- Methods that operate on its Commands --------------------------
|
| 971 |
+
|
| 972 |
+
def run_command(self, command):
|
| 973 |
+
"""Do whatever it takes to run a command (including nothing at all,
|
| 974 |
+
if the command has already been run). Specifically: if we have
|
| 975 |
+
already created and run the command named by 'command', return
|
| 976 |
+
silently without doing anything. If the command named by 'command'
|
| 977 |
+
doesn't even have a command object yet, create one. Then invoke
|
| 978 |
+
'run()' on that command object (or an existing one).
|
| 979 |
+
"""
|
| 980 |
+
# Already been here, done that? then return silently.
|
| 981 |
+
if self.have_run.get(command):
|
| 982 |
+
return
|
| 983 |
+
|
| 984 |
+
log.info("running %s", command)
|
| 985 |
+
cmd_obj = self.get_command_obj(command)
|
| 986 |
+
cmd_obj.ensure_finalized()
|
| 987 |
+
cmd_obj.run()
|
| 988 |
+
self.have_run[command] = 1
|
| 989 |
+
|
| 990 |
+
# -- Distribution query methods ------------------------------------
|
| 991 |
+
|
| 992 |
+
def has_pure_modules(self):
|
| 993 |
+
return len(self.packages or self.py_modules or []) > 0
|
| 994 |
+
|
| 995 |
+
def has_ext_modules(self):
|
| 996 |
+
return self.ext_modules and len(self.ext_modules) > 0
|
| 997 |
+
|
| 998 |
+
def has_c_libraries(self):
|
| 999 |
+
return self.libraries and len(self.libraries) > 0
|
| 1000 |
+
|
| 1001 |
+
def has_modules(self):
|
| 1002 |
+
return self.has_pure_modules() or self.has_ext_modules()
|
| 1003 |
+
|
| 1004 |
+
def has_headers(self):
|
| 1005 |
+
return self.headers and len(self.headers) > 0
|
| 1006 |
+
|
| 1007 |
+
def has_scripts(self):
|
| 1008 |
+
return self.scripts and len(self.scripts) > 0
|
| 1009 |
+
|
| 1010 |
+
def has_data_files(self):
|
| 1011 |
+
return self.data_files and len(self.data_files) > 0
|
| 1012 |
+
|
| 1013 |
+
def is_pure(self):
|
| 1014 |
+
return (
|
| 1015 |
+
self.has_pure_modules()
|
| 1016 |
+
and not self.has_ext_modules()
|
| 1017 |
+
and not self.has_c_libraries()
|
| 1018 |
+
)
|
| 1019 |
+
|
| 1020 |
+
# -- Metadata query methods ----------------------------------------
|
| 1021 |
+
|
| 1022 |
+
# If you're looking for 'get_name()', 'get_version()', and so forth,
|
| 1023 |
+
# they are defined in a sneaky way: the constructor binds self.get_XXX
|
| 1024 |
+
# to self.metadata.get_XXX. The actual code is in the
|
| 1025 |
+
# DistributionMetadata class, below.
|
| 1026 |
+
|
| 1027 |
+
|
| 1028 |
+
class DistributionMetadata:
|
| 1029 |
+
"""Dummy class to hold the distribution meta-data: name, version,
|
| 1030 |
+
author, and so forth.
|
| 1031 |
+
"""
|
| 1032 |
+
|
| 1033 |
+
_METHOD_BASENAMES = (
|
| 1034 |
+
"name",
|
| 1035 |
+
"version",
|
| 1036 |
+
"author",
|
| 1037 |
+
"author_email",
|
| 1038 |
+
"maintainer",
|
| 1039 |
+
"maintainer_email",
|
| 1040 |
+
"url",
|
| 1041 |
+
"license",
|
| 1042 |
+
"description",
|
| 1043 |
+
"long_description",
|
| 1044 |
+
"keywords",
|
| 1045 |
+
"platforms",
|
| 1046 |
+
"fullname",
|
| 1047 |
+
"contact",
|
| 1048 |
+
"contact_email",
|
| 1049 |
+
"classifiers",
|
| 1050 |
+
"download_url",
|
| 1051 |
+
# PEP 314
|
| 1052 |
+
"provides",
|
| 1053 |
+
"requires",
|
| 1054 |
+
"obsoletes",
|
| 1055 |
+
)
|
| 1056 |
+
|
| 1057 |
+
def __init__(self, path=None):
|
| 1058 |
+
if path is not None:
|
| 1059 |
+
self.read_pkg_file(open(path))
|
| 1060 |
+
else:
|
| 1061 |
+
self.name = None
|
| 1062 |
+
self.version = None
|
| 1063 |
+
self.author = None
|
| 1064 |
+
self.author_email = None
|
| 1065 |
+
self.maintainer = None
|
| 1066 |
+
self.maintainer_email = None
|
| 1067 |
+
self.url = None
|
| 1068 |
+
self.license = None
|
| 1069 |
+
self.description = None
|
| 1070 |
+
self.long_description = None
|
| 1071 |
+
self.keywords = None
|
| 1072 |
+
self.platforms = None
|
| 1073 |
+
self.classifiers = None
|
| 1074 |
+
self.download_url = None
|
| 1075 |
+
# PEP 314
|
| 1076 |
+
self.provides = None
|
| 1077 |
+
self.requires = None
|
| 1078 |
+
self.obsoletes = None
|
| 1079 |
+
|
| 1080 |
+
def read_pkg_file(self, file):
|
| 1081 |
+
"""Reads the metadata values from a file object."""
|
| 1082 |
+
msg = message_from_file(file)
|
| 1083 |
+
|
| 1084 |
+
def _read_field(name):
|
| 1085 |
+
value = msg[name]
|
| 1086 |
+
if value and value != "UNKNOWN":
|
| 1087 |
+
return value
|
| 1088 |
+
|
| 1089 |
+
def _read_list(name):
|
| 1090 |
+
values = msg.get_all(name, None)
|
| 1091 |
+
if values == []:
|
| 1092 |
+
return None
|
| 1093 |
+
return values
|
| 1094 |
+
|
| 1095 |
+
metadata_version = msg['metadata-version']
|
| 1096 |
+
self.name = _read_field('name')
|
| 1097 |
+
self.version = _read_field('version')
|
| 1098 |
+
self.description = _read_field('summary')
|
| 1099 |
+
# we are filling author only.
|
| 1100 |
+
self.author = _read_field('author')
|
| 1101 |
+
self.maintainer = None
|
| 1102 |
+
self.author_email = _read_field('author-email')
|
| 1103 |
+
self.maintainer_email = None
|
| 1104 |
+
self.url = _read_field('home-page')
|
| 1105 |
+
self.license = _read_field('license')
|
| 1106 |
+
|
| 1107 |
+
if 'download-url' in msg:
|
| 1108 |
+
self.download_url = _read_field('download-url')
|
| 1109 |
+
else:
|
| 1110 |
+
self.download_url = None
|
| 1111 |
+
|
| 1112 |
+
self.long_description = _read_field('description')
|
| 1113 |
+
self.description = _read_field('summary')
|
| 1114 |
+
|
| 1115 |
+
if 'keywords' in msg:
|
| 1116 |
+
self.keywords = _read_field('keywords').split(',')
|
| 1117 |
+
|
| 1118 |
+
self.platforms = _read_list('platform')
|
| 1119 |
+
self.classifiers = _read_list('classifier')
|
| 1120 |
+
|
| 1121 |
+
# PEP 314 - these fields only exist in 1.1
|
| 1122 |
+
if metadata_version == '1.1':
|
| 1123 |
+
self.requires = _read_list('requires')
|
| 1124 |
+
self.provides = _read_list('provides')
|
| 1125 |
+
self.obsoletes = _read_list('obsoletes')
|
| 1126 |
+
else:
|
| 1127 |
+
self.requires = None
|
| 1128 |
+
self.provides = None
|
| 1129 |
+
self.obsoletes = None
|
| 1130 |
+
|
| 1131 |
+
def write_pkg_info(self, base_dir):
|
| 1132 |
+
"""Write the PKG-INFO file into the release tree."""
|
| 1133 |
+
with open(
|
| 1134 |
+
os.path.join(base_dir, 'PKG-INFO'), 'w', encoding='UTF-8'
|
| 1135 |
+
) as pkg_info:
|
| 1136 |
+
self.write_pkg_file(pkg_info)
|
| 1137 |
+
|
| 1138 |
+
def write_pkg_file(self, file):
|
| 1139 |
+
"""Write the PKG-INFO format data to a file object."""
|
| 1140 |
+
version = '1.0'
|
| 1141 |
+
if (
|
| 1142 |
+
self.provides
|
| 1143 |
+
or self.requires
|
| 1144 |
+
or self.obsoletes
|
| 1145 |
+
or self.classifiers
|
| 1146 |
+
or self.download_url
|
| 1147 |
+
):
|
| 1148 |
+
version = '1.1'
|
| 1149 |
+
|
| 1150 |
+
# required fields
|
| 1151 |
+
file.write('Metadata-Version: %s\n' % version)
|
| 1152 |
+
file.write('Name: %s\n' % self.get_name())
|
| 1153 |
+
file.write('Version: %s\n' % self.get_version())
|
| 1154 |
+
|
| 1155 |
+
def maybe_write(header, val):
|
| 1156 |
+
if val:
|
| 1157 |
+
file.write(f"{header}: {val}\n")
|
| 1158 |
+
|
| 1159 |
+
# optional fields
|
| 1160 |
+
maybe_write("Summary", self.get_description())
|
| 1161 |
+
maybe_write("Home-page", self.get_url())
|
| 1162 |
+
maybe_write("Author", self.get_contact())
|
| 1163 |
+
maybe_write("Author-email", self.get_contact_email())
|
| 1164 |
+
maybe_write("License", self.get_license())
|
| 1165 |
+
maybe_write("Download-URL", self.download_url)
|
| 1166 |
+
maybe_write("Description", rfc822_escape(self.get_long_description() or ""))
|
| 1167 |
+
maybe_write("Keywords", ",".join(self.get_keywords()))
|
| 1168 |
+
|
| 1169 |
+
self._write_list(file, 'Platform', self.get_platforms())
|
| 1170 |
+
self._write_list(file, 'Classifier', self.get_classifiers())
|
| 1171 |
+
|
| 1172 |
+
# PEP 314
|
| 1173 |
+
self._write_list(file, 'Requires', self.get_requires())
|
| 1174 |
+
self._write_list(file, 'Provides', self.get_provides())
|
| 1175 |
+
self._write_list(file, 'Obsoletes', self.get_obsoletes())
|
| 1176 |
+
|
| 1177 |
+
def _write_list(self, file, name, values):
|
| 1178 |
+
values = values or []
|
| 1179 |
+
for value in values:
|
| 1180 |
+
file.write('{}: {}\n'.format(name, value))
|
| 1181 |
+
|
| 1182 |
+
# -- Metadata query methods ----------------------------------------
|
| 1183 |
+
|
| 1184 |
+
def get_name(self):
|
| 1185 |
+
return self.name or "UNKNOWN"
|
| 1186 |
+
|
| 1187 |
+
def get_version(self):
|
| 1188 |
+
return self.version or "0.0.0"
|
| 1189 |
+
|
| 1190 |
+
def get_fullname(self):
|
| 1191 |
+
return "{}-{}".format(self.get_name(), self.get_version())
|
| 1192 |
+
|
| 1193 |
+
def get_author(self):
|
| 1194 |
+
return self.author
|
| 1195 |
+
|
| 1196 |
+
def get_author_email(self):
|
| 1197 |
+
return self.author_email
|
| 1198 |
+
|
| 1199 |
+
def get_maintainer(self):
|
| 1200 |
+
return self.maintainer
|
| 1201 |
+
|
| 1202 |
+
def get_maintainer_email(self):
|
| 1203 |
+
return self.maintainer_email
|
| 1204 |
+
|
| 1205 |
+
def get_contact(self):
|
| 1206 |
+
return self.maintainer or self.author
|
| 1207 |
+
|
| 1208 |
+
def get_contact_email(self):
|
| 1209 |
+
return self.maintainer_email or self.author_email
|
| 1210 |
+
|
| 1211 |
+
def get_url(self):
|
| 1212 |
+
return self.url
|
| 1213 |
+
|
| 1214 |
+
def get_license(self):
|
| 1215 |
+
return self.license
|
| 1216 |
+
|
| 1217 |
+
get_licence = get_license
|
| 1218 |
+
|
| 1219 |
+
def get_description(self):
|
| 1220 |
+
return self.description
|
| 1221 |
+
|
| 1222 |
+
def get_long_description(self):
|
| 1223 |
+
return self.long_description
|
| 1224 |
+
|
| 1225 |
+
def get_keywords(self):
|
| 1226 |
+
return self.keywords or []
|
| 1227 |
+
|
| 1228 |
+
def set_keywords(self, value):
|
| 1229 |
+
self.keywords = _ensure_list(value, 'keywords')
|
| 1230 |
+
|
| 1231 |
+
def get_platforms(self):
|
| 1232 |
+
return self.platforms
|
| 1233 |
+
|
| 1234 |
+
def set_platforms(self, value):
|
| 1235 |
+
self.platforms = _ensure_list(value, 'platforms')
|
| 1236 |
+
|
| 1237 |
+
def get_classifiers(self):
|
| 1238 |
+
return self.classifiers or []
|
| 1239 |
+
|
| 1240 |
+
def set_classifiers(self, value):
|
| 1241 |
+
self.classifiers = _ensure_list(value, 'classifiers')
|
| 1242 |
+
|
| 1243 |
+
def get_download_url(self):
|
| 1244 |
+
return self.download_url
|
| 1245 |
+
|
| 1246 |
+
# PEP 314
|
| 1247 |
+
def get_requires(self):
|
| 1248 |
+
return self.requires or []
|
| 1249 |
+
|
| 1250 |
+
def set_requires(self, value):
|
| 1251 |
+
import distutils.versionpredicate
|
| 1252 |
+
|
| 1253 |
+
for v in value:
|
| 1254 |
+
distutils.versionpredicate.VersionPredicate(v)
|
| 1255 |
+
self.requires = list(value)
|
| 1256 |
+
|
| 1257 |
+
def get_provides(self):
|
| 1258 |
+
return self.provides or []
|
| 1259 |
+
|
| 1260 |
+
def set_provides(self, value):
|
| 1261 |
+
value = [v.strip() for v in value]
|
| 1262 |
+
for v in value:
|
| 1263 |
+
import distutils.versionpredicate
|
| 1264 |
+
|
| 1265 |
+
distutils.versionpredicate.split_provision(v)
|
| 1266 |
+
self.provides = value
|
| 1267 |
+
|
| 1268 |
+
def get_obsoletes(self):
|
| 1269 |
+
return self.obsoletes or []
|
| 1270 |
+
|
| 1271 |
+
def set_obsoletes(self, value):
|
| 1272 |
+
import distutils.versionpredicate
|
| 1273 |
+
|
| 1274 |
+
for v in value:
|
| 1275 |
+
distutils.versionpredicate.VersionPredicate(v)
|
| 1276 |
+
self.obsoletes = list(value)
|
| 1277 |
+
|
| 1278 |
+
|
| 1279 |
+
def fix_help_options(options):
|
| 1280 |
+
"""Convert a 4-tuple 'help_options' list as found in various command
|
| 1281 |
+
classes to the 3-tuple form required by FancyGetopt.
|
| 1282 |
+
"""
|
| 1283 |
+
new_options = []
|
| 1284 |
+
for help_tuple in options:
|
| 1285 |
+
new_options.append(help_tuple[0:3])
|
| 1286 |
+
return new_options
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/errors.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.errors
|
| 2 |
+
|
| 3 |
+
Provides exceptions used by the Distutils modules. Note that Distutils
|
| 4 |
+
modules may raise standard exceptions; in particular, SystemExit is
|
| 5 |
+
usually raised for errors that are obviously the end-user's fault
|
| 6 |
+
(eg. bad command-line arguments).
|
| 7 |
+
|
| 8 |
+
This module is safe to use in "from ... import *" mode; it only exports
|
| 9 |
+
symbols whose names start with "Distutils" and end with "Error"."""
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class DistutilsError(Exception):
|
| 13 |
+
"""The root of all Distutils evil."""
|
| 14 |
+
|
| 15 |
+
pass
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class DistutilsModuleError(DistutilsError):
|
| 19 |
+
"""Unable to load an expected module, or to find an expected class
|
| 20 |
+
within some module (in particular, command modules and classes)."""
|
| 21 |
+
|
| 22 |
+
pass
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class DistutilsClassError(DistutilsError):
|
| 26 |
+
"""Some command class (or possibly distribution class, if anyone
|
| 27 |
+
feels a need to subclass Distribution) is found not to be holding
|
| 28 |
+
up its end of the bargain, ie. implementing some part of the
|
| 29 |
+
"command "interface."""
|
| 30 |
+
|
| 31 |
+
pass
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class DistutilsGetoptError(DistutilsError):
|
| 35 |
+
"""The option table provided to 'fancy_getopt()' is bogus."""
|
| 36 |
+
|
| 37 |
+
pass
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
class DistutilsArgError(DistutilsError):
|
| 41 |
+
"""Raised by fancy_getopt in response to getopt.error -- ie. an
|
| 42 |
+
error in the command line usage."""
|
| 43 |
+
|
| 44 |
+
pass
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
class DistutilsFileError(DistutilsError):
|
| 48 |
+
"""Any problems in the filesystem: expected file not found, etc.
|
| 49 |
+
Typically this is for problems that we detect before OSError
|
| 50 |
+
could be raised."""
|
| 51 |
+
|
| 52 |
+
pass
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class DistutilsOptionError(DistutilsError):
|
| 56 |
+
"""Syntactic/semantic errors in command options, such as use of
|
| 57 |
+
mutually conflicting options, or inconsistent options,
|
| 58 |
+
badly-spelled values, etc. No distinction is made between option
|
| 59 |
+
values originating in the setup script, the command line, config
|
| 60 |
+
files, or what-have-you -- but if we *know* something originated in
|
| 61 |
+
the setup script, we'll raise DistutilsSetupError instead."""
|
| 62 |
+
|
| 63 |
+
pass
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class DistutilsSetupError(DistutilsError):
|
| 67 |
+
"""For errors that can be definitely blamed on the setup script,
|
| 68 |
+
such as invalid keyword arguments to 'setup()'."""
|
| 69 |
+
|
| 70 |
+
pass
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
class DistutilsPlatformError(DistutilsError):
|
| 74 |
+
"""We don't know how to do something on the current platform (but
|
| 75 |
+
we do know how to do it on some platform) -- eg. trying to compile
|
| 76 |
+
C files on a platform not supported by a CCompiler subclass."""
|
| 77 |
+
|
| 78 |
+
pass
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
class DistutilsExecError(DistutilsError):
|
| 82 |
+
"""Any problems executing an external program (such as the C
|
| 83 |
+
compiler, when compiling C files)."""
|
| 84 |
+
|
| 85 |
+
pass
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
class DistutilsInternalError(DistutilsError):
|
| 89 |
+
"""Internal inconsistencies or impossibilities (obviously, this
|
| 90 |
+
should never be seen if the code is working!)."""
|
| 91 |
+
|
| 92 |
+
pass
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
class DistutilsTemplateError(DistutilsError):
|
| 96 |
+
"""Syntax error in a file list template."""
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
class DistutilsByteCompileError(DistutilsError):
|
| 100 |
+
"""Byte compile error."""
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
# Exception classes used by the CCompiler implementation classes
|
| 104 |
+
class CCompilerError(Exception):
|
| 105 |
+
"""Some compile/link operation failed."""
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
class PreprocessError(CCompilerError):
|
| 109 |
+
"""Failure to preprocess one or more C/C++ files."""
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
class CompileError(CCompilerError):
|
| 113 |
+
"""Failure to compile one or more C/C++ source files."""
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
class LibError(CCompilerError):
|
| 117 |
+
"""Failure to create a static library from one or more C/C++ object
|
| 118 |
+
files."""
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
class LinkError(CCompilerError):
|
| 122 |
+
"""Failure to link one or more C/C++ object files into an executable
|
| 123 |
+
or shared library file."""
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
class UnknownFileError(CCompilerError):
|
| 127 |
+
"""Attempt to process an unknown file type."""
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/extension.py
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.extension
|
| 2 |
+
|
| 3 |
+
Provides the Extension class, used to describe C/C++ extension
|
| 4 |
+
modules in setup scripts."""
|
| 5 |
+
|
| 6 |
+
import os
|
| 7 |
+
import warnings
|
| 8 |
+
|
| 9 |
+
# This class is really only used by the "build_ext" command, so it might
|
| 10 |
+
# make sense to put it in distutils.command.build_ext. However, that
|
| 11 |
+
# module is already big enough, and I want to make this class a bit more
|
| 12 |
+
# complex to simplify some common cases ("foo" module in "foo.c") and do
|
| 13 |
+
# better error-checking ("foo.c" actually exists).
|
| 14 |
+
#
|
| 15 |
+
# Also, putting this in build_ext.py means every setup script would have to
|
| 16 |
+
# import that large-ish module (indirectly, through distutils.core) in
|
| 17 |
+
# order to do anything.
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class Extension:
|
| 21 |
+
"""Just a collection of attributes that describes an extension
|
| 22 |
+
module and everything needed to build it (hopefully in a portable
|
| 23 |
+
way, but there are hooks that let you be as unportable as you need).
|
| 24 |
+
|
| 25 |
+
Instance attributes:
|
| 26 |
+
name : string
|
| 27 |
+
the full name of the extension, including any packages -- ie.
|
| 28 |
+
*not* a filename or pathname, but Python dotted name
|
| 29 |
+
sources : [string]
|
| 30 |
+
list of source filenames, relative to the distribution root
|
| 31 |
+
(where the setup script lives), in Unix form (slash-separated)
|
| 32 |
+
for portability. Source files may be C, C++, SWIG (.i),
|
| 33 |
+
platform-specific resource files, or whatever else is recognized
|
| 34 |
+
by the "build_ext" command as source for a Python extension.
|
| 35 |
+
include_dirs : [string]
|
| 36 |
+
list of directories to search for C/C++ header files (in Unix
|
| 37 |
+
form for portability)
|
| 38 |
+
define_macros : [(name : string, value : string|None)]
|
| 39 |
+
list of macros to define; each macro is defined using a 2-tuple,
|
| 40 |
+
where 'value' is either the string to define it to or None to
|
| 41 |
+
define it without a particular value (equivalent of "#define
|
| 42 |
+
FOO" in source or -DFOO on Unix C compiler command line)
|
| 43 |
+
undef_macros : [string]
|
| 44 |
+
list of macros to undefine explicitly
|
| 45 |
+
library_dirs : [string]
|
| 46 |
+
list of directories to search for C/C++ libraries at link time
|
| 47 |
+
libraries : [string]
|
| 48 |
+
list of library names (not filenames or paths) to link against
|
| 49 |
+
runtime_library_dirs : [string]
|
| 50 |
+
list of directories to search for C/C++ libraries at run time
|
| 51 |
+
(for shared extensions, this is when the extension is loaded)
|
| 52 |
+
extra_objects : [string]
|
| 53 |
+
list of extra files to link with (eg. object files not implied
|
| 54 |
+
by 'sources', static library that must be explicitly specified,
|
| 55 |
+
binary resource files, etc.)
|
| 56 |
+
extra_compile_args : [string]
|
| 57 |
+
any extra platform- and compiler-specific information to use
|
| 58 |
+
when compiling the source files in 'sources'. For platforms and
|
| 59 |
+
compilers where "command line" makes sense, this is typically a
|
| 60 |
+
list of command-line arguments, but for other platforms it could
|
| 61 |
+
be anything.
|
| 62 |
+
extra_link_args : [string]
|
| 63 |
+
any extra platform- and compiler-specific information to use
|
| 64 |
+
when linking object files together to create the extension (or
|
| 65 |
+
to create a new static Python interpreter). Similar
|
| 66 |
+
interpretation as for 'extra_compile_args'.
|
| 67 |
+
export_symbols : [string]
|
| 68 |
+
list of symbols to be exported from a shared extension. Not
|
| 69 |
+
used on all platforms, and not generally necessary for Python
|
| 70 |
+
extensions, which typically export exactly one symbol: "init" +
|
| 71 |
+
extension_name.
|
| 72 |
+
swig_opts : [string]
|
| 73 |
+
any extra options to pass to SWIG if a source file has the .i
|
| 74 |
+
extension.
|
| 75 |
+
depends : [string]
|
| 76 |
+
list of files that the extension depends on
|
| 77 |
+
language : string
|
| 78 |
+
extension language (i.e. "c", "c++", "objc"). Will be detected
|
| 79 |
+
from the source extensions if not provided.
|
| 80 |
+
optional : boolean
|
| 81 |
+
specifies that a build failure in the extension should not abort the
|
| 82 |
+
build process, but simply not install the failing extension.
|
| 83 |
+
"""
|
| 84 |
+
|
| 85 |
+
# When adding arguments to this constructor, be sure to update
|
| 86 |
+
# setup_keywords in core.py.
|
| 87 |
+
def __init__(
|
| 88 |
+
self,
|
| 89 |
+
name,
|
| 90 |
+
sources,
|
| 91 |
+
include_dirs=None,
|
| 92 |
+
define_macros=None,
|
| 93 |
+
undef_macros=None,
|
| 94 |
+
library_dirs=None,
|
| 95 |
+
libraries=None,
|
| 96 |
+
runtime_library_dirs=None,
|
| 97 |
+
extra_objects=None,
|
| 98 |
+
extra_compile_args=None,
|
| 99 |
+
extra_link_args=None,
|
| 100 |
+
export_symbols=None,
|
| 101 |
+
swig_opts=None,
|
| 102 |
+
depends=None,
|
| 103 |
+
language=None,
|
| 104 |
+
optional=None,
|
| 105 |
+
**kw # To catch unknown keywords
|
| 106 |
+
):
|
| 107 |
+
if not isinstance(name, str):
|
| 108 |
+
raise AssertionError("'name' must be a string")
|
| 109 |
+
if not (isinstance(sources, list) and all(isinstance(v, str) for v in sources)):
|
| 110 |
+
raise AssertionError("'sources' must be a list of strings")
|
| 111 |
+
|
| 112 |
+
self.name = name
|
| 113 |
+
self.sources = sources
|
| 114 |
+
self.include_dirs = include_dirs or []
|
| 115 |
+
self.define_macros = define_macros or []
|
| 116 |
+
self.undef_macros = undef_macros or []
|
| 117 |
+
self.library_dirs = library_dirs or []
|
| 118 |
+
self.libraries = libraries or []
|
| 119 |
+
self.runtime_library_dirs = runtime_library_dirs or []
|
| 120 |
+
self.extra_objects = extra_objects or []
|
| 121 |
+
self.extra_compile_args = extra_compile_args or []
|
| 122 |
+
self.extra_link_args = extra_link_args or []
|
| 123 |
+
self.export_symbols = export_symbols or []
|
| 124 |
+
self.swig_opts = swig_opts or []
|
| 125 |
+
self.depends = depends or []
|
| 126 |
+
self.language = language
|
| 127 |
+
self.optional = optional
|
| 128 |
+
|
| 129 |
+
# If there are unknown keyword options, warn about them
|
| 130 |
+
if len(kw) > 0:
|
| 131 |
+
options = [repr(option) for option in kw]
|
| 132 |
+
options = ', '.join(sorted(options))
|
| 133 |
+
msg = "Unknown Extension options: %s" % options
|
| 134 |
+
warnings.warn(msg)
|
| 135 |
+
|
| 136 |
+
def __repr__(self):
|
| 137 |
+
return '<{}.{}({!r}) at {:#x}>'.format(
|
| 138 |
+
self.__class__.__module__,
|
| 139 |
+
self.__class__.__qualname__,
|
| 140 |
+
self.name,
|
| 141 |
+
id(self),
|
| 142 |
+
)
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
def read_setup_file(filename): # noqa: C901
|
| 146 |
+
"""Reads a Setup file and returns Extension instances."""
|
| 147 |
+
from distutils.sysconfig import parse_makefile, expand_makefile_vars, _variable_rx
|
| 148 |
+
|
| 149 |
+
from distutils.text_file import TextFile
|
| 150 |
+
from distutils.util import split_quoted
|
| 151 |
+
|
| 152 |
+
# First pass over the file to gather "VAR = VALUE" assignments.
|
| 153 |
+
vars = parse_makefile(filename)
|
| 154 |
+
|
| 155 |
+
# Second pass to gobble up the real content: lines of the form
|
| 156 |
+
# <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...]
|
| 157 |
+
file = TextFile(
|
| 158 |
+
filename,
|
| 159 |
+
strip_comments=1,
|
| 160 |
+
skip_blanks=1,
|
| 161 |
+
join_lines=1,
|
| 162 |
+
lstrip_ws=1,
|
| 163 |
+
rstrip_ws=1,
|
| 164 |
+
)
|
| 165 |
+
try:
|
| 166 |
+
extensions = []
|
| 167 |
+
|
| 168 |
+
while True:
|
| 169 |
+
line = file.readline()
|
| 170 |
+
if line is None: # eof
|
| 171 |
+
break
|
| 172 |
+
if _variable_rx.match(line): # VAR=VALUE, handled in first pass
|
| 173 |
+
continue
|
| 174 |
+
|
| 175 |
+
if line[0] == line[-1] == "*":
|
| 176 |
+
file.warn("'%s' lines not handled yet" % line)
|
| 177 |
+
continue
|
| 178 |
+
|
| 179 |
+
line = expand_makefile_vars(line, vars)
|
| 180 |
+
words = split_quoted(line)
|
| 181 |
+
|
| 182 |
+
# NB. this parses a slightly different syntax than the old
|
| 183 |
+
# makesetup script: here, there must be exactly one extension per
|
| 184 |
+
# line, and it must be the first word of the line. I have no idea
|
| 185 |
+
# why the old syntax supported multiple extensions per line, as
|
| 186 |
+
# they all wind up being the same.
|
| 187 |
+
|
| 188 |
+
module = words[0]
|
| 189 |
+
ext = Extension(module, [])
|
| 190 |
+
append_next_word = None
|
| 191 |
+
|
| 192 |
+
for word in words[1:]:
|
| 193 |
+
if append_next_word is not None:
|
| 194 |
+
append_next_word.append(word)
|
| 195 |
+
append_next_word = None
|
| 196 |
+
continue
|
| 197 |
+
|
| 198 |
+
suffix = os.path.splitext(word)[1]
|
| 199 |
+
switch = word[0:2]
|
| 200 |
+
value = word[2:]
|
| 201 |
+
|
| 202 |
+
if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"):
|
| 203 |
+
# hmm, should we do something about C vs. C++ sources?
|
| 204 |
+
# or leave it up to the CCompiler implementation to
|
| 205 |
+
# worry about?
|
| 206 |
+
ext.sources.append(word)
|
| 207 |
+
elif switch == "-I":
|
| 208 |
+
ext.include_dirs.append(value)
|
| 209 |
+
elif switch == "-D":
|
| 210 |
+
equals = value.find("=")
|
| 211 |
+
if equals == -1: # bare "-DFOO" -- no value
|
| 212 |
+
ext.define_macros.append((value, None))
|
| 213 |
+
else: # "-DFOO=blah"
|
| 214 |
+
ext.define_macros.append((value[0:equals], value[equals + 2 :]))
|
| 215 |
+
elif switch == "-U":
|
| 216 |
+
ext.undef_macros.append(value)
|
| 217 |
+
elif switch == "-C": # only here 'cause makesetup has it!
|
| 218 |
+
ext.extra_compile_args.append(word)
|
| 219 |
+
elif switch == "-l":
|
| 220 |
+
ext.libraries.append(value)
|
| 221 |
+
elif switch == "-L":
|
| 222 |
+
ext.library_dirs.append(value)
|
| 223 |
+
elif switch == "-R":
|
| 224 |
+
ext.runtime_library_dirs.append(value)
|
| 225 |
+
elif word == "-rpath":
|
| 226 |
+
append_next_word = ext.runtime_library_dirs
|
| 227 |
+
elif word == "-Xlinker":
|
| 228 |
+
append_next_word = ext.extra_link_args
|
| 229 |
+
elif word == "-Xcompiler":
|
| 230 |
+
append_next_word = ext.extra_compile_args
|
| 231 |
+
elif switch == "-u":
|
| 232 |
+
ext.extra_link_args.append(word)
|
| 233 |
+
if not value:
|
| 234 |
+
append_next_word = ext.extra_link_args
|
| 235 |
+
elif suffix in (".a", ".so", ".sl", ".o", ".dylib"):
|
| 236 |
+
# NB. a really faithful emulation of makesetup would
|
| 237 |
+
# append a .o file to extra_objects only if it
|
| 238 |
+
# had a slash in it; otherwise, it would s/.o/.c/
|
| 239 |
+
# and append it to sources. Hmmmm.
|
| 240 |
+
ext.extra_objects.append(word)
|
| 241 |
+
else:
|
| 242 |
+
file.warn("unrecognized argument '%s'" % word)
|
| 243 |
+
|
| 244 |
+
extensions.append(ext)
|
| 245 |
+
finally:
|
| 246 |
+
file.close()
|
| 247 |
+
|
| 248 |
+
return extensions
|
ACE_plus/flashenv/lib/python3.10/site-packages/setuptools/_distutils/fancy_getopt.py
ADDED
|
@@ -0,0 +1,470 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.fancy_getopt
|
| 2 |
+
|
| 3 |
+
Wrapper around the standard getopt module that provides the following
|
| 4 |
+
additional features:
|
| 5 |
+
* short and long options are tied together
|
| 6 |
+
* options have help strings, so fancy_getopt could potentially
|
| 7 |
+
create a complete usage summary
|
| 8 |
+
* options set attributes of a passed-in object
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import sys
|
| 12 |
+
import string
|
| 13 |
+
import re
|
| 14 |
+
import getopt
|
| 15 |
+
from distutils.errors import DistutilsGetoptError, DistutilsArgError
|
| 16 |
+
|
| 17 |
+
# Much like command_re in distutils.core, this is close to but not quite
|
| 18 |
+
# the same as a Python NAME -- except, in the spirit of most GNU
|
| 19 |
+
# utilities, we use '-' in place of '_'. (The spirit of LISP lives on!)
|
| 20 |
+
# The similarities to NAME are again not a coincidence...
|
| 21 |
+
longopt_pat = r'[a-zA-Z](?:[a-zA-Z0-9-]*)'
|
| 22 |
+
longopt_re = re.compile(r'^%s$' % longopt_pat)
|
| 23 |
+
|
| 24 |
+
# For recognizing "negative alias" options, eg. "quiet=!verbose"
|
| 25 |
+
neg_alias_re = re.compile("^({})=!({})$".format(longopt_pat, longopt_pat))
|
| 26 |
+
|
| 27 |
+
# This is used to translate long options to legitimate Python identifiers
|
| 28 |
+
# (for use as attributes of some object).
|
| 29 |
+
longopt_xlate = str.maketrans('-', '_')
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class FancyGetopt:
|
| 33 |
+
"""Wrapper around the standard 'getopt()' module that provides some
|
| 34 |
+
handy extra functionality:
|
| 35 |
+
* short and long options are tied together
|
| 36 |
+
* options have help strings, and help text can be assembled
|
| 37 |
+
from them
|
| 38 |
+
* options set attributes of a passed-in object
|
| 39 |
+
* boolean options can have "negative aliases" -- eg. if
|
| 40 |
+
--quiet is the "negative alias" of --verbose, then "--quiet"
|
| 41 |
+
on the command line sets 'verbose' to false
|
| 42 |
+
"""
|
| 43 |
+
|
| 44 |
+
def __init__(self, option_table=None):
|
| 45 |
+
# The option table is (currently) a list of tuples. The
|
| 46 |
+
# tuples may have 3 or four values:
|
| 47 |
+
# (long_option, short_option, help_string [, repeatable])
|
| 48 |
+
# if an option takes an argument, its long_option should have '='
|
| 49 |
+
# appended; short_option should just be a single character, no ':'
|
| 50 |
+
# in any case. If a long_option doesn't have a corresponding
|
| 51 |
+
# short_option, short_option should be None. All option tuples
|
| 52 |
+
# must have long options.
|
| 53 |
+
self.option_table = option_table
|
| 54 |
+
|
| 55 |
+
# 'option_index' maps long option names to entries in the option
|
| 56 |
+
# table (ie. those 3-tuples).
|
| 57 |
+
self.option_index = {}
|
| 58 |
+
if self.option_table:
|
| 59 |
+
self._build_index()
|
| 60 |
+
|
| 61 |
+
# 'alias' records (duh) alias options; {'foo': 'bar'} means
|
| 62 |
+
# --foo is an alias for --bar
|
| 63 |
+
self.alias = {}
|
| 64 |
+
|
| 65 |
+
# 'negative_alias' keeps track of options that are the boolean
|
| 66 |
+
# opposite of some other option
|
| 67 |
+
self.negative_alias = {}
|
| 68 |
+
|
| 69 |
+
# These keep track of the information in the option table. We
|
| 70 |
+
# don't actually populate these structures until we're ready to
|
| 71 |
+
# parse the command-line, since the 'option_table' passed in here
|
| 72 |
+
# isn't necessarily the final word.
|
| 73 |
+
self.short_opts = []
|
| 74 |
+
self.long_opts = []
|
| 75 |
+
self.short2long = {}
|
| 76 |
+
self.attr_name = {}
|
| 77 |
+
self.takes_arg = {}
|
| 78 |
+
|
| 79 |
+
# And 'option_order' is filled up in 'getopt()'; it records the
|
| 80 |
+
# original order of options (and their values) on the command-line,
|
| 81 |
+
# but expands short options, converts aliases, etc.
|
| 82 |
+
self.option_order = []
|
| 83 |
+
|
| 84 |
+
def _build_index(self):
|
| 85 |
+
self.option_index.clear()
|
| 86 |
+
for option in self.option_table:
|
| 87 |
+
self.option_index[option[0]] = option
|
| 88 |
+
|
| 89 |
+
def set_option_table(self, option_table):
|
| 90 |
+
self.option_table = option_table
|
| 91 |
+
self._build_index()
|
| 92 |
+
|
| 93 |
+
def add_option(self, long_option, short_option=None, help_string=None):
|
| 94 |
+
if long_option in self.option_index:
|
| 95 |
+
raise DistutilsGetoptError(
|
| 96 |
+
"option conflict: already an option '%s'" % long_option
|
| 97 |
+
)
|
| 98 |
+
else:
|
| 99 |
+
option = (long_option, short_option, help_string)
|
| 100 |
+
self.option_table.append(option)
|
| 101 |
+
self.option_index[long_option] = option
|
| 102 |
+
|
| 103 |
+
def has_option(self, long_option):
|
| 104 |
+
"""Return true if the option table for this parser has an
|
| 105 |
+
option with long name 'long_option'."""
|
| 106 |
+
return long_option in self.option_index
|
| 107 |
+
|
| 108 |
+
def get_attr_name(self, long_option):
|
| 109 |
+
"""Translate long option name 'long_option' to the form it
|
| 110 |
+
has as an attribute of some object: ie., translate hyphens
|
| 111 |
+
to underscores."""
|
| 112 |
+
return long_option.translate(longopt_xlate)
|
| 113 |
+
|
| 114 |
+
def _check_alias_dict(self, aliases, what):
|
| 115 |
+
assert isinstance(aliases, dict)
|
| 116 |
+
for (alias, opt) in aliases.items():
|
| 117 |
+
if alias not in self.option_index:
|
| 118 |
+
raise DistutilsGetoptError(
|
| 119 |
+
("invalid %s '%s': " "option '%s' not defined")
|
| 120 |
+
% (what, alias, alias)
|
| 121 |
+
)
|
| 122 |
+
if opt not in self.option_index:
|
| 123 |
+
raise DistutilsGetoptError(
|
| 124 |
+
("invalid %s '%s': " "aliased option '%s' not defined")
|
| 125 |
+
% (what, alias, opt)
|
| 126 |
+
)
|
| 127 |
+
|
| 128 |
+
def set_aliases(self, alias):
|
| 129 |
+
"""Set the aliases for this option parser."""
|
| 130 |
+
self._check_alias_dict(alias, "alias")
|
| 131 |
+
self.alias = alias
|
| 132 |
+
|
| 133 |
+
def set_negative_aliases(self, negative_alias):
|
| 134 |
+
"""Set the negative aliases for this option parser.
|
| 135 |
+
'negative_alias' should be a dictionary mapping option names to
|
| 136 |
+
option names, both the key and value must already be defined
|
| 137 |
+
in the option table."""
|
| 138 |
+
self._check_alias_dict(negative_alias, "negative alias")
|
| 139 |
+
self.negative_alias = negative_alias
|
| 140 |
+
|
| 141 |
+
def _grok_option_table(self): # noqa: C901
|
| 142 |
+
"""Populate the various data structures that keep tabs on the
|
| 143 |
+
option table. Called by 'getopt()' before it can do anything
|
| 144 |
+
worthwhile.
|
| 145 |
+
"""
|
| 146 |
+
self.long_opts = []
|
| 147 |
+
self.short_opts = []
|
| 148 |
+
self.short2long.clear()
|
| 149 |
+
self.repeat = {}
|
| 150 |
+
|
| 151 |
+
for option in self.option_table:
|
| 152 |
+
if len(option) == 3:
|
| 153 |
+
long, short, help = option
|
| 154 |
+
repeat = 0
|
| 155 |
+
elif len(option) == 4:
|
| 156 |
+
long, short, help, repeat = option
|
| 157 |
+
else:
|
| 158 |
+
# the option table is part of the code, so simply
|
| 159 |
+
# assert that it is correct
|
| 160 |
+
raise ValueError("invalid option tuple: {!r}".format(option))
|
| 161 |
+
|
| 162 |
+
# Type- and value-check the option names
|
| 163 |
+
if not isinstance(long, str) or len(long) < 2:
|
| 164 |
+
raise DistutilsGetoptError(
|
| 165 |
+
("invalid long option '%s': " "must be a string of length >= 2")
|
| 166 |
+
% long
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
if not ((short is None) or (isinstance(short, str) and len(short) == 1)):
|
| 170 |
+
raise DistutilsGetoptError(
|
| 171 |
+
"invalid short option '%s': "
|
| 172 |
+
"must a single character or None" % short
|
| 173 |
+
)
|
| 174 |
+
|
| 175 |
+
self.repeat[long] = repeat
|
| 176 |
+
self.long_opts.append(long)
|
| 177 |
+
|
| 178 |
+
if long[-1] == '=': # option takes an argument?
|
| 179 |
+
if short:
|
| 180 |
+
short = short + ':'
|
| 181 |
+
long = long[0:-1]
|
| 182 |
+
self.takes_arg[long] = 1
|
| 183 |
+
else:
|
| 184 |
+
# Is option is a "negative alias" for some other option (eg.
|
| 185 |
+
# "quiet" == "!verbose")?
|
| 186 |
+
alias_to = self.negative_alias.get(long)
|
| 187 |
+
if alias_to is not None:
|
| 188 |
+
if self.takes_arg[alias_to]:
|
| 189 |
+
raise DistutilsGetoptError(
|
| 190 |
+
"invalid negative alias '%s': "
|
| 191 |
+
"aliased option '%s' takes a value" % (long, alias_to)
|
| 192 |
+
)
|
| 193 |
+
|
| 194 |
+
self.long_opts[-1] = long # XXX redundant?!
|
| 195 |
+
self.takes_arg[long] = 0
|
| 196 |
+
|
| 197 |
+
# If this is an alias option, make sure its "takes arg" flag is
|
| 198 |
+
# the same as the option it's aliased to.
|
| 199 |
+
alias_to = self.alias.get(long)
|
| 200 |
+
if alias_to is not None:
|
| 201 |
+
if self.takes_arg[long] != self.takes_arg[alias_to]:
|
| 202 |
+
raise DistutilsGetoptError(
|
| 203 |
+
"invalid alias '%s': inconsistent with "
|
| 204 |
+
"aliased option '%s' (one of them takes a value, "
|
| 205 |
+
"the other doesn't" % (long, alias_to)
|
| 206 |
+
)
|
| 207 |
+
|
| 208 |
+
# Now enforce some bondage on the long option name, so we can
|
| 209 |
+
# later translate it to an attribute name on some object. Have
|
| 210 |
+
# to do this a bit late to make sure we've removed any trailing
|
| 211 |
+
# '='.
|
| 212 |
+
if not longopt_re.match(long):
|
| 213 |
+
raise DistutilsGetoptError(
|
| 214 |
+
"invalid long option name '%s' "
|
| 215 |
+
"(must be letters, numbers, hyphens only" % long
|
| 216 |
+
)
|
| 217 |
+
|
| 218 |
+
self.attr_name[long] = self.get_attr_name(long)
|
| 219 |
+
if short:
|
| 220 |
+
self.short_opts.append(short)
|
| 221 |
+
self.short2long[short[0]] = long
|
| 222 |
+
|
| 223 |
+
def getopt(self, args=None, object=None): # noqa: C901
|
| 224 |
+
"""Parse command-line options in args. Store as attributes on object.
|
| 225 |
+
|
| 226 |
+
If 'args' is None or not supplied, uses 'sys.argv[1:]'. If
|
| 227 |
+
'object' is None or not supplied, creates a new OptionDummy
|
| 228 |
+
object, stores option values there, and returns a tuple (args,
|
| 229 |
+
object). If 'object' is supplied, it is modified in place and
|
| 230 |
+
'getopt()' just returns 'args'; in both cases, the returned
|
| 231 |
+
'args' is a modified copy of the passed-in 'args' list, which
|
| 232 |
+
is left untouched.
|
| 233 |
+
"""
|
| 234 |
+
if args is None:
|
| 235 |
+
args = sys.argv[1:]
|
| 236 |
+
if object is None:
|
| 237 |
+
object = OptionDummy()
|
| 238 |
+
created_object = True
|
| 239 |
+
else:
|
| 240 |
+
created_object = False
|
| 241 |
+
|
| 242 |
+
self._grok_option_table()
|
| 243 |
+
|
| 244 |
+
short_opts = ' '.join(self.short_opts)
|
| 245 |
+
try:
|
| 246 |
+
opts, args = getopt.getopt(args, short_opts, self.long_opts)
|
| 247 |
+
except getopt.error as msg:
|
| 248 |
+
raise DistutilsArgError(msg)
|
| 249 |
+
|
| 250 |
+
for opt, val in opts:
|
| 251 |
+
if len(opt) == 2 and opt[0] == '-': # it's a short option
|
| 252 |
+
opt = self.short2long[opt[1]]
|
| 253 |
+
else:
|
| 254 |
+
assert len(opt) > 2 and opt[:2] == '--'
|
| 255 |
+
opt = opt[2:]
|
| 256 |
+
|
| 257 |
+
alias = self.alias.get(opt)
|
| 258 |
+
if alias:
|
| 259 |
+
opt = alias
|
| 260 |
+
|
| 261 |
+
if not self.takes_arg[opt]: # boolean option?
|
| 262 |
+
assert val == '', "boolean option can't have value"
|
| 263 |
+
alias = self.negative_alias.get(opt)
|
| 264 |
+
if alias:
|
| 265 |
+
opt = alias
|
| 266 |
+
val = 0
|
| 267 |
+
else:
|
| 268 |
+
val = 1
|
| 269 |
+
|
| 270 |
+
attr = self.attr_name[opt]
|
| 271 |
+
# The only repeating option at the moment is 'verbose'.
|
| 272 |
+
# It has a negative option -q quiet, which should set verbose = 0.
|
| 273 |
+
if val and self.repeat.get(attr) is not None:
|
| 274 |
+
val = getattr(object, attr, 0) + 1
|
| 275 |
+
setattr(object, attr, val)
|
| 276 |
+
self.option_order.append((opt, val))
|
| 277 |
+
|
| 278 |
+
# for opts
|
| 279 |
+
if created_object:
|
| 280 |
+
return args, object
|
| 281 |
+
else:
|
| 282 |
+
return args
|
| 283 |
+
|
| 284 |
+
def get_option_order(self):
|
| 285 |
+
"""Returns the list of (option, value) tuples processed by the
|
| 286 |
+
previous run of 'getopt()'. Raises RuntimeError if
|
| 287 |
+
'getopt()' hasn't been called yet.
|
| 288 |
+
"""
|
| 289 |
+
if self.option_order is None:
|
| 290 |
+
raise RuntimeError("'getopt()' hasn't been called yet")
|
| 291 |
+
else:
|
| 292 |
+
return self.option_order
|
| 293 |
+
|
| 294 |
+
def generate_help(self, header=None): # noqa: C901
|
| 295 |
+
"""Generate help text (a list of strings, one per suggested line of
|
| 296 |
+
output) from the option table for this FancyGetopt object.
|
| 297 |
+
"""
|
| 298 |
+
# Blithely assume the option table is good: probably wouldn't call
|
| 299 |
+
# 'generate_help()' unless you've already called 'getopt()'.
|
| 300 |
+
|
| 301 |
+
# First pass: determine maximum length of long option names
|
| 302 |
+
max_opt = 0
|
| 303 |
+
for option in self.option_table:
|
| 304 |
+
long = option[0]
|
| 305 |
+
short = option[1]
|
| 306 |
+
ell = len(long)
|
| 307 |
+
if long[-1] == '=':
|
| 308 |
+
ell = ell - 1
|
| 309 |
+
if short is not None:
|
| 310 |
+
ell = ell + 5 # " (-x)" where short == 'x'
|
| 311 |
+
if ell > max_opt:
|
| 312 |
+
max_opt = ell
|
| 313 |
+
|
| 314 |
+
opt_width = max_opt + 2 + 2 + 2 # room for indent + dashes + gutter
|
| 315 |
+
|
| 316 |
+
# Typical help block looks like this:
|
| 317 |
+
# --foo controls foonabulation
|
| 318 |
+
# Help block for longest option looks like this:
|
| 319 |
+
# --flimflam set the flim-flam level
|
| 320 |
+
# and with wrapped text:
|
| 321 |
+
# --flimflam set the flim-flam level (must be between
|
| 322 |
+
# 0 and 100, except on Tuesdays)
|
| 323 |
+
# Options with short names will have the short name shown (but
|
| 324 |
+
# it doesn't contribute to max_opt):
|
| 325 |
+
# --foo (-f) controls foonabulation
|
| 326 |
+
# If adding the short option would make the left column too wide,
|
| 327 |
+
# we push the explanation off to the next line
|
| 328 |
+
# --flimflam (-l)
|
| 329 |
+
# set the flim-flam level
|
| 330 |
+
# Important parameters:
|
| 331 |
+
# - 2 spaces before option block start lines
|
| 332 |
+
# - 2 dashes for each long option name
|
| 333 |
+
# - min. 2 spaces between option and explanation (gutter)
|
| 334 |
+
# - 5 characters (incl. space) for short option name
|
| 335 |
+
|
| 336 |
+
# Now generate lines of help text. (If 80 columns were good enough
|
| 337 |
+
# for Jesus, then 78 columns are good enough for me!)
|
| 338 |
+
line_width = 78
|
| 339 |
+
text_width = line_width - opt_width
|
| 340 |
+
big_indent = ' ' * opt_width
|
| 341 |
+
if header:
|
| 342 |
+
lines = [header]
|
| 343 |
+
else:
|
| 344 |
+
lines = ['Option summary:']
|
| 345 |
+
|
| 346 |
+
for option in self.option_table:
|
| 347 |
+
long, short, help = option[:3]
|
| 348 |
+
text = wrap_text(help, text_width)
|
| 349 |
+
if long[-1] == '=':
|
| 350 |
+
long = long[0:-1]
|
| 351 |
+
|
| 352 |
+
# Case 1: no short option at all (makes life easy)
|
| 353 |
+
if short is None:
|
| 354 |
+
if text:
|
| 355 |
+
lines.append(" --%-*s %s" % (max_opt, long, text[0]))
|
| 356 |
+
else:
|
| 357 |
+
lines.append(" --%-*s " % (max_opt, long))
|
| 358 |
+
|
| 359 |
+
# Case 2: we have a short option, so we have to include it
|
| 360 |
+
# just after the long option
|
| 361 |
+
else:
|
| 362 |
+
opt_names = "{} (-{})".format(long, short)
|
| 363 |
+
if text:
|
| 364 |
+
lines.append(" --%-*s %s" % (max_opt, opt_names, text[0]))
|
| 365 |
+
else:
|
| 366 |
+
lines.append(" --%-*s" % opt_names)
|
| 367 |
+
|
| 368 |
+
for ell in text[1:]:
|
| 369 |
+
lines.append(big_indent + ell)
|
| 370 |
+
return lines
|
| 371 |
+
|
| 372 |
+
def print_help(self, header=None, file=None):
|
| 373 |
+
if file is None:
|
| 374 |
+
file = sys.stdout
|
| 375 |
+
for line in self.generate_help(header):
|
| 376 |
+
file.write(line + "\n")
|
| 377 |
+
|
| 378 |
+
|
| 379 |
+
def fancy_getopt(options, negative_opt, object, args):
|
| 380 |
+
parser = FancyGetopt(options)
|
| 381 |
+
parser.set_negative_aliases(negative_opt)
|
| 382 |
+
return parser.getopt(args, object)
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
WS_TRANS = {ord(_wschar): ' ' for _wschar in string.whitespace}
|
| 386 |
+
|
| 387 |
+
|
| 388 |
+
def wrap_text(text, width):
|
| 389 |
+
"""wrap_text(text : string, width : int) -> [string]
|
| 390 |
+
|
| 391 |
+
Split 'text' into multiple lines of no more than 'width' characters
|
| 392 |
+
each, and return the list of strings that results.
|
| 393 |
+
"""
|
| 394 |
+
if text is None:
|
| 395 |
+
return []
|
| 396 |
+
if len(text) <= width:
|
| 397 |
+
return [text]
|
| 398 |
+
|
| 399 |
+
text = text.expandtabs()
|
| 400 |
+
text = text.translate(WS_TRANS)
|
| 401 |
+
chunks = re.split(r'( +|-+)', text)
|
| 402 |
+
chunks = [ch for ch in chunks if ch] # ' - ' results in empty strings
|
| 403 |
+
lines = []
|
| 404 |
+
|
| 405 |
+
while chunks:
|
| 406 |
+
cur_line = [] # list of chunks (to-be-joined)
|
| 407 |
+
cur_len = 0 # length of current line
|
| 408 |
+
|
| 409 |
+
while chunks:
|
| 410 |
+
ell = len(chunks[0])
|
| 411 |
+
if cur_len + ell <= width: # can squeeze (at least) this chunk in
|
| 412 |
+
cur_line.append(chunks[0])
|
| 413 |
+
del chunks[0]
|
| 414 |
+
cur_len = cur_len + ell
|
| 415 |
+
else: # this line is full
|
| 416 |
+
# drop last chunk if all space
|
| 417 |
+
if cur_line and cur_line[-1][0] == ' ':
|
| 418 |
+
del cur_line[-1]
|
| 419 |
+
break
|
| 420 |
+
|
| 421 |
+
if chunks: # any chunks left to process?
|
| 422 |
+
# if the current line is still empty, then we had a single
|
| 423 |
+
# chunk that's too big too fit on a line -- so we break
|
| 424 |
+
# down and break it up at the line width
|
| 425 |
+
if cur_len == 0:
|
| 426 |
+
cur_line.append(chunks[0][0:width])
|
| 427 |
+
chunks[0] = chunks[0][width:]
|
| 428 |
+
|
| 429 |
+
# all-whitespace chunks at the end of a line can be discarded
|
| 430 |
+
# (and we know from the re.split above that if a chunk has
|
| 431 |
+
# *any* whitespace, it is *all* whitespace)
|
| 432 |
+
if chunks[0][0] == ' ':
|
| 433 |
+
del chunks[0]
|
| 434 |
+
|
| 435 |
+
# and store this line in the list-of-all-lines -- as a single
|
| 436 |
+
# string, of course!
|
| 437 |
+
lines.append(''.join(cur_line))
|
| 438 |
+
|
| 439 |
+
return lines
|
| 440 |
+
|
| 441 |
+
|
| 442 |
+
def translate_longopt(opt):
|
| 443 |
+
"""Convert a long option name to a valid Python identifier by
|
| 444 |
+
changing "-" to "_".
|
| 445 |
+
"""
|
| 446 |
+
return opt.translate(longopt_xlate)
|
| 447 |
+
|
| 448 |
+
|
| 449 |
+
class OptionDummy:
|
| 450 |
+
"""Dummy class just used as a place to hold command-line option
|
| 451 |
+
values as instance attributes."""
|
| 452 |
+
|
| 453 |
+
def __init__(self, options=[]):
|
| 454 |
+
"""Create a new OptionDummy instance. The attributes listed in
|
| 455 |
+
'options' will be initialized to None."""
|
| 456 |
+
for opt in options:
|
| 457 |
+
setattr(self, opt, None)
|
| 458 |
+
|
| 459 |
+
|
| 460 |
+
if __name__ == "__main__":
|
| 461 |
+
text = """\
|
| 462 |
+
Tra-la-la, supercalifragilisticexpialidocious.
|
| 463 |
+
How *do* you spell that odd word, anyways?
|
| 464 |
+
(Someone ask Mary -- she'll know [or she'll
|
| 465 |
+
say, "How should I know?"].)"""
|
| 466 |
+
|
| 467 |
+
for w in (10, 20, 30, 40):
|
| 468 |
+
print("width: %d" % w)
|
| 469 |
+
print("\n".join(wrap_text(text, w)))
|
| 470 |
+
print()
|