pypa / pypa/setuptools

[BUG] `extension.Extension` does not update `LDSHARED` from `CC`

Open
#2,933 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug Needs Triage
Dominant language
Python
Stars
2.9k
Forks
1.4k
Avg merge
1d 1h
Merged PRs (30d)
1

Description

setuptools version

59.7.0

Python version

Python 3.9.9

OS

Ubuntu Linux (20.04 LTS)

Additional environment information

Running setuptools with Homebrew's bottled Python. See Homebrew/homebrew-core#91616: Bottled Python causes the third-party CXX project to fail to build.

Homebrew's python3 (bottled):

$ brew install python3

$ python3 -c "print(__import__('sysconfig').get_config_var('CC'))"
gcc-5 -pthread

$ python3 -c "print(__import__('sysconfig').get_config_var('LDSHARED'))"
gcc-5 -pthread -shared

$ echo "${CC}"  # user defined
/usr/bin/gcc

$ echo "${LDSHARED}"  # empty

Description

The Homebrew's bottled Python was compiled with gcc-5 in a Ubuntu 16.04 container.

setuptools tries to use the C compiler and linker which the Python was built with (i.e. gcc-5) when running build_ext. However, gcc-5 does not exist on my machine (Ubuntu 20.04 LTS). I have set environment variable CC=/usr/bin/gcc but haven't set LDSHARED.


extension.Library do a plain inherence from extension.Extension.

https://github.com/pypa/setuptools/blob/a0f456a063e779b5d5263d2c0a8d0e731e27ad6e/setuptools/extension.py#L54-L55

The developers usually think they are the same, and use Extension instead of Library. It is much easier to import though (from setuptools import Extension vs. from setuptools.extension import Library).

https://github.com/pypa/setuptools/blob/a0f456a063e779b5d5263d2c0a8d0e731e27ad6e/setuptools/command/build_ext.py#L139-L142

build_ext calls sysconfig.customize_compiler(compiler) only when there is at least one Library instance provided. If the developer uses Extension rather than Library, build_ext will use CC from the environment variable but do not update LDSHARED to a proper value.

In _distutils.command.build_ext.buid_ext.run(), we have customize_compiler(compiler):

https://github.com/pypa/setuptools/blob/a0f456a063e779b5d5263d2c0a8d0e731e27ad6e/setuptools/_distutils/command/build_ext.py#L303-L309

but it doesn't seem to work.

Expected behavior

Update LDSHARED to the corresponding value when CC is provided when running build_ext with Extension instances (already done for Library instances).

How to Reproduce
  1. Install Homebrew's Python
  2. Clone mrab-regex and change the working directory
  3. Set CC=/usr/bin/gcc
  4. Run pip3 install .
Output

Commands inside brew's docker (docker run -it --rm -h ubuntu ghcr.io/homebrew/ubuntu20.04:latest) (see https://github.com/Homebrew/homebrew-core/issues/91616#issuecomment-997226208):

linuxbrew@ubuntu:~$ git clone --depth=1 https://bitbucket.org/mrabarnett/mrab-regex.git
Cloning into 'mrab-regex'...
remote: Enumerating objects: 27, done.
remote: Counting objects: 100% (27/27), done.
remote: Compressing objects: 100% (27/27), done.
remote: Total 27 (delta 5), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (27/27), 380.98 KiB | 363.00 KiB/s, done.
linuxbrew@ubuntu:~$ cd mrab-regex

linuxbrew@ubuntu:~/mrab-regex$ export CC="$(which gcc)"

linuxbrew@ubuntu:~/mrab-regex$ pip3 install .
DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
Processing /home/linuxbrew/mrab-regex
  Preparing metadata (setup.py) ... done
Building wheels for collected packages: regex
  Building wheel for regex (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /home/linuxbrew/.linuxbrew/opt/python@3.9/bin/python3.9 -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/home/linuxbrew/mrab-regex/setup.py'"'"'; __file__='"'"'/home/linuxbrew/mrab-regex/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-99ov22m7
       cwd: /home/linuxbrew/mrab-regex/
  Complete output (9 lines):
  running bdist_wheel
  running build
  running build_py
  running build_ext
  building 'regex._regex' extension
  /usr/bin/gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC -I/home/linuxbrew/.linuxbrew/include -I/home/linuxbrew/.linuxbrew/opt/openssl@1.1/include -I/home/linuxbrew/.linuxbrew/opt/sqlite/include -I/home/linuxbrew/.linuxbrew/opt/python@3.9/include/python3.9 -c regex_3/_regex.c -o build/temp.linux-x86_64-3.9/regex_3/_regex.o
  /usr/bin/gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC -I/home/linuxbrew/.linuxbrew/include -I/home/linuxbrew/.linuxbrew/opt/openssl@1.1/include -I/home/linuxbrew/.linuxbrew/opt/sqlite/include -I/home/linuxbrew/.linuxbrew/opt/python@3.9/include/python3.9 -c regex_3/_regex_unicode.c -o build/temp.linux-x86_64-3.9/regex_3/_regex_unicode.o
  gcc-5 -pthread -shared build/temp.linux-x86_64-3.9/regex_3/_regex.o build/temp.linux-x86_64-3.9/regex_3/_regex_unicode.o -L/home/linuxbrew/.linuxbrew/lib -L/home/linuxbrew/.linuxbrew/opt/openssl@1.1/lib -L/home/linuxbrew/.linuxbrew/opt/sqlite/lib -L/home/linuxbrew/.linuxbrew/opt/python@3.9/lib -o build/lib.linux-x86_64-3.9/regex/_regex.cpython-39-x86_64-linux-gnu.so
  error: command 'gcc-5' failed: No such file or directory
  ----------------------------------------
  ERROR: Failed building wheel for regex
  Running setup.py clean for regex
Failed to build regex
Installing collected packages: regex
  DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
    Running setup.py install for regex ... error
    ERROR: Command errored out with exit status 1:
     command: /home/linuxbrew/.linuxbrew/opt/python@3.9/bin/python3.9 -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/home/linuxbrew/mrab-regex/setup.py'"'"'; __file__='"'"'/home/linuxbrew/mrab-regex/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-d74r2fkr/install-record.txt --single-version-externally-managed --compile --install-headers /home/linuxbrew/.linuxbrew/include/python3.9/regex
         cwd: /home/linuxbrew/mrab-regex/
    Complete output (20 lines):
    running install
    /home/linuxbrew/.linuxbrew/opt/python@3.9/lib/python3.9/site-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
      warnings.warn(
    running build
    running build_py
    creating build
    creating build/lib.linux-x86_64-3.9
    creating build/lib.linux-x86_64-3.9/regex
    copying regex_3/__init__.py -> build/lib.linux-x86_64-3.9/regex
    copying regex_3/regex.py -> build/lib.linux-x86_64-3.9/regex
    copying regex_3/_regex_core.py -> build/lib.linux-x86_64-3.9/regex
    copying regex_3/test_regex.py -> build/lib.linux-x86_64-3.9/regex
    running build_ext
    building 'regex._regex' extension
    creating build/temp.linux-x86_64-3.9
    creating build/temp.linux-x86_64-3.9/regex_3
    /usr/bin/gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC -I/home/linuxbrew/.linuxbrew/include -I/home/linuxbrew/.linuxbrew/opt/openssl@1.1/include -I/home/linuxbrew/.linuxbrew/opt/sqlite/include -I/home/linuxbrew/.linuxbrew/opt/python@3.9/include/python3.9 -c regex_3/_regex.c -o build/temp.linux-x86_64-3.9/regex_3/_regex.o
    /usr/bin/gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC -I/home/linuxbrew/.linuxbrew/include -I/home/linuxbrew/.linuxbrew/opt/openssl@1.1/include -I/home/linuxbrew/.linuxbrew/opt/sqlite/include -I/home/linuxbrew/.linuxbrew/opt/python@3.9/include/python3.9 -c regex_3/_regex_unicode.c -o build/temp.linux-x86_64-3.9/regex_3/_regex_unicode.o
    gcc-5 -pthread -shared build/temp.linux-x86_64-3.9/regex_3/_regex.o build/temp.linux-x86_64-3.9/regex_3/_regex_unicode.o -L/home/linuxbrew/.linuxbrew/lib -L/home/linuxbrew/.linuxbrew/opt/openssl@1.1/lib -L/home/linuxbrew/.linuxbrew/opt/sqlite/lib -L/home/linuxbrew/.linuxbrew/opt/python@3.9/lib -o build/lib.linux-x86_64-3.9/regex/_regex.cpython-39-x86_64-linux-gnu.so
    error: command 'gcc-5' failed: No such file or directory
    ----------------------------------------
ERROR: Command errored out with exit status 1: /home/linuxbrew/.linuxbrew/opt/python@3.9/bin/python3.9 -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/home/linuxbrew/mrab-regex/setup.py'"'"'; __file__='"'"'/home/linuxbrew/mrab-regex/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-d74r2fkr/install-record.txt --single-version-externally-managed --compile --install-headers /home/linuxbrew/.linuxbrew/include/python3.9/regex Check the logs for full command output.

linuxbrew@ubuntu:~/mrab-regex$ export LDSHARED="${CC} -pthread -shared"
linuxbrew@ubuntu:~/mrab-regex$ pip3 install .
DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
Processing /home/linuxbrew/mrab-regex
  Preparing metadata (setup.py) ... done
Building wheels for collected packages: regex
  Building wheel for regex (setup.py) ... done
  Created wheel for regex: filename=regex-2021.10.23-cp39-cp39-linux_x86_64.whl size=743993 sha256=ad8b1a83e9a5c0808f789ffe44d15bc8543e1dc290fdb3e91cdcfb7c14f4dfad
  Stored in directory: /home/linuxbrew/.cache/pip/wheels/f5/4d/0e/b3ae0f959231f3977fc584696d03011bcdb48d02ba86ae9468
Successfully built regex
Installing collected packages: regex
  DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621
Successfully installed regex-2021.10.23
Code of Conduct
  • I agree to follow the PSF Code of Conduct

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in setuptools/extension.py and setuptools/command/build_ext.py, then compare the customize_compiler call in setuptools/_distutils/command/build_ext.py. Reproduce the issue with CC set and LDSHARED unset using the mrab-regex example. Done means an Extension build uses the corresponding linker setting and no longer invokes the unavailable gcc-5.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
build-system
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.