I have a binary file (written in C) and I’d like to build/wrap a snap of it. This binary file also uses some additional libraries (lib1.a, lib2.a, etc.). Is there a way I can do this? I tried to search on the canonical website but I couldn’t find much. Any suggestion on how to start?
You might find some useful information on the docs for building C applications here.
If it’s a pre-compiled binary, you can use the
dump plugin and include libraries with the
parts: part-1: source: . plugin: dump stage-packages: - lib1 - lib2
Otherwise, I would recommend looking at the tutorials here: https://snapcraft.io/docs/creating-a-snap
Yes, it’s a pre-compiled binary and I already use the dump plugin. I have a directory like this:
project release snap snapcraft.yaml
and my snapcraft.yaml is:
name: examplebinarysnap base: core20 version: '0.1' summary: example snap description: | This is description. grade: devel confinement: devmode architectures: - build-on: amd64 parts: examplebin: plugin: dump source: release stage-packages: - lib1.a - lib2.a - lib3.a - c-binary #mybinary. Here? apps: examplebin: command: examplebin
Should the c-binary be on the stage-packages section?
If I try to run “snapcraft” I get the error “Failed to fetch stage packages: Error downloading packages for part ‘fdoclientbin’: The package ‘lib1.a’ was not found…”
Are these libraries part of your project and in your
release directory? Or are they in the Ubuntu repositories? The
stage-packages keyword is fetches libraries with
If everything (binary and libraries) is inside
release/, then you don’t need the
stage-packages keyword at all. The
dump plugin copies the contents of
release/ into the snap package.
These libraries are needed by the main binary (c-binary), they are not on the Ubuntu repositories. So if I understand correctly this is all I need in the parts section:
parts: examplebin: plugin: dump source: release
Also, I get the error “Failed to generate snap metadata: The specified command ‘examplebin’ defined in the app ‘examplebin’ does not exist. Ensure that ‘examplebin’ is installed with the correct path.”
I suppose this is not the correct way to write the apps section…
The apps section would look something like this:
apps: part-os-release: command: bin/os-release.sh
I pulled that from https://snapcraft.io/docs/defining-a-command.
You also may need to add an
environment key with
LD_LIBRARY_PATH in your snapcraft.yaml so your binary can load your libraries. You should be able to find some references for that on the forum or in the documentation.
Thank you very much. One last question though. What is the “bin/os-release.sh”? I do not have an .sh to run, just my binary in C.
bin/os-release.sh is just an example executable file to call. You can replace that to the filepath of your binary.
Thank you very much. Now the snapcraft process ends successfully. Then I install the snap with “snap install snap_name.snap --devmode” and I can run the binary with “snap_name.part-name”.
LD_LIBRARY_PATH , how I have to set this variable in the snapcraft.yaml?
apps: examplebin: command: mybinary environment: LD_LIBRARY_PATH: ???
Glad to hear you were able to package it!
Yes, that’s how I would recommend setting it. You can append to it with:
apps: examplebin: command: mybinary environment: LD_LIBRARY_PATH: $LD_LIBRARY_PATH:$SNAP/<path-to-your-custom-library-directory>
P.S. If you set the app name to the snap name, you can execute it directly.
name: examplebinarysnap ... apps: examplebinarysnap: command: bin/os-release.sh
Then you can execute it as
examplebinarysnap instead of
All my custom libraries are in the “release” directory along with my binary so I suppose the correct directory for LD_LIBRARY_PATH is:
Is it correct?
However, if I do so I get the error "CVE-2020-27348: A potentially empty LD_LIBRARY_PATH has been set for environment in… "
You can remove the self-reference, just
will be fine. If you include the self-reference, you’ll trigger the security warning above.
$LD_LIBRARY_PATH folders are handled elsewhere in runtime environment, so you’ll still get e.g
$SNAP/lib/ & etc as appropriate.
Thank you very much for all your answers. I have one last problem I’m facing.
When I run the examplesnap executing my binary I get the error “error while loading shared libraries: libcurl-gnutls.so.4: cannot open shared object file: No such file or directory”. This “libcurl-gnutls.so.4” is not a library I have in my “release” directory (along with my binary) but I don’t understand why it needs it.
If I run my binary like “./mybinary” without any snap wrapping it works fine.
You’d need to include libcurl-gnults (add it as a stage package) in your snap and update
LD_LIBRARY_PATH to point at it.
With some specific libraries, you might find that they make a subdirectory in the usual folder, e.g
$SNAP/lib/x86_64-linux-gnu/example-library, and place the
.so files in there; where it wouldn’t be checked by default. Often this is because there’ll be a post-install hook in the apt package that handles symlinks in “real” environments, but those hooks aren’t executed for snaps. I don’t know if that library is one, but given the variety of implementations of TLS, I suspect it might be.
Aside from using
$LD_LIBRARY_PATH to point to it directly, you could also consider modifying your snapcraft.yaml to move the file up a level into the normal search path; assuming that this might be the issue. Same end result but might be cleaner than having architecture-specific workarounds to set