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

CPack: Refactor AppImage and Apple DMG Generation #7252

Open
wants to merge 64 commits into
base: master
Choose a base branch
from

Conversation

tresf
Copy link
Member

@tresf tresf commented May 12, 2024

Features:

  • Simplifies Mac and Linux packaging command to simply: make package
    - make install && make appimage
    - make install && make dmg
    + make package
    # -- AppImage create: /__w/lmms/lmms/build/lmms-1.3.0-alpha.1.638+pr7252.gaaa9b4816-linux-x86_64.AppImage
  • Adds new WANT_DEBUG_CPACK flag to easily show detailed console messages about packaging
    cmake .. -DWANT_DEBUG_CPACK=true
      Developer options
      -----------------------------------------
      * Debug FP exceptions               : Disabled
      * Debug using AddressSanitizer      : Disabled
      * Debug using ThreadSanitizer       : Disabled
      * Debug using MemorySanitizer       : Disabled
      * Debug using UBSanitizer           : Disabled
    + * Debug packaging commands          : Enabled
    • Preserves old CPack TGZ behavior through a hidden flag, WANT_CPACK_TARBALL. Does anyone use this?
  • Adds new CPACK_TOOL parameter to switch between .AppImage (default) and .run (experimental)
    export CPACK_TOOL=makeself
    make package
    # -- Installer create: /__w/lmms/lmms/build/lmms-1.3.0-alpha.1.638+pr7252.gaaa9b4816-linux-x86_64.run

TODO:

  • Fix Carla crashing
  • Investigate possibly using the provided Mac DMG generators.
    • Port the install_apple.sh script to CMake.
      It's called MacDeployQt.cmake now.
  • Investigate possibility using CPack for creating Linux AppImages
    • Port the package_linux.sh script to Cmake
      It's called LinuxDeploy.cmake now.
  • Upgrade CMake for Linux runners

BUGS:

STRETCH GOALS:

Background:

Click to expand
  • The AppImage and Apple DMG installers historically (confusingly) require make install to be run prior to making packages. This PR is a proposal to remove that by switching to CPack.
    • Utilizes make package now, just like Windows does
    • Mac utilizes CPACK_GENERATOR of DragNDrop Bundle which will create a DMG without the need for node's appdmg package (still requires macdeployqt)
    • Linux will utilize CPACK_GENERATOR of "External", which will use custom CMake commands to replace package_linux.sh (still requires linuxdeployqt).

@tresf
Copy link
Member Author

tresf commented May 12, 2024

Rule out possibly using the provided Mac DMG generators.

I was able to get the CPack DMG generator to work with macdeployqt however in order for us to brand our own DMG, we either need to leverage AppleScript (which is much slower and requires user interaction over appdmg), or we need to provide a premade .DS_Store file to bundle.

Edit: For simplicity, I've checked in the .DS_Store from our current DMG. Since it will be unobvious how to update this file in the event of a rebranding, I've kept basic support for appdmg for recreating it, although it's not used or needed unless we rebrand the installer.

@tresf tresf changed the title CPack: Proof of concept for making Apple installers CPack: Refactor AppImage and Apple DMG Generation May 14, 2024
@tresf
Copy link
Member Author

tresf commented May 14, 2024

Hmm... the AppImage is missing... investigating...

@tresf
Copy link
Member Author

tresf commented May 14, 2024

The AppImage is missing because the CPack feature for running custom scripts through variable CPACK_PRE_BUILD_SCRIPTS was not available in Ubuntu 20.04. There doesn't seem to be a replacement for this feature, which is alarming, I wonder how people used "External" packaging techniques prior to CMake 3.19. Hmm...

@midi-pascal
Copy link
Contributor

Perhaps I have a hint for this:

I use Ubuntu 20.04 that comes with cmake version 3.16 BUT Qt (5.15.2 installed from Qt site) comes with cmake 3.27 in its tools directory. This is the one I use.

@tresf
Copy link
Member Author

tresf commented May 14, 2024

I use Ubuntu 20.04 that comes with cmake version 3.16 BUT Qt (5.15.2 installed from Qt site) comes with cmake 3.27 in its tools directory. This is the one I use.

Thanks! Any recommendation for getting this into a CI (command line?)

@midi-pascal
Copy link
Contributor

midi-pascal commented May 14, 2024

Not sure of what I will suggest below since I build using Qt Creator(so all is set automagically) but there are environment variables related to cmake:

CMAKE_PREFIX_PATH

CMAKE_PREFIX_PATH
Semicolon-separated list of directories specifying installation
prefixes to be searched by the find_package(),
find_program(), find_library(), find_file(), and
find_path() commands. Each command will add appropriate
subdirectories (like bin, lib, or include) as specified in its own
documentation.
By default this is empty. It is intended to be set by the project.
There is also an environment variable CMAKE_PREFIX_PATH, which is used
as an additional list of search prefixes.
See also CMAKE_SYSTEM_PREFIX_PATH, CMAKE_INCLUDE_PATH,
CMAKE_LIBRARY_PATH, CMAKE_PROGRAM_PATH, and
CMAKE_IGNORE_PATH.

Hope this can help :-)

@PhysSong
Copy link
Member

FYI, CMake homepage lists the official PPA and pip package as alternative installation methods.

@messmerd
Copy link
Member

@tresf I could update the Linux image with a newer CMake using the official PPA if you want. That might be easiest and also won't impact build times

@tresf
Copy link
Member Author

tresf commented May 15, 2024

@tresf I could update the Linux image with a newer CMake using the official PPA if you want. That might be easiest and also won't impact build times

If parties agree on this CPack strategy, yes please (or from snap).

Tested on Ubuntu 20.04:

sudo snap install cmake --classic
alias cmake='snap run cmake'
# cmake --version
# cmake version 3.29.3
#
# CMake suite maintained and supported by Kitware (kitware.com/cmake).

... I had reservations about whether or not the snap version of cmake would play nicely... and it seems to work just fine.

@tresf
Copy link
Member Author

tresf commented May 15, 2024

@tresf I could update the Linux image with a newer CMake using the official PPA if you want. That might be easiest and also won't impact build times

@messmerd yeah, I'll take that offer. 🤣

image

@Rossmaxx
Copy link
Contributor

can we use the PPA for mingw ci image too?

@messmerd
Copy link
Member

messmerd commented May 15, 2024

yeah, I'll take that offer. 🤣

I'll try to do it sometime today

can we use the PPA for mingw ci image too?

Yes, I think so, though I don't think it will be needed for this PR

@tresf
Copy link
Member Author

tresf commented May 15, 2024

Yes, I think so, though I don't think it will be needed for this PR

Actually, we can justify it here since bad79a8.

@tresf tresf marked this pull request as ready for review May 16, 2024 04:40
@tresf
Copy link
Member Author

tresf commented May 16, 2024

I've marked this ready for review because I think it's in pretty good shape. (artifacts should start generating once cmake is updated).

ARM64.AppImage.mp4

@tresf tresf mentioned this pull request May 16, 2024
@tresf
Copy link
Member Author

tresf commented Jun 1, 2024

Basic .run (via makeself) support has been added via 177cd21.

Testing on Discord shows the following error, investigating...

- ./lmms-1.3.0.run: /home/ubuntu/lmms2/build/cmake/linux/setup.sh: inaccessible or not found

@tresf
Copy link
Member Author

tresf commented Jun 2, 2024

I'll have to revert the MacDeployQt script back to using appdmg.

Done via ddca4e7.

@tresf tresf mentioned this pull request Jun 5, 2024
19 tasks
@tresf
Copy link
Member Author

tresf commented Jun 5, 2024

Due to unreliability with FUSE (availability, compatibility), I'm changing this PR to always extracting AppImages before running them. Quoting #dev-only on Discord:

On the cpack branch, I'm making an executive decision to just never trust AppImages will ever work without extraction. So far:

  • ✅ Ubuntu 20.04 Desktop
  • 🚫 Ubuntu 22.04 Desktop
  • 🚫 Ubuntu 20.04 Server
  • 🚫 Ubuntu 22.04 Server

This will be transient to devs but I just don't see a good reason to ever try to run the AppImage from FUSE when the majority of systems just seem to be missing it or have problems with the version.

Note, master does this already, but for different reasons.

At a glance, this may be a bit confusing, because the build system will create a symlink with the AppImage name. e.g. linuxdeploy-x86_64.Appimage --> .linuxdeploy-x86_64.AppImage/squashfs-root/AppRun, but this allows developers to call the binary by its expected name without having to know where the AppRun was placed. Hopefully this change is percevied as intuitive and not too confuscated™️ . 🍻

@JohannesLorenz JohannesLorenz added this to the 1.3 milestone Aug 4, 2024
@messmerd
Copy link
Member

messmerd commented Oct 23, 2024

On Linux, Carla Rack and Carla Patchbay crash when I try to use them, and this is not the case on master

EDIT: Here's the command-line output:

Carla appears to be installed on this system at /usr/lib[64]/carla so we'll use it.
Jack appears to be installed on this system, so we'll use it.
Lv2 plugin SUMMARY: 18 of 40 loaded in 80 msecs.
For details about not loaded plugins, please set
environment variable "LMMS_LV2_DEBUG" to nonempty.
/tmp/.mount_lmms-1XSszgf/AppRun.wrapped: line 24: 800103 Segmentation fault (core dumped) QT_X11_NO_NATIVE_MENUBAR=1 "$DIR"/usr/bin/lmms "$@"

if(BASHCOMP_PKG_PATH)
# TODO: CMake 3.21 Use "file(COPY_FILE ...)"
install(CODE "
execute_process(COMMAND ${CMAKE_COMMAND} -E copy \"${SCRIPT_NAME}\" \"${BASHCOMP_PKG_PATH}\" ERROR_QUIET RESULT_VARIABLE result)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does it install SCRIPT_NAME twice, once in line 47 and once in line 51?
Also, where is the BASHCOMP_PKG_PATH variable from?

Copy link
Member Author

@tresf tresf Oct 24, 2024

Choose a reason for hiding this comment

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

Why does it install SCRIPT_NAME twice, once in line 47 and once in line 51?

It's due to cmake's lack of conditional INSTALL(...) logic. For some reason, I removed the comment that describes this. It's here: 00d4ddd#diff-7960a523ea4d93951917fb0445e1145899f31c5a796e123ee06c805095e37221R59-R71.

In short:

  1. Always install to user-space
  2. Attempt to install system-wide, but don't fail the build if it doesn't work.

We did have some talks about this "system wide" install previously because this is the first time that we've had a component to install in a prefix that's outside of our own install prefix. I suppose we could instead detect a system-wide prefix and handle this in a more standard fashion. If that's the case, we can fix it as part of this PR if needed. I know some environments (such as Apple's Homebrew) ARE user-writable, so perhaps that was my motivation for this but that does NOT make sense to try when building a DMG or AppImage, so this logic is likely flawed.

Furthermore, I think there's a typo in the status message though.... I think this should say BASHCOMP_PKG_PATH not BASHCOMP_USER_PATH.

-						message(STATUS  "Unable to install bash-completion support system-wide: ${BASHCOMP_USER_PATH}/${SCRIPT_NAME})
+ -						message(STATUS  "Unable to install bash-completion support system-wide: ${BASHCOMP_PKG_PATH}/${SCRIPT_NAME})

Also, where is the BASHCOMP_PKG_PATH variable from?

It's from #4604. This is not a newly introduced variable with this PR. I believe its intended to be the completionsdir component, found by pkg-config. My memory is foggy from back then and the conversations seem to have largely occurred on Discord so decisions are not all obvious. Anyway, we also re-use this variable name for cmake's find_package(bash-completion) portion as well. It's probably a bad name, but I do not plan on changing it as part of this PR but can if needed.

Copy link
Contributor

@JohannesLorenz JohannesLorenz Oct 26, 2024

Choose a reason for hiding this comment

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

I believe its intended to be the completionsdir component, found by pkg-config.

Indeed! The top of the file actually explains it. You can even set this variable using -DBASHCOMP_PKG_PATH=....

Furthermore, I think there's a typo in the status message though.... I think this should say BASHCOMP_PKG_PATH not BASHCOMP_USER_PATH.

Agreeing. Please feel free to fix.

Attempt to install system-wide, but don't fail the build if it doesn't work.

IMO, the natural behavior would be: If the user does a local install, install bashcomp locally. If they do a system install ("root"), install it system-wide. I assume that back then, we thought: "An install should always try to be system-wide, because local installed bashcomp is not sourced by your bashrc". However, you could give the same argument for the PATH variable (a local install of bin/lmms will never be in your PATH by default). In both cases, you can extend your bashrc to source a local bashcomp or to extend your PATH to a local directory. All in all, I would favor to do the install exactly one, and always in the normal install tree. However, it is just my basic opinion, and also it might be considered out of scope of this PR. Tagging @PhysSong because they were also active in that bashcomp PR in 2018.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the feedback. I'll put some time into fixing this.

@tresf
Copy link
Member Author

tresf commented Oct 25, 2024

On Linux, Carla Rack and Carla Patchbay crash when I try to use them, and this is not the case on master

Thanks! Should be fixed via aab4cc5.

@tresf
Copy link
Member Author

tresf commented Oct 25, 2024

On Linux, Carla Rack and Carla Patchbay crash when I try to use them, and this is not the case on master

Thanks! Should be fixed via aab4cc5.

Nevermind, still crashes. Investigating...

@messmerd
Copy link
Member

@tresf
There are 119 files and 2 directories under squashfs-root/usr/lib in this PR, but just 92 files and 1 directory in master.

I'm not sure why there are so many more, but of those extra files, there were libcarlabase.so and libcarla_native-plugin.so. After I removed them, Carla now longer crashed LMMS.

@tresf
Copy link
Member Author

tresf commented Oct 25, 2024

@tresf There are 119 files and 2 directories under squashfs-root/usr/lib in this PR, but just 92 files and 1 directory in master.

I'm not sure why there are so many more, but of those extra files, there were libcarlabase.so and libcarla_native-plugin.so. After I removed them, Carla now longer crashed LMMS.

@messmerd thank you. I'm fully aware of the cause of the crash. linuxdeploy is run twice. First using a qt plugin, which we first use to crawl dependencies and create the .AppDir structure, but then we call it a second time passing the --output appimage flag which we call only after manual cleanup of these carla libraries is performed. Instead of being a replacement for the appimagetool command, it re-runs the dependency tree, so any manually removed files are copied back in. Here's the offending line:

execute_process(COMMAND "${LINUXDEPLOY_BIN}"
--appdir "${APP}"
--output appimage
--verbosity ${VERBOSITY}
${OUTPUT_QUIET}
COMMAND_ECHO ${COMMAND_ECHO}
COMMAND_ERROR_IS_FATAL ANY)

There's a new --exclude-library flag which takes a globbing pattern that I'm experimenting with to see if it can replace the manual cleanup efforts.

@tresf
Copy link
Member Author

tresf commented Oct 25, 2024

Apologies for the whitespace changes in the latest commit 508f430, but spaces and tabs were inconsistent.

The relevant fix is the addition of ${EXCLUDES} variable which adds --exclude-library=pattern. It could be argued that the glob should be provided to both calls to linuxdeploy and the manual cleanup effort removed (rather than having two steps 1. cmake do the glob, 2. provide any found filenames to the --exclude-library flag) but at this point I'm afraid to change too much in fear of causing other issues.

Another big miss was never providing linuxdeploy the -executable= flags. We were building it but never passing it to linuxdeploy. This was would likely have caused some linking issues if not fixed prior to merging. (ignore the double dash change, that's just for readiblity).

There are 119 files and 2 directories under squashfs-root/usr/lib in this PR, but just 92 files and 1 directory in master.

I haven't done a comparison yet, but one thing that linuxdeploy does that linuxdeployqt did not is to attempt to fetch the licensing information for all dependencies. Most of these attempts fail when verbose logging is turned on, but it's one possible culprit. The second directory is a qt wrapper script exclusive to this tool.

I haven't tested the AppImage yet but I believe the Carla loading issue is at least resolved. I'm curious what the directory tree compare looks like. I used to use a commercial tool called "Beyond Compare" for comparing file trees, perhaps there's a FOSS equivalent.

@messmerd
Copy link
Member

I've confirmed that Carla no longer crashes.

However, it looks like there are copies of all the LMMS plugins and some other .so files in both usr/bin and usr/lib/lmms instead of just the latter.
And for at least the past couple commits, the LMMS icon hasn't been showing up on the AppImage file.

As a side note, I just realized xpressive is a whopping 71 MB. It's also always last to finish compiling in our CI builds, so maybe something should be done about that. (Though not in this PR of course)

@tresf
Copy link
Member Author

tresf commented Oct 25, 2024

Although undocumented, it appears appimagetool is available as part of the linuxdeploy tool, as can be observed when verbose logging WANT_DEBUG_CPACK is enabled. I may attempt to use this directly. I'll have to put a few more hours into it.

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.

Request: ARM64 version for Raspberry Pi OS
6 participants