The payload application binary must not contain any hardcoded paths that would prevent it from being relocatable. You can check this by running strings MyApp.AppDir/usr/bin/myapp | grep /usr. Should this return something, then you need to modify your app programmatically (i.e., by changing the source code).

If you prefer not to change the source code of your app and/or would not like to recompile your app, you can also patch the binary, for example using the command sed -i -e 's|/usr|././|g' MyApp.AppDir/usr/bin/myapp. To make this kind of binary patching possible, AppRun.c does a chdir() into usr/ in the AppImage prior to executing the main payload application.

If you prefer not to change the source code of your app and/or would not like to recompile your app, you can also patch the binary, for example using the command sed -i -e ‘s|/usr|././|g’ MyApp.AppDir/usr/bin/myapp. To make this kind of binary patching possible, AppRun.c does a chdir() into usr/ in the AppImage prior to executing the main payload application.

Ok let me rephrase this to make sure I got it right:

Patching only just works, because /usr and ././ has the same length. Otherwise it would screw up the binary. Replacing /usr by usr or ./usr is therefore not possible. That’s why we want to be in usr/ and not in the AppDir’s root.