Skip to content
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

Feature design proposal/prototype: pixi build #1654

Open
ruben-arts opened this issue Jul 23, 2024 · 9 comments · May be fixed by #2250
Open

Feature design proposal/prototype: pixi build #1654

ruben-arts opened this issue Jul 23, 2024 · 9 comments · May be fixed by #2250
Labels
area:build Related to pixi build

Comments

@ruben-arts
Copy link
Contributor

ruben-arts commented Jul 23, 2024

As #793 didn't give us enough discussion to finalize a design that fit our ideas, so we've started an ultra simple prototype. This issue is to share the status and hopefully fetch more input from our contributors.

The goal:

  • Allow pixi to call build tools to build packages for distribution.
  • Allow pixi projects to depend on pixi project, which invokes build to build the dependency on the spot.

Out of scope

  • We're not looking at mixed conda and pypi projects.

The build section in the manifest file

# Users can define multiple build backend
[build.conda]
# These requirements are installed in a pixi specific build environment.
# This tool is going to do the actual build.
requires = { pixi-build-python = "3.12" } 
# A pixi task to run the build. Uses the normal `pixi task` workflow.
# Including depends-on, inputs, outputs, etc.
task = { cmd = "pixi-build-conda", ..., inputs = ["*.py"] }

# We allow extra metadata in a `tool` section. 
# This enables build-tool specific configuration to be stored.
[tool.pixi-build-python]
build = "noarch"

The build command

pixi build conda

  • Pixi will create an build environment where it installs the required tool.
  • Pixi will run the build.conda.task in that environment.
  • The build tool will do its thing, and notify pixi with the result.

The build tool.

We want users to not get locked in by our build backend for which tools they can use to build packages.
Building a backend should be simple and straight forward, with a small communication layer between pixi and the tool.
But most logic should happen in the build tool.

  • The build tool reads directly from the pixi manifest. (e.g. [tool.pixi-build-python])
  • The build tool invokes the actual build. e.g. using or other backend tools e.g. rattler-build.

Related work

@ruben-arts ruben-arts changed the title Feature pixi build Feature design proposal/prototype: pixi build Jul 23, 2024
@olivier-lacroix
Copy link
Contributor

olivier-lacroix commented Jul 29, 2024

How do you see the build tasks interact with regular pixi tasks? I wonder if having a build task may confuse users, given the existence of more generic pixi tasks.

edit: I see also that #1653 adds dependencies to the build section. wouldn't this risk confusing users? Would there be a way to 'promote' a given environment to be used for a build task?

I assume we could also infer automatically a pixi build --name pypi build command when using a pyproject.toml manifest ? Would we also be able to infer automatically a conda build command (as a wrapper around a pypi package) ?

@kfot
Copy link

kfot commented Jul 29, 2024

As a user, I would get confused if the package building task were named anything other than build. It follows the same convention as conda and poetry CLIs and cannot be more explicit than that.

@ruben-arts
Copy link
Contributor Author

Hi @olivier-lacroix,

I've updated the description with the latest discussed idea. If hopefully getting your worries out of the way.
We renamed the dependencies to requires and removed the name field and make it a part of the toml table.

Automatically infer what build to run is of course an interesting idea, which shouldn't be to complex. The wheel building is an interesting part as we can already do that with the uv integration in pixi itself. So this story doesn't talk about that yet.

@ruben-arts
Copy link
Contributor Author

For those following the issue. The current prototype plan is:

  • Build a branch on pixi where we build this experiment. (optionally building artifacts for early adopters to try out)
  • Build a frontend where pixi can invoke a build tool.
  • Build a backend tool in a seperate repo for python packages.
  • Test the workflow and play with it to find out if this could work.

@pablovela5620
Copy link
Contributor

Following up on this, I wanted to understand what you mean exactly by We're not looking at mixed conda and pypi projects.

Does this mean that if you have a project that has both conda and pypi deps, this initial version of pixi build won't work, but it should still allow potentially building a wheel for pypi (along with being able to create condage packages)?

@rgommers
Copy link
Contributor

rgommers commented Aug 8, 2024

  • Allow pixi projects to depend on pixi project, which invokes build to build the dependency on the spot.

I think this will do pretty much exactly what I'd like to do, especially if it includes the last bullet point from gh-793 ("Have a workflow like cargo or pip to depend on local versions").

What I have in mind is working on a stack of related packages (e.g., meson, meson-python, cython, numpy, scipy) where each of those have their own pixi.toml and recipe.yaml, and having the ability to make changes in one project (or several) and test them with the downstream projects that depend on them. This is usually pretty tedious and fragile to set up - my current workflow is mostly to have one conda dev env per project, and pip install . and overwrite the conda package with a local build (e.g. mamba env create -f environment.yaml to create scipy-dev and then pip install path/to/local/numpy --no-build-isolation to install the numpy changes I want to test with scipy into scipy-dev).


One question I have is whether you are planning to make a distinction between building a package that's relocatable locally vs. one that is portable to other machines. Or will pixi build do only one (and if so, which one)?

To clarify, say I'm linking to a system library like Apple Accelerate (the new one, in macOS >=13.3) or I'm using -march=native to build. Those kinds of things are fine for relocation to other envs on the same machine, but not for uploading to a channel for other users on the same platform. To draw an analogy to wheels:

  1. python -m build --wheel will build a non-relocatable wheel
  2. running delocate over the wheel from step 1 will make it relocatable to other envs (assuming it doesn't choke on something too non-portable)
  3. doing step 1 with MACOSX_DEPLOYMENT_TARGET=11.0 and dropping non-portable compiler flags and then step (2) will yield something suitable for uploading to PyPI for all macOS arm64 users. Or running cibuildwheel of course (either way, there are a lot more constraints here for "relocatable to other machines").

For conda packages there's no analogy to (1), but there is for (2) and (3). I'd mostly use (2) I think, because (3) is usually happening in CI for the things I work on - but I can see (3) being useful as well for team-based projects and private conda channels (perhaps avoiding the work to set up separate CI).

@baszalmstra
Copy link
Contributor

@rgommers Thanks for your input! What you are describing is what we call the workspace workflow where you can have multiple local (or remote) pixi projects reference each-other. And this is something we aim to specifically support in the future.

Besides pixi projects we also want to support both conda-builds meta.yaml and rattler-builds/recipe-v2 recipe.yaml as source dependencies. This should allow you to have a conda-forge feedstock as a source dependency!

This will require a lot more thinking and experimenting though. :) Fun times!

One question I have is whether you are planning to make a distinction between building a package that's relocatable locally vs. one that is portable to other machines. Or will pixi build do only one (and if so, which one)?

I see at last two workflows that we need to support:

  1. Generate one or more artifacts (be it conda packages or something else) from your pixi project that you want to distribute as binary packages.
  2. Generate one or more conda artifacts to be consumed locally by another pixi project.

I think by design we want the artifacts that are produced for those two workflows to be as much the same as possible so that you can't get into a situation where it works as a source dependency but not when the source dependency is first published as a binary (through CI or otherwise) and you would consume that. In that sense, we should always generate binaries that are relocatable to other machines as well.

However, I recognize that for local development this might not be ideal. Debug vs release builds, or pythons editable installs are another example of this. This is something we are going to have to figure out.

Currently, we are working towards an initial solution that, although still far from ideal, will work and will still allow for enough flexibility to add more advanced use cases or optimizations for speeding up local development.

Does that answer your questions?

@tdejager
Copy link
Contributor

tdejager commented Aug 8, 2024

Following up on this, I wanted to understand what you mean exactly by We're not looking at mixed conda and pypi projects.

Does this mean that if you have a project that has both conda and pypi deps, this initial version of pixi build won't work, but it should still allow potentially building a wheel for pypi (along with being able to create condage packages)?

Yes! And Ideally, if at some point, we have a way to tell pixi to interpret your project.dependencies as conda-dependencies just for pixi and pixi build, so it will not interfere with regular wheel builds. Then you can use a single manifest format for building both a wheel and a .conda package, at least simple cases. Which I think would be very cool.

@rgommers
Copy link
Contributor

rgommers commented Aug 8, 2024

Thanks for the detailed answer @baszalmstra, that answers my questions and all makes perfect sense to me.

@baszalmstra baszalmstra added the area:build Related to pixi build label Sep 23, 2024
@tdejager tdejager linked a pull request Oct 10, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:build Related to pixi build
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants