Skip to content

Use isolated virtual environments for app builds. - #2967

Merged
freakboy3742 merged 12 commits into
beeware:mainfrom
freakboy3742:app-envs
Jul 30, 2026
Merged

Use isolated virtual environments for app builds.#2967
freakboy3742 merged 12 commits into
beeware:mainfrom
freakboy3742:app-envs

Conversation

@freakboy3742

@freakboy3742 freakboy3742 commented Jul 28, 2026

Copy link
Copy Markdown
Member

Part of series of changes extracted from #2917.

Use fully isolated environments for app builds. This ensures that the environment running Briefcase has no influence on how apps are constructed, and allows the installation of requirements to be fully abstracted as an environment behaviour.

Adds tooling to create a virtual environment as part of app creation, and that virtual environment is used to install requirements into the app. The app environment is re-created whenever requirements are installed (or re-installed)

During update, the support package is now installed before installing requirements. This matches the order of the create command.

Moves app verification to before the installation of the support package but after template generation.

As part of this change, install_requirements() and _install_requirements() have been required so that the latter just does the requirements install; this allows platforms like iOS and macOS to override that to do 2-pass and/or merged installs.

PR Checklist:

  • I will abide by the BeeWare Code of Conduct
  • I have read and have followed the CONTRIBUTING.md file
  • This PR was generated or assisted using an AI tool

@freakboy3742
freakboy3742 requested a review from mhsmith July 28, 2026 07:27
@mhsmith

mhsmith commented Jul 28, 2026

Copy link
Copy Markdown
Member

This ensures that the environment running Briefcase has no influence on how apps are constructed

What kinds of influence have you seen?

The app environment is re-created whenever requirements are installed (or re-installed)

This causes a significant slowdown in reinstalling requirements, for example briefcase update -r for a simple app has gone from 3 seconds to 6 on my laptop. Presumably the same thing has already happened to briefcase dev -r.

The vast majority of this is from installing pip into the new environment, and then updating it to its current version. However, there's a way to avoid this:

  • Pass the --without-pip argument to python -m venv.
  • Use the copy of pip from Briefcase's own virtual environment, passing the --python argument to point at the app's virtual environment. This will cause pip to re-execute itself within that environment, which I believe should give sufficient isolation.

@freakboy3742

Copy link
Copy Markdown
Member Author

This ensures that the environment running Briefcase has no influence on how apps are constructed

What kinds of influence have you seen?

The main way I see this manifest: If I have a environment with an editable install of Briefcase and Toga installed, and I create an app that lists toga==something (any specific version), pip will raise warnings about incompatible versions of toga (because the environment has a version that isn't compatible with what is being installed).

The app environment is re-created whenever requirements are installed (or re-installed)

This causes a significant slowdown in reinstalling requirements, for example briefcase update -r for a simple app has gone from 3 seconds to 6 on my laptop. Presumably the same thing has already happened to briefcase dev -r.

That's correct. I agree this performance isn't great; but it's also a case where I think correctness trumps performance.

That said - it's also an area where uv helps a lot - environment creation (and thus app creation) is near instantaneous.

The vast majority of this is from installing pip into the new environment, and then updating it to its current version. However, there's a way to avoid this:

  • Pass the --without-pip argument to python -m venv.
  • Use the copy of pip from Briefcase's own virtual environment, passing the --python argument to point at the app's virtual environment. This will cause pip to re-execute itself within that environment, which I believe should give sufficient isolation.

Interesting... and that has the added benefit that pip won't be in the installed app environment. I'll tinker with this and see if I can make it work.

@freakboy3742

Copy link
Copy Markdown
Member Author

Interesting... and that has the added benefit that pip won't be in the installed app environment. I'll tinker with this and see if I can make it work.

Well... that was really straightforward, and works incredibly well. The environment creation step is now near-instantaneous, in both dev and create.

Comment on lines 331 to +334
requires = [
"pillow==9.1.0",
"--no-binary", "pillow",
"--no-binary",
"pillow",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest changing this example to userequirement_installer_args, and moving it to that option's section, because it doesn't currently have any examples except for those involving path transformation.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed this example needs to be updated; I was planning to tweak these docs as part of the uv update (since that's the point where requires strictly stops being a "you can pass in any installer arg" option.



class WindowsCreateCommand(CreateCommand):
require_binary_installs = True

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why require this on Windows? If there's a good reason, then it should be explained in a comment, and a removal change note should be included.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason is similar, but not identical to macOS - a combination of security (so app builders aren't running code to do an install), and protection against the lack of a compiler by default on Windows.

I've reworked how this is set up so that "require = True" is the default (migrating the documentation from the macOS version), with Linux getting a specific opt-out.

Comment thread src/briefcase/platforms/iOS/xcode.py Outdated
@freakboy3742
freakboy3742 merged commit dacd763 into beeware:main Jul 30, 2026
195 of 197 checks passed
@freakboy3742
freakboy3742 deleted the app-envs branch July 30, 2026 02:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants