astral-sh / uv

An extremely fast Python package and project manager, written in Rust.
https://docs.astral.sh/uv
Apache License 2.0
22.25k stars 651 forks source link

Is `clang` required for compiling C extensions? #8036

Open cbrnr opened 11 hours ago

cbrnr commented 11 hours ago

I wanted to uv pip install -e . a local package which contains a C extension, but I received an error: command 'clang' failed: No such file or directory. Is this something that uv requires, or is it some upstream package (setuptools maybe)? I'm asking because I already have a C compiler installed (cc -> gcc), so maybe this can be changed with an environment variable? Also, installing the package with the OG pip seems to use gcc.

``` Resolved 68 packages in 1.64s error: Failed to prepare distributions Caused by: Failed to fetch wheel: sleepecg @ file:///home/clemens/Projects/sleepecg Caused by: Build backend failed to build editable through `build_editable` (exit status: 1) [stdout] No `packages` or `py_modules` configuration, performing automatic discovery. `src-layout` detected -- analysing ./src discovered packages -- ['sleepecg', 'sleepecg.classifiers', 'sleepecg.data', 'sleepecg.io'] discovered py_modules -- [] running editable_wheel creating /home/clemens/.cache/uv/sdists-v4/editable/06d660b39b152d1a/jBYKEmid6Pcy_Yhu3Phiy/.tmp4dOrcC/.tmp-ea2n0bef/sleepecg.egg-info writing /home/clemens/.cache/uv/sdists-v4/editable/06d660b39b152d1a/jBYKEmid6Pcy_Yhu3Phiy/.tmp4dOrcC/.tmp-ea2n0bef/sleepecg.egg-info/PKG-INFO writing dependency_links to /home/clemens/.cache/uv/sdists-v4/editable/06d660b39b152d1a/jBYKEmid6Pcy_Yhu3Phiy/.tmp4dOrcC/.tmp-ea2n0bef/sleepecg.egg-info/dependency_links.txt writing requirements to /home/clemens/.cache/uv/sdists-v4/editable/06d660b39b152d1a/jBYKEmid6Pcy_Yhu3Phiy/.tmp4dOrcC/.tmp-ea2n0bef/sleepecg.egg-info/requires.txt writing top-level names to /home/clemens/.cache/uv/sdists-v4/editable/06d660b39b152d1a/jBYKEmid6Pcy_Yhu3Phiy/.tmp4dOrcC/.tmp-ea2n0bef/sleepecg.egg-info/top_level.txt writing manifest file '/home/clemens/.cache/uv/sdists-v4/editable/06d660b39b152d1a/jBYKEmid6Pcy_Yhu3Phiy/.tmp4dOrcC/.tmp-ea2n0bef/sleepecg.egg-info/SOURCES.txt' adding license file 'LICENSE' writing manifest file '/home/clemens/.cache/uv/sdists-v4/editable/06d660b39b152d1a/jBYKEmid6Pcy_Yhu3Phiy/.tmp4dOrcC/.tmp-ea2n0bef/sleepecg.egg-info/SOURCES.txt' creating '/home/clemens/.cache/uv/sdists-v4/editable/06d660b39b152d1a/jBYKEmid6Pcy_Yhu3Phiy/.tmp4dOrcC/.tmp-ea2n0bef/sleepecg-0.6.0.dev0.dist-info' creating /home/clemens/.cache/uv/sdists-v4/editable/06d660b39b152d1a/jBYKEmid6Pcy_Yhu3Phiy/.tmp4dOrcC/.tmp-ea2n0bef/sleepecg-0.6.0.dev0.dist-info/WHEEL running build_py running build_ext building 'sleepecg._heartbeat_detection' extension creating /tmp/tmpwhxe1s8c.build-temp/src/sleepecg clang -pthread -fno-strict-overflow -Wsign-compare -Wunreachable-code -DNDEBUG -g -O3 -Wall -fPIC -fPIC -I/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/numpy/_core/include -I/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/include -I/home/clemens/.local/share/uv/python/cpython-3.13.0-linux-x86_64-gnu/include/python3.13 -c src/sleepecg/_heartbeat_detection.c -o /tmp/tmpwhxe1s8c.build-temp/src/sleepecg/_heartbeat_detection.o [stderr] Traceback (most recent call last): File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/spawn.py", line 70, in spawn subprocess.check_call(cmd, env=_inject_macos_ver(env)) ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/clemens/.local/share/uv/python/cpython-3.13.0-linux-x86_64-gnu/lib/python3.13/subprocess.py", line 414, in check_call retcode = call(*popenargs, **kwargs) File "/home/clemens/.local/share/uv/python/cpython-3.13.0-linux-x86_64-gnu/lib/python3.13/subprocess.py", line 395, in call with Popen(*popenargs, **kwargs) as p: ~~~~~^^^^^^^^^^^^^^^^^^^^^^ File "/home/clemens/.local/share/uv/python/cpython-3.13.0-linux-x86_64-gnu/lib/python3.13/subprocess.py", line 1036, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pass_fds, cwd, env, ^^^^^^^^^^^^^^^^^^^ ...<5 lines>... gid, gids, uid, umask, ^^^^^^^^^^^^^^^^^^^^^^ start_new_session, process_group) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/clemens/.local/share/uv/python/cpython-3.13.0-linux-x86_64-gnu/lib/python3.13/subprocess.py", line 1966, in _execute_child raise child_exception_type(errno_num, err_msg, err_filename) FileNotFoundError: [Errno 2] No such file or directory: 'clang' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/unixccompiler.py", line 200, in _compile self.spawn(compiler_so + cc_args + [src, '-o', obj] + extra_postargs) ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/ccompiler.py", line 1045, in spawn spawn(cmd, dry_run=self.dry_run, **kwargs) ~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/spawn.py", line 72, in spawn raise DistutilsExecError( f"command {_debug(cmd)!r} failed: {exc.args[-1]}" ) from exc distutils.errors.DistutilsExecError: command 'clang' failed: No such file or directory During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/command/editable_wheel.py", line 138, in run self._create_wheel_file(bdist_wheel) ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/command/editable_wheel.py", line 341, in _create_wheel_file files, mapping = self._run_build_commands(dist_name, unpacked, lib, tmp) ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/command/editable_wheel.py", line 264, in _run_build_commands self._run_build_subcommands() ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/command/editable_wheel.py", line 291, in _run_build_subcommands self.run_command(name) ~~~~~~~~~~~~~~~~^^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/cmd.py", line 316, in run_command self.distribution.run_command(command) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/dist.py", line 950, in run_command super().run_command(command) ~~~~~~~~~~~~~~~~~~~^^^^^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/dist.py", line 973, in run_command cmd_obj.run() ~~~~~~~~~~~^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/command/build_ext.py", line 98, in run _build_ext.run(self) ~~~~~~~~~~~~~~^^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/command/build_ext.py", line 359, in run self.build_extensions() ~~~~~~~~~~~~~~~~~~~~~^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/command/build_ext.py", line 476, in build_extensions self._build_extensions_serial() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/command/build_ext.py", line 502, in _build_extensions_serial self.build_extension(ext) ~~~~~~~~~~~~~~~~~~~~^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/command/build_ext.py", line 263, in build_extension _build_ext.build_extension(self, ext) ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/command/build_ext.py", line 557, in build_extension objects = self.compiler.compile( sources, ...<5 lines>... depends=ext.depends, ) File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/ccompiler.py", line 606, in compile self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/unixccompiler.py", line 202, in _compile raise CompileError(msg) distutils.errors.CompileError: command 'clang' failed: No such file or directory /home/clemens/.cache/uv/builds-v0/.tmpIpFClq/lib/python3.13/site-packages/setuptools/_distutils/dist.py:973: _DebuggingTips: Problem in editable installation. !! ******************************************************************************** An error happened while installing `sleepecg` in editable mode. The following steps are recommended to help debug this problem: - Try to install the project normally, without using the editable mode. Does the error still persist? (If it does, try fixing the problem before attempting the editable mode). - If you are using binary extensions, make sure you have all OS-level dependencies installed (e.g. compilers, toolchains, binary libraries, ...). - Try the latest version of setuptools (maybe the error was already fixed). - If you (or your project dependencies) are using any setuptools extension or customization, make sure they support the editable mode. After following the steps above, if the problem still persists and you think this is related to how setuptools handles editable installations, please submit a reproducible example (see https://stackoverflow.com/help/minimal-reproducible-example) to: https://github.com/pypa/setuptools/issues See https://setuptools.pypa.io/en/latest/userguide/development_mode.html for details. ******************************************************************************** !! cmd_obj.run() error: command 'clang' failed: No such file or directory ```
charliermarsh commented 8 hours ago

It's not required -- I believe you can override with export CC=gcc or similar when running a uv command.

cbrnr commented 8 hours ago

Great, thanks! Yes, the CC env variable overwrites the behavior. However, I don't know if it is desired that uv pip behaves like pip in this case; if so, it seems like either pip has a different default (e.g. gcc), or it tries multiple options (e.g. clang, then gcc). I would think that this is a useful behavior, but it is certainly also OK to just set the env varbiable.