-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
add a depfile support to cythonize #4563
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
Conversation
First, a note on the correct place for this argument. There are two tools:
It is possible to use cythonize without building, as they are both just providing an interface into similar (shared) functionality, but the UX of each CLI command is, I think, geared towards its primary use. ;) Hence I believe both tools might benefit from the command line argument, and particularly, meson currently uses |
The produced file is foo.c, and you want to add rules for what files force foo.c to be regenerated. foo.pyx is checked into git, so you do not need dependency rules that say "bar.pxd baz.pxi got modified, so foo.pyx needs to be regenerated". tl;dr The rule to create is |
Thanks. Regarding tests, you can add a srctree file under |
Addendum to "the correct place for the argument": this was discussed a bit in mesonbuild/meson#8706 (comment) and @scoder's comment there is relevant.
|
I'd rather consider the main feature of I agree that both tools should support dependency file generation. I guess that |
… That said, it's probably easier to make (As I mentioned before.) |
Ah yeah, I guess a better way of phrasing it would be "also implements a bit of a basic build system, powered under the hood by setuptools, which collects all the files for you, and optionally builds them while detecting out of date files etc. etc." I agree that an MVP to have cythonize create depfiles is useful on its own (meson could always switch to that, if it needs to), just thought I'd make sure the |
So that $ cythonize -M foo.pyx produces `foo.c.dep` file in with foo.pyx dependencies (`foo.c` is produced as well).
Thanks! I've updated the PR with a simple srctree test. It passes locally, but needs somebody with the commit bit to please approve the CI run. Re: correct place for this. So far it's only implemented in |
Co-authored-by: scoder <stefan_ml@behnel.de>
Co-authored-by: scoder <stefan_ml@behnel.de>
Also rework the paths in depfiles: paths below the source are relative, others are absolute (e.g. system dependencies, numpy, cython itself etc)
Thanks Stefan. The PR's updated with Stefan's edits and two more tests : with numpy headers and cythonizing a package (just a slightly modified From my side, the PR is ready for review. |
submit a trivial typo fix PR to sidestep this issue on your next pushes? |
@@ -957,6 +957,8 @@ def cythonize(module_list, exclude=None, nthreads=0, aliases=None, quiet=False, | |||
:param compiler_directives: Allow to set compiler directives in the ``setup.py`` like this: | |||
``compiler_directives={'embedsignature': True}``. | |||
See :ref:`compiler-directives`. | |||
|
|||
:param depfile: produce depfiles for the sources if True. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's funny that we list options here that are not actually arguments of the function. I'm not sure if that's really a good idea. I think we should stick to the explicit options that we allow and only state that we also accept arbitrary CompilationOptions
.
This new option is not currently a part of CompilationOptions
. It would probably be better if it was, but then we'd have to make sure that we support it wherever we accept CompilationOptions
in the programmatic interface. And that's currently not the case. So …
Choices I see:
- make this an explicit argument only for
cythonize
and leave it as a frontend feature (which could then optionally be copied to thecython
command – not decided yet if we should do that) - move it into
CompilationOptions
and make it a general compiler feature (which would then also be available to thecython
command) – requires a different implementation then, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you be open to considering the current implementation (of a scotch-tape-and-chewing-gum variety, yes) to unblock downstream and deferring a cleanup to a follow-up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The interface is fine and won't change in the future. Let's keep it for now, stick with cythonize
only, and see if users can adapt. We can still extend it or reimplement it later if they can't.
Cython/Build/Dependencies.py
Outdated
# paths below the base_dir are relative, otherwise absolute | ||
paths = [] | ||
for fname in dependencies: | ||
if src_base_dir in fname: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem safe. Rather use prefix comparisons. I'm sure we already do this … somewhere. Probably something to have in Cython/Utils.py
Cython/Build/Dependencies.py
Outdated
# manually add missing *.pyx files for each *.pxd : | ||
# `cimport foo` means a possible dependence on a `foo.pyx` | ||
# but `all_dependencies(...)` above only list a `foo.pxd` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes in a .pyx
file should not trigger a rebuild of files that only depend on the .pxd
. That's intentional. If anything changes in the binary interface, that should be reflected by the .pxd (or fail when building the other module itself).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow. As a silly example (tests/build/depfile_package.srctree below) : pkg/sub/test.pyx
does from ..test cimport get_str
; the get_str
function is declared in pkg/test.pxd
and implemented in pkg/test.pyx
. If the implementation changes (i.e. pkg/test.pyx
), I'd naively expect a rebuild of the module which is built from pkg/sub/test.pyx
, is not so?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the implementation changes, but the interface doesn't, then nothing that uses the interface needs to be rebuilt.
Note: You may get different results at runtime, but that's not a build issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, so a full build system notices that pkg/test.pyx
changes and marks its targets for a rebuild. Thanks, am rolling back this part of the patch. I think it's nearly done now, the last thing is to figure out what you meant by the prefix comparisons. Will push after that.
OK, review comments addressed, test finally pass locally, let's see if CI agrees (needs approval, again). |
Checked locally on python 2.7 + numpy 1.16 : it's |
Oh, it doesn't depend on the Python version, only on the Cython version (0.x or 3.x) and NumPy version (whether it ships the Thinking about that a bit more, it means that our test would potentially fail if NumPy decided to stop shipping that file or if it started providing an additional |
- Avoid hadcoding the version in np_prefix/__init__.cython-30.pxd - Recognize cy_prefix/Include/numpy/__init__.pxd fallbacks for legacy numpy versions.
Trying it on python 2.7 was mostly to pick a definitely old numpy version (which needs a fallback I've to say I'm amazed by how easy it is to switch Cython between python 2.7 and 3.8. Wow. |
I'd be happy with just stripping out any And yes, older NumPy versions that do not ship a |
That being said, what about the header files? If there is a EDIT: No, hang on. Actually not. They are dependencies of the |
My search-foo failed to find it, mind giving me a pointer? Or is it OK the way it is at the moment? |
https://github.com/cython/cython/blob/master/tests/run/versioned_pxds.srctree |
I think a |
Thanks. Did not know about pxd versioning! The last commit uses |
Thanks. Let's see what users make of this. |
Thanks Stefan! |
Awesome, thanks all! @scoder can I ask how you feel about backporting a PR like this? We're going to release SciPy 1.9.0 with Meson as the build system around June, and for that we could really use this feature and gh-4548. And it's unlikely we'll be able to start depending on a |
Yes please. It would be great if we can include support for this in meson as soon as possible . |
It feels like a new feature, but I'd say that build system improvements are important enough to make an exception. And they don't hurt. Users who need them can just depend on the point version and others will (hopefully) not be impacted. However, the patch doesn't apply cleanly since it is based off a couple of earlier changes in the master branch (which shouldn't be backported). Anyone up for a backport PR? |
$ cythonize -M foo.pyx produces a file `foo.c.dep` with dependencies of foo.pyx, in addition to `foo.c`. Try to write relative paths as much as possible. Backport of cythongh-4563
|
Update: after exploration, it turns out that the In the meantime, I poked around at the frontends and hacked depfile support into the |
See #4916 |
Here's an initial WIP attempt at addressing #4510 (comment), gh-1214 and gh-1459; see also mesonbuild/meson#9049
This PR is deliberately simplistic : given a
foo.pyx
which cimportbar.pxd
and includesbaz.pxi
,produces
foo.c.dep
file in with foo.pyx dependencies along withfoo.c
.An immediate question to mainainers: is this a reasonable place to plug it? Is this simple interface OK?
I'd also appreciate a pointer to how to best add tests for this. I can of course write out several tempfiles, or is there a better way?
Also, @eli-schwartz what would meson need --- in the example above, does it need a list of dependencies for the
foo.c
file (thusfoo.c: foo.pyx bar.pxd baz.pxi
) or for thepyx
file (thusfoo.pyx: bar.pxd baz.pxi
)?