3

When trying to install a package with pip on Windows 10 (Python=3.11.13, pip=25.2, setuptools=80.9.0) via

pip install --no-binary :all: pycryptodome

I get apparently infamous error with not particularly insightful message:

 Testing support for clang
 Traceback (most recent call last):
 File "G:\dev\AIPY\Anaconda\Lib\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 389, in <module>
 main()
 File "G:\dev\AIPY\Anaconda\Lib\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 373, in main
 json_out["return_val"] = hook(**hook_input["kwargs"])
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "G:\dev\AIPY\Anaconda\Lib\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 143, in get_requires_for_build_wheel
 return hook(config_settings)
 ^^^^^^^^^^^^^^^^^^^^^
 File "C:\Users\pcuser\AppData\Local\Temp\pip-build-env-6vq0slrk\overlay\Lib\site-packages\setuptools\build_meta.py", line 331, in get_requires_for_build_wheel
 return self._get_build_requires(config_settings, requirements=[])
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "C:\Users\pcuser\AppData\Local\Temp\pip-build-env-6vq0slrk\overlay\Lib\site-packages\setuptools\build_meta.py", line 301, in _get_build_requires
 self.run_setup()
 File "C:\Users\pcuser\AppData\Local\Temp\pip-build-env-6vq0slrk\overlay\Lib\site-packages\setuptools\build_meta.py", line 317, in run_setup
 exec(code, locals())
 File "<string>", line 497, in <module>
 File "C:\Users\pcuser\AppData\Local\Temp\pip-install-jgu9gndw\pycryptodome_de2d839aee6b4295aed8e8f887f27c7f\compiler_opt.py", line 333, in set_compiler_options
 clang = compiler_is_clang()
 ^^^^^^^^^^^^^^^^^^^
 File "C:\Users\pcuser\AppData\Local\Temp\pip-install-jgu9gndw\pycryptodome_de2d839aee6b4295aed8e8f887f27c7f\compiler_opt.py", line 257, in compiler_is_clang
 return test_compilation(source, msg="clang")
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "C:\Users\pcuser\AppData\Local\Temp\pip-install-jgu9gndw\pycryptodome_de2d839aee6b4295aed8e8f887f27c7f\compiler_opt.py", line 82, in test_compilation
 objects = compiler.compile([fname], extra_postargs=extra_cc_options)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "C:\Users\pcuser\AppData\Local\Temp\pip-build-env-6vq0slrk\overlay\Lib\site-packages\setuptools\_distutils\compilers\C\msvc.py", line 384, in compile
 self.initialize()
 File "C:\Users\pcuser\AppData\Local\Temp\pip-build-env-6vq0slrk\overlay\Lib\site-packages\setuptools\_distutils\compilers\C\msvc.py", line 294, in initialize
 vc_env = _get_vc_env(plat_spec)
 ^^^^^^^^^^^^^^^^^^^^^^
 File "C:\Users\pcuser\AppData\Local\Temp\pip-build-env-6vq0slrk\overlay\Lib\site-packages\setuptools\_distutils\compilers\C\msvc.py", line 155, in _get_vc_env
 raise DistutilsPlatformError(
 distutils.errors.DistutilsPlatformError: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/

Given that I have recent MSVC Build Tools installed (same shell):

G:\dev\AIPY\Anaconda>cl
Microsoft (R) C/C++ Optimizing Compiler Version 19.44.35217 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ]

the error message does not help at all. No helpful information in Google, similar SO questions, or from Gemini. So what is wrong and how do I fix it?

asked Oct 13, 2025 at 19:26
1
  • error shows problem in msvc.py", line 155, in _get_vc_env and here is source code - maybe this help you understand how it checks if you have installed compiler. You could try to find this file on your disk and add some print() to see what values are in variables. Commented Oct 13, 2025 at 19:40

1 Answer 1

4

TL;DR

The most robust solution, perhaps, is the not very well documented variable DISTUTILS_USE_SDK=1. If set, it instructs setuptools to use activated (via vcvarsall.bat ) MSVC environment.

Note, see this SO answer regarding installing MS Build Tools, if not already installed.

Detailed Discussion

While the error message itself is not particularly helpful, the trace does provide some initial clues. Given the keywords in the trace, it is reasonable to assume that the associated code is looking for a compiler. Since my interest is in MSVC, the reference to the module

setuptools\_distutils\compilers\C\msvc.py

proved to be the right place to focus on. The stack specifically points to the _get_vc_env() routine, apparently tasked with locating MSVC tools.

The relevant module section:

def _find_vc2015():
 try:
 key = winreg.OpenKeyEx(
 winreg.HKEY_LOCAL_MACHINE,
 r"Software\Microsoft\VisualStudio\SxS\VC7",
 access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY,
 )
 except OSError:
 log.debug("Visual C++ is not registered")
 return None, None
 best_version = 0
 best_dir = None
 with key:
 for i in count():
 try:
 v, vc_dir, vt = winreg.EnumValue(key, i)
 except OSError:
 break
 if v and vt == winreg.REG_SZ and os.path.isdir(vc_dir):
 try:
 version = int(float(v))
 except (ValueError, TypeError):
 continue
 if version >= 14 and version > best_version:
 best_version, best_dir = version, vc_dir
 return best_version, best_dir
def _find_vc2017():
 """Returns "15, path" based on the result of invoking vswhere.exe
 If no install is found, returns "None, None"
 The version is returned to avoid unnecessarily changing the function
 result. It may be ignored when the path is not None.
 If vswhere.exe is not available, by definition, VS 2017 is not
 installed.
 """
 root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles")
 if not root:
 return None, None
 variant = 'arm64' if get_platform() == 'win-arm64' else 'x86.x64'
 suitable_components = (
 f"Microsoft.VisualStudio.Component.VC.Tools.{variant}",
 "Microsoft.VisualStudio.Workload.WDExpress",
 )
 for component in suitable_components:
 # Workaround for `-requiresAny` (only available on VS 2017 > 15.6)
 with contextlib.suppress(
 subprocess.CalledProcessError, OSError, UnicodeDecodeError
 ):
 path = (
 subprocess.check_output([
 os.path.join(
 root, "Microsoft Visual Studio", "Installer", "vswhere.exe"
 ),
 "-latest",
 "-prerelease",
 "-requires",
 component,
 "-property",
 "installationPath",
 "-products",
 "*",
 ])
 .decode(encoding="mbcs", errors="strict")
 .strip()
 )
 path = os.path.join(path, "VC", "Auxiliary", "Build")
 if os.path.isdir(path):
 return 15, path
 return None, None # no suitable component found
PLAT_SPEC_TO_RUNTIME = {
 'x86': 'x86',
 'x86_amd64': 'x64',
 'x86_arm': 'arm',
 'x86_arm64': 'arm64',
}
def _find_vcvarsall(plat_spec):
 # bpo-38597: Removed vcruntime return value
 _, best_dir = _find_vc2017()
 if not best_dir:
 best_version, best_dir = _find_vc2015()
 
 if not best_dir:
 log.debug("No suitable Visual C++ version found")
 return None, None
 vcvarsall = os.path.join(best_dir, "vcvarsall.bat")
 if not os.path.isfile(vcvarsall):
 log.debug("%s cannot be found", vcvarsall)
 return None, None
 return vcvarsall, None
def _get_vc_env(plat_spec):
 if os.getenv("DISTUTILS_USE_SDK"):
 return {key.lower(): value for key, value in os.environ.items()}
 vcvarsall, _ = _find_vcvarsall(plat_spec)
 if not vcvarsall:
 raise DistutilsPlatformError(
 'Microsoft Visual C++ 14.0 or greater is required. '
 'Get it with "Microsoft C++ Build Tools": '
 'https://visualstudio.microsoft.com/visual-cpp-build-tools/'
 )
 <IRRELEVANT PART>
 return env

The _get_vc_env() routine calls _find_vcvarsall(), which, in turn, calls _find_vc2015() and _find_vc2017(). One of them tries to check a known registry key, the other - default paths. While being reasoable checks, MS Build Tools do not need to be registered at all or installed in the default location. A common use case is by invoking a standard shell setting script vcvarsall.bat, also referenced in this snippet. For this reason, it is striking that this code makes no attempt to check relevant environment variables or availablity of the necessary tools on the Path. In fact, I would argue that this missing check should be done first. The module is clearly deffective. As a temporary fix, I added vcvarsall.bat containing directory to Path in my shell "activation" script and the following lines

 if not best_dir:
 import shutil
 best_dir = os.path.dirname(shutil.which("vcvarsall.bat"))

after _find_vc2015() call in _find_vcvarsall (in the snippet above), resolving the issue.

answered Oct 13, 2025 at 20:03
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.