This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: new_compiler() called 2nd time causes error
Type: behavior Stage: resolved
Components: Distutils Versions: Python 3.8, Python 3.7, Python 3.6
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: dstufft, eric.araujo, jkloth, steve.dower, televi
Priority: normal Keywords:

Created on 2020-03-09 20:01 by televi, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (3)
msg363765 - (view) Author: Todd Levi (televi) Date: 2020-03-09 20:01
Action:
Run the following command in py36, py37, and py3 for package uvloop

python setup.py build_ext --inline bdist_wheel

Expected behavior:

The package is built and bundled as a wheel.

Observed behavior:

The build fails at the bdist_wheel stage with the following error:

error: don't know how to compile C/C++ code on platform 'posix' with '<distutils.unixccompiler.UnixCCompiler object at 0x7f6054587438>' compiler

Additional Notes:

If I split the two commands (build_ext and bdist_wheel) into separate invocations (e.g. python setup.py build_ext --inline && python setup.py bdist_wheel) then the wheel is successfully built.  It only (and always) fails when build_ext and bdist_wheel are on the same command line.

What "seems" to be happening is that bdist_wheel is somehow inheriting the existing CCompiler object that was used by build_ext and is then passing that back to distutils.compiler.new_compiler().  The new_compiler() function simply checks to see if compiler is None and, if not, uses its value as a key to the compiler_class dict.

The distutils/command/build_ext build_ext object initially sets self.compiler to None so the first invocation of new_compiler() in build_ext.run() will work as expected.  In build_ext.run() at around line 306 (in master), however, it simply does self.compiler = new_compiler(compiler=self.compiler,...) so any subsequent invocation of run() seems like it will fail and produce the error message I'm seeing.  new_compiler() is the only place I see that error message being emitted.

The package I'm building (uvloop) is being built with Cython but all the object paths I've been able to track come back to distutils.ccompiler.py.  That packages setup.py file doesn't seem to do anything weird that I can see (which doesn't mean it isn't doing something weird).  It sets the sdist and build_ext cmdclass entries to their own methods (that don't seem to set compiler - just compiler options) and also registers an extension via ext_modules.  The setup.py code is here: https://github.com/MagicStack/uvloop/blob/master/setup.py

Possible Fix:

Two simple possibilities come to mind.  1) In run, see if self.compiler is not None and alter the call to new_compiler() to use self.compiler.compiler_type.  2) In new_compiler(), check the type of compiler and simply return if its a CCompiler object.
msg364571 - (view) Author: Todd Levi (televi) Date: 2020-03-18 21:59
In looking through the setup.py file for uvloop, I see that they purposely do not call super().initialize_options() or super().finalize_options() in their code if they've already been called once.

I think that is why their code is revealing this problem - the 2nd command to be run is inheriting the self.compiler value from the first command since build_ext.initialize_options() isn't being called to (re)set self.compiler to be None.

I'm not sure if there's a "rule" that says each command must call initialize_options() to "sanitize" the object or not but that does explain why the 2nd command is seeing a CCompiler object() for self.compiler on the 2nd time through.
msg386263 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2021-02-03 18:07
Distutils is now deprecated (see PEP 632) and all tagged issues are being closed. From now until removal, only release blocking issues will be considered for distutils.

If this issue does not relate to distutils, please remove the component and reopen it. If you believe it still requires a fix, most likely the issue should be re-reported at https://github.com/pypa/setuptools
History
Date User Action Args
2022-04-11 14:59:27adminsetgithub: 84098
2021-02-03 18:07:56steve.dowersetstatus: open -> closed

nosy: + steve.dower
messages: + msg386263

resolution: out of date
stage: resolved
2020-03-18 21:59:51televisetmessages: + msg364571
2020-03-09 20:34:32jklothsetnosy: + jkloth
2020-03-09 20:01:52televicreate