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

Add AppImage support to Linux builds #3688

Merged
merged 60 commits into from
Oct 16, 2017
Merged

Add AppImage support to Linux builds #3688

merged 60 commits into from
Oct 16, 2017

Conversation

tresf
Copy link
Member

@tresf tresf commented Jul 7, 2017

Help us test this on your OS:

  • Download a test .AppImage here:
    https://lmms.io/download/
  • Make executable and run:
    cd ~/Downloads
    chmod +x *.AppImage
    ./lmms-1.2.0-rc5-linux-x86_64.AppImage

This Pull Request will create an .AppImage installer in the build directory. Closes #3558 .

Developer Usage: make install && make appimage

Todo:

screen shot 2017-07-10 at 11 04 45 pm

image

@probonopd
Copy link

Where can the resulting AppImage built by Travis CI be downloaded?

@tresf
Copy link
Member Author

tresf commented Jul 7, 2017

Where can the resulting AppImage built by Travis CI be downloaded?

So far, we haven't integrated this into Travis-CI yet (and we only upload our stable releases currently). I'd probably defer that task to @lukas-w once we have the portable installation working properly.

The primary purpose of this PR is to make the AppImage available to developers to create and test to get the kinks with the software worked out.

@probonopd
Copy link

Hi @tresf how would developers test this if it cannot be downloaded? In my AppImage generation scripts, I use http://transfer.sh to get "out" the build products from Travis CI by uploading them to a temporary location where they will be available for 14 days.

@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

how would developers test this if it cannot be downloaded?

Those interested (which tend to be very few) would compile the code, like any other feature. The temporary upload is a nice feature. I generally do something similar but manually when I need testers and which doesn't add additional logic to Travis-CI that would later have to be pulled out just prior to merge.

We should consider uploading all PRs to a temporary location as you've suggested. It'll be a welcome addition as we ramp up for nightly builds.

Copy link

@probonopd probonopd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comments, I hope these are helpful.

chmod +x "$LINUXDEPLOYQT"
echo " [success]"

# Make skeleton AppDir

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you think this is needed? When you install your build products with make INSTALL_ROOT="$APPDIR" install then they will end up there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is post-install step, so it's irrelevant.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this comment, why are you doing it when it is irrelevant?

Copy link
Member Author

@tresf tresf Jul 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your comment is irrelevant. You're telling a project how to specify the install target, which is too late when it's a post-install step. We can script the entire thing like we do for Windows, but then it takes away the granularity of developers specifying their own build environment.

We copy the install instead of messing it all up. Ideally, the /usr mandate would be dropped and then we can use whatever folder we want. That's how macdeployqt works for us.

It's really not your place to tell a project, or a user for that matter where to drop an install target. This may make sense for a small project. But (I feel) for large, complex projects, it's presumptuous.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So where would you ideally like to install? The reasonis that (at least for some software), the path specified with DCMAKE_INSTALL_PREFIX ends up in the compiled binaries, which is what I generally want to avoid, hence recommending /usr as the generic prefix. This is not a hard requirement though and you are free to use another prefix.

Copy link
Member Author

@tresf tresf Jul 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where would you ideally like to install

Wherever the user says to, would be the ideal location. For our tutorials, this is usually /home/user/lmms/target, but I often run a second copy from /home/user/Desktop/lmms/target and others may prefer their own place.

DCMAKE_INSTALL_PREFIX ends up in the compiled binaries, which is what I generally want to avoid

This is the part that confuses me... I would expect a relinking tool to be agnostic of the prefix, but to be fair, I've also never written one. :)

mkdir -p "$APPDIR"
echo " [success]"

# Clone install to AppDir

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you think this is needed? When you install your build products with make INSTALL_ROOT="$APPDIR" install then they will end up there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a post-install step, so it's irrelevant.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this comment, why are you doing it when it is irrelevant?

cp -R "$INSTALL/usr" "$APPDIR"
echo " [success]"

# Prepare the launcher

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you think this is needed? linuxdeployqt will copy the desktop file and icon when you invoke it with linuxdeployqt $APPDIR/usr/share/applications/*.desktop

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per portablelinuxapps.com, I thought that was the way to do it.

Create an AppDir structure that looks (as a minimum) like this:

MyApp.AppDir/
MyApp.AppDir/AppRun
MyApp.AppDir/myapp.desktop
MyApp.AppDir/myapp.png
MyApp.AppDir/usr/bin/myapp
MyApp.AppDir/usr/lib/libfoo.so.0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That documentation describes how to do things by hand, it is from 2010 (7 years old). Nowadays we have tools like linuxdeployqt and appimagetool which can do the work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nowadays we have tools like linuxdeployqt and appimagetool which can do the work.

I started researching the layout when I had initial problems and there was no argument against it in #3558 so I thought I was on the right track. But we'll switch to using the recommended approach instead, thanks. 👍

mv "$APPDIR/usr/share/pixmaps/@[email protected]" "$APPDIR"
echo " [success]"

echo -e "${GREEN}Cleaning up...${PLAIN}"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't do this. $APPDIR/usr/share/applications/ and $APPDIR/usr/share/icons/ shall still be populated because that is what the optional appimaged daemon will use to integrate your application into the desktop (menus, icons, etc.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.

# Workaround per https://github.com/probonopd/linuxdeployqt/issues/52
# export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/pulseaudio/:$LD_LIBRARY_PATH
# ^--- Shouldn't be needed anymore via https://github.com/probonopd/linuxdeployqt/commit/9a93e030cff2cb10e9e672ebb3360d30b3099c6d
export LD_LIBRARY_PATH="$APPDIR/usr/lib/lmms/":$LD_LIBRARY_PATH

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed should not be needed anymore, did you try without this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet. It's on the todo list.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried it, still fails. Re-enabling.

ERROR: ldd outputLine: "libZynAddSubFxCore.so => not found" 
ERROR: Please ensure that all libraries can be found by ldd. Aborting. 
make[3]: *** [cmake/linux/CMakeFiles/appimage] Error 1
make[2]: *** [cmake/linux/CMakeFiles/appimage.dir/all] Error 2
make[1]: *** [cmake/linux/CMakeFiles/appimage.dir/rule] Error 2
make: *** [appimage] Error 2


echo -e "${GREEN}Bundling dependencies...${PLAIN}"
# Bundle both qt and non-qt dependencies into appimage format
"$LINUXDEPLOYQT" "$APPDIR/usr/bin/@CMAKE_PROJECT_NAME@" -executable="$APPDIR/usr/lib/@CMAKE_PROJECT_NAME@/RemoteZynAddSubFx" -bundle-non-qt-libs

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move it to $APPDIR/usr/bin/RemoteZynAddSubFx and retry. I think linuxdeployqt fails because it expects executables to be in usr/bin and not in a subdirectory of usr/lib.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not where it lives, so it will be more work. We can try it.

Copy link
Member Author

@tresf tresf Jul 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to clarify a bit on this... RemoteZynAddSubFx is not a binary usable by the system, so it's not something we'd ever install to $PATH. That's why it doesn't live there.

We have a similar problem with this executable on Mac and I haven't figured it out. Mac too makes mention that executables should be in a specific directory for macdeployqt to work properly, it's just not as straightforward as moving it. It may work for this PR, but it wouldn't make sense in general and when the remote process is launched from C++ it would need to know the new place to find it as well.

@@ -0,0 +1,95 @@
#!/usr/bin/env bash
# Creates Linux ".AppImage" for @PROJECT_NAME_UCASE@

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you going through all the hassle of making this part of CMake when a few lines of .travis.yml or shell script would do? Just curious. Do you think it would be possible/advantageous to have a generic CMake AppImage module/plugin? If so, would you know where to start?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you going through all the hassle of making this part of CMake when a few lines of .travis.yml or shell script would do?

I hope I explained this (same?) question properly in #3688 (comment).

Do you think it would be possible/advantageous to have a generic CMake AppImage module/plugin? If so, would you know where to start?

Hesitant "yes" to "advantageous ... cmake module" question.

A "no" to knowing where to start. The first that comes to mind is CMake's NSIS integration, but it's really ugly to use.

CMake also offers CPackDMG for Mac, but it wasn't really useful for us. Our project requires macdeployqt combined with manual relinking. So from my perspective it's much easier to test, troubleshoot and patch in a common scripting language (which is bash for the time being)

INSTALL="@CMAKE_BINARY_DIR@/../target"

# linuxdeployqt assumes installations contain /usr/ prefixes.
# 1. Make a directory containing /usr

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 1 should not be necessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please explain.

Copy link

@probonopd probonopd Jul 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you install your build products with make INSTALL_ROOT="$APPDIR" install then they will end up there. The needed directories will be created for you.

Copy link
Member Author

@tresf tresf Jul 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, you make mention of INSTALL_ROOT but your wiki references DESTDIR. Is there a difference?

# quoted from wiki
CMake wants DESTDIR instead:

  - cmake . -DCMAKE_INSTALL_PREFIX=/usr
  - make -j$(nproc)
  - make DESTDIR=appdir install ; find appdir/

Second, I did wonder if the parent directory would be created. We normally use cmake flags, as then we can use them in our scripts as well. If we can specify this through cmake instead, then we can configure it in and not have to guess. (Problem 2 above).

@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

I'd like to look into the issues stated above. But for that I need the build artifacts...

The package should be identical to this. I've simply mirrored the steps outlined in #3558 and chain them into a post-cmake-install step, which is (mostly) how we package for the other platforms. Windows has direct make package integration, so that's a bit more integrated.

I'll see if I can add the build artifacts through Travis-CI. We normally don't override the CMAKE_INSTALL_PREFIX or DESTDIR parameter, so I was intending on tackling this as a separate step (something more permanent with our release process).

@probonopd
Copy link

Please describe exactly what you need with regard to CMAKE_INSTALL_PREFIX and DESTDIR and I will think about a solution.

@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

Please describe exactly what you need with regard to CMAKE_INSTALL_PREFIX and DESTDIR and I will think about a solution.

Well, ideally we'd never want to pass install parameters directly to the make command as then our build toolchain doesn't know about it.

Our current build process simply states to the developer that if they want to install to a non-standard location, they can provide it as CMAKE_INSTALL_PREFIX. This is how we do sandboxed installs now, such as when the developer need to install, but doesn't want to do it to system space. I tried like hell to get this working with linuxdeployqt, but I couldn't get anything to work unless it was exactly /usr (something you helped me with in #3558 (comment)) which means something like DESTDIR is needed to put it back into user space. At least that's the impression I had in #3558. Open to alternatives. :)

This all may seem like overkill when something like Travis-CI can install the app to system space and then bundle it all up nicely, but Travis-CI is essentially a temporary sandbox, where our workstations aren't. As one of the primary package maintainers, I need the process to occur 100% in user space, even if Travis-CI won't necessarily benefit from it. Edit: macdeployqt works ok like this.

Does that help?

@probonopd
Copy link

probonopd commented Jul 8, 2017

Since linuxdeployqt not only bundles libraries but also resources like icons, desktop files, mime types and so on, we need a FHS-like tree somewhere with directories like bin/, lib/, share/icons/..., share/applications/*desktop, and so on. Where does not matter (as long as it is not /).

Can you provide such a tree in some (=whatever) writeable location to run linudeployqt on without much hassle? It does not have to be named $APPDIR/usr but can be named however you like. Just keep in mind that the parent directory of that directory should contain nothing else, as that is the location where AppRun will get put.

@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

Can you provide such a tree in some (=whatever) writeable location to run linudeployqt on without much hassle? It does not have to be named $APPDIR/usr but can be named however you like. Just keep in mind that the parent directory of that directory should contain nothing else, as that is the location where AppRun will get put.

By default, this is how we do it, but the tool didn't work when I called it against /bin/lmms (or more properly ~/lmms/target/bin/lmms). Will the behavior differ when the desktop file is used instead of the binary?

as long as it is not /

I'm not sure what this means.

@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

Ok... backtracking a bit... I'm re-reading our Gitter conversation from May...

I guess my question after re-reading all of this is, what is LHS (FHS?) and how do I tell it to stop assuming everything is in usr/ ?

Conversation quoted below.

@tresf wrote:

I'm getting started with linuxdeployqt. I may be reading the documenting incorrectly but I have a few beginner questions. ​
First, where does the AppDir go when the command is called? ​
Second, what is the purpose of the travis scripts all calling unset QTDIR; ...? ​
The first time I ran the command it just exited, no errors. The second time I specifically asked it to bundle non-qt dependencies but it gave an error about a missing library. ​
... and finally... is AppImageKit required to produce an AppImage? I see the separate repo, but I'm not sure if a separate download is needed.

@probonopd wrote:

please check out the .travis.yml files in the sample projects linked in the README
it does not matter where the AppDir is when you invoke linuxdeployqt
As long as you provide it with a path to the main executable binary or even better the desktop file
You should be able to replicate the commands from the example .travis.yml in the README

@tresf wrote:

@probonopd thanks. I'm starting from scratch. I'm not writing a travis recipe just yet, I'd like to get to know the tools on CLI first.
When I make a CMAKE install inside e.g. Foo.AppDir, and then run linuxdeployqt ..>
/Foo.AppDir/bin/foo, it places the AppRun inside <src> instead of inside Foo.AppDir. I think I'm following the instructions properly.

@tresf wrote:

According to the wiki, I think I'm a directory off. The wiki says

MyApp.AppDir/
MyApp.AppDir/AppRun
MyApp.AppDir/usr/bin/myapp

I'll install to <src>/usr instead and move that inside MyApp.AppDir
One part of the tutorial references DESTDIR whereas another references INSTALL_ROOT Are they the same?

@tresf wrote:

Prefix did the trick. Now off to testing.

@probonopd wrote:

linuxdeployqt has a normal mode and a LHS-like mode. In the latter, it assumes the PREFIX inside the AppDir to be usr, i.e., the main binary resides in Your.AppDir/usr/bin/yourbinary
in the normal, non-FHS-like mode, you put the binary directly into Your.AppDir/yourbinary

@probonopd
Copy link

probonopd commented Jul 8, 2017

~/lmms/target/bin/lmms should work fine, if you invoke linuxdeployqt against ~/lmms/target/share/applications/lmms.desktop. In this case, AppRun will become placed in ~/lmms and the AppImage will end up in ~. It should work, but the resulting AppImage has files in target/share rather than usr/share which violates the FHS conventions, and the optional appimaged daemon will be unable to integrate icons, mime types and menu entries into the system because it is looking for these in usr/share. Also, the binaries that are in target/bin will not end up on the $PATH when the AppImage is executed.

@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

Right, these are the points made in my very first conversation. I would not consider these "fine". :)

There are still several unanswered questions. If they're not answered I'll assume the previous assumptions were and continue to be true.

@probonopd
Copy link

  1. linuxdeployqt has some unorthorox rules, the worst of them being installation must be prefixed by /usr

As discussed above, it is not a linuxdeployqt restriction but the optional appimaged daemon assumes that the content of an AppImage follows a FHS-like usr/ tree,

This means our standard build, target directories can't be used, but instead some custom commands must be used.

Alternatively, copy your tree prior to executing linudeployqt:

mkdir -p LMMS.AppDir/usr
cp -r ~/lmms/target/* LMMS.AppDir/usr/
  1. Since DESTDIR isn't provided until build time, cmake knows nothing about it. This is bad!

As per 2., you don't need to use it.

  1. RemoteZynAddSubFX is temporarily broken until we can find a way to fix linking on that.

Did you try putting it into usr/bin in the AppDir? If that works, then we can go from there.

  1. The icon isn't working. Not sure what I'm missing there.

See AppImage/AppImageKit#346.

  1. Registering LMMS and associating its files isn't yet tested and needs some work.

Did you install the optional appimaged daemon? As long as the files are in their usual places under usr/share/..., the optional appimaged daemon should register and unregister them with the system without additional work to be done on your side.

@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

copy your tree prior to executing linudeployqt

If this works, that would remove DESTDIR and settle it. I'll take a swing at it that way, thanks!

@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

As long as the files are in their usual places under usr/share/..., the optional appimaged daemon should register and unregister them with the system without additional work to be done on your side.

That's great news as well, thanks.

@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

@probonopd What about this question...

I can't yet find a way to specify the DESTINATION parameter. Perhaps @probonopd can shed some light. I'm pretty sure shellcheck won't like the *.AppImage command.

@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

Updates...

  1. The machine I'm on today is i386, so I had to fix the download link to assume architecture. This should be quite obvious if someone's trying on i386 or arm. I've also included quick build instructions. Logic could be better, but it should do the trick for now. 91a000b#diff-5b07d65c1f1bdd29f324c363c12c9c9bR19

  2. Our desktop file uses Exec=env QT_X11_NO_NATIVE_MENUBAR=1 lmms %f but it seems to confuse linuxdeployqt. I've written a workaround to create a temporary .desktop file that is compatible with linuxdeployqt. I'd be happy to file an upstream bug report for this if needed. The error was:

    ERROR: Could not determine the path to the executable based on the desktop file
    
  3. Now I'm stuck. linuxdeployqt finds the desktop file and icon, but this happens:

    Desktop file as first argument: "/home/tres/lmms/build/LMMS.AppDir/usr/share/applications/lmms.desktop" 
    desktopExecEntry: "lmms" 
    desktopIconEntry: "lmms" 
    Found binary from desktop file: "/home/tres/lmms/build/LMMS.AppDir/usr/bin/lmms" 
    FHS-like mode with PREFIX, fhsPrefix: "/home/tres/lmms/build/LMMS.AppDir/usr" 
    app-binary: "/home/tres/lmms/build/LMMS.AppDir/usr/bin/lmms" 
    appDirPath: "/home/tres/lmms/build/LMMS.AppDir" 
    relativeBinPath: "usr/bin/lmms" 
    Copied "/home/tres/lmms/build/LMMS.AppDir/usr/share/applications/lmms.desktop" to    "/home/tres/lmms/build/LMMS.AppDir/lmms.desktop" 
    Found icons from desktop file:("/home/tres/lmms/build/LMMS.AppDir/usr/share/pixmaps/lmms.png", "/home/tres/lmms/build/LMMS.AppDir/usr/share/lmms/backgrounds/lmms_tile.png") 
    ERROR: Could not start patchelf tool. Process error is "Not a directory" 
    make[3]: *** [cmake/linux/CMakeFiles/appimage] Error 1
    make[2]: *** [cmake/linux/CMakeFiles/appimage.dir/all] Error 2
    make[1]: *** [cmake/linux/CMakeFiles/appimage.dir/rule] Error 2
    make: *** [appimage] Error 2
    

@probonopd
Copy link

linuxeployqt has no DESTINATION parameter. The name of the AppImage is automatically determined based on the Name= entry in the desktop file. (The message you see in the log comes from the underlying appimagetool that is being used.)

You don't need to use an *.AppImage command tough. Just replace the Asterisk with the real name, should be fine.

@probonopd
Copy link

Exec=env QT_X11_NO_NATIVE_MENUBAR=1 lmms %f

Not sure how to parse the payload executable from this line, and if we allow this, there might be countless other more complex ones, including bash -e ... ones. Currently we are expecting a straightforward Exec=nameofthebinary entry.

If you urgently need the QT_X11_NO_NATIVE_MENUBAR=1 environment variable, then move usr/bin/lmms to usr/bin/lmms.real and put a bash script in its place that exports the variable and launches the real executable.

But if QT_X11_NO_NATIVE_MENUBAR=1 is essentially needed for everyone, why not hardcode it in the application in the first place? Then it'd behave correctly also when launched from a command line.

@probonopd
Copy link

probonopd commented Jul 8, 2017

ERROR: Could not start patchelf tool. Process error is "Not a directory"

Where did you get your linuxdeployqt from?

probonopd added a commit to AppImage/AppImageKit that referenced this pull request Jul 8, 2017
@tresf
Copy link
Member Author

tresf commented Jul 8, 2017

Added debug logs: https://gist.github.com/tresf/28bf36131c090a385e9fdf47e851e5c3

Where did you get your linuxdeployqt from?

I compiled it like this:

git clone https://github.com/probonopd/linuxdeployqt
cd linuxdeployqt
qmake
make
mv bin/linuxdeployqt ~/bin/

If you urgently need the QT_X11_NO_NATIVE_MENUBAR=1 environment variable, then move usr/bin/lmms to usr/bin/lmms.real and put a bash script in its place that exports the variable and launches the real executable.

Is there an order of operations that avoids a hacked solution? In the foo.real approach, our .desktop file still requires divergence from what we use today. Is there a way to get our desktop files in the right place manually and just tell linuxdeployqt to use the binary?

If not, fine. Perhaps we're allowing the application to assume too much because I'm also not opposed to separating linuxdeployqt and appimagekit. This would also allow us to bring back the requested DESTINATION parameter. On Mac, we don't use a singular tool for relinking and packaging, we separate the steps. This seems like a perfectly reasonably workflow.

But if QT_X11_NO_NATIVE_MENUBAR=1 is essentially needed for everyone, why not hardcode it in the application in the first place?

This is an environmental variable picked up by Unity. It was added per #488. It's a desktop workaround and has no place inside the C++ codebase.

@probonopd
Copy link

I compiled it like this

Do you also have patchelf and appimagetool on your $PATH? linuxdeployqt uses them to do the actual work.

Is there an order of operations that avoids a hacked solution?

Yes:

  1. Run linuxdeployqt ... -bundle-non-qt-libs
  2. Delete the AppRun symlink, replace it by a bash script that sets the environment variable and launches your application
  3. Run appimagetool on your AppDir to produce the AppImage

Is there a way to get our desktop files in the right place manually and just tell linuxdeployqt to use the binary?

It's not just about appimagetool finding the main executable, it's also for the AppImage at runtime to find its main (payload) executable. This works as follows:

  1. User executes AppImage
  2. The AppImage gets mounted to a temporary mountpoint
  3. The file called "AppRun" in the top-level directory of the AppDir is executed (by default, linuxdeployqt puts a symlink to the payload application there, but it could also be a C executable or even a bash script)
  4. AppRun runs the payload application
  5. After AppRun exits, the AppImage gets unmounted and the mountpoint deleted

@tresf
Copy link
Member Author

tresf commented Jul 9, 2017

Do you also have patchelf and appimagetool on your $PATH?

Thanks that got it working on i686. 👍

It's not just about appimagetool finding the main executable, it's also for the AppImage at runtime to find its main (payload) executable.

That makes perfect sense. Ok... I'll see what I can hack together. I'd prefer if we didn't have to hardcode this in two separate places so I'll have to think about it a bit more in regards to how to wrap it into the portable image. It's a minor inconvenience, so it's certainly not a show stopper.

@tresf
Copy link
Member Author

tresf commented Nov 13, 2017

Please, don't forget to update it =)

I've refreshed the link with some fixes to the jack implementation. We'll be providing these as official builds on our downloads page when 1.2.0 is official released.

https://github.com/tresf/lmms/releases/download/v1.2.0-rc4/lmms-1.2.0-rc4.96-linux-x86_64.AppImage

@vlad0337187
Copy link

vlad0337187 commented Nov 15, 2017

I don't know where is better to write, but can I somehow add Carla to the appimage build ?
My system version of LMMS (1.1.3) has Carla Rack, Carla Patchbay in the list of instruments.
Also, I installed standalone Carla packages. But RC4 doesn't have Carla.
I open .sfz libraries with it.
screenshot from 2017-11-16 00-14-35
screenshot from 2017-11-16 00-14-58

@tresf
Copy link
Member Author

tresf commented Nov 15, 2017

@vlad1777d probably a separate bug report would be the place. I don't know how portable Carla is and I also don't know what happens if we build with system (non-portable) support for it and it's missing. I recommend tagging @falkTX -- the Carla author -- in the new bug report. We can offer this for stable-1.2 fairly sanely since it's not a new feature, just working out the bugs of packaging another dependency.

For starters, you can try to use make install && make appimage on a build that has Carla enabled and see how far you get. Note, appimages are broken due to an upstream bug here: probonopd/linuxdeployqt#184. So you'll have to hack a workaround in --
also explained in the bug report -- in order for LMMS to actually package properly. The bug is marked as high priority, so it should be fixed very soon.

@vlad0337187
Copy link

Thanks, @tresf , I created new bugreport and tagged you there. If I wrote something wrong or didn't tell something - correct my message.

@vlad0337187
Copy link

vlad0337187 commented Nov 19, 2017

Hello @tresf .
This appimage loads near 2 minutes, it's normal ?
(lmms-1.2.0-rc4.96-linux-x86_64.AppImage)

Here is it's ourput:

'/home/vlad/Programs/audio/lmms-1.2.0-rc4.96-linux-x86_64.AppImage' 
Jack appears to be installed on this system, so we'll use it.
Notice: could not set realtime priority.
VST sync support disabled in your configuration
Cannot lock down 82274202 byte memory area (Cannot allocate memory)
Cannot use real-time scheduling (RR/5)(1: Operation not permitted)
JackClient::AcquireSelfRealTime error

@probonopd
Copy link

probonopd commented Nov 19, 2017

To find out whether AppImage is at fault here, please extract the AppImage with ./Your.AppImage --appimage-extract, and then run ./squashfs-root/AppRun to compare the performance of the AppImage vs. the unpacked version. Thanks.

@vlad0337187
Copy link

vlad0337187 commented Nov 19, 2017

@probonopd ,
The appimage ran:

  • totally: 41 seconds,
  • the most of time took "Preparing UI": 38 seconds

Unpacked appimage ran:

  • totally: 47 seconds,
  • the most of time took "Preparing UI": 44 seconds

LMMS 1.1.3 ran:

  • totally: 3 seconds

Appimage output:

'/home/vlad/Programs/audio/lmms-1.2.0-rc4.96-linux-x86_64.AppImage' 
Jack appears to be installed on this system, so we'll use it.
Notice: could not set realtime priority.
VST sync support disabled in your configuration
Cannot lock down 82274202 byte memory area (Cannot allocate memory)
Cannot use real-time scheduling (RR/5)(1: Operation not permitted)
JackClient::AcquireSelfRealTime error

Unpacked appimage output:

./squashfs-root/AppRun
Jack appears to be installed on this system, so we'll use it.
Notice: could not set realtime priority.
VST sync support disabled in your configuration
Cannot lock down 82274202 byte memory area (Cannot allocate memory)
Cannot use real-time scheduling (RR/5)(1: Operation not permitted)
JackClient::AcquireSelfRealTime error

LMMS 1.1.3 output:

Notice: could not set realtime priority.
VST sync support disabled in your configuration
Cannot lock down 82274202 byte memory area (Cannot allocate memory)
Cannot use real-time scheduling (RR/5)(1: Operation not permitted)
JackClient::AcquireSelfRealTime error

Seems, they (packed and unpacked RC4) load the same time.

Also after pressing button "Add effect" in "FX-Mixer", now left near 3.30 minutes, nothing loaded, seems, it's a freeze. I tried pressing this button several times.

For comparison, LMMS 1.1.3 loaded in 3 seconds, after pressing "Add effect" to appearing window with list of effects was spend near 1 second.

(I use standard jack installed with "aptitude install qjackctl")
Jackd version:
jackd2:
i A 1.9.10+20150825git1ed50c92~dfsg-1ubuntu1 xenial 500

System: Linux Mint 18.2 x64 Cinnamon.
CPU: Intel Core i3 540 (3.07 gHz x2, 4 threads).
GPU: Nvidia GT 630
Ram: 7.8 Gib DDR3

@probonopd
Copy link

So that AppImage is actually faster than the unpacked binaries? That should rule out the AppImage itself as the root cause. I cannot say what causes the contents of the AppImage to be that slow, but I doubt it's normal.

@vlad0337187
Copy link

vlad0337187 commented Nov 19, 2017

@probonopd , updated answer. I think that it's inaccuracy. They load near the same time (packed and unpacked), but they load in times slower than LMMS 1.1.3.
RC4.29 acts the same like RC4.96.

System: Linux Mint 18.2 x64 Cinnamon.
CPU: Intel Core i3 540 (3.07 gHz x2, 4 threads).
GPU: Nvidia GT 630
Ram: 7.8 Gib DDR3

LMMS 1.1.3 loads near 3-8 seconds,
LMMS 1.2.0 RC4.96 now ran in 80 seconds (first time, it differs sometimes)

I think it's obvious that somewhere is something wrong =)
Main is to figure out what certainly.

@TheAssassin
Copy link

@probonopd @vlad1777d running each of these cases once on some machine with unspecified specs which is also used for other stuff in the background doesn't produce meaningful results (even running 100 times won't in my opinion).

@probonopd
Copy link

Yes, my only point was that I don't think the slowdown is coming from AppImage.

@TheAssassin
Copy link

Calling strace or using a profiler might help.

@vlad0337187
Copy link

I can do this if you tell me certain steps, because I'm not familiar with those things.

@vlad0337187
Copy link

vlad0337187 commented Nov 19, 2017

I figured out. It was so when I turned on jack manually before launching RC4.
When I turn it off, than it loads near 3 seconds too.

(in both cases in settings "Jack" is chosen as audio driver)

But problem with long loading after pressing "Add effect" button in "FX-Mixer" is still present.

@vlad0337187
Copy link

vlad0337187 commented Nov 19, 2017

No, that was not the matter. I figured out now a real matter.
It's because I created link in /home/username/lmms/samples to my instruments folder on other disc (there are all my instruments, it's large).

Was Jack runned manually or automatically by LMMS it doesn't matter.

But anyway, LMMS 1.1.3 runs in near 3 seconds with present link too.

I created that link not to select each time "Computer/media/username/Storm/instruments/sf2/drums/hpa_drumkit/file.sf2" when I'm trying to load instrument.

And the problem in waiting near 4 minutes after pressing "Add effect" in "FX-Mixer" is still present.

@TheAssassin
Copy link

@vlad1777d call sudo strace LMMS*.AppImage (sudo is required here because of how the AppImage works (technical detail: it's because of FUSE)), or strace squashfs-root/AppRun for the extracted (beware, no sudo here).

@vlad0337187
Copy link

@TheAssassin ,
Here is strace: https://pastebin.com/Sf5xsFVj
But I don't know, is it normal that it's terminated and nothing started.

@zapashcanon
Copy link
Contributor

wait4(-1, LMMS cannot be run as root.
Use "--allowroot" to override.

@vlad0337187
Copy link

vlad0337187 commented Nov 19, 2017

Strace: LMMS (appimage) normal launch:

Strace: LMMS (appimage) launch with link to instrumens folder in /home/user/lmms/samples:

  • https://pastebin.com/kFyiimXq
    It stacked on this line in console (onto near 1.5 minutes):
    You can render your songs and listen to the output files...
    While in spash screen was written: "Preparing UI"

Added separate bugreport about pressing "Add effect" button: #3990

@Luraktinus
Copy link

a thousand times: "THANK YOU, FINALLY I CAN JUST USE IT ON ANY DISTRO"

tresf referenced this pull request in probonopd/linuxdeployqt Oct 3, 2018
Signed-off-by: Patrick José Pereira <[email protected]>
@tresf
Copy link
Member Author

tresf commented Feb 11, 2019

But if QT_X11_NO_NATIVE_MENUBAR=1 is essentially needed for everyone, why not hardcode it in the application in the first place? Then it'd behave correctly also when launched from a command line.

This is an environmental variable picked up by Unity. It was added per #488. It's a desktop workaround and has no place inside the C++ codebase.

@probonopd just following up, more as an FYI... we found a way to set it in C++ so we'll be back to just lmms %f with our next release.

Reference:
https://github.com/LMMS/lmms/pull/4818/files#diff-01990f45b9969995efd402052be03d4bR256

@tresf tresf mentioned this pull request Mar 5, 2019
sdasda7777 pushed a commit to sdasda7777/lmms that referenced this pull request Jun 28, 2022
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

Successfully merging this pull request may close these issues.

Create a Pull Request for an AppImage Travis build