Use the classic linter¶
The classic linter in Snapcraft verifies binary file parameters to ensure they are set
appropriately for snaps. The classic linter is only invoked when a snap has
classic confinement or it stages libc
.
The classic linter will issue a warning if the ELF binary it is testing either:
Doesn’t have the correct dynamic linker (either from the base or the staged
libc
), orDoesn’t have an
rpath
(run-time search path) set to a value needed to load shared library dependencies, either from the base or from the snap if the dependency is not part of the base.
See Disable a linter for details on how to stop this linter from running.
Fix Make warnings with linker flags¶
In this example, the warnings about the ELF interpreter and rpath
can be handled by
adding options to the linker:
-Wl,-dynamic-linker=/snap/core22/current/lib64/ld-linux-x86-64.so.2
-Wl,-rpath=/snap/core22/current/lib/x86_64-linux-gnu
In an Autotools project, if the LDFLAGS
environment variable is used, the project file can be updated to pass these options to
the Autotools plugin. This is done by using the autotools-configure-parameters
key:
plugin: autotools
source: .
autotools-configure-parameters:
- LDFLAGS="-Wl,-dynamic-linker=/snap/core22/current/lib64/ld-linux-x86-64.so.2
-Wl,-rpath=/snap/core22/current/lib/x86_64-linux-gnu"
In a Makefile-based project, if the LDFLAGS
environment variable is used, the
project file can be updated to pass these options to the Make plugin, like this:
plugin: make
source: .
make-parameters:
- LDFLAGS="-Wl,-dynamic-linker=/snap/core22/current/lib64/ld-linux-x86-64.so.2
-Wl,-rpath=/snap/core22/current/lib/x86_64-linux-gnu"
Both of these options will only be useful for projects where the LDFLAGS
variable
can be used to influence the build process.
Fix Go warnings with linker flags¶
Unlike regular binaries built with gcc, Go ELF binaries may not be correctly patched
using patchelf. In this case, it’s necessary to add the appropriate parameters to the
linker so that the executable is created with the correct ELF interpreter and
rpath
. To do so, add the following #cgo
directive to your source code:
/*
#cgo LDFLAGS: -L${SRCDIR}/lib -Wl,-rpath=\$ORIGIN/lib:/snap/core22/current/lib/x86_64-linux-gnu -Wl,--disable-new-dtags -Wl,-dynamic-linker=/snap/core22/current/lib64/ld-linux-x86-64.so.2 -lzstd
#include <zstd.h>
*/
func zstdVersion() int {
return int(C.ZSTD_versionNumber())
}
func main() {
fmt.Println("libzstd version is", zstdVersion())
}
You may also need to define the following environment variables in the part’s
build-environment
key:
plugin: go
# ...
build-environment:
- CGO_ENABLED: 1
- CGO_LDFLAGS_ALLOW: ".*"
For more information on cgo
, see the Go docs.
Patch ELF binaries¶
If the other methods aren’t applicable to the build process used by a snap, the
rpath
can instead be set by modifying the existing binary using a tool such as
patchelf
:
patchelf --force-rpath --set-rpath \$ORIGIN/lib foo
Or, to set the ELF interpreter, the following command can be used:
patchelf --set-interpreter /snap/core22/current/lib64/ld-linux-x86-64.so.2 foo
This can be done using override scripts in order to patch the binaries as part of the packaging of the snap. For more information, see Override build steps.
Enable automatic ELF file patching¶
Snapcraft 7.3 or higher is required to perform automatic ELF patching for core22 and up classic snaps. To use it, declare:
build-attributes:
- enable-patchelf
in all parts that should have ELF binaries automatically patched.