Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make application paths relative in AppImage? #1035

Closed
cecilios opened this issue Mar 18, 2020 · 9 comments
Closed

How to make application paths relative in AppImage? #1035

cecilios opened this issue Mar 18, 2020 · 9 comments

Comments

@cecilios
Copy link

I'm attempting to create my first AppImage package for my application (c++). I built it without errors but when run it the program fails to locate the needed resources.

After some research (e.g. #508 and #172) I understand that my problem is caused because my app is trying to load some resources from an absolute path (e.g. /usr/share/xxxxx) and AppImage requires that all paths must be relative to the AppImage executable.

For instance, in #508 it is suggested to use getcwd() and in #172 they point to using $APPIMAGE.

But IMO, using getcwd() is not the solution as the value provided by getcwd() points to the directory in which the app was started, and not to the folder in which the app is installed. So it does not work when the user runs the appimage by mouse click on symlinks.

In Linux I've not found a simple way of determining the app installation path at run time (see for example https://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe).

So, my options are reduced to using $APPIMAGE but I don't know how to use it:

  • Is it always accessible with getenv("APPIMAGE") when running the appimage file and it always points to the folder in which the appimage file is located? Even when the appimage is run by clicking on a symlink?
  • My app must work also in normal installation packages so the solution must detect when it is running in an appimage and when it is a 'native' running.

How is this solved in other programs? Any help and code examples will be especially welcome. Thank you!

@TheAssassin
Copy link
Member

Please see linuxdeploy/linuxdeploy#123, where exactly this has been discussed not even one hour ago. getcwd() does not work at all, $APPIMAGE is not portable, your best bet is to use /proc/self/exe, which works fine in many applications.

@cecilios
Copy link
Author

Thanks! I moved the issue here as I though it was the right place and was not getting feedback in linuxdeploy/linuxdeploy#123. Didn't know they were repos from the same team and didn't see your answer. Thanks and sorry for the noise.

@TheAssassin
Copy link
Member

Shame on me for not recognizing the same user name... happens very rarely to me.

Please feel free to join our IRC chat, too (#appimage on Freenode), where you can get in touch with lots of other AppImage authors.

@probonopd
Copy link
Member

Do you want to get the path in which the AppImage is located, or do you want to get the path to your executable inside the AppImage?

@cecilios
Copy link
Author

I need the path to the resorces packaged inside my AppImage. So I unsderstand that I first need to get the path to my executable inside the AppImage, and then find any other resorce path relative to the root of the binary. Is this the correct approach?

@TheAssassin
Copy link
Member

Yep. That's perfectly portable, works both in AppImages (which have to be relocatable) and "regular" installations (where a prefix might be known). Qt for instance also recommends this approach, and they provide a proper API for that.

@cecilios
Copy link
Author

In my app I use a prefix but now I have to use it when it is a "regular" run and replace it when it is an "appimage" run. But need to identify at run time the case and need to replace the prefix by something: $APPIMAGE? /proc/self/exe? other?

@TheAssassin
Copy link
Member

$APPIMAGE is, again, not portable, only works for AppImages. You don't need to rely on that.

If your application is usually in /usr/bin/myapp and your resources are in e.g., /usr/share/myapp, you can also express it as /usr/bin/../share/myapp, right? So, basically, resolve the symlink /proc/self/exe, get its dirname, then append ../share/myapp and you're all set. Again, this approach works fine for AppImage and also for your regularly installed application.

@cecilios
Copy link
Author

If your application is usually in /usr/bin/myapp and your resources are in e.g., /usr/share/myapp, you can also express it as /usr/bin/../share/myapp, right?

Yes, that's my case. I will try your suggestion of using /proc/self/exe.

Thanks!!

hdclark pushed a commit to hdclark/DICOMautomaton that referenced this issue Aug 3, 2021
This workaround is currently necessary because '/usr' is replaced by '././' in binaries, so a chdir() is needed to make
'./' point to the root of the AppDir. Unfortunately, linuxdeployqt, which is an alternative, is not available on all required platforms.

Note that another workaround that works prior to this commit is to provide absolute path names.

See the following issue threads for additional context:
- AppImage/AppImageKit#172
- AppImage/AppImageKit#989
- https://docs.appimage.org/packaging-guide/environment-variables.html#type-2-appimage-runtime
- AppImage/AppImageKit#1035
- linuxdeploy/linuxdeploy#123
- AppImage/AppImageKit#508
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants