-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose compiler classes for customized use #2806
Comments
I would also be interested in the migration process for |
FWIW, this is how I've created compilers without calling private APIs: from setuptools import setup
from setuptools import Extension
from setuptools.command.build_ext import build_ext
class GetCompiler(build_ext):
def finalize_options(self):
super().finalize_options()
# need to have an Extension for `.run()` to create self.compiler
self.extensions = [Extension("unused", ["unused.c"])]
def build_extensions(self):
"""Empty to skip actual compilation"""
# because we need self.extensions to be defined and unused,
# we _also_ need to skip actually building them
def run(self):
super().run()
print(f"Got my compiler! {self.compiler}")
setup(
cmdclass={"compiler": GetCompiler},
) Relying on Then I replaced all my calls to new_compiler/configure_compiler to passing around copies of To always get a fresh compiler, you can do the same thing by patching a from setuptools import Distribution, Extension
def get_compiler():
d = Distribution()
build_ext = Distribution().get_command_obj("build_ext")
build_ext.finalize_options()
# register an extension to ensure a compiler is created
build_ext.extensions = [Extension("ignored", ["ignored.c"])]
# disable building fake extensions
build_ext.build_extensions = lambda: None
# run to populate self.compiler
build_ext.run()
return build_ext.compiler |
Hi @abravalheri, do you think this could get some "official" answer ? |
Hi @neutrinoceros, compilers are still outside of my area of expertise in setuptools. Recently I got more acquainted with I noticed that in #2372, @jaraco seems to be open to implement some changes in order to support the migration, e.g.:
I think that one thing that can help in this process is to collect what are the requirements for the developers (and potentially, if you have any suggestions, what would be the desired interfaces). Would you guys be happy if
What would be the use case for running |
Thanks for your reply ! I will answer on behalf of yt
Pretty much, though any official recommendation would satisfy us.
Not that I know of. |
As a side note, we also rely on |
Thank you very much @neutrinoceros. If the other maintainers are ok with exposing this interface, I can go ahead and try something out (please also feel free to submit a PR - I am a bit busy for July so it may take time...).
I would not mind to track them together... |
@abravalheri @minrk I've opened a PR to try to address this: #3445 |
Thank you very much @neutrinoceros, that is very helpful. I think we should ask Jason to review the PR to see if he agrees with this direction. |
I'm also interested in getting the CCompiler, because I want to write a custom command to compile a shared(!) library that is then accessed by We can do this for statically linked archives (.lib) using the |
Thanks everybody for the patience. This issue had not risen to my attention until now, so bear with me as I catch up. I appreciate the work done here, but I'd like to take this in a different direction.
Definitely not. That location is an implementation detail. If you wish to access distutils modules through the compatibility interface, use I want to be cautious about simply mirroring distutils interfaces under similar names in Setuptools. I don't want to, for example, expose I'm beginning to think that there may be a rationale here for having compiler functionality exposed independent of setuptools (i.e. in a
We're trying to deprecate everything in |
@jaraco : Thanks for tackling this issue!
I have the same use-case in several scientific computing packages, where I have several components:
In general, I need to have access to a C compiler before building the Cython extension so that I can detect some platform-specific functions and headers (like a At the moment I'm never creating a |
our use case for yt is also very well described by @althonos' answer: we use distutils to build Cython extensions.
Wait, this is news to me. Does it mean that |
My main use-case is similar to that of @althonos. Set platform-specific flags before building extensions. The other use-case that I have is that I have a package that offers Another thing that I would be curious to try is to use intel's C compiler when building the extensions instead of MSVC on Windows. I have to date never attempted this, but (or rather because) this would involve creating a custom CCompiler and hooking it into the packaging process. This would be a really cool thing, but maybe treat it as more of a nice-to-have ... at least from my side.
I had the same thought while putting together the package to build the shared library for my ctypes project thingy. I think a dedicated library for this would be an excellent idea and if it does get enough support to make it happen I'm happy to contribute :) |
Yes. That's correct. The only exception is that if
We do, though it's our goal to obviate the need for accessing distutils altogether (eventually deprecating and removing it). Meaning that we do want to identify use-cases like the ones described above and provide a robust, long-term solution that doesn't involve distutils. That's why I'd like to avoid simply exposing distutils interfaces in Setuptools and instead step back and think about the problems that these approaches address. I need to create a milestone to track these efforts. It seems to me from the responses above that there are basically these use-cases we want to meet:
I'm thinking we should create new issues for each and close this issue as "invalid" as the compatibility shim already exposes the compiler classes. Does that sound right? |
@jaraco Sounds like a workable solution from my side. Thanks for taking the time to move this issue forward! |
@jaraco that sounds like a good summary. To answer your questions directly:
I haven't needed this.
Only during setup.py, in a pre-build step I call
Compile test libraries and executables for detection/discovery of dependencies, etc. Similar to autotools' feature/package discovery. These produce information used to configure the 'real' compiler used in
I do it exclusively during package building.
The first two points cover my use case. |
I wouldn't rule out the possibility that people would want to compile C-code during program execution, e.g. for construction of compiled plugins. |
Yes, I think that's a totally valid and reasonable use case. I can't speak for it myself, and can't immediately find an example. cffi, for example instantiates Distribution and Extension objects, invoking |
Cython's inline is another runtime-compilation example where |
Related to this, at package build time, from setup.py I detect the compiler that is in use, using from distutils import ccompiler
...
if compiler == 'msvc':
extension_kwargs['extra_compile_args'] = [
'/Ot',
'/Wall',
'/wd4711',
'/wd4820',
]
elif compiler in ('unix', 'mingw32'):
if liblz4_found:
extension_kwargs = pkgconfig_parse('liblz4')
else:
extension_kwargs['extra_compile_args'] = [
'-O3',
'-Wall',
'-Wundef'
]
else:
print('Unrecognized compiler: {0}'.format(compiler))
sys.exit(1) I don't see any |
@jonathanunderwood did you find a replacement for |
### Background * `distutils` is deprecated with removal planned for Python 3.12 ([pep-0632](https://peps.python.org/pep-0632/)), thus we're trying to replace all distutils usage with setuptools. * Please note that user still have access to `distutils` if setuptools is installed and `SETUPTOOLS_USE_DISTUTILS` is set to `local` (The default in setuptools, more details can be found [in this discussion](pypa/setuptools#2806 (comment))). ### How we decide the replacement * We're following setuptools [Porting from Distutils guide](https://setuptools.pypa.io/en/latest/deprecated/distutils-legacy.html#porting-from-distutils) when deciding the replacement. #### Replacement not mentioned in the guide * Replaced `distutils.utils.get_platform()` with `sysconfig.get_platform()`. * Based on the [answer here](https://stackoverflow.com/questions/71664875/what-is-the-replacement-for-distutils-util-get-platform), and also checked the document that `sysconfig.get_platform()` is good enough for our use cases. * Replaced `DistutilsOptionError` with `OptionError`. * `setuptools.error` is exporting it as `OptionError` [in the code](https://github.com/pypa/setuptools/blob/v59.6.0/setuptools/errors.py). * Upgrade `setuptools` in `test_packages.sh` and changed the version ping to `59.6.0` in `build_artifact_python.bat`. * `distutils.errors.*` is not fully re-exported until `59.0.0` (See [this issue](pypa/setuptools#2698) for more details). ### Changes not included in this PR * We're patching some compiler related functions provided by distutils in our code ([example](https://github.com/grpc/grpc/blob/ee4efc31c1dde7389ece70ba908049d7baeb9c65/src/python/grpcio/_spawn_patch.py#L30)), but since `setuptools` doesn't have similar interface (See [this issue for more details](pypa/setuptools#2806)), we don't have a clear path to replace them yet. <!-- If you know who should review your pull request, please assign it to that person, otherwise the pull request would get assigned randomly. If your pull request is for a specific language, please add the appropriate lang label. -->
Same here. I fail to see how the current situation is usable as a replacement of plain access to Our usecase here is actually simple - let Cython generate the descriptions and then amend the settings inside - by using those from get_default_compiler() and appending a few flags. This is a simple operation. And the only replacement which I can see with the current setuptools is something like sub-classing the default interface manually and adapting something (a poorly documented something). This is NOT user-friendly. |
In pypa/distutils#295, I've started work on refactoring the compilers functionality in distutils such that it can be exposed separately and publicaly in a new namespace. Along with the other recent work to allow Setuptools and distutils to have dependencies, consolidating MSVC support in distutils, and removing deprecated compilers, this behavior gets us closer to having an independent and re-usable library for compiler behavior. There's still some work to do as far as decoupling some of the distutils-specific behaviors, but it's getting close. |
Late addition to this discussion: pywin32 replaces the |
Summary
The porting from distutils docs are a bit sparse, and could use some more specific examples. Specifically, for
distutils.ccompiler
anddistutils.util.get_platform
were the replacements I was looking for, and didn't find.Maybe it would be good to start populating a FAQ section at or linked from the docs. Starting out with finishing the the table in the pep with actual recommended import substitutions that work (4 are there already), would be a huge help for migrators like myself.
OS / Environment
No response
Additional Information
In attempting to migrate https://github.com/zeromq/pyzmq away from distutils, I came up with some questions that don't appear to have clear answers in docs, and it seems like setuptools is the right place for such docs (if that's wrong, what is the right place?).
The pep lists setuptools as the thing to switch to for several APIs, such as
ccompiler
, etc., but at leastccompiler
does not appear to be available from public setuptools APIs. Is importing formsetuptools._distutils
the 'right' way in general to get distutils functionality that hasn't been exposed at public level of setuptools yet? Or are there plans to expose these as top-level APIs (e.g.setutools.ccompiler
)?I can import
new_compiler
andcustomize_compiler
fromsetuptools.command.build_ext
, but that doesn't seem better thansetuptools._distutils.ccompiler
to me. If it were documented as the suggested alternative, I'd be happy, though.Could we perhaps have a statement in the docs about when, if ever, importing from
setuptools._distutils
is appropriate? The text already there:suggests anything that requires importing from
setuptools._distutils
should result in an Issue (how I got here), but maybe could be more explicit about what to do while finding a resolution. A blessing of "import fromsetuptools._distutils
" in the interim would ease some stress on migrators, but may not be what you all want to support.The pep also lists the
platform
module as the replacement fordistutils.util.get_platform
, but in my experience this is not the right advice. Where I've useddistutils.util.get_platform()
, what I really wanted was the build platform string, which is available asdist.get_command_obj('build').plat_name
. I don't always call it from within a command so this is a bit inconvenient, but I think I can manage. I don't think it's possible to construct this from theplatform
module.Code of Conduct
The text was updated successfully, but these errors were encountered: