linuxdeploy icon indicating copy to clipboard operation
linuxdeploy copied to clipboard

Subfolder handling in /usr/lib

Open tresf opened this issue 10 months ago • 2 comments

Hi,

I'm migrating a project from linuxdeployqt to linuxdeploy and I'm running into an issue where shared objects are relocated into the root of /usr/lib.

For example, the project expects a plugin in:

  • /usr/lib/myapp/myplugin.so

... but after packaging, the plugin ends up in:

  • /usr/lib/myplugin.so

Naturally, this breaks the historical scanning process for these files in the app. Despite these files being "plugins", they often do rely on bundled libraries, such as fftw3f, or in some cases use Qt libs for UI, so relinking them using linuxdeploy (or some other method) is needed for a portable application.

Previously, I used -executable flag. Starting with linuxdepoy, I've tried both the --executable and the --library flags but I'm struggling to keep the expected layout. Do other project have this problem? If so, how did you work around them?

Link to downstream bug report for context: https://github.com/LMMS/lmms/pull/7252#issuecomment-2563151383

tresf avatar Jan 14 '25 16:01 tresf

@TheAssassin Any thoughts about this?

I think it's an important feature to have since sometimes manual control over where shared objects are copied is necessary.

When creating Conan packages, for example, Conan's copy function has a keep_path parameter which I believe provides the same kind of functionality @tresf is requesting here. (See: https://docs.conan.io/2/reference/tools/files/basic.html#conan-tools-file-copy)

When Conan's keep_path is True, relative paths from the source folder are kept when copying to the destination folder, but when keep_path is False, it functions similar to how linuxdeploy does today - copying all files to the same destination folder regardless of the subfolder it originated in. By default, Conan's keep_path is True, but in linuxdeploy it would probably need to default to False to avoid breaking backwards compatibility.

messmerd avatar Jan 22 '25 18:01 messmerd

@TheAssassin Hi, could you please respond to this issue?

The lack of subdirectory preservation is causing us huge headaches over at LMMS and it is forcing us to use ugly hacks that don't fully work.

If you think this feature could be added, or if you know of a solution we haven't thought of, please let us know

messmerd avatar Feb 20 '25 08:02 messmerd

Are there any plans to add this functionality, or at least a workaround we could use in its absence? It's been 7 months now since this issue was opened, and we still have not heard anything. @TheAssassin

messmerd avatar Aug 14 '25 21:08 messmerd

Typically, direct dependencies of the app are packaged to usr/lib and this works for the vast majority of all applications. In my own use, I have never come across the need to also auto-package dependencies for subdirectories. This just adds a lot of complexity. I am also not aware of plugin systems directly linking to shared objects in subdirectories, only the ones that dlopen.

To package dependencies of files in subdirectories, one can use --deploy-deps-only on all of these subdirectories, which will bundle the dependencies into usr/lib as well.

Doing so keeps the directory tree relative flat and makes things easier overall.

I personally do not need this feature and do not have the time or will to implement this.

TheAssassin avatar Aug 18 '25 18:08 TheAssassin

To package dependencies of files in subdirectories, one can use --deploy-deps-only on all of these subdirectories, which will bundle the dependencies into usr/lib as well.

Thanks, however unless it fixes linking of those libraries too, I don't believe this helps the situation.

In my own use, I have never come across the need to also auto-package dependencies for subdirectories.

I like the simplicity of usr/lib, but in the case of LMMS specifically, this really gets polluted with plugin files. We can rename these so that they're easier to distinguish, but this solution would introduce more compat hacks at runtime.

Another example of an AppImage that makes regular use of lib subdirectories is Audacity.

tresf avatar Aug 18 '25 19:08 tresf

I wonder why your plugins would be deployed to that directory at all. Could you share your build script, please?

TheAssassin avatar Aug 19 '25 14:08 TheAssassin

I wonder why your plugins would be deployed to that directory at all. Could you share your build script, please?

Hmm... I'm not sure what you mean by "why" since we deploy our plugins to usr/lib/lmms (or usr/lib/lmms/ladspa, etc). The issue that occurs is when we provide them to linuxdeploy using --library to help with linking against dependencies, we have no ability to specify their destination.

Here's the relevant portions of the script (also copied below for brevity): https://github.com/LMMS/lmms/blob/dec6a045746f5cc3ba831f2521cbcd95a7e314de/cmake/linux/LinuxDeploy.cmake#L128-L133

... 

# Build list of libraries to inform linuxdeploy about
# e.g. --library=foo.so --library=bar.so
file(GLOB LIBS "${APP}/usr/lib/${lmms}/*.so")

# Inform linuxdeploy about LADSPA plugins; may depend on bundled fftw3f, etc.
file(GLOB LADSPA "${APP}/usr/lib/${lmms}/ladspa/*.so")

...

What I think would solve the problem is to allow a --library to also have some type of --destination flag, so that we could influence the end-location of these. I understand that cyclical dependencies make this task difficult and I'm not trying to minimize the work involved in fixing this problem, I'm just not sure how to solve this problem otherwise and I don't think that it's a use-case that's as far-fetched as expressed in sentiments above.

tresf avatar Aug 19 '25 16:08 tresf

Why do you even have to use -l to deploy those plugins? Normally, you would have your build system (in this case CMake, I guess, without having had a look yet) to make install the install tree to the AppDir, then use linuxdeploy with --deploy-deps-only to deploy the dependencies of the files in the subdirectories to usr/lib (while also setting their rpath accordingly, but without deploying the libraries themselves again into usr/lib). -l is meant for the manual packaging mode (e.g., when not using make install at all).

I will have a closer look at your setup later. Nevertheless, you should probably use some make install-based workflow, it's going to make your life easier nevertheless.

TheAssassin avatar Aug 19 '25 17:08 TheAssassin

Why do you even have to use -l to deploy those plugins? Normally, you would have your build system (in this case CMake, I guess, without having had a look yet) to make install the install tree to the AppDir

Well, fundamentally, make install isn't really intended for relocatable and we do use this. cmake uses something called "CPack" which does a make install, but to a temporary directory, we're just leveraging that. But my question earlier still stands...

unless it fixes linking of those libraries too, I don't believe this helps the situation.

If these libraries are relinked-but-not-moved, this would certainly fix the problem and we'd happily close this bug report in favor of using the tool correctly, but --deploy-deps-only doesn't clarify this, quoting:

Path to ELF file or directory containing such files (libraries or executables) in the AppDir whose dependencies shall be deployed by linuxdeploy without copying them into the AppDir

What's not obvious about this is whether or not the "not copied" lib gets relinked properly. If that's the case, I'd happily switch to this technique. My understanding based on the description was that the "not copied" lib was treated as read-only, but that's just how I interpreted it and I'd be elated to be wrong.

tresf avatar Aug 19 '25 17:08 tresf

What's not obvious about this is whether or not the "not copied" lib gets relinked properly. If that's the case, I'd happily switch to this technique. My understanding based on the description was that the "not copied" lib was treated as read-only, but that's just how I interpreted it and I'd be elated to be wrong.

For libraries in directories passed to --deploy-deps-only, linuxdeploy sets the correct rpath and deploys their dependencies into usr/lib. I think the flag's help text explains this already: it is used on files already inside the AppDir.

TheAssassin avatar Aug 20 '25 23:08 TheAssassin

For libraries in directories passed to --deploy-deps-only, linuxdeploy sets the correct rpath and deploys their dependencies into usr/lib.

Great this will fix the problem outright. Will confirm and close this bug report.

I think the flag's help text explains this already: it is used on files already inside the AppDir.

I agree in hindsight, but at first read, it was not obvious... Perhaps...

- Path to ELF file or directory containing such files (libraries or executables) in the AppDir whose dependencies shall be deployed by linuxdeploy without copying them into the AppDir
+ Path to ELF file or directory containing such files (libraries or executables) already present in the AppDir whose dependencies shall be deployed by linuxdeploy without copying them again into the AppDir.  rpath for these libraries or executables will be updated accordingly.

Thanks for clarification on this. In hindsight of my original bug report, I'm receptive to criticism as well.. here's my original question...

Previously, I used -executable flag. Starting with linuxdepoy, I've tried both the --executable and the --library flags but I'm struggling to keep the expected layout.

Perhaps this is primarily a migration problem, since linuxdeploy has support for entire directories while also leavning them intact, which greatly simplifies our script (e.g. over linuxdeployqt).

It'll take some time to refactor and test on our end. Thanks again for pointing us in the right direction.

tresf avatar Aug 21 '25 15:08 tresf

Thanks for the improved wording. Could you send a PR, please?

I'm glad we figured it out anyway.

TheAssassin avatar Aug 21 '25 18:08 TheAssassin

Thanks for the improved wording. Could you send a PR, please?

Done https://github.com/linuxdeploy/linuxdeploy/pull/321.

Meanwhile, I'll get to testing the correct flags ASAP and update this bug report appropriately.

tresf avatar Aug 26 '25 18:08 tresf

Switched to using --deploy-deps-only and it works great. Thanks for the pointer @TheAssassin. As a friendly reminder the PR for improving the wording is still open at #321.

Closing as invalid, linuxdeploy supports this out of the box.

tresf avatar Sep 04 '25 20:09 tresf

Cool, I'm glad we could solve this. I'll have a look, it's been a busy few weeks.

TheAssassin avatar Sep 04 '25 20:09 TheAssassin