Strip files included by a content interface from prime

I’m working on creating snaps for GNOME app using the gnome-3-24 snap’s content interface. In order to keep all the libs linked in the build from being included we have to trick snapcraft in stripping all those files. For example:

  # workaround snapcraft trying to outsmart us by copying ldd listed libraries
  workaround:
    plugin: nil
    stage-packages:
      - libgtk-3-0
    prime:
      - "-*"

This strips everything out of the workaround part because we know it’s actually available via the content interface from the gnome-3-24 snap.

This is hacky, but isn’t too bad for apps that really only need libs provided by that interface. However, say for example you have an app that needs a couple other libs, like gedit needs libgspell and libgtksourceview. We need to expand that “-*” out into a much more extensive list to strip out everything provided from the interface.

It would be handy if snapcraft could mount the content interface and determine which libs are provided there and automatically strip those out from prime.

1 Like

How are you building these “gnome consumer” snaps? Our recommended practice is to tar up the staging area of the producer snap and use it as a part to build the consumer snap (you can even make this a remote part for easy use). Then use the prime keyword exactly as you’re doing to strip it out of the final snap. An example of this is the shared ROS demo.

Indeed, if you don’t do it this way, you have no guarantee that the consumer snaps are built against the same version of the libraries actually contained in the producer snap.

I don’t think the tarball approach really helps here. For example, the gnome-3-24 snap includes common libs for GNOME apps, but not everything. If we tarred up a staging area that included what’s in gnome-3-24, but then the app needed another lib that’s not included but still linked against libgtk we’d need to add that lib to stage-packages. Then depends resolution will pull in the packages for all those depends anyway. For example:

gedit needs much of what’s in gnome-3-24, plus a couple other less common libs like libgtksourceview, which depends on libgtk-3-0. We would have to add libgtksourceview to our stage-packages which will bring in libgtk-3-0 and other depends even though they are in the stage tarball.

Am I right?

I think what makes sense is to build then that library against the source in the prime/ directory and not mix tarball + stage-packages due to this issue (or at least, no stage-packages which has some deps on things in the tarball).

However, this is a very good use case that this triggers and question for the snapcraft/launchpad/build.snapcraft.io). We autobuild the platform snap (in launchpad right now, but I guess it’s the snap in build.snapcraft.io): how can we store the tarball artefacts (dev content like .h/.pc + bins) from the stage/ directory? If this isn’t possible, is there anything on the roadmap to address that?

Otherwise, it would mean that everyone doing their own platform snap will either build from another build system (which reduces the arch availabilities) or will need to build them manually, which isn’t scalable.

That’s a great question, but one to which I don’t know the answer. @evan is probably the guy there.

I think Travis would meet your needs well. We don’t want to overcomplicate https://build.snapcraft.io by supporting edge cases, and I don’t see this particular one becoming prolific.

Looking at how snapcraft works at the moment, it won’t copy system libraries listed in /usr/share/snapcraft/libraries/16.04 into the snap.

One option here would be to provide some way to give snapcraft more lists of sonames of libraries to exclude. It might be nice if these extra exclusion lists could be defined within a part. That would make it possible for a cloud part designed to make using a runtime snap (e.g. desktop-gtk3) to introduce the exclusions rather than each app developer needing to reproduce this.

That functionality will probably go away in snapcraft v3, it’s just not clear enough what’s happening. Allowing a part to specify a snap-wide blacklist (as opposed to part-specific) is an interesting idea, though.

1 Like

Is there any solution for this at the moment?

For example, the mc-installer snap size goes from 112M to 58M when I manually exclude all libraries present in the gnome-3-28-1804 snap.

Using the following workaround gets it to 77M, but then I also need to manually exclude a bunch of conflicting files from my other parts because they are present but different in the gnome-3-28-1804 snap.

  workaround:
    plugin: nil
    stage-snaps:
      - gnome-3-28-1804
    prime:
      - "-*"

I think it was @kenvandine who wrote the snippet I’m using. I’ve catalogued and documented it at my utils library page: https://snapcraft-utils-library.readthedocs.io/en/latest/lib/cleanup.html

2 Likes

That’s great! When I add the following part, the size goes down to 39M!

  cleanup:
    after:  # Make this part run last; list all your other parts here
      - game
      - launcher
    plugin: nil
    build-snaps:  # List all content-snaps and base snaps you're using here
      - core18
      - gnome-3-28-1804
    override-prime: |
      set -eux
      for snap in "core18" "gnome-3-28-1804"; do  # List all content-snaps and base snaps you're using here
        cd "/snap/$snap/current" && find . -type f,l -exec rm -f "$SNAPCRAFT_PRIME/{}" \;
      done
1 Like

@daniel

This script almost seems to good to be true… The SDLPoP snap went from 35M -> 1M and it still runs correctly… Have you ever had any issues with it?

1 Like

I’ve not seen any issues, and I’ve been using it for some time… I believe the LibreOffice snap is also using it.

1 Like