Skip to content

Commit

Permalink
AppImage: Improve build scripts
Browse files Browse the repository at this point in the history
- fix #279707 automatic updates on Linux
    - except for Nightly Builds as this would require
      changes on the Nightly server (see PR musescore#4757)
- fix #271232 create type2 AppImage
- Bundle with linuxdeploy
- Shared Recipe for all architectures

linuxdeploy detects library dependencies and automatically puts
them in the AppImage. This makes the copy-libs scripts redundant.
  • Loading branch information
shoogle committed Jul 11, 2019
1 parent 91b4788 commit 684f641
Show file tree
Hide file tree
Showing 7 changed files with 294 additions and 167 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ matrix:
- ARTIFACTS_CACHE_CONTROL='public, max-age=315360000'
- 'ARTIFACTS_PATHS="$(ls vtest/html | tr "\n" ":")" artifacts upload'

# 2nd parallel build job - portable Linux AppImage 64-bit x86 build on CentOS
# 2nd parallel build job - portable Linux AppImage (x86_64)
- env: "JOB=AppImage_x86_64"
addons:
apt:
Expand Down
4 changes: 1 addition & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,7 @@ portable: install
&& cp "share/applications/$${dsktp}" "$${dsktp}" \
&& cp "share/icons/hicolor/scalable/apps/$${icon}" "$${icon}" \
&& <"$${build_dir}/$${mani}" >"$${mani}" \
sed -rn 's/.*(share\/)(man|mime|icons|applications)(.*)/\1\2\3/p' \
&& "$${build_dir}/../build/Linux+BSD/portable/copy-libs" . \
; ./AppRun check-depends | tee "$${build_dir}/dependencies.txt"
sed -rn 's/.*(share\/)(man|mime|icons|applications)(.*)/\1\2\3/p'

installdebug: debug
cd build.debug \
Expand Down
25 changes: 5 additions & 20 deletions build/Linux+BSD/portable/AppRun.in
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@
#!/bin/bash

# TODO: rewrite this file in a faster, more portable language (e.g. C)
#!/usr/bin/env bash

# APPDIR and APPIMAGE are environment variables which are set when the user
# runs the AppImage. They won't be set if you try to run this outside of an
# AppImage, so here we set them to something sensible instead for testing.
[ "${APPDIR}" ] || export APPDIR="$(dirname "$(readlink -f "${0}")")"
[ "${APPIMAGE}" ] || export APPIMAGE="${APPDIR}/AppRun"

libs="${APPDIR}/lib"

# Workaround for Jack library
# Based on the solution https://github.com/LMMS/lmms/pull/3958/files
if ldconfig -p | grep libjack.so.0 > /dev/null 2>&1; then
echo "Jack appears to be installed on this system, so we'll use it."
else
echo "Jack does not appear to be installed. That's OK, we'll use a dummy version instead."
export LD_LIBRARY_PATH="${APPDIR}/optional:${LD_LIBRARY_PATH}"
fi
[[ "${APPDIR}" ]] || export APPDIR="$(dirname "$(readlink -f "${0}")")"
[[ "${APPIMAGE}" ]] || export APPIMAGE="${APPDIR}/AppRun"

# Setting LD_LIBRARY_PATH won't override AppImage libraries, but advanced users
# can do that with APPIMAGE_LIBRARY_PATH if they really want to.
libs="${APPDIR}/lib"
export LD_LIBRARY_PATH="${APPIMAGE_LIBRARY_PATH}:${libs}:${libs}/qt5/lib:${LD_LIBRARY_PATH}"

export QT_STYLE_OVERRIDE="GTK+" # use system font size

# Launch MuseScore or an accompanying script
case "$1" in
-h|--help|install|uninstall|remove|man|manual|manpage|check-depends|check-dependencies )
"${APPDIR}/bin/portable-utils" "$@"
Expand All @@ -33,5 +20,3 @@ case "$1" in
"${APPDIR}/bin/mscore@MSCORE_INSTALL_SUFFIX@" "$@"
;;
esac

exit $?
248 changes: 248 additions & 0 deletions build/Linux+BSD/portable/Recipe
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
#!/usr/bin/env bash

# For maximum AppImage compatibility, build on the oldest Linux distribution
# that still receives security updates from its manufacturer.

set -e # Exit on errors
set -x # Be verbose

# Go one-up from MuseScore root dir regardless of where script was run from:
cd "$(dirname "$(readlink -f "${0}")")/../../../.."

##########################################################################
# GET DEPENDENCIES
##########################################################################

# DISTRIBUTION PACKAGES

# These are installed by default on Travis CI, but not on Docker
apt_packages_basic=(
# Alphabetical order please!
file
git
pkg-config
software-properties-common # installs `add-apt-repository`
unzip
)

# These are the same as on Travis CI
apt_packages_standard=(
# Alphabetical order please!
# cmake # using more recent upstream version from cmake.org
curl
libasound2-dev # ALSA
libfontconfig1-dev
libfreetype6-dev
libgl1-mesa-dev
libjack-dev
libmp3lame-dev
libnss3-dev
libportmidi-dev
libpulse-dev
libsndfile1-dev
make
portaudio19-dev
wget
)

# MuseScore compiles without these but won't run without them
apt_packages_runtime=(
# Alphabetical order please!
libegl1-mesa-dev
libodbc1
libpq-dev
libxcomposite-dev
libxcursor-dev
libxi-dev
libxkbcommon-x11-0
libxtst-dev
)

apt-get update # no package lists in Docker image
apt-get install -y --no-install-recommends \
"${apt_packages_basic[@]}" \
"${apt_packages_standard[@]}" \
"${apt_packages_runtime[@]}"

# NON-DISTRIBUTION PACKAGES
# We use these when the default version provided by the distribution is
# too old or has unwelcome modifications compared to the upstream version.

# Get newer compiler
gcc_version="4.9"
if [[ ! -f /etc/apt/sources.list.d/ubuntu-toolchain-r-test-*.list ]]; then
add-apt-repository -y ppa:ubuntu-toolchain-r/test
apt-get update
fi
apt-get install -y --no-install-recommends "g++-${gcc_version}"
update-alternatives \
--install /usr/bin/gcc gcc "/usr/bin/gcc-${gcc_version}" 40 \
--slave /usr/bin/g++ g++ "/usr/bin/g++-${gcc_version}"
export CC="/usr/bin/gcc-${gcc_version}"
export CXX="/usr/bin/g++-${gcc_version}"

# Get newer Qt (only used cached version if it is the same)
qt_version="5124"
qt_dir="qt/${qt_version}"
if [[ ! -d "${qt_dir}" ]]; then
mkdir -p "${qt_dir}"
qt_url="https://s3.amazonaws.com/utils.musescore.org/qt${qt_version}.zip"
wget -q --show-progress -O qt5.zip "${qt_url}"
unzip -qq qt5.zip -d "${qt_dir}"
rm -f qt5.zip
fi
qt_path="${PWD%/}/${qt_dir}"
export PATH="${qt_path}/bin:${PATH}"
export LD_LIBRARY_PATH="${qt_path}/lib:${LD_LIBRARY_PATH}"
export QT_PLUGIN_PATH="${qt_path}/plugins"
export QML2_IMPORT_PATH="${qt_path}/qml"

# Get newer CMake (only used cached version if it is the same)
cmake_version="3.10.1"
cmake_dir="cmake/${cmake_version}"
if [[ ! -d "${cmake_dir}" ]]; then
mkdir -p "${cmake_dir}"
cmake_url="https://cmake.org/files/v${cmake_version%.*}/cmake-${cmake_version}-Linux-x86_64.tar.gz"
wget -q --show-progress --no-check-certificate -O - "${cmake_url}" \
| tar --strip-components=1 -xz -C "${cmake_dir}"
fi
export PATH="${PWD%/}/${cmake_dir}/bin:${PATH}"

# Build MuseScore on Travis but not on Docker Cloud (reduce container size)
if [[ ! -d "MuseScore" ]]; then
# tidy up (reduce size of Docker image)
apt-get clean autoclean
apt-get autoremove --purge -y
rm -rf /tmp/* /var/{cache,log,backups}/* /var/lib/apt/*
exit 0
fi

##########################################################################
# BUILD MUSESCORE
##########################################################################

cd MuseScore
make revision
make "$@" portable
cd ..

##########################################################################
# GET APPIMAGETOOL AND LINUXDEPLOY
##########################################################################

function extract_appimage()
{
# Extract AppImage so we can run it without having to install FUSE
local -r appimage="$1" binary_name="$2"
local -r appdir="${appimage%.AppImage}.AppDir"
"./${appimage}" --appimage-extract >/dev/null # dest folder "squashfs-root"
mv squashfs-root "${appdir}" # rename folder to avoid collisions
ln -s "${appdir}/AppRun" "${binary_name}" # symlink for convenience
rm -f "${appimage}"
}

function download_github_release()
{
local -r repo_slug="$1" release_tag="$2" file="$3"
wget -q --show-progress \
"https://github.com/${repo_slug}/releases/download/${release_tag}/${file}"
chmod +x "${file}"
}

function download_appimage_release()
{
local -r github_repo_slug="$1" binary_name="$2"
local -r appimage="${binary_name}-x86_64.AppImage"
download_github_release "${github_repo_slug}" continuous "${appimage}"
extract_appimage "${appimage}" "${binary_name}"
}

function download_linuxdeploy_component()
{
download_appimage_release "linuxdeploy/$1" "$1"
}

# GET LATEST APPIMAGETOOL AND LINUXDEPLOY
# We didn't do this earlier because we don't want them to get cached in the
# Docker image. We always want the latest versions with the latest features.
# We still check for an existing version to avoid re-downloading if the
# script is run again in the same container (e.g. during local development).

if [[ ! -d "appimagetool" ]]; then
mkdir appimagetool
cd appimagetool
download_appimage_release AppImage/AppImageKit appimagetool
cd ..
fi
export PATH="${PWD%/}/appimagetool:$PATH"
appimagetool --version

if [[ ! -d "linuxdeploy" ]]; then
mkdir linuxdeploy
cd linuxdeploy
download_linuxdeploy_component linuxdeploy
download_linuxdeploy_component linuxdeploy-plugin-qt
cd ..
fi
export PATH="${PWD%/}/linuxdeploy:$PATH"
linuxdeploy --list-plugins

##########################################################################
# BUNDLE DEPENDENCIES INTO APPDIR
##########################################################################

cd MuseScore
prefix="$(cat build.release/PREFIX.txt)" # MuseScore was installed here
cd "$(dirname "${prefix}")"
appdir="$(basename "${prefix}")" # directory that will become the AppImage

linuxdeploy --appdir "${appdir}" # adds all shared library dependencies
linuxdeploy-plugin-qt --appdir "${appdir}" # adds all Qt dependencies

# Final tidy-up before creating the AppImage
chmod u+x "${appdir}/bin/QtWebEngineProcess"

##########################################################################
# TURN APPDIR INTO AN APPIMAGE
##########################################################################

appimage="${appdir%.AppDir}.AppImage" # name to use for AppImage file

appimagetool_args=( # array
# none
)

created_files=(
"${appimage}"
)

if [[ "${UPDATE_INFORMATION}" ]]; then
appimagetool_args+=( # append to array
--updateinformation "${UPDATE_INFORMATION}"
)
created_files+=(
"${appimage}.zsync" # this file will contain delta update data
)
else
cat >&2 <<EOF
$0: Automatic updates disabled.
To enable automatic updates, please set the env. variable UPDATE_INFORMATION
according to <https://github.com/AppImage/AppImageSpec/blob/master/draft.md>.
EOF
fi

# create AppImage
appimagetool "${appimagetool_args[@]}" "${appdir}" "${appimage}"

# We are running as root in the Docker image so all created files belong to
# root. Allow non-root users outside the Docker image to access these files.
chmod a+rwx "${created_files[@]}"
parent_dir="${PWD}"
while [[ "$(dirname "${parent_dir}")" != "${parent_dir}" ]]; do
[[ "$parent_dir" == "/" ]] && break
chmod a+rwx "$parent_dir"
parent_dir="$(dirname "$parent_dir")"
done

ls -lh "${created_files[@]}"
echo "Recipe has finished!" >&2
25 changes: 21 additions & 4 deletions build/Linux+BSD/portable/x86_64/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
FROM library/ubuntu:14.04
ADD Recipe /Recipe
RUN bash -ex Recipe && apt-get clean autoclean
RUN apt-get autoremove -y && rm -rf /var/lib/{apt,dpkg,cache,log}/ /tmp/*
FROM library/ubuntu:16.04
# For maximum AppImage compatibility, build on the oldest Linux distribution
# that still receives security updates from its manufacturer.
COPY build/Linux+BSD/portable/Recipe /Recipe
RUN bash -ex Recipe
# Note that each additional ADD, RUN or COPY command creates a new "layer"
# (i.e. an intermediate Docker image). Any clean-up steps after a RUN command
# must be done as part of that same command, like this:
#
# RUN command \
# && clean-up-command # creates single clean layer
#
# Or if `command` is a script, clean-up could be done as part of that script.
#
# Avoid doing this:
#
# RUN command # creates dirty layer
# RUN clean-up-command # creates clean layer
#
# This is like reverting a bad commit: you can't see the dirtiness any more,
# but it's still in the history and still takes up space on your hard drive.
Loading

0 comments on commit 684f641

Please sign in to comment.