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

Add information on releasing Bevy games #1885

Open
alice-i-cecile opened this issue Apr 11, 2021 · 21 comments
Open

Add information on releasing Bevy games #1885

alice-i-cecile opened this issue Apr 11, 2021 · 21 comments
Labels
C-Docs An addition or correction to our documentation

Comments

@alice-i-cecile
Copy link
Member

alice-i-cecile commented Apr 11, 2021

For relative newcomers to Rust, we should start a section on Releasing Bevy games, to go along with our advice on fast compilations.

This should include:

This information likely deserves its own page, but should be linked on the Bevy website, perhaps near the section on fast compilation.

@alice-i-cecile alice-i-cecile added C-Docs An addition or correction to our documentation D-Trivial Nice and easy! A great choice to get started with Bevy labels Apr 11, 2021
@alice-i-cecile
Copy link
Member Author

This Bevy game template is another great source of inspiration for tricks to draw from.

@NiklasEi
Copy link
Member

NiklasEi commented Apr 11, 2021

* using relative rather than absolute paths

This is about privacy-sensitive paths in the compiled executable, right? Reading through the relevant rust issues (e.g. rust-lang/rust#40552) it does not sound like there is an actual fix or an easy workaround for now. Several people wrote that the mentioned solutions do not work (and I did not see anything about "relative rather than absolute paths").

The way to avoid leaking paths at the moment seems to be not distributing executables compiled on your private machine.

I would propose recommending to only publish builds from CI/CD e.g. GitHub workflows in the new "Releasing Bevy games" section.

@alice-i-cecile
Copy link
Member Author

This is about privacy-sensitive paths in the compiled executable, right?

Correct. I think your proposal is sensible then; it's a shame there's no local machine workaround.

@mockersf
Copy link
Member

it's a shame there's no local machine workaround.

Probably building in docker or similar would work... but I would recommend setting up CI anyway

@lberrymage
Copy link
Contributor

Probably building in docker or similar would work... but I would recommend setting up CI anyway

I think CI makes the most sense for most people, but if someone's project isn't open-source, then CI could cost money.

Maybe we should focus on CI on the website, but also link to some documentation on local alternatives like Docker, chroot jails, etc.?

@mockersf
Copy link
Member

mockersf commented May 5, 2021

Just noticed some of our dependencies have licenses that needs to be mentioned when releasing a game made with Bevy. For example wgpu with MPL-2.0
see #2101 (comment) (and #2101 (comment) for wgpu)

@cart
Copy link
Member

cart commented May 5, 2021

I just left some thoughts on that here: #2101 (comment)

@mockersf
Copy link
Member

mockersf commented May 5, 2021

We could also consider getting "cute" here by doing something like include_bytes!("uber_license_file") by default (with a way to opt out for people who want slimmer binaries and have other compliance plans), but thats not really in the spirit of these licenses and might not even hold up in court.

The file produced by https://crates.io/crates/cargo-bom for Bevy is 568KB

@cart
Copy link
Member

cart commented May 5, 2021

Maybe we can compress it by removing redundant license boilerplate? no clue if that is valid.

@bjorn3
Copy link
Contributor

bjorn3 commented May 5, 2021

Another option would be to gzip (or any common method) compress it and add a header that describes in plain text that the following bytes are the gzipped license text. A function to get the license text at runtime could transparently decompress it.

@cart
Copy link
Member

cart commented May 5, 2021

I dig that. We could have a bevy_license_compliance plugin that include_bytes!() the gzipped license, adds support for a command line: --print-bevy-licenses argument, and provides a function to get the full text at runtime.

@cart
Copy link
Member

cart commented May 5, 2021

And then (depending on the size) we could include it by default.

@Bekreth
Copy link

Bekreth commented May 8, 2021

I've been starting to do a bit of poking around on this topic and could use some advice. I'm fairly new to Bevy (and machine languages more generally) and been struggling to make a Debian package file for my example application. When I build the application, I'm unable to directly run the binary due to missing shared libraries. Is the entire target/release/deps folder required in the linker path in order to run the Bevy app? Is there existing best practice on how to bundle up all of these shared libraries? Can some of these dynamically linked libraries be statically linked instead?

@bjorn3
Copy link
Contributor

bjorn3 commented May 8, 2021

If you aren't using --features bevy/dynamic all shared libraries necessary are native dependencies. See https://github.com/bevyengine/bevy/blob/main/docs/linux_dependencies.md for all dependencies.

@Bekreth
Copy link

Bekreth commented May 8, 2021

Egg on my face; thank you @bjorn3. I forget that all of my child crates had been using the dynamic linking feature.

@follower
Copy link
Contributor

Using cargo-about for crate license credits

In addition to cargo-bom mentioned in #1885 (comment) I thought I'd mention https://github.com/EmbarkStudios/cargo-about/ as an option which I recently used to produce about dialog crate credits.

This particular app used egui directly for the UI rather than via the Bevy integration but my plan is to get to that point eventually. :D

Display template flexibility

After cargo-about has collected the list of licenses used by your dependencies, you can customize the display of the list of crate licenses using a (handlebars-style) template like this which provides a reasonable degree of display flexibility:

  • Click to display an example template for `cargo-about` license display.

    This template is a modified version of one shipped with cargo-about.

    ## Third Party Licenses
    
    List of the licenses of the Rust projects used in "Button Up Community".
    
    
    ### Overview of licenses
    
    {{#each overview}}
     * {{{name}}} ({{{count}}})
    {{/each}}
    
    ### All license text
    {{#each licenses}}
    #### {{{name}}}
    
    ##### Used by
    
    {{#each used_by}}
     * {{{crate.name}}} {{{crate.version}}} -- {{#if crate.repository}}{{{crate.repository}}}{{else}}https://crates.io/crates/{{{crate.name}}}{{/if}}
    {{/each}}
    
    {{{text}}}
    
    {{/each}}
    

Final license display output

Here's some examples of the result:

  • Click to show initial dialog view with multiple terms/license sections

    This part of the UI was created manually...

    eos-button-up-about-dialog--Screenshot from 2021-10-28 00 16 23

  • Click to show generated summary of crate licenses

    eos-button-up-about-dialog-crates-credits-Screenshot from 2021-10-28 00 17 40

  • Click to show further example license summary display

    As you can tell from the scrollbar this is followed by many more pages. :D

    eos-button-up-about-dialog-crate-credits-more-Screenshot from 2021-10-28 00 19 09

Related observations

A couple of observations:

  • Even after de-duplication, in the case of this app there's about 260KB of license text!

  • I'm not 100% certain what the implications of license text de-duplication are in terms of explicit copyright date & project copyright holder details when specified in the text. But when you start wondering about this you discover that there's seemingly many instances where people haven't actually modified the license file to contain this information!

Anyway, hope this might be a helpful pointer/experience to have shared.

@bjorn3
Copy link
Contributor

bjorn3 commented Oct 27, 2021

@follower How big is the license text after compression? I would assume that it compresses very well.

@follower
Copy link
Contributor

@bjorn3 Yeah, it's a bit under 20KB with random right-click compression action applied.

So it'd be interesting to see what sort of trade-offs make sense in terms of size+compression+ease of use.

(And, for a GUI app at least, it feels like its probably primarily an amusing situation rather than a major issue. :) )

@66OJ66
Copy link
Contributor

66OJ66 commented Sep 14, 2023

One thing I've not seen mentioned yet is around building portable executables when distributing for Linux.

My understanding is that building with the x86_64-unknown-linux-gnu target dynamically links to GLIBC, but there's issues with backwards compatibility. E.g. if you build your app using v2.38, it won't run on any machines using earlier GLIBC versions.

A solution to this is to build using MUSL instead e.g.
cargo build --target x86_64-unknown-linux-musl

This produces a static binary which should just work on any Linux machine.

I've tried the above but I'm getting pkg_config errors whilst compiling the alsa-sys crate (open issue for this: diwic/alsa-sys#10) - not sure if there's a workaround for now.

Regardless, using MUSL then has its own issue in that its memory allocator performs relatively poorly in multi-threaded workloads. To resolve this, a different memory allocator would need to be used.

This recent blog post covers 2 ways of using the MiMalloc allocator - the easiest approach seems to be just using this crate: https://github.com/purpleprotocol/mimalloc_rust

This post gives a bit more context to the above, and also found that using a MUSL + MiMalloc combination can outperform GLIBC.

It might be worth running the stress tests whilst using MiMalloc (on Windows or Linux) and see if that grants an easy performance boost?

@bjorn3
Copy link
Contributor

bjorn3 commented Sep 14, 2023

This produces a static binary which should just work on any Linux machine.

You can't statically link a program that needs to use the GPU. The userspace part of the graphics driver has to be dynamically linked. If you were to statically link it, you wouldn't be able to use any future gpu's with the game, nor be able to use nvidia's graphics driver (which doesn't have a stable syscall abi). If you are dynamically linking, using glibc instead of musl is a much better option. Most distros use glibc and thus compile the graphics driver against it. And the main musl based distro that I know of (Alpine linux) has a glibc compatibility shim.

My understanding is that building with the x86_64-unknown-linux-gnu target dynamically links to GLIBC, but there's issues with backwards compatibility. E.g. if you build your app using v2.38, it won't run on any machines using earlier GLIBC versions.

There are three options:

  • Compile the game on an older distro.
  • Use steam's runtime which includes glibc and graphics drivers. (IMHO best option for games on steam)
  • Use flatpak with and the org.freedesktop.Platform runtime for glibc and the right org.freedesktop.Platform.GL.* runtime extension for the graphics driver. (IMHO best option otherwise)

@66OJ66
Copy link
Contributor

66OJ66 commented Sep 14, 2023

Ah okay, thanks for your reply @bjorn3 - I've learnt something new today!

Will have a look into Steam's runtime/Flatpak and see what I can get working

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-Docs An addition or correction to our documentation
Projects
None yet
Development

No branches or pull requests

9 participants