-
Notifications
You must be signed in to change notification settings - Fork 22
Add support for building without isolation #152
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
|
Hi @ryanking13, I've been able to build and test out the feature(s) I've added in this PR, but one problem still exists: the compiler wrappers for Emscripten are still being placed inside temporary directories as a part of the build process for some reason: https://github.com/pyodide/pyodide-build/actions/runs/14151180877/job/39644562112?pr=152#step:11:449 What this means in action is that if I were to build NumPy without isolation via the below command invocation in a persistent build directory, say, in pyodide build . \
-Csetup-args="--cross-file=$(pyodide config get meson_cross_file)" \
-Csetup-args="-Dblas=none" -Csetup-args="-Dlapack=none" \
-nx \ # i.e., --no-isolation and --skip-dependency-check args, which this PR adds
-Cbuild-dir=build`I am able to build a NumPy wheel. However, if I were to rerun the same command, hoping to make use of the caching provided by the persistent build directory and achieve a speedup for the subsequent run(s) , it would fail because Meson stores its build metadata inside the build directory, which also contains information about the compiler, etc. Meson then fails to find the compiler, as the temporary directory used the previous wheel build where the compiler wrappers were stored no longer exists. When I build NumPy with a persistent build dir with native compilation on my macOS machine, the compilers are picked up correctly from conda-forge each time – this makes me think that this is a I think you would be the best person to know why this is the case and on how we can address it, so I thought I should ask you about it! :) |
|
Hi @agriyakhetarpal, thanks for working on this.
Yep, we are using temporary directory for now, but I think you can change it. We've already changed it in recipe build to store the symlinks in the build directory (#96), so I think you can do the similar thing in the The directory where the symlinks are stored is decided here and here. I think you can pass the |
| config_settings: ConfigSettingsType, | ||
| output_lockfile: str | None, | ||
| isolation: bool = True, | ||
| skip_dependency_check: bool = False, |
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.
(No action is required for this PR)
It may be weird to build all the dependencies in a no-isolation mode. But let's go as-is for now. I personally want to deprecate the feature to build the dependencies if package maintainers in Python ecosystem starts to build Pyodide wheel themselves.
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.
Joe Marshall added this and we were always a bit unsure if it made sense as a feature.
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.
Yes, I added these extra args to normalise what passes through these functions, even if unused. I agree that it makes sense to drop it entirely. I don't think I've used it personally, and I I haven't seen it being used in the main Pyodide repo.
pyodide_build/pypabuild.py
Outdated
| builder = _ProjectBuilder(srcdir, runner=_gen_runner(build_env)) | ||
|
|
||
| if not skip_dependency_check: | ||
| missing = builder.check_dependencies( |
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.
👍
check_dependencies looks like a union of
- get_requires_for_build (== dependencies for the build backend such as setuptools, meson)
- build_system_requires (== dependencies in the pyproject.toml)
In the isolated build, we've been dealing with them separately. I guess we can use check_dependencies there too (no action required for this PR).
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.
Moved this to a new issue: #175.
Co-Authored-By: Gyeongjae Choi <def6488@gmail.com>
Thanks a lot for the pointer! I'm able to get subsequent builds for NumPy working. :D I was able to compile NumPy in 77 seconds on my machine, and taking advantage of the build caching through the persistence of the build dir, |
This reverts commit abad178.
217185c to
6088aba
Compare
|
Thanks again Agriya! I didn't forget this PR, but I've been a little busy this week and haven't been keeping up with all the PRs. I would like to review this in detail, so please wait for me until the weekend! 🙏 |
|
No rush, thank you! :) |
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.
I left some minor comments, but it looks good to me overall.
I was able to compile NumPy in 77 seconds on my machine, and taking advantage of the build caching through the persistence of the build dir, numpy-tests compiles in 8 seconds.
Nice!
BTW, some of the Google's Bazel-based packages were relying on no-isolated builds, such as JAX. There were a lot of other build issues as well, but I think would make one step closer to supporting those packages. Thank you!
| @contextmanager | ||
| def _create_symlink_dir(env: dict[str, str], build_dir: Path | None): | ||
| if build_dir: | ||
| # If we're running under build-recipes, leave the symlinks in | ||
| # the build directory. This helps with reproducing. | ||
| symlink_dir = build_dir / "pywasmcross_symlinks" | ||
| shutil.rmtree(symlink_dir, ignore_errors=True) | ||
| symlink_dir.mkdir() | ||
| yield symlink_dir | ||
| return | ||
|
|
||
| # Running from "pyodide build". Put symlinks in a temporary directory. | ||
| # TODO: Add a debug option to save the symlinks. | ||
| with TemporaryDirectory() as symlink_dir_str: | ||
| yield Path(symlink_dir_str) | ||
| def _create_symlink_dir( |
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.
We are not using a temporary directory anymore, so I don't think this needs to be a context manager anymore. No cleanup is done at the function end.
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.
I tried this, and it still requires a temporary directory to be created in one more case, as get_build_env also allows build_dir to be None. It looks like it's a little more complex than expected, so I hope it's okay to leave this and try it out in a follow-up PR?
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.
Moved it to a new issue: #176
|
Many thanks for the detailed review, @ryanking13! I'll merge this now, and I've opened issues for adding follow-ups. |
Description
This PR is the first in a series of PRs aiming to unblock #109 and also towards strides in other areas; such as being able to build a package from one directory twice, see pyodide/pyodide#5031. In particular, this adds two new flags:
--no-isolation/-nand--skip-dependency-check/-x, to thepyodide buildCLI. These will allow us not to use an isolated virtual environment when building a wheel for a package if required.Closes #136
See also
Some TODO items