The current problem
When I was trying to use this plugin to pack gstreamer plugins into my AppImage I got into some troubles. Current implementation just copies all plugins to usr/lib/gstreamer-1.0 folder, however, some plugins can have additional dependencies which are not listed in the executable itself.
The first approach to solve it
Rather straightforward approach is to use linuxdeploy again inside the plugin. I've found that $LINUXDEPLOY environment variable is accessible in plugin. So after plugins are copied to appropriate folder I'm running something like this.
$LINUXDEPLOY --appdir $APPDIR
This method is good enough - it deploys all dependencies for plugins but still one issue exists: rpath is not set correctly. It's specified as $ORIGIN while it should point to one directory lower ($ORIGIN/..).
Second attempt
Another possible solution could be to deploy dependencies only for gstreamer plugins. Plugins still should be copied in advance. It could be done like this:
gstreamer_plugins=""
for i in "$plugins_target_dir"/*; do
[ -d "$i" ] && continue
gstreamer_plugins+="--deploy-deps-only=$i "
done
$LINUXDEPLOY --appdir $APPDIR $gstreamer_plugins
However, the problem is that firtsly linuxdeploy executes deployDependenciesForExistingFiles and after that it executes deployDependenciesOnlyForElfFile. Basically it means that it deployDependenciesOnlyForElfFile sets the correct rpath ($ORIGIN/..) while deployDependenciesForExistingFiles overwrites it with $ORIGIN rpath.
Third attempt
Probably we could rid of manual copying and use -l flag to deploy the library with its dependencies.
gstreamer_plugins=""
for i in "$plugins_dir"/*; do
[ -d "$i" ] && continue
gstreamer_plugins+="-l $i "
done
$LINUXDEPLOY --appdir $APPDIR $gstreamer_plugins
The problem is that it will copy all plugins in usr/lib instead of usr/lib/gstreamer-1.0 and moreover the issue with $ORIGIN rpath will remain.
Final solution
To tell the truth, each of this attempt can be fixed by patching linuxdeploy tool but I decided not to do it for personal use. The first attempt was almost perfect apart from rpath issue, so I've tuned it a little bit:
$LINUXDEPLOY --appdir $APPDIR
for i in "$plugins_target_dir"/*; do
[ -d "$i" ] && continue
patchelf --set-rpath '$ORIGIN/..:$ORIGIN' $i
echo "Manually setting rpath for $i"
done
This means that after linuxdeploy execution I'm setting correct rpath manually to all this files.
More generalized approach (based on first attempt)
Probably this approach will give more benefit but it requires linuxdeploy patching. In method deployDependenciesForExistingFiles for shared libraries we're always using $ORIGIN rpath which implies that all dependencies for libraries are placed in usr/lib. However, as I stated at the beginning there could be situation when some libs are placed in different folder (gstreamer-1.0 in our case) but are still using dependencies from usr/lib. So the solution would be to change rpath calculation a little.
for (const auto& sharedLibrary : listSharedLibraries()) {
if (bf::is_symlink(sharedLibrary))
continue;
if (!d->deployElfDependencies(sharedLibrary))
return false;
std::string rpath = "$ORIGIN";
auto libraryDir = bf::absolute(d->appDirPath) / "usr" /
PrivateData::getLibraryDirName(sharedLibrary);
if (sharedLibrary.parent_path() != libraryDir) {
rpath = PrivateData::calculateRelativeRPath(libraryDir,
sharedLibrary.parent_path());
}
d->setElfRPathOperations[sharedLibrary] = rpath;
}
Actually, it's just a possible fix, so I haven't tested it properly due to my decision to stay in *-plugin-*.sh domain. If you like the above mentioned solution we could implement it in linuxdeploy tool otherwise this PR has already fixed my issues for gstreamer.
The current problem When I was trying to use this plugin to pack gstreamer plugins into my AppImage I got into some troubles. Current implementation just copies all plugins to
usr/lib/gstreamer-1.0
folder, however, some plugins can have additional dependencies which are not listed in the executable itself.The first approach to solve it Rather straightforward approach is to use linuxdeploy again inside the plugin. I've found that
$LINUXDEPLOY
environment variable is accessible in plugin. So after plugins are copied to appropriate folder I'm running something like this.$LINUXDEPLOY --appdir $APPDIR
This method is good enough - it deploys all dependencies for plugins but still one issue exists: rpath is not set correctly. It's specified as$ORIGIN
while it should point to one directory lower ($ORIGIN/..
).Second attempt Another possible solution could be to deploy dependencies only for gstreamer plugins. Plugins still should be copied in advance. It could be done like this:
However, the problem is that firtsly linuxdeploy executes
deployDependenciesForExistingFiles
and after that it executesdeployDependenciesOnlyForElfFile
. Basically it means that itdeployDependenciesOnlyForElfFile
sets the correct rpath ($ORIGIN/..
) whiledeployDependenciesForExistingFiles
overwrites it with$ORIGIN
rpath.Third attempt Probably we could rid of manual copying and use
-l
flag to deploy the library with its dependencies.The problem is that it will copy all plugins in
usr/lib
instead ofusr/lib/gstreamer-1.0
and moreover the issue with$ORIGIN
rpath will remain.Final solution To tell the truth, each of this attempt can be fixed by patching linuxdeploy tool but I decided not to do it for personal use. The first attempt was almost perfect apart from rpath issue, so I've tuned it a little bit:
This means that after linuxdeploy execution I'm setting correct rpath manually to all this files.
More generalized approach (based on first attempt) Probably this approach will give more benefit but it requires linuxdeploy patching. In method
deployDependenciesForExistingFiles
for shared libraries we're always using$ORIGIN
rpath which implies that all dependencies for libraries are placed inusr/lib
. However, as I stated at the beginning there could be situation when some libs are placed in different folder (gstreamer-1.0
in our case) but are still using dependencies fromusr/lib
. So the solution would be to change rpath calculation a little.Actually, it's just a possible fix, so I haven't tested it properly due to my decision to stay in
*-plugin-*.sh
domain. If you like the above mentioned solution we could implement it in linuxdeploy tool otherwise this PR has already fixed my issues for gstreamer.