burtonageo / cargo-bundle Goto Github PK
View Code? Open in Web Editor NEWWrap rust executables in OS-specific app bundles
License: Other
Wrap rust executables in OS-specific app bundles
License: Other
[ Stumbled over this, and did a quick review over the implementation for conformance issues. :) ]
The generated Installed-Size
field appears to be created using an out of date algorithm, which produces unreproducible values depending on the file system type and settings.
The current algorithm used by dpkg-gencontrol
is described in the deb-substvars(5) man page, the Debian policy is currently out of date, see the following Debian policy bug for the reference to the discussion that prompted the change.
It would be nice to use serde
and serde-derive
crates in order to write the TOML config parsing in an elegant way (without the boilerplate code and self-written macro rules).
Having serde-derive
would allow usage of #[derive(Deserialize)]
on the corresponding config structures, so the parsing would as simple as let config: Settings = toml::from_str(buffer)?;
While implementing workspace awareness, I have realized that the definition of CargoSettings does not contemplate all fields of a Cargo.toml file.
e.g. a Cargo.toml file with a "workspace" table broke the deserialization as an unexpected field.
e.g. when parsing 'parent' Cargo.toml files in a workspace setup) the lack of a package table broke it.
I suggest we add some tests to test Cargo.toml deserialization against valid Cargo formats with newer fields and lacking some optional ones.
Ideally (I haven't checked) the Cargo project would offer a crate that defines the struct and deserialization using serde, then we could all use it directly and track updates.
Bundles for some operating systems may have more options available than for others.
For instance if we're talking about OS X, it has several properties which you can specify in Info.plist such as CFBundleURLName
(quite a common thing if you want your app to be able to catch the corresponding URI requests), at the moment there is no way to add additional properties to Info.plist as it has a fixed, hardcoded format with only certain (the most common) values.
It would be nice to be able to specify OS-specific bundle properties.
Have a project with this structure:
and this Cargo.toml:
[[bin]]
name = "flowc"
path = "src/flowc.rs"
[package.metadata.bundle]
identifier = "net.mackenzie-serres.flow.flowc"
icon = ["icons/32x32.png", "icons/128x128.png"]
resources = ["resources"]
(parts removed for brevity)
when I run "cargo bundle" I get this error:
cargo bundle
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Bundling flowc.app
Error: the source path is not an existing regular file
Any ideas of what is wrong?
I suggest extending cargo-bundle
with generating also ZIP and tar.gz acrhive bundles.
For many applications, espectially portable (like many of rust binaries are) it's
quite convenient way to deploy the binaries over installers
(which may require user to have root/admin permissions).
The Cargo.toml
configuration section could be extended with arrays of archive
type to generate on a specific platform:
[package.metadata.bundle]
osx_archives=["tar.gz"]
linux_archives=["tar.gz", "zip"]
windows_archives=["zip"]
For a package named foo
version 0.1.0 on 64-bit Linux platform the output file could be:
foo_0.1.0_amd64.tar.gz
and could be generated aside other bundles (DEB, MSI etc).
The internall structure of the archive could follow the same structure that
OS specific bundles have at the moment, e.g. for Linux, same as
DEB packages have with bin
, lib
, share
) directories etc.
Looks like if the cargo build
(or however it's called) fails, it doesn't cause cargo-bundle to exit with a non-zero exit status.
I changed the example to be non-buildable rust and did:
$ cargo bundle --example hello --target x86_64-apple-ios && echo $?
Compiling cargo-bundle v0.4.0 (/Users/simlay/projects/cargo-bundle)
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `events_loop`
--> examples/hello/main.rs:20:5
|
18 | aoeu
| - expected one of 8 possible tokens
19 |
20 | events_loop.run(move |event, _, control_flow| {
| ^^^^^^^^^^^ unexpected token
warning: unused imports: `ControlFlow`, `Event`, `WindowEvent`
--> examples/hello/main.rs:4:18
|
4 | event_loop::{ControlFlow, EventLoop}, event::{
| ^^^^^^^^^^^
5 | Event, WindowEvent
| ^^^^^ ^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error: aborting due to previous error
error: could not compile `cargo-bundle`.
To learn more, run the command again with --verbose.
error: Result of `cargo build` operation was unsuccessful: exit code: 101
0
when it should probably be 101 or something.
I get this error
error: Failed to collect resource file information
Caused by: Le fichier spécifié est introuvable. (os error 2)
I've been meaning to write this issue for a few weeks but can't seem to find the exact stack overflow page(s) that lead me to this issue so I'm doing this a bit from memory.
Anyway, I've been using winit as the main event loop and window creation tool for my projects and the main issue I've had consistently is that the iOS app screen resolution is 320x480 if I take the same app and bundle it with xcodegen
, it doesn't have this issue. There are a number of stack over pages mentioning similar issue:
I've tested both cargo-bundle
and the same code using xcodegen
testing the size of of UIScreen::mainScreen().bounds()
with uikit-sys.
Frankly, the Xcode release notes aren't super clear on what's being deprecated but what I've inferred is that the screen size was based on using an image per phone but now it's based on something mildly magic using the UILaunchStoryboard. If someone knows more about this I'm all ears.
Anyway, I just wanted to write this down for the next person who has this type of issue.
When testing cargo-bundle to bundle and install the example project I run into the following error
Error while installing package: parsing file '/var/lib/dpkg/tmp.ci/control' near line 1
I'm using Eddy to manage my deb installs, it might be an issue on their end.
This builds on #42
That implementation is a simple first implementation of detecting a folder/crate is part of a workspace.
But when it detects the "parent" Cargo.toml file with the workspace key, it should:
We should double check if those keys can include wildcards or globs, as that would make it all a bit more complicated.
I'm not clear on what is correct if the parent has a simple "workspace" key, and this crate is defined as a dependency via a file path. Is it then part of the workspace? We can check where it's compiled into (which target directory) as that's basically what we are after to be able to package correctly.
Hi! Just bounced in here, thanks for the application. Currently testing it out!
I wondered whether it would be difficult to have a project split up in different packages; for example, I have three executables in my src/bin
, and most of the time, executable A doesn't make sense to be installed, and vice versa.
It would be useful if you could specify one icon file, and have it automatically converted to the appropriate format for the platform you're bundling for (e.g. .icns for Mac, .ico for windows, etc.), as well as adding support for hidipi displays
I am cross-compiling a program on Linux to MacOS and my build process cannot use build.rs
as it needs to set environment variables used by transitive dependencies to configure their builds.
Because cargo-bundle
always tries to build this makes things awkward. Also, I would like to run strip
on the generated executables before bundling too which I am not sure is possible right now.
Could we allow an environment variable to skip the build step, maybe CARGO_BUNDLE_SKIP_BUILD
which when set would omit the call to build_project_if_unbuilt()
?
cargo install cargo-bundle
installs an old version of cargo bundle.
I haven't checked when this was introduced, but currently it is possible to use Cargo.toml
for storing external metadata info.
This would work by putting the following on Cargo.toml
[package.metadata.bundle]
name = "ExampleApplication"
identifier = "com.doe.exampleapplication"
icon = ["32x32.png", "128x128.png", "[email protected]"]
version = "1.0.0"
resources = ["assets", "configuration", "secrets/public_key.txt"]
copyright = "Copyright (c) Jane Doe 2016. All rights reserved."
When maintaining packages I always prefer to keep things close, and having them on a single file seems like a good idea.
What do you think?
AppImage is another useful format besides rpm and deb.
Seems like one of the strengths of cargo-bundle is being able to easily handle resource files in a cross-platform way (something I've found to be a pain to deal with on previous, non-Rust projects). While it already provides an easy way to include arbitrary resource files in the bundle, that still leaves the other half of the job: finding and loading those resources once the application is running.
A few ideas for what this could look like:
resources
field of the bundle spec, and returns a path to where that file was actually placed by the bundle, depending on what system you're running on (so on OSX it would use e.g. CFBundleCopyResourcesDirectoryURL
, on Debian it would look in /usr/lib/package_name/
, etc). That way your actual application code doesn't need to care about what OS it's running on.cargo run
rather than bundling it first, in which case it would load the resources from their original location as written in the resources
field of the bundle spec. (Although I'm not sure off the top of my head what is the best way for the library to detect this situation).Thoughts?
At the moment cargo-build is not aware of cargo workspaces.
So, when it is used in a "member" project of a workspace the target directory is calculated incorrectly, and it does not find the files constructed (e.g. binary) by cargo prior to it running and they cannot be packaged.
Running cargo bundle currently in a member directory of such a project will lead to this output:
cargo bundle
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Bundling flowc.app
Error: the source path is not an existing regular file
Make cargo-build aware of workspaces.
When it runs, search for cargo workspaces in the parent directories (need to check if that is recursive and multiple levels or not), and parse that Cargo.toml to determine the correct target directory to us.
Need to check for any ways that the standard target directory can be overridden.
According to this issue (rust-lang/cargo#1657) there are at least two:
build.target-dir configuration key
(I'm not sure if that is in Cargo.toml, or any of the .cargo/config files that might apply!)
CARGO_TARGET_DIR=foo; cargo run args
I suspect I might not get all that 100% correct first time, but help fleshing out the correct spec and algorithm for determining what the target
directory should be would be appreciated.
Info.plist
file called called LSApplicationCategoryType
that specifies what kind of app it is (e.g. for listing in the app store); the valid values are listed here..desktop
file called Categories
that specifies what kind of app it is; the valid values are listed here. Naturally, it is a similar-but-not-quite-the-same list of categories as for OS X apps.It would be nice to have a single category
config field you could set, and have cargo-bundle
automatically translate as needed for each OS. For example, if you specified category = "BoardGame"
, then cargo-bundle
would set LSApplicationCategoryType
to "public.app-category.board-games"
for OS X.
I know it is still work in progress (mostly because I had to use the code from master instead of the regular released version). I tried to create a .deb package, which went mostly well. However, it would be great if I could somehow specify the dependencies for the package (the deb package currently has none). Or did I miss it somewhere in the documentation?
README is a bit out of date with what the code does and the example shown is planned to be deprecated I think.
Thought you may be interested:
https://github.com/goreleaser/goreleaser
https://goreleaser.com
Personally, I'd be interested in a Rust based approach to build from a TOML config, rather than having any integration with cargo
. Similar to fpm
, and nfpm
from that aforementioned gorelease project.
I understand that a child crate in a workspace can include a "workspace" key with a path - that points directly to the workspace root folder (where the workspace's Cargo.toml file should reside).
This means the parent folder doesn't have to be a direct parent of the current crate, and could be in a "sibling" (or child, which would be weird) folder on the file system.
I updated cargo-bundle via cargo install --force cargo-bundle
and found myself with an older version.
I've since updated via cargo install cargo-bundle --git https://github.com/burtonageo/cargo-bundle
to get the version I actually wanted but figured I'd write a ticket for the next person who ends up going down a small rabbit hole and wonders why it's broken.
I am not sure what is actually the cause here, but I tried to bundle a simple gtk-rs program and after launching, normal keys do not work in a text box. Delete, arrow keys etc., however, work perfectly. This doesn't happen when the program is run from the command line.
cargo bundle
will call cargo build
if necessary. Because of that, cargo bundle
should support the --features=xxx
argument, the same way cargo run
does.
I tried to build cargo-bundle and it failed (sorry I don't have the message handy), but someone pointed out to me that if you run cargo update
and then cargo install
things work out.
Please run cargo update
and check in the new Cargo.lock
and make a new release.
Thanks!
Currently cargo-bundle
relies on term
to determine a terminal (see print_bundling()
function as example), thus when term::stdout()
returns None
, we will observe the following behavior:
...
let mut output = match term::stdout() {
Some(terminal) => terminal,
None => bail!("Can't write to stdout"),
...
Because of this limitation, cargo-bundle
will make things like CI/CD Jenkins fail when executing this place (in my case the builds have failed multiple times and I had to investigate to understand where the problem is).
An way to go would be to use std::io::stdout()
when term::stdout()
fails to get a terminal.
What do you think about that?
A quick fix which did a trick in my case was:
diff --git a/src/bundle/common.rs b/src/bundle/common.rs
index e5d67fe..22b0edf 100644
--- a/src/bundle/common.rs
+++ b/src/bundle/common.rs
@@ -1,6 +1,6 @@
use std::ffi::OsStr;
use std::fs::{self, File};
-use std::io::BufWriter;
+use std::io::{self, BufWriter, Write};
use std::path::Path;
use term;
use walkdir::WalkDir;
@@ -52,16 +52,21 @@ pub fn copy_to_dir(from: &Path, to_dir: &Path) -> ::Result<()> {
/// Prints a message to stdout, in the same format that `cargo` uses,
/// indicating that we are creating a bundle with the given filename.
pub fn print_bundling(filename: &str) -> ::Result<()> {
- let mut output = match term::stdout() {
- Some(terminal) => terminal,
- None => bail!("Can't write to stdout"),
+ match term::stdout() {
+ Some(mut output) => {
+ output.attr(term::Attr::Bold)?;
+ output.fg(term::color::GREEN)?;
+ write!(output, " Bundling")?;
+ output.reset()?;
+ write!(output, " {}\n", filename)?;
+ output.flush()?;
+ }
+ None => {
+ let mut stdout = io::stdout();
+ write!(stdout, " Bundling")?;
+ write!(stdout, " {}\n", filename)?;
+ }
};
- output.attr(term::Attr::Bold)?;
- output.fg(term::color::GREEN)?;
- write!(output, " Bundling")?;
- output.reset()?;
- write!(output, " {}\n", filename)?;
- output.flush()?;
Ok(())
}
The readme states that if the name is not present in Bundle.toml
, it'll use one from Cargo.toml
. However, the deb package's control
file has empty Package
field in that case.
There's a comment in create_icns_file()
in src/bundle/osx_bundle.rs
:
// TODO: If none of the icons are of usable sizes, we could also use
// the image crate to scale icons to the appropriate sizes.
I ran into this when I supplied a 500x500 PNG and got a "No usable icon files found." error. Manually resizing it to 256x256 made it go away.
#47 implemented awareness of parent workspaces when running cargo bundle
. It seems not to work, though, when the parent workspace is also a project of its own - e.g. foo
contains bar
, like so:
foo
├── Cargo.toml
├── bar
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── src
└── main.rs
The contents of foo/Cargo.toml
are:
[package]
name = "foo"
version = "0.1.0"
authors = ["Søren Mortensen <[email protected]>"]
[dependencies]
[workspace]
members = [
"bar",
]
I'm not entirely sure this is an intended usage of Cargo workspaces, but I had this setup in a project (until I changed it to work around this issue1). Running cargo bundle
within bar/
results in the following error message:
error: Failed to copy binary from "/private/tmp/foo/bar/target/debug/bar"
Caused by: "/private/tmp/foo/bar/target/debug/bar" does not exist
It seems to be the case that the parent foo/target/
directory is not detected in the way it should be, and foo/bar/target/
is being used instead.
1Edit: to clarify, the workaround I used was to change the structure of the project so that it looks like so:
baz
├── bar
│ ├── Cargo.toml
│ └── src
│ └── main.rs
├── Cargo.toml
└── foo
├── Cargo.toml
└── src
└── main.rs
...where the contents of baz/Cargo.toml
are:
[workspace]
members = [
"foo",
"bar",
]
Hello, thanks for a great tool.
I'm using cargo bundle on macOS to successfully build an .app
bundle.
On Windows, it errors when creating the msi bundle (this is already recorded as an issue).
However, my app doesn't really need to be an installer. It's just a simple executable and I was hoping to use cargo bundle to set the icon and metadata so that it can be run as an .exe
file directly.
At the moment, I can do this with the winres crate. However, that requires a different set of config that has to be kept in-sync with cargo bundle's config. It also requires a small build script to set the icon and it doesn't support converting from a png, etc.
I was wondering whether it would be possible to roll this functionality into cargo bundle so it's just another --format
it supports? That way, many of the people running into the msi problem could use this approach instead if their app is simple enough.
Thanks
I use cargo-bundle
pretty regularly for testing out some rust integration with iOS frameworks on the iOS simulator. While building the bundle isn't all that difficult, I've come to realize that installing it on the simulator and running it can be annoying due to all the iOS specific crap there is.
For example, I'm currently playing around with iOS support for iced (the GUI library) and this is how I rebuild, install and launch the example:
cargo bundle --format ios --target x86_64-apple-ios && xcrun simctl install booted $PWD/../../target/x86_64-apple-ios/debug/bundle/ios/ios-example.app && xcrun simctl launch booted com.github.iced.simple
To describe what's going on, after the bundle is built xcrun simctl install booted $PATH_TO_BUNDLE
installs the bundled iOS app on a booted simulator. One can also specify the ios simulator ID. The xcrun simctl launch booted $BUNDLE_ID
launches the bundled iOS app. In my case, it's the bundled identifier used in the package.metadata.bundle
from the Cargo.toml
.
Anyway, if there's interest in accepting a PR adding something like --install
and --launch
as parameters to cargo-bundle
, I'd be to do it.
If the binary isn't already built when you run cargo bundle
, then cargo-bundle tries to run cargo build
for you automatically, but it's not working for me. I get:
Error: Result of `cargo build` operation was unsuccessful: exit code: 1
Hi,
I encounter the following error
error: Failed to generate Component table
Caused by: "xxx-xxx-xxx.exe" is not a valid value for column "KeyPath"
Any idea?
Thanks,
Cem
As per the explanation here: rust-lang/cargo#8875
I can build for a different architecture with cargo build --target
(for example to build a statically linked binary, or to build a 32bit binary on 64bit system). It would be great if I could pass --target
to cargo bundle
as well and it could create a corresponding package. For example, the static binaries would help deploying the same .deb package on both ubuntu and debian systems of different versions in our company instead of having to build a different package for each of them.
I'd like to have a set of resource files in a lib project, that then get installed as part of the .app bundle when a binary using that lib is built.
Is that possible? Thanks!
When a file is to be opened with a new program in the GNOME desktop, only those programs are considered that specify a compatible mime type in their .desktop files. EDIT: Only those programs are considered that specify an input file or url in the Exec field. (See #87)
Currently a program bundled with cargo-bundle
cannot be associated to any file-type on a GNOME desktop (as far as I can tell).
In the Bundle.toml file, it should be possible to have assets specified as a url, and then cargo bundle should download them. Bonus: support for remote repositories
It would be helpful to add a few lines to the Readme specifying that cargo-bundle
can be added to the user's cargo
installation using cargo install cargo-bundle
. Took me a little bit of googling to find that, only discovered from the users.rust-lang.org page announcing cargo-apk
.
I'll submit a PR to this effect.
Simple Cargo.toml
file, looking something like this:
[package]
name = "my-project"
version = "0.1.0"
authors = ["Oluseyi Sonaiya <[email protected]>"]
and simple Bundle.toml
, like this:
identifier = "domain.organization.my-project"
icon = "path/to/icon.png"
copyright = "(C) Organization, 2017"
short_description = "My Project for macOS"
long_description = "My Project lorme ipsum"
Consistently, running cargo bundle
yields an app bundle named target/debug/.app
. It's a valid app bundle, and I just rename it for convenience, but this is clearly a bug.
Btw, perhaps it explains #28.
I've noticed some design inconsistency between platforms while implementing #12. As mentioned in #92, it makes sense to having some option to generate not an installer but just a bundle, but then we need some clarification for the term "bundle". I think current implementation is like below:
Platform | What it's called | Can be run directly? |
---|---|---|
Windows | installer | need to be installed by itself |
macOS | bundle | can be run directly, portable but can be installed by user |
Debian | package | need to be installed by package manager |
I think installing stuff is a little out of scope of cargo bundle
subcommand and our primary business is just wrapping up essential files needed to run the application. Installers and packages are just to place these files onto specific directory and/or register the app to the "Installed Applications" list of user's OS. Ofcourse it would be great if cargo
becomes capable of such stuff by using cargo-bundle
though, it's a secondary or subsequent step.
There may be multiple steps in bundling process:
cargo build
When a user runs cargo bundle
, we just have to do upto 1. On macOS, this results in generating an *.app
bundle, while others are just a bare directory containing an executable and resources. (But another concern is, we may have cargo bundle --bare
option for macOS users who want just a bare directory)
Though, this is just a rough idea... Could someone advise?
Hi! I'm involved in a similar project: https://github.com/mmstick/cargo-deb
Would you be interested in joining the effort? I could make cargo-deb usable as a library.
After fixing issues for #77 the msi gets created but has this error.
Hey, Is it possible to create an msi installer file on my ubuntu laptop, I installed the toolchain and linker to set up cross compilation, and I can successfully create a .exe on my computer, and I was wondering if it was possible to cross compile and make a .msi from my linux laptop. I tried it, but it failed with:
warning: MSI bundle support is still experimental.
Bundling cof_application.msi
error: Failed to collect resource file information
Caused by: No such file or directory (os error 2)
Does anyone know if this is possible?
The .deb files produced by cargo-bundle on a Raspberry Pi cannot be installed on the Pi due to cargo-bundle labeling them as "arm" architecture while the Pi is "armhf"
license
and/or license-file
fields from [package] should be
reflected in the DEB copyright
file as license information, following:
https://www.debian.org/doc/manuals/maint-guide/dreq.en.html#copyright
This is probably just due to a new version of xcode
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.