Skip to content

Conversation

@kengoon
Copy link

@kengoon kengoon commented Aug 6, 2025

This pull request introduces a targeted improvement to the dependency installation process for Kivy apps on Windows platforms. Specifically, it ensures that shared Kivy dependencies are moved to the default system prefix after installation. It also includes a bootstrap for kivy as a gui option in briefcase

Dependency management improvement for Kivy on Windows:

  • In the _pip_install function in src/briefcase/commands/create.py, after installing dependencies, if the platform is Windows and Kivy is among the dependencies, the share directory is moved from the app's packages path to the parent directory to align with Briefcase's default system prefix.fixes kivy app crash when briefcase run command is executed due to kivy unable to find core dependency in sys.prefix location

fixes #452

PR Checklist:

  • All new features have been tested
  • All new features have been documented
  • I have read the CONTRIBUTING.md file
  • I will abide by the code of conduct

kengoon added 3 commits August 6, 2025 20:18
fixes kivy app crash when `briefcase run` command is executed due to kivy unable to find core dependency in sys.prefix location
)

# move kivy share deps to briefcase default sys.prefix
if self.platform.lower() == "window" and "kivy" in pip_args:
Copy link
Member

Choose a reason for hiding this comment

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

If something like this is needed, it needs to either be a generic feature, or refactored into being feature of the backend, rather than being part of the generic create command.

However, I'd be a lot more interested in understanding why this is required at all. Why does the install work for Kivy "by default", but not for Briefcase?

Copy link
Author

Choose a reason for hiding this comment

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

@freakboy3742 Kivy works by default because, when installed without the --target flag, it places its core dependencies in the share directory (on Windows only). If you check the metadata for Kivy’s core dependencies, you’ll see binaries like ../../share/glew/bin/glew32.dll,sha256=mkzO8kYHqSwXhGhQjbKXKCnvjfO94EsWyv5ZEr9TZTM,464896 are located there. In Kivy, the following code:

_root = sys.prefix
dep_bins = [join(_root, 'share', '{}', 'bin')]

looks for these dependencies in the .venv directory, not in .venv/Lib/site-packages. Here, .venv corresponds to sys.prefix. However, in Briefcase, sys.prefix points to <app-name>/build/<app-name>/windows/app/src. When the --target flag is used, the share folder ends up in app_package instead of src (which is Briefcase’s default sys.prefix), causing the difference in behavior.

Please can you explain more about the backend. I'm a little bit confused and I'm new to briefcase codebase structure.

Copy link
Member

Choose a reason for hiding this comment

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

@freakboy3742 Kivy works by default because, when installed without the --target flag, it places its core dependencies in the share directory (on Windows only). If you check the metadata for Kivy’s core dependencies, you’ll see binaries like ../../share/glew/bin/glew32.dll,sha256=mkzO8kYHqSwXhGhQjbKXKCnvjfO94EsWyv5ZEr9TZTM,464896 are located there. In Kivy, the following code:

_root = sys.prefix
dep_bins = [join(_root, 'share', '{}', 'bin')]

I'd argue this is a bug in Kivy, and how it's packaging its dependencies. There's no guarantee that ../../share exists, is writable, or that ../../share is guaranteed to be equivalent to {sys.prefix}/share. It will be if you're installing into a full Python install, or as part of a virtual environment - but that's not a hard guarantee that Python makes. Kivy is missing an edge case of PEP 376 interpretation.

PEP 376 defines the entries in RECORD as:

the file’s path:

  • a ‘/’-separated path, relative to the base location, if the file is under the base location.
  • a ‘/’-separated path, relative to the base location, if the file is under the installation prefix AND if the base location is a subpath of the installation prefix.
  • an absolute path, using the local platform separator

The base location is defined as "the path defined by the --install-lib option, which defaults to the site-packages directory."; the installation prefix is defined as "path defined by the --prefix option, which defaults to sys.prefix."

Kivy is leaning on the second definition. In a standard Windows virtual environment, the installation prefix (sys.prefix) is the venv directory, and the base location is Lib/site-packages relative to that path, so it works, and it's legal.

However, there's no requirement that the base location is a subpath of the installation prefix - and when you use --target to install, it won't be.

Unfortunately, the PEP doesn't specify the fallback behavior in this case; evidently pip is stripping the relative path portions if the base location isn't a subpath of the installation prefix.

That said - there are evidently other packages that make a similar assumption - pywin32, for example. So - it would appear Briefcase needs to make a change here.

One possible workaround would be to restructure the Windows app template so that Briefcase uses Lib/app_packages rather than a bare app_packages folder. That would ensure that ../../share would resolve to a consistent location - but would also require us to redirect sys.prefix at time of installation to ensure that pip believes the base location is a subpath of the installation prefix.

Please can you explain more about the backend. I'm a little bit confused and I'm new to briefcase codebase structure.

The point I'm trying to make is that we're not going to add code to Briefcase that makes a special case of one specific package on one specific platform. Either we add a feature that can be used by all packages, based on a clearly documented standard (or, at least, commonly understood convention in the Python ecosystem), or the feature that is added needs to be isolated into a context where it only applies where it is needed (in this case, windows, when building a Kivy app).

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.

Can't use kivy with briefcase on windows

2 participants