-
-
Notifications
You must be signed in to change notification settings - Fork 388
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
Added code for supporting arch system package #1143
Conversation
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.
corrected a typo
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've updated your PR to fix some indentation and formatting issues, and tried it out; even with those changes, I get the following error:
[togatest] Building .pkg.tar.zst package...
Building source archive... done
Generating pkgbuild layout... done
Entering Docker context...
Docker| ------------------------------------------------------------------
Docker| ==> ERROR: togatest is not available for the 'x86_64' architecture.
Docker| ==> ERROR: changelog file (/Users/rkm/beeware/briefcase/local/togatest/CHANGELOG) does not exist or is not a regular file.
Docker| ------------------------------------------------------------------
Leaving Docker context.
Building Arch package...
Error while building .pkg.tar.zst package for togatest.
I'm also slightly dubious whether this will work in general. You're shipping the /usr/bin/<myapp>
binary as part of the distribution artefact - won't that cause problems if the person installing the binary doesn't have exactly the same versions of the package? I thought Arch packages needed to be completely compiled from source - which means the distribution artefact needs to not include the binary, include the bootstrap
folder, and perform a make as part of the installation process.
Hello The second error must be due, not being able to find the You are right the stub binary won't work if the libraries are not compatible. ( sorry, force of habit of distributing only for a single architecture) I'll make the changes and update the pull request soon. Thanks. |
Tests will be needed, but that's got nothing to do with this error. Togatest is the name of my test application. It's nothing more than the "Hello World" generated by Briefcase, but with a customised name (because I need to test against PySide, PPB, Pygame,...)
For the record - the referenced filename exists, and is a regular file. It's the package builder that is failing.
To be clear: Its not just "single architecture" that is the issue here - it's "incompatible version of libraries". Distributions like Ubuntu are able to provide guarantees on the specific version (and thus ABI) that various libraries will provide - locking a specific set of ABIs is the major reason for having tagged releases. AFAIK, Arch doesn't do this - every user is compiling everything from scratch, so there's no way to provide ABI guarantees. |
Modified so that `makepkg` will compile the stub binary. Changed `arch` to `'any'` to prevent architecture error. Also, the `CHANGELOG` file will be added to the source archive so that `makepkg` will be able to find it while running the `PKGBUILD` file.
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.
Modified to tackle the errors.
root_dir=self.bundle_path(app), | ||
base_dir=f"{app.app_name}-{app.version}", | ||
root_dir=self.build_path(app), | ||
base_dir=self.bundle_path(app), |
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 archive will include a pre-build binary unless you either exclude usr/bin/{app.app_name}
as a path, or disable the call to make
during the Build command.
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.
Hello
I mean, doesn't briefcase build
just run make
and make install
. So, we could just briefcase create
and then briefcase package
. If this is not the intended behavior, then I will modify it.
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 can tell you for free - It's not going to be easy to remove the build step conditionally based on the packaging format, because there's a whole lot of logic that is shared across all backends that determines how to infer that a build is needed. It's going to be a lot easier to skip the specific call to make in the arch packaging case.
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.
You are right, skipping the make call should solve the problem.
# Generate the pkgbuild layout | ||
pkgbuild_path = self.bundle_path(app) / "pkgbuild" | ||
pkgbuild_path = self.build_path(app) / "pkgbuild" |
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 isn't correct - it definitely needs to be bundle_path
, or you'll generate code in a directory outside the Arch bundle.
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, we need to generate the code outside the bundle_path
as the whole bundle_path will be archived for source tarball as bundle_path
contains the bootstrap
directory.
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 setup is going to lead to a briefcase file layout that looks like:
- build
- myapp
- arch
- pkgbuild
- ...
- rolling
- bootstrap
- ...
- myapp-1.2.3
- usr
- ...
- usr
- bootstrap
- pkgbuild
- arch
- myapp
That's the wrong location for the pkgbuild
folder. It should be inside the rolling
folder. This is, at the very least, needed to support Docker builds, because Docker mounts build/myapp/arch/rolling
as /app
; so the pkgbuild
folder won't be visible inside the Docker container. More generally, all the artefacts of the arch/rolling
build should be in the arch/rolling
folder.
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.
Thanks! I was confused about the directory structure. I will modify it.
with self.input.wait_bar("Generating pkgbuild layout..."): | ||
if pkgbuild_path.exists(): | ||
self.tools.shutil.rmtree(pkgbuild_path) | ||
(pkgbuild_path).mkdir(parents=True) | ||
|
||
# Build the source archive | ||
with self.input.wait_bar("Building source archive..."): | ||
|
||
# Copy the CHANGELOG file to the bundle_path so it can be included in the source archive | ||
self.tools.shutil.copy(changelog_source, self.bundle_path(app) / "CHANGELOG") |
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.
Why does it need to be copied? Couldn't you add a single file directly to the archive?
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.
Since we are archiving the whole bundle_path
directory, I thought first copying and then archiving would be better.
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.
Copying is a last resort; by copying, you're creating a duplicate file, which could lead to drift between the source and the packaged artefact. Packaging the source file directly is vastly preferred, and I can't see any reason it couldn't be done here.
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.
Sure. I will change it.
Hello Moreover, probably you are confusing with the AUR system. In AUR repository, there are only We do not necessarily need to run If you agree to let briefcase build the binary stub and makepkg to only create the Moreover, if you choose the former solution then we can also skip creating the source archive (source tarball) before creating the actual |
(Apologies on the close - hit the wrong button)
Sure - in that regard, you're describing a process that is functionally identical to both Debian and Redhat packages. However, Debian and Redhat have a significant difference with Arch: they are able to guarantee binary compatibility. If I have Debian 11, you know exactly what version of (say) GTK I have, because that's part of the "GTK" package definition for the Debian 11 release. Arch doesn't provide that guarantee, because it doesn't tag releases in that way. So - if you build a package for your Toga app, and you give it to me... how can I guarantee that the package will work? You know nothing about my system, other than the fact that I'm running Arch. If I'm running on an arch system where GTK was built 2 years ago, and you build your package on a "bleeding edge" Arch install... how do you know that your app will run on my machine?
I have no idea what I'm confusing with what, because I'm not an Arch user. :-) Functionally, I want to be able to guarantee that user X can build a package, give it to user Y, and that package will Just Work. I was under the impression that the only way that would happen on Arch is if the compiled components were compiled on the installing system; but if that's not the case, then I'll gladly stand corrected. |
f'pkgdesc="{app.description}"', | ||
f"arch=('any')", # We should use {self.linux_arch}, but doing this as the architecture error | ||
# was probably caused due to this parameter. | ||
# Moreover arch wiki recommends 'any' for architecture independent packages. |
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 smell right to me.
If you have numpy
(or any other binary dependency) in your app, Briefcase will be installing an architecture-specific binary wheel. Python is able to guarantee that the wheel will work because it adheres to the manylinux
specification, which constraints the libraries that the wheel can link against; but it means that the artefacts in the wheel are platform specific. If you build your package on x86-64, you won't be able to deploy it on arm64.
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 architecture error is usually caused if the host machine and target package architectures are different. That means, the previous error was caused due to mismatch of host architecture string. I have modified it to use self.tools.host_arch
. Now, it should work fine.
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.
Modified for addressing issues. The architecture error is usually caused if the host machine and target package architectures are different. I will research more and post about it.
For dependencies compatibility This will be checked by |
Yes - you've just given a description of how dependencies work in every environment. What you're missing are the practical application of these dependency specification for Arch as a distribution. On every other Linux distro, we don't need to do any version pinning, because the version of GTK that is provided on Ubuntu 22.04 (or any other distro) is implicitly pinned. All Ubuntu 22.04 machines have binary compatible versions of GTK - that's why they tag releases. If I produce a binary package for Ubuntu 22.04 that depends on GTK, I know that package will still work in 2 years time. On Arch, a description like "latest" isn't helpful when you're building an app for distribution. If I build a package with a dependency on the "latest" GTK, and 2 weeks pass, the "latest" isn't the same version any more, so there's no guarantee that someone who downloads a 2 week old package with a dependency on the "latest" GTK will be able to install it. So, if an Arch package contains a pre-compiled binary, we need to guarantee the specific versions of every dependency - which means hard-pins on every library version (or, at best, very narrow ranges). This leads to a bad user experience as well - if I download a 2 year old package, I will discover that I have to downgrade my version of GTK just so I can support the binary requirements of this old package - something that may be mutually incompatible with other packages that I'm running. This is why I'm suggesting that shipping a pre-compiled binary in an Arch package isn't a viable option. At the very least, we would need to have specific (or very narrow) version pins on every dependency, which is a maintenance overhead for app developers - and for Briefcase as well - as we need to take on the burden of ensuring that the version pins in the templates we provide are up to date with what Arch is currently publishing. |
Modified towards a working state.
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.
Modified to use the current working solution for the changelog.
Hello This is because the Also, we cannot use Since, you are not too keen to copy the Until you decide, I am keeping the copying solution, as it is the only working solution. |
Hello Yes, may be the "latest" will not be the same for everyone, but any sane person running a bleeding edge rolling distro should be keeping their system up to date( should be running If the developers want to hard pin the dependencies, then they can manually add them to the generated |
Now it shows, the packager name correctly:
But the
|
Package signing is definitely something we're interested in adding; we have it already for macOS, and there's a PR in flight adding it for Windows. I'd consider it a separate feature to this PR, though; we need to ensure that whatever approach to signing we take, it is as broadly applicable as possible. |
Yes you are right, package signing should be a separate PR. Researching on the subject, linux package signing is a bit of mess. I mean the signing part is easy but the part where the user verifies and installs the app is a mess. In Debian and derivatives, although package signing and verifying tools exists but by default Debian and derivatives verify the signature of the repository instead of the package. So, even if we would sign the generated package, it would not be verified, as this verifying tool and feature is disabled by default. And in Arch and derivatives system, signed packages cannot be installed on the system, until the public key is imported into pacman's keyring. But it will let users install packages without any signatures without raising any warnings. In RHEL, I am not sure but it seems like there would be some sort of such nuances. All in all, signing is easy but verifying and installing the package on users' system is difficult. |
Okay, here's the problem. If I run the commands as outlined in the PR description, this is the package content:
As you can see, all the Python files are missing. |
Hello |
I've just ran $ pacman -Qi helloworld
Name : helloworld
Version : 0.0.1-1
Description : My first application
Architecture : x86_64
URL : https://example.com/helloworld
Licenses : BSD license
Groups : None
Provides : None
Depends On : glibc>=2.37 python3 gtk3 gobject-introspection-runtime
Optional Deps : None
Required By : None
Optional For : None
Conflicts With : None
Replaces : None
Installed Size : 2.98 MiB
Packager : Jane Developer <jane@example.com>
Build Date : Sun 26 Mar 2023 04:34:35 PM CEST
Install Date : Sun 26 Mar 2023 04:35:00 PM CEST
Install Reason : Explicitly installed
Install Script : No
Validated By : None |
Hello |
I reran these commands: ~$ cd /tmp/bee-test
/tmp/bee-test$ source venv/bin/activate
(venv) /tmp/bee-test$ rm -rf helloworld
(venv) /tmp/bee-test$ pip install git+https://github.com/proneon267/briefcase.git@patch-1
(venv) /tmp/bee-test$ briefcase new --template https://github.com/beeware/briefcase-template --template-branch arch
(venv) /tmp/bee-test$ cd helloworld
(venv) /tmp/bee-test/helloworld$ briefcase run
(venv) /tmp/bee-test/helloworld$ briefcase package
(venv) /tmp/bee-test/helloworld$ sudo pacman -U dist/helloworld-0.0.1-1-x86_64.pkg.tar.zst |
I am able to reproduce the error. On a fresh new installation of Manjaro, I got the same The error suddenly disappears when you exit the But, this doesn't occur when you run the steps without using |
Here is the directory structure, of
|
Confirmed this error is caused when the requirements are not installed on a fresh system. For example, on a new system, the following error would be raised:
Now install the missing dependencies with
Again running Looks like something is getting cached in the |
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 is great; glad we're able to round this out with arch packaging.
Toga worked fine for me including with webview and numpy.
PySide6 was a different story....because ofc it was 🙃
makepkg
is eager to strip the binaries in the package which is likely to cause problems for libraries from PyPI wheels- Adding
options=('!strip')
toPKGBUILD
mitigates this
- Adding
- I needed
qt6-base
at runtime for the pyside6 helloworld app- Interestingly,
makepkg
complained unlessqt6-base
was also installed at build time...
- Interestingly,
Other Notes
- Adding
libcanberra
as a dependency avoids the typical canberra module error - I hit an error for missing
gcc
forbriefcase package
; installingbase-devel
fixed this. We should add this to the BeeWare tutorial as well like we did withbuild-essential
.- I presume I got the error from
pip
aboutgcc
missing because of what's outlined in system_requires aren't verified when building system packages locally #1137.
- I presume I got the error from
@proneon267: Related to the empty build directories and differences between I believe this is stemming from the fact the app template is rolled out in the |
So, what do you suggest we should do with this issue for now? |
Well, unless you want to fix #1137 (which I don't think would be appropriate for this PR), we probably shouldn't do anything. Once Briefcase is updated to confirm all of the needed system requirements are installed before making changes to the filesystem, this issue shouldn't happen anymore then. |
Created |
…rectly formatted. Co-authored-by: Russell Martin <rmartin16@gmail.com>
@MarkusH Awesome - thanks for that testing. Looks like you might have been bitten by #1137 on your first pass. That's a failure mode that will be particularly common when building system packages, so it's something we're definitely going to need to look at, but it's not an inherent problem with this Arch packaging PR, so we probably won't consider it a blocker on this PR. On a more general note: the package works, but is it... "right"? i.e., does the way we're packaging the app conform to your expectations as an Arch user? In particular, the fact that we're including a pre-compiled binary on a system that doesn't have a hard concept of dependency pinning (in the sense of Debian/Ubuntu/Fedora that provide binary ABI guarantees for "Bullseye"/"22.04"/"37" et al) seems odd to me, but I also don't have a good read on Arch user expectations. @rmartin16 Unfortunately, I can't get a working Arch/Manjaro system in my test config (Parallels doesn't have full integration for either AFAICT); I can build packages in Docker, but I can't do a non-Docker build or test the results. It looks like you're able to do runtime tests - are you happy with where this patch is at? |
Yeah - I think so; the only thing that seems off is toga apparently isn't respecting dark mode in Gnome 43 in arch. On my primary machine with Gnome 42, it does respect dark mode. Everything else is working 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.
@proneon267 Thanks for the contribution!
@freakboy3742
Also, I am planning to add support for generating a package which could be used for distributing through AUR. I mean it won't be like a traditional package per se, just a tarball containing the |
@proneon267 Thanks for the tips - I am able to get Manjaro installed; the issue is with the Parallels integration with the native system (such as mounting the native system drive as a network drive) which is what allows me to efficiently test multiple platforms concurrently. Moving to virtualbox won't fix those problem, as virtualbox doesn't provide those features (to the best of my knowledge). As for the AUR package - it sounds like what you're describing is what is called a "source distribution" on Debian/Redhat platforms. That definitely sounds like an option worth adding; I've opened #1152 to track the feature. If you decide to work on this feature, can I please ask that you do your development work locally, rather than through the Github editing interface. The approach you took on this PR results in lots of individual commits without meaningful commit messages, and causes a lot of CI resources to be wasted. |
Sure, I will do the development work locally this time. Thank you for helping. I couldn't have done it without you. |
Testing instructions:
If you're on an Arch Linux system, or any derivative of an Arch system (e.g., Manjaro), you can test this branch with:
Accept all the default values from the template, then run:
You should get a running Toga GTK app. Then, run:
This should generate a
dist/helloworld-0.0.1-x86_64.pkg.tar.zst
file, which you can install withpacman -U dist/helloworld-0.0.1-x86_64.pkg.tar.zst
If you have any problems building, running or installing this package, or the package that is generated doesn't match your expectations as an Arch* user, let us know in the comments below, including details of the specific distro that you are using for testing.
For creating arch packages, we need to build a
PKGBUILD
file which will be used bymakepkg
utility to create the.pkg.tar.zst
file.A sample
PKGBUILD
file:There are many parameters but we do not need to use them all. As you can see among all these functions, only
package()
is necessary, others are optional.makepkg
doesn't necessarily need to compile the stub binary. Since,briefcase build
does the stub binary compilation, we can skip this step.A simplified and tested
PKGBUILD
file:I will add more details later on.
This PR relates to an issue: #1064
PR Checklist: