CPack: Refactor AppImage and Apple DMG Generation (#7252)
* CPack: Refactor AppImage and Apple DMG Generation * Switch from linuxdeployqt to linuxdelpoy * Add ARM64 AppImage support * Add support for `.run` installers using `makeself`, an alternative to AppImage * Refactor BashCompletion.cmake * Enable CPack debugging via `WANT_DEBUG_CPACK` * Add `download_binary`, `create_symlink` macros * Qt6: Fix @rpath bug on macOS * Detect and bundle LV2 UI Suil modules (Related #7201) * Allow remote plugins to honor `LMMS_PLUGIN_DIR` * Add .github/workflows/deps-ubuntu-24.04-gcc.txt * Fix waveforms FileDialog Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
This commit is contained in:
78
.github/workflows/build.yml
vendored
78
.github/workflows/build.yml
vendored
@@ -5,8 +5,8 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
linux:
|
||||
name: linux
|
||||
linux-x86_64:
|
||||
name: linux-x86_64
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/lmms/linux.gcc:20.04
|
||||
env:
|
||||
@@ -39,7 +39,6 @@ jobs:
|
||||
source /opt/qt5*/bin/qt5*-env.sh || true
|
||||
cmake -S . \
|
||||
-B build \
|
||||
-DCMAKE_INSTALL_PREFIX=./install \
|
||||
$CMAKE_OPTS
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
@@ -49,8 +48,7 @@ jobs:
|
||||
ctest --output-on-failure -j2
|
||||
- name: Package
|
||||
run: |
|
||||
cmake --build build --target install
|
||||
cmake --build build --target appimage
|
||||
cmake --build build --target package
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -65,6 +63,71 @@ jobs:
|
||||
ccache --show-stats
|
||||
env:
|
||||
CCACHE_MAXSIZE: 500M
|
||||
linux-arm64:
|
||||
name: linux-arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
env:
|
||||
CMAKE_OPTS: >-
|
||||
-DUSE_WERROR=ON
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DUSE_COMPILE_CACHE=ON
|
||||
-DWANT_DEBUG_CPACK=ON
|
||||
CCACHE_MAXSIZE: 0
|
||||
CCACHE_NOCOMPRESS: 1
|
||||
MAKEFLAGS: -j2
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
steps:
|
||||
- name: Configure git
|
||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
- name: Check out
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
- name: Install system packages
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
$(xargs < .github/workflows/deps-ubuntu-24.04-gcc.txt)
|
||||
- name: Cache ccache data
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
key: ccache-${{ github.job }}-${{ github.ref }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.job }}-${{ github.ref }}-
|
||||
ccache-${{ github.job }}-
|
||||
path: ~/.ccache
|
||||
- name: Configure
|
||||
run: |
|
||||
ccache --zero-stats
|
||||
cmake -S . \
|
||||
-B build \
|
||||
-DWANT_VST_32=OFF \
|
||||
-DWANT_VST_64=OFF \
|
||||
$CMAKE_OPTS
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd build/tests
|
||||
ctest --output-on-failure -j2
|
||||
- name: Package
|
||||
run: |
|
||||
cmake --build build --target package
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-arm64
|
||||
path: build/lmms-*.AppImage
|
||||
- name: Trim ccache and print statistics
|
||||
run: |
|
||||
ccache --cleanup
|
||||
echo "[ccache config]"
|
||||
ccache --show-config
|
||||
echo "[ccache stats]"
|
||||
ccache --show-stats
|
||||
env:
|
||||
CCACHE_MAXSIZE: 500M
|
||||
macos:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -129,7 +192,6 @@ jobs:
|
||||
mkdir build
|
||||
cmake -S . \
|
||||
-B build \
|
||||
-DCMAKE_INSTALL_PREFIX="../target" \
|
||||
-DCMAKE_PREFIX_PATH="$(brew --prefix qt@5)" \
|
||||
-DCMAKE_OSX_ARCHITECTURES=${{ matrix.arch }} \
|
||||
$CMAKE_OPTS \
|
||||
@@ -142,8 +204,7 @@ jobs:
|
||||
ctest --output-on-failure -j3
|
||||
- name: Package
|
||||
run: |
|
||||
cmake --build build --target install
|
||||
cmake --build build --target dmg
|
||||
cmake --build build --target package
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -208,7 +269,6 @@ jobs:
|
||||
ccache --zero-stats
|
||||
cmake -S . \
|
||||
-B build \
|
||||
-DCMAKE_INSTALL_PREFIX=./install \
|
||||
-DCMAKE_TOOLCHAIN_FILE="./cmake/toolchains/MinGW-W64-64.cmake" \
|
||||
$CMAKE_OPTS
|
||||
- name: Build
|
||||
|
||||
52
.github/workflows/deps-ubuntu-24.04-gcc.txt
vendored
Normal file
52
.github/workflows/deps-ubuntu-24.04-gcc.txt
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
binutils
|
||||
ca-certificates
|
||||
ccache
|
||||
cmake
|
||||
file
|
||||
fluid
|
||||
gcc
|
||||
git
|
||||
gpg
|
||||
g++
|
||||
libasound2-dev
|
||||
libc6-dev
|
||||
libfftw3-dev
|
||||
libfltk1.3-dev
|
||||
libfluidsynth-dev
|
||||
libgig-dev
|
||||
libgtk2.0-0
|
||||
libjack-jackd2-dev
|
||||
liblilv-dev
|
||||
liblist-moreutils-perl
|
||||
libmp3lame-dev
|
||||
libogg-dev
|
||||
libqt5svg5-dev
|
||||
libqt5x11extras5-dev
|
||||
libsamplerate0-dev
|
||||
libsdl2-dev
|
||||
libsndfile1-dev
|
||||
libsoundio-dev
|
||||
libstk-dev
|
||||
libsuil-dev
|
||||
libvorbis-dev
|
||||
libx11-xcb-dev
|
||||
libxcb-keysyms1-dev
|
||||
libxcb-util0-dev
|
||||
libxft-dev
|
||||
libxinerama-dev
|
||||
libxml2-utils
|
||||
libxml-perl
|
||||
lsb-release
|
||||
lv2-dev
|
||||
make
|
||||
perl
|
||||
portaudio19-dev
|
||||
qt5-qmake
|
||||
qtbase5-dev
|
||||
qtbase5-dev-tools
|
||||
qtbase5-private-dev
|
||||
qttools5-dev-tools
|
||||
software-properties-common
|
||||
ssh-client
|
||||
stk
|
||||
wget
|
||||
@@ -104,6 +104,8 @@ option(WANT_DEBUG_MSAN "Enable MemorySanitizer" OFF)
|
||||
option(WANT_DEBUG_UBSAN "Enable UndefinedBehaviorSanitizer" OFF)
|
||||
option(WANT_DEBUG_GPROF "Enable gprof profiler" OFF)
|
||||
OPTION(BUNDLE_QT_TRANSLATIONS "Install Qt translation files for LMMS" OFF)
|
||||
option(WANT_DEBUG_CPACK "Show detailed logs for packaging commands" OFF)
|
||||
option(WANT_CPACK_TARBALL "Request CPack to create a tarball instead of an installer" OFF)
|
||||
|
||||
|
||||
IF(LMMS_BUILD_APPLE)
|
||||
@@ -268,6 +270,7 @@ IF(WANT_SUIL)
|
||||
IF(SUIL_FOUND)
|
||||
SET(LMMS_HAVE_SUIL TRUE)
|
||||
SET(STATUS_SUIL "OK")
|
||||
find_package(SuilModules)
|
||||
ELSE()
|
||||
SET(STATUS_SUIL "not found, install it or set PKG_CONFIG_PATH appropriately")
|
||||
ENDIF()
|
||||
@@ -606,6 +609,17 @@ ELSE()
|
||||
SET (STATUS_DEBUG_FPE "Disabled")
|
||||
ENDIF(WANT_DEBUG_FPE)
|
||||
|
||||
if(WANT_DEBUG_CPACK)
|
||||
if((LMMS_BUILD_WIN32 AND CMAKE_VERSION VERSION_LESS "3.19") OR WANT_CPACK_TARBALL)
|
||||
set(STATUS_DEBUG_CPACK "Wanted but disabled due to unsupported configuration")
|
||||
else()
|
||||
set(CPACK_DEBUG TRUE)
|
||||
set(STATUS_DEBUG_CPACK "Enabled")
|
||||
endif()
|
||||
else()
|
||||
set(STATUS_DEBUG_CPACK "Disabled")
|
||||
endif()
|
||||
|
||||
# check for libsamplerate
|
||||
FIND_PACKAGE(Samplerate 0.1.8 MODULE REQUIRED)
|
||||
|
||||
@@ -679,7 +693,7 @@ if(WANT_DEBUG_GPROF)
|
||||
add_link_options(-pg)
|
||||
set(STATUS_GPROF "OK")
|
||||
else()
|
||||
set(STATUS_GPROF "DISABLED ${STATUS_GPROF}")
|
||||
set(STATUS_GPROF "Disabled ${STATUS_GPROF}")
|
||||
endif()
|
||||
|
||||
# add enabled sanitizers
|
||||
@@ -745,7 +759,7 @@ IF(LMMS_BUILD_LINUX)
|
||||
"${CMAKE_BINARY_DIR}/lmmsconfig.h"
|
||||
"${CMAKE_BINARY_DIR}/lmmsversion.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/embed.cpp"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/include/lmms/")
|
||||
DESTINATION "include/lmms/")
|
||||
ENDIF(LMMS_BUILD_LINUX)
|
||||
|
||||
#
|
||||
@@ -849,6 +863,7 @@ MESSAGE(
|
||||
"* Debug using ThreadSanitizer : ${STATUS_DEBUG_TSAN}\n"
|
||||
"* Debug using MemorySanitizer : ${STATUS_DEBUG_MSAN}\n"
|
||||
"* Debug using UBSanitizer : ${STATUS_DEBUG_UBSAN}\n"
|
||||
"* Debug packaging commands : ${STATUS_DEBUG_CPACK}\n"
|
||||
"* Profile using GNU profiler : ${STATUS_GPROF}\n"
|
||||
)
|
||||
|
||||
|
||||
@@ -14,10 +14,14 @@ ENDIF()
|
||||
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME_UCASE}")
|
||||
SET(CPACK_SOURCE_GENERATOR "TBZ2")
|
||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}")
|
||||
IF(NOT DEFINED WIN32)
|
||||
SET(CPACK_STRIP_FILES "bin/${CMAKE_PROJECT_NAME};${PLUGIN_DIR}/*.so")
|
||||
SET(CPACK_PACKAGE_EXECUTABLES "${CMAKE_PROJECT_NAME}" "${PROJECT_NAME_UCASE} binary")
|
||||
ENDIF()
|
||||
SET(CPACK_PACKAGE_EXECUTABLES "${CMAKE_PROJECT_NAME}" "${PROJECT_NAME_UCASE} binary")
|
||||
|
||||
# Disable strip for Debug|RelWithDebInfo
|
||||
if(CMAKE_BUILD_TYPE MATCHES "Deb")
|
||||
unset(CPACK_STRIP_FILES)
|
||||
else()
|
||||
set(CPACK_STRIP_FILES TRUE)
|
||||
endif()
|
||||
|
||||
IF(LMMS_BUILD_WIN32)
|
||||
ADD_SUBDIRECTORY(nsis)
|
||||
|
||||
@@ -1,24 +1,3 @@
|
||||
SET(MACOSX_BUNDLE_ICON_FILE "icon.icns")
|
||||
SET(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_NAME_UCASE}")
|
||||
SET(MACOSX_BUNDLE_LONG_VERSION_STRING "${VERSION}")
|
||||
SET(MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME_UCASE}")
|
||||
SET(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VERSION}")
|
||||
SET(MACOSX_BUNDLE_BUNDLE_VERSION "${VERSION}")
|
||||
SET(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT}")
|
||||
SET(MACOSX_BUNDLE_MIMETYPE "application/x-lmms-project")
|
||||
SET(MACOSX_BUNDLE_MIMETYPE_ICON "project.icns")
|
||||
SET(MACOSX_BUNDLE_MIMETYPE_ID "io.lmms")
|
||||
SET(MACOSX_BUNDLE_PROJECT_URL "${PROJECT_URL}")
|
||||
SET(MACOSX_BUNDLE_DMG_TITLE "${MACOSX_BUNDLE_BUNDLE_NAME} ${MACOSX_BUNDLE_LONG_VERSION_STRING}")
|
||||
|
||||
# FIXME: appdmg won't allow volume names > 27 char
|
||||
# See also https://github.com/LinusU/node-appdmg/issues/48
|
||||
STRING(SUBSTRING "${MACOSX_BUNDLE_DMG_TITLE}" 0 27 MACOSX_BUNDLE_DMG_TITLE)
|
||||
|
||||
CONFIGURE_FILE("lmms.plist.in" "${CMAKE_BINARY_DIR}/Info.plist")
|
||||
CONFIGURE_FILE("install_apple.sh.in" "${CMAKE_BINARY_DIR}/install_apple.sh" @ONLY)
|
||||
CONFIGURE_FILE("package_apple.json.in" "${CMAKE_BINARY_DIR}/package_apple.json" @ONLY)
|
||||
|
||||
IF(CMAKE_OSX_ARCHITECTURES)
|
||||
SET(DMG_ARCH "${CMAKE_OSX_ARCHITECTURES}")
|
||||
ELSEIF(IS_ARM64)
|
||||
@@ -29,18 +8,31 @@ ELSE()
|
||||
SET(DMG_ARCH "x86_64")
|
||||
ENDIF()
|
||||
|
||||
# DMG creation target
|
||||
SET(DMG_FILE "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-${VERSION}-mac${APPLE_OS_VER}-${DMG_ARCH}.dmg")
|
||||
# Standard CPack options
|
||||
set(CPACK_GENERATOR "External" PARENT_SCOPE)
|
||||
set(CPACK_EXTERNAL_ENABLE_STAGING TRUE PARENT_SCOPE)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-mac${APPLE_OS_VER}-${DMG_ARCH}")
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}" PARENT_SCOPE)
|
||||
set(CPACK_PRE_BUILD_SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/MacDeployQt.cmake" PARENT_SCOPE)
|
||||
# disable cpack's strip: causes missing symbols on macOS
|
||||
set(CPACK_STRIP_FILES_ORIG "${CPACK_STRIP_FILES}" PARENT_SCOPE)
|
||||
set(CPACK_STRIP_FILES FALSE PARENT_SCOPE)
|
||||
|
||||
FILE(REMOVE "${DMG_FILE}")
|
||||
ADD_CUSTOM_TARGET(removedmg
|
||||
COMMAND touch "\"${DMG_FILE}\"" && rm "\"${DMG_FILE}\""
|
||||
COMMENT "Removing old DMG")
|
||||
ADD_CUSTOM_TARGET(dmg
|
||||
COMMAND appdmg "\"${CMAKE_BINARY_DIR}/package_apple.json\"" "\"${DMG_FILE}\""
|
||||
DEPENDS "${CMAKE_BINARY_DIR}/package_apple.json"
|
||||
COMMENT "Generating DMG")
|
||||
ADD_DEPENDENCIES(dmg removedmg)
|
||||
|
||||
# see also ../postinstall/CMakeLists.txt
|
||||
# Custom vars to expose to Cpack
|
||||
# must be prefixed with "CPACK_" per https://stackoverflow.com/a/46526757/3196753)
|
||||
set(CPACK_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" PARENT_SCOPE)
|
||||
set(CPACK_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PARENT_SCOPE)
|
||||
set(CPACK_BINARY_DIR "${CMAKE_BINARY_DIR}" PARENT_SCOPE)
|
||||
set(CPACK_SOURCE_DIR "${CMAKE_SOURCE_DIR}" PARENT_SCOPE)
|
||||
set(CPACK_QMAKE_EXECUTABLE "${QT_QMAKE_EXECUTABLE}" PARENT_SCOPE)
|
||||
set(CPACK_CARLA_LIBRARIES "${CARLA_LIBRARIES}" PARENT_SCOPE)
|
||||
set(CPACK_PROJECT_NAME "${PROJECT_NAME}" PARENT_SCOPE)
|
||||
set(CPACK_PROJECT_VERSION "${VERSION}" PARENT_SCOPE)
|
||||
set(CPACK_PROJECT_NAME_UCASE "${PROJECT_NAME_UCASE}" PARENT_SCOPE)
|
||||
set(CPACK_PROJECT_URL "${PROJECT_URL}" PARENT_SCOPE)
|
||||
set(CPACK_SUIL_MODULES "${Suil_MODULES}" PARENT_SCOPE)
|
||||
set(CPACK_SUIL_MODULES_PREFIX "${Suil_MODULES_PREFIX}" PARENT_SCOPE)
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS "3.19")
|
||||
message(WARNING "DMG creation requires at least CMake 3.19")
|
||||
endif()
|
||||
|
||||
172
cmake/apple/MacDeployQt.cmake
Normal file
172
cmake/apple/MacDeployQt.cmake
Normal file
@@ -0,0 +1,172 @@
|
||||
# Create a macOS .dmg desktop installer using macdeployqt
|
||||
#
|
||||
# Copyright (c) 2025, Tres Finocchiaro, <tres.finocchiaro@gmail.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
# Variables must be prefixed with "CPACK_" to be visible here
|
||||
set(lmms "${CPACK_PROJECT_NAME}")
|
||||
set(APP "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/${CPACK_PROJECT_NAME_UCASE}.app")
|
||||
|
||||
# Toggle command echoing & verbosity
|
||||
# 0 = no output, 1 = error/warning, 2 = normal, 3 = debug
|
||||
if(NOT CPACK_DEBUG)
|
||||
set(VERBOSITY 1)
|
||||
set(COMMAND_ECHO NONE)
|
||||
else()
|
||||
set(VERBOSITY 2)
|
||||
set(COMMAND_ECHO STDOUT)
|
||||
endif()
|
||||
|
||||
# Detect release|debug build
|
||||
if(NOT CPACK_STRIP_FILES_ORIG)
|
||||
# -use-debug-libs implies -no-strip
|
||||
if(CPACK_QMAKE_EXECUTABLE MATCHES "/homebrew/|/usr/local")
|
||||
message(STATUS "Homebrew does not provide debug qt libraries, replacing \"-use-debug-libs\" with \"-no-strip\" instead")
|
||||
set(USE_DEBUG_LIBS -no-strip)
|
||||
else()
|
||||
set(USE_DEBUG_LIBS -use-debug-libs)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Cleanup CPack "External" json, txt files, old DMG files
|
||||
file(GLOB cleanup "${CPACK_BINARY_DIR}/${lmms}-*.json"
|
||||
"${CPACK_BINARY_DIR}/${lmms}-*.dmg"
|
||||
"${CPACK_BINARY_DIR}/install_manifest.txt")
|
||||
list(SORT cleanup)
|
||||
file(REMOVE ${cleanup})
|
||||
|
||||
# Create bundle structure
|
||||
file(MAKE_DIRECTORY "${APP}/Contents/MacOS")
|
||||
file(MAKE_DIRECTORY "${APP}/Contents/Frameworks")
|
||||
file(MAKE_DIRECTORY "${APP}/Contents/Resources")
|
||||
|
||||
# Fix layout
|
||||
file(RENAME "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/lib" "${APP}/Contents/lib")
|
||||
file(RENAME "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/share" "${APP}/Contents/share")
|
||||
file(RENAME "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/bin" "${APP}/Contents/bin")
|
||||
|
||||
# Move binaries into Contents/MacOS
|
||||
file(RENAME "${APP}/Contents/bin/${lmms}" "${APP}/Contents/MacOS/${lmms}")
|
||||
file(RENAME "${APP}/Contents/lib/${lmms}/RemoteZynAddSubFx" "${APP}/Contents/MacOS/RemoteZynAddSubFx")
|
||||
file(REMOVE_RECURSE "${APP}/Contents/bin")
|
||||
file(REMOVE_RECURSE "${APP}/Contents/share/man1")
|
||||
file(REMOVE_RECURSE "${APP}/Contents/include")
|
||||
|
||||
# Copy missing files
|
||||
# Convert https://lmms.io to io.lmms
|
||||
string(REPLACE "." ";" mime_parts "${CPACK_PROJECT_URL}")
|
||||
string(REPLACE ":" ";" mime_parts "${mime_parts}")
|
||||
string(REPLACE "/" "" mime_parts "${mime_parts}")
|
||||
list(REMOVE_AT mime_parts 0)
|
||||
list(REVERSE mime_parts)
|
||||
list(JOIN mime_parts "." MACOS_MIMETYPE_ID)
|
||||
configure_file("${CPACK_CURRENT_SOURCE_DIR}/lmms.plist.in" "${APP}/Contents/Info.plist" @ONLY)
|
||||
file(COPY "${CPACK_CURRENT_SOURCE_DIR}/project.icns" DESTINATION "${APP}/Contents/Resources")
|
||||
file(COPY "${CPACK_CURRENT_SOURCE_DIR}/icon.icns" DESTINATION "${APP}/Contents/Resources")
|
||||
file(RENAME "${APP}/Contents/Resources/icon.icns" "${APP}/Contents/Resources/${lmms}.icns")
|
||||
|
||||
# Copy Suil modules
|
||||
if(CPACK_SUIL_MODULES)
|
||||
set(SUIL_MODULES_TARGET "${APP}/Contents/Frameworks/${CPACK_SUIL_MODULES_PREFIX}")
|
||||
file(MAKE_DIRECTORY "${SUIL_MODULES_TARGET}")
|
||||
file(COPY ${CPACK_SUIL_MODULES} DESTINATION "${SUIL_MODULES_TARGET}")
|
||||
endif()
|
||||
|
||||
# Make all libraries writable for macdeployqt
|
||||
file(CHMOD_RECURSE "${APP}/Contents" PERMISSIONS
|
||||
OWNER_EXECUTE OWNER_WRITE OWNER_READ
|
||||
GROUP_EXECUTE GROUP_WRITE GROUP_READ
|
||||
WORLD_READ)
|
||||
|
||||
# Qt6: Fix @rpath bug https://github.com/orgs/Homebrew/discussions/2823
|
||||
include(CreateSymlink)
|
||||
get_filename_component(QTBIN "${CPACK_QMAKE_EXECUTABLE}" DIRECTORY)
|
||||
get_filename_component(QTDIR "${QTBIN}" DIRECTORY)
|
||||
create_symlink("${QTDIR}/lib" "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/lib")
|
||||
|
||||
# Replace @rpath with @loader_path for Carla
|
||||
execute_process(COMMAND install_name_tool -change
|
||||
"@rpath/libcarlabase.dylib"
|
||||
"@loader_path/libcarlabase.dylib"
|
||||
"${APP}/Contents/lib/${lmms}/libcarlapatchbay.so"
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
execute_process(COMMAND install_name_tool -change
|
||||
"@rpath/libcarlabase.dylib"
|
||||
"@loader_path/libcarlabase.dylib"
|
||||
"${APP}/Contents/lib/${lmms}/libcarlarack.so"
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
# Build list of executables to inform macdeployqt about
|
||||
# e.g. -executable=foo.dylib -executable=bar.dylib
|
||||
file(GLOB LIBS "${APP}/Contents/lib/${lmms}/*.so")
|
||||
|
||||
# Inform macdeployqt about LADSPA plugins; may depend on bundled fftw3f, etc.
|
||||
file(GLOB LADSPA "${APP}/Contents/lib/${lmms}/ladspa/*.so")
|
||||
|
||||
# Inform linuxdeploy about remote plugins
|
||||
list(APPEND REMOTE_PLUGINS "${APP}/Contents/MacOS/*Remote*")
|
||||
|
||||
# Collect, sort and dedupe all libraries
|
||||
list(APPEND LIBS ${LADSPA})
|
||||
list(APPEND LIBS ${REMOTE_PLUGINS})
|
||||
list(APPEND LIBS ${CPACK_SUIL_MODULES})
|
||||
list(REMOVE_DUPLICATES LIBS)
|
||||
list(SORT LIBS)
|
||||
|
||||
# Construct macdeployqt parameters
|
||||
foreach(_lib IN LISTS LIBS)
|
||||
if(EXISTS "${_lib}")
|
||||
list(APPEND EXECUTABLES "-executable=${_lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Call macdeployqt
|
||||
get_filename_component(QTBIN "${CPACK_QMAKE_EXECUTABLE}" DIRECTORY)
|
||||
message(STATUS "Calling ${QTBIN}/macdeployqt ${APP} [... executables]")
|
||||
execute_process(COMMAND "${QTBIN}/macdeployqt" "${APP}" ${EXECUTABLES}
|
||||
-verbose=${VERBOSITY}
|
||||
${USE_DEBUG_LIBS}
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
# Cleanup symlink
|
||||
file(REMOVE "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/lib")
|
||||
|
||||
# Remove dummy carla libs, relink to a sane location (e.g. /Applications/Carla.app/...)
|
||||
# (must be done after calling macdeployqt)
|
||||
file(GLOB CARLALIBS "${APP}/Contents/lib/${lmms}/libcarla*")
|
||||
foreach(_carlalib IN LISTS CARLALIBS)
|
||||
foreach(_lib "${CPACK_CARLA_LIBRARIES}")
|
||||
set(_oldpath "../../Frameworks/lib${_lib}.dylib")
|
||||
set(_newpath "Carla.app/Contents/MacOS/lib${_lib}.dylib")
|
||||
execute_process(COMMAND install_name_tool -change
|
||||
"@loader_path/${_oldpath}"
|
||||
"@executable_path/../../../${_newpath}"
|
||||
"${_carlalib}"
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
file(REMOVE "${APP}/Contents/Frameworks/lib${_lib}.dylib")
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
# Call ad-hoc codesign manually (CMake offers this as well)
|
||||
execute_process(COMMAND codesign --force --deep --sign - "${APP}"
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
# Create DMG
|
||||
# appdmg won't allow volume names > 27 char https://github.com/LinusU/node-alias/issues/7
|
||||
find_program(APPDMG_BIN appdmg REQUIRED)
|
||||
string(SUBSTRING "${CPACK_PROJECT_NAME_UCASE} ${CPACK_PROJECT_VERSION}" 0 27 APPDMG_VOLUME_NAME)
|
||||
# We'll configure this file twice (again in MacDeployQt.cmake once we know CPACK_TEMPORARY_INSTALL_DIRECTORY)
|
||||
configure_file("${CPACK_CURRENT_SOURCE_DIR}/appdmg.json.in" "${CPACK_CURRENT_BINARY_DIR}/appdmg.json" @ONLY)
|
||||
|
||||
execute_process(COMMAND "${APPDMG_BIN}"
|
||||
"${CPACK_CURRENT_BINARY_DIR}/appdmg.json"
|
||||
"${CPACK_BINARY_DIR}/${CPACK_PACKAGE_FILE_NAME}.dmg"
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
9
cmake/apple/appdmg.json.in
Normal file
9
cmake/apple/appdmg.json.in
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"title": "@APPDMG_VOLUME_NAME@",
|
||||
"background": "@CPACK_SOURCE_DIR@/cmake/apple/background.png",
|
||||
"icon-size": 128,
|
||||
"contents": [
|
||||
{ "x": 139, "y": 200, "type": "file", "path": "@CPACK_TEMPORARY_INSTALL_DIRECTORY@/@CPACK_PROJECT_NAME_UCASE@.app" },
|
||||
{ "x": 568, "y": 200, "type": "link", "path": "/Applications" }
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
BIN
cmake/apple/background@2x.png
Normal file
BIN
cmake/apple/background@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 114 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 113 KiB |
@@ -1,104 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Creates Apple ".app" bundle for @PROJECT_NAME_UCASE@
|
||||
# Note:
|
||||
# Examine linkings using `otool -L somelib.so`
|
||||
# Debug the loading of dynamic libraries using `export DYLD_PRINT_LIBRARIES=1`
|
||||
|
||||
set -e
|
||||
|
||||
# Place to create ".app" bundle
|
||||
APP="@CMAKE_BINARY_DIR@/@PROJECT_NAME_UCASE@.app"
|
||||
|
||||
MSG_COLOR='\x1B[1;36m'
|
||||
COLOR_RESET='\x1B[0m'
|
||||
echo -e "$MSG_COLOR\n\nCreating App Bundle \"$APP\"...$COLOR_RESET"
|
||||
|
||||
qtpath="$(dirname "@QT_QMAKE_EXECUTABLE@")"
|
||||
export PATH="$PATH:$qtpath"
|
||||
|
||||
# Remove any old .app bundles
|
||||
rm -Rf "$APP"
|
||||
|
||||
# Copy/overwrite Info.plist
|
||||
command cp "@CMAKE_BINARY_DIR@/Info.plist" "@CMAKE_INSTALL_PREFIX@/"
|
||||
|
||||
# Create .app bundle containing contents from CMAKE_INSTALL_PREFIX
|
||||
mkdir -p "$APP/Contents/MacOS"
|
||||
mkdir -p "$APP/Contents/Frameworks"
|
||||
mkdir -p "$APP/Contents/Resources"
|
||||
cd "@CMAKE_INSTALL_PREFIX@"
|
||||
cp -R ./* "$APP/Contents"
|
||||
cp "@CMAKE_SOURCE_DIR@/cmake/apple/"*.icns "$APP/Contents/Resources/"
|
||||
|
||||
# Make all libraries writable for macdeployqt
|
||||
cd "$APP"
|
||||
find . -type f -print0 | xargs -0 chmod u+w
|
||||
|
||||
lmmsbin="MacOS/@CMAKE_PROJECT_NAME@"
|
||||
zynbin="MacOS/RemoteZynAddSubFx"
|
||||
|
||||
# Move lmms binary
|
||||
mv "$APP/Contents/bin/@CMAKE_PROJECT_NAME@" "$APP/Contents/$lmmsbin"
|
||||
|
||||
# Fix zyn linking
|
||||
mv "$APP/Contents/lib/lmms/RemoteZynAddSubFx" "$APP/Contents/$zynbin"
|
||||
|
||||
# Replace @rpath with @loader_path for Carla
|
||||
# See also plugins/CarlaBase/CMakeLists.txt
|
||||
# This MUST be done BEFORE calling macdeployqt
|
||||
install_name_tool -change @rpath/libcarlabase.dylib \
|
||||
@loader_path/libcarlabase.dylib \
|
||||
"$APP/Contents/lib/lmms/libcarlapatchbay.so"
|
||||
|
||||
install_name_tool -change @rpath/libcarlabase.dylib \
|
||||
@loader_path/libcarlabase.dylib \
|
||||
"$APP/Contents/lib/lmms/libcarlarack.so"
|
||||
|
||||
# Link lmms binary
|
||||
_executables="${_executables} -executable=$APP/Contents/$zynbin"
|
||||
|
||||
# Build a list of shared objects in target/lib/lmms
|
||||
for file in "$APP/Contents/lib/lmms/"*.so; do
|
||||
_thisfile="$APP/Contents/lib/lmms/${file##*/}"
|
||||
_executables="${_executables} -executable=$_thisfile"
|
||||
done
|
||||
|
||||
# Build a list of shared objects in target/lib/lmms/ladspa
|
||||
for file in "$APP/Contents/lib/lmms/ladspa/"*.so; do
|
||||
_thisfile="$APP/Contents/lib/lmms/ladspa/${file##*/}"
|
||||
_executables="${_executables} -executable=$_thisfile"
|
||||
done
|
||||
|
||||
# Finalize .app
|
||||
# shellcheck disable=SC2086
|
||||
macdeployqt "$APP" $_executables
|
||||
|
||||
# Carla is a standalone plugin. Remove library, look for it side-by-side LMMS.app
|
||||
# This MUST be done AFTER calling macdeployqt
|
||||
#
|
||||
# For example:
|
||||
# /Applications/LMMS.app
|
||||
# /Applications/Carla.app
|
||||
carlalibs=$(echo "@CARLA_LIBRARIES@"|tr ";" "\n")
|
||||
|
||||
# Loop over all libcarlas, fix linking
|
||||
for file in "$APP/Contents/lib/lmms/"libcarla*; do
|
||||
_thisfile="$APP/Contents/lib/lmms/${file##*/}"
|
||||
for lib in $carlalibs; do
|
||||
_oldpath="../../Frameworks/lib${lib}.dylib"
|
||||
_newpath="Carla.app/Contents/MacOS/lib${lib}.dylib"
|
||||
# shellcheck disable=SC2086
|
||||
install_name_tool -change @loader_path/$_oldpath \
|
||||
@executable_path/../../../$_newpath \
|
||||
"$_thisfile"
|
||||
rm -f "$APP/Contents/Frameworks/lib${lib}.dylib"
|
||||
done
|
||||
done
|
||||
|
||||
# Cleanup
|
||||
rm -rf "$APP/Contents/bin"
|
||||
|
||||
# Codesign
|
||||
codesign --force --deep --sign - "$APP"
|
||||
|
||||
echo -e "\nFinished.\n\n"
|
||||
@@ -7,13 +7,13 @@
|
||||
<string>English</string>
|
||||
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>@MACOSX_BUNDLE_ICON_FILE@</string>
|
||||
<string>@CPACK_PROJECT_NAME@</string>
|
||||
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>@MACOSX_BUNDLE_GUI_IDENTIFIER@ @MACOSX_BUNDLE_LONG_VERSION_STRING@</string>
|
||||
<string>@CPACK_PROJECT_NAME_UCASE@ @CPACK_PROJECT_VERSION@</string>
|
||||
|
||||
<!--
|
||||
#############################################################
|
||||
@@ -29,38 +29,38 @@
|
||||
#############################################################
|
||||
-->
|
||||
<key>CFBundleSignature</key>
|
||||
<string>@MACOSX_BUNDLE_GUI_IDENTIFIER@</string>
|
||||
<string>@CPACK_PROJECT_NAME_UCASE@</string>
|
||||
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>@MACOSX_BUNDLE_GUI_IDENTIFIER@</string>
|
||||
<string>@CPACK_PROJECT_NAME@</string>
|
||||
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@MACOSX_BUNDLE_LONG_VERSION_STRING@</string>
|
||||
<string>@CPACK_PROJECT_VERSION@</string>
|
||||
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@MACOSX_BUNDLE_LONG_VERSION_STRING@</string>
|
||||
<string>@VERSIONCPACK_PROJECT_VERSION@</string>
|
||||
|
||||
<key>CFBundleName</key>
|
||||
<string>@MACOSX_BUNDLE_BUNDLE_NAME@</string>
|
||||
<string>@CPACK_PROJECT_NAME_UCASE@</string>
|
||||
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>@MACOSX_BUNDLE_MIMETYPE_ID@</string>
|
||||
<string>@MACOS_MIMETYPE_ID@</string>
|
||||
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
|
||||
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>mmpz</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>@MACOSX_BUNDLE_MIMETYPE_ICON@</string>
|
||||
<string>project</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>@MACOSX_BUNDLE_GUI_IDENTIFIER@ Project</string>
|
||||
<string>@CPACK_PROJECT_NAME_UCASE@ Project</string>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>mmpz</string>
|
||||
@@ -69,19 +69,19 @@
|
||||
<string>Editor</string>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>@MACOSX_BUNDLE_MIMETYPE@</string>
|
||||
<string>application/x-@CPACK_PROJECT_NAME@-project</string>
|
||||
</array>
|
||||
</dict>
|
||||
|
||||
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>mmp</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>@MACOSX_BUNDLE_MIMETYPE_ICON@</string>
|
||||
<string>project</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>@MACOSX_BUNDLE_GUI_IDENTIFIER@ Project (uncompressed)</string>
|
||||
<string>@CPACK_PROJECT_NAME_UCASE@ Project (uncompressed)</string>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>mmp</string>
|
||||
@@ -90,23 +90,23 @@
|
||||
<string>Editor</string>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>@MACOSX_BUNDLE_MIMETYPE@</string>
|
||||
<string>application/x-@CPACK_PROJECT_NAME@-project</string>
|
||||
</array>
|
||||
</dict>
|
||||
|
||||
|
||||
</array>
|
||||
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>@MACOSX_BUNDLE_MIMETYPE_ID@.mmpz</string>
|
||||
<string>@MACOS_MIMETYPE_ID@.mmpz</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>@MACOSX_BUNDLE_PROJECT_URL@</string>
|
||||
<string>@CPACK_PROJECT_URL@</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>@MACOSX_BUNDLE_GUI_IDENTIFIER@ Project</string>
|
||||
<string>@CPACK_PROJECT_VERSIONPROJECT_NAME_UCASE@ Project</string>
|
||||
<key>UTTypeIconFile</key>
|
||||
<string>@MACOSX_BUNDLE_MIMETYPE_ICON@</string>
|
||||
<string>project</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
@@ -122,13 +122,13 @@
|
||||
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>@MACOSX_BUNDLE_MIMETYPE_ID@.mmp</string>
|
||||
<string>@MACOS_MIMETYPE_ID@.mmp</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>@MACOSX_BUNDLE_PROJECT_URL@</string>
|
||||
<string>@CPACK_PROJECT_URL@</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>@MACOSX_BUNDLE_GUI_IDENTIFIER@ Project (uncompressed)</string>
|
||||
<string>@CPACK_PROJECT_NAME_UCASE@ Project (uncompressed)</string>
|
||||
<key>UTTypeIconFile</key>
|
||||
<string>@MACOSX_BUNDLE_MIMETYPE_ICON@</string>
|
||||
<string>project</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.xml</string>
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"title": "@MACOSX_BUNDLE_DMG_TITLE@",
|
||||
"background": "@CMAKE_SOURCE_DIR@/cmake/apple/dmg_branding.png",
|
||||
"icon-size": 128,
|
||||
"contents": [
|
||||
{ "x": 139, "y": 200, "type": "file", "path": "@CMAKE_BINARY_DIR@/@MACOSX_BUNDLE_BUNDLE_NAME@.app" },
|
||||
{ "x": 568, "y": 200, "type": "link", "path": "/Applications" }
|
||||
]
|
||||
}
|
||||
@@ -43,17 +43,10 @@ ENDIF()
|
||||
if(LMMS_HAVE_STK AND (LMMS_BUILD_WIN32 OR LMMS_BUILD_APPLE))
|
||||
if(STK_RAWWAVE_ROOT)
|
||||
file(GLOB RAWWAVES "${STK_RAWWAVE_ROOT}/*.raw")
|
||||
list(SORT RAWWAVES)
|
||||
install(FILES ${RAWWAVES} DESTINATION "${DATA_DIR}/stk/rawwaves")
|
||||
else()
|
||||
message(WARNING "Can't find STK rawwave root!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
IF(LMMS_BUILD_APPLE)
|
||||
INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x ${CMAKE_BINARY_DIR}/install_apple.sh)")
|
||||
INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_BINARY_DIR}/install_apple.sh RESULT_VARIABLE EXIT_CODE)
|
||||
IF(NOT EXIT_CODE EQUAL 0)
|
||||
MESSAGE(FATAL_ERROR \"Execution of install_apple.sh failed\")
|
||||
ENDIF()
|
||||
")
|
||||
ENDIF()
|
||||
|
||||
@@ -1,19 +1,53 @@
|
||||
INSTALL(DIRECTORY icons/ DESTINATION "${DATA_DIR}/icons/hicolor")
|
||||
INSTALL(FILES lmms.desktop DESTINATION "${DATA_DIR}/applications")
|
||||
INSTALL(FILES lmms.xml DESTINATION "${DATA_DIR}/mime/packages")
|
||||
install(DIRECTORY icons/ DESTINATION "${DATA_DIR}/icons/hicolor")
|
||||
install(FILES lmms.desktop DESTINATION "${DATA_DIR}/applications")
|
||||
install(FILES lmms.xml DESTINATION "${DATA_DIR}/mime/packages")
|
||||
|
||||
# AppImage creation target
|
||||
SET(APPIMAGE_FILE "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-${VERSION}-linux-${CMAKE_SYSTEM_PROCESSOR}.AppImage")
|
||||
# Preserve old CPack behavior
|
||||
if(WANT_CPACK_TARBALL)
|
||||
message(STATUS "Skipping AppImage creation")
|
||||
return()
|
||||
endif()
|
||||
|
||||
CONFIGURE_FILE("package_linux.sh.in" "${CMAKE_BINARY_DIR}/package_linux.sh" @ONLY)
|
||||
install(FILES launch_lmms.sh DESTINATION bin)
|
||||
|
||||
FILE(REMOVE "${APPIMAGE_FILE}")
|
||||
ADD_CUSTOM_TARGET(removeappimage
|
||||
COMMAND rm -f "${APPIMAGE_FILE}"
|
||||
COMMENT "Removing old AppImage")
|
||||
ADD_CUSTOM_TARGET(appimage
|
||||
COMMAND chmod +x "${CMAKE_BINARY_DIR}/package_linux.sh"
|
||||
COMMAND "${CMAKE_BINARY_DIR}/package_linux.sh"
|
||||
COMMENT "Generating AppImage"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
ADD_DEPENDENCIES(appimage removeappimage)
|
||||
# Standard CPack options
|
||||
set(CPACK_GENERATOR "External" PARENT_SCOPE)
|
||||
set(CPACK_EXTERNAL_ENABLE_STAGING true PARENT_SCOPE)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${VERSION}-linux-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}" PARENT_SCOPE)
|
||||
set(CPACK_PRE_BUILD_SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/LinuxDeploy.cmake" PARENT_SCOPE)
|
||||
|
||||
# Custom vars to expose to Cpack
|
||||
# must be prefixed with "CPACK_" per https://stackoverflow.com/a/46526757/3196753)
|
||||
set(CPACK_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" PARENT_SCOPE)
|
||||
set(CPACK_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PARENT_SCOPE)
|
||||
set(CPACK_BINARY_DIR "${CMAKE_BINARY_DIR}" PARENT_SCOPE)
|
||||
set(CPACK_SOURCE_DIR "${CMAKE_SOURCE_DIR}" PARENT_SCOPE)
|
||||
set(CPACK_QMAKE_EXECUTABLE "${QT_QMAKE_EXECUTABLE}" PARENT_SCOPE)
|
||||
set(CPACK_CARLA_LIBRARIES "${CARLA_LIBRARIES}" PARENT_SCOPE)
|
||||
set(CPACK_WINE_32_LIBRARY_DIRS "${WINE_32_LIBRARY_DIRS}" PARENT_SCOPE)
|
||||
set(CPACK_WINE_64_LIBRARY_DIRS "${WINE_64_LIBRARY_DIRS}" PARENT_SCOPE)
|
||||
set(CPACK_PROJECT_NAME "${PROJECT_NAME}" PARENT_SCOPE)
|
||||
set(CPACK_PROJECT_NAME_UCASE "${PROJECT_NAME_UCASE}" PARENT_SCOPE)
|
||||
set(CPACK_PROJECT_VERSION "${VERSION}" PARENT_SCOPE)
|
||||
set(CPACK_CMAKE_COMMAND "${CMAKE_COMMAND}" PARENT_SCOPE)
|
||||
set(CPACK_SUIL_MODULES "${Suil_MODULES}" PARENT_SCOPE)
|
||||
set(CPACK_SUIL_MODULES_PREFIX "${Suil_MODULES_PREFIX}" PARENT_SCOPE)
|
||||
set(CPACK_STK_RAWWAVE_ROOT "${STK_RAWWAVE_ROOT}" PARENT_SCOPE)
|
||||
|
||||
# TODO: Canidate for DetectMachine.cmake
|
||||
if(IS_X86_64)
|
||||
set(CPACK_TARGET_ARCH x86_64 PARENT_SCOPE)
|
||||
elseif(IS_X86)
|
||||
set(CPACK_TARGET_ARCH i386 PARENT_SCOPE)
|
||||
elseif(IS_ARM64)
|
||||
set(CPACK_TARGET_ARCH aarch64 PARENT_SCOPE)
|
||||
elseif(IS_ARM32)
|
||||
set(CPACK_TARGET_ARCH armhf PARENT_SCOPE)
|
||||
else()
|
||||
set(CPACK_TARGET_ARCH unknown PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS "3.19")
|
||||
message(WARNING "AppImage creation requires at least CMake 3.19")
|
||||
endif()
|
||||
295
cmake/linux/LinuxDeploy.cmake
Normal file
295
cmake/linux/LinuxDeploy.cmake
Normal file
@@ -0,0 +1,295 @@
|
||||
# Create a Linux desktop installer using linuxdeploy
|
||||
# * Creates a relocatable LMMS.AppDir installation in build/_CPack_Packages using linuxdeploy
|
||||
# * If CPACK_TOOL=appimagetool or is not set, bundles AppDir into redistributable ".AppImage" file
|
||||
# * If CPACK_TOOL=makeself is provided, bundles into a redistributable ".run" file
|
||||
#
|
||||
# Copyright (c) 2025, Tres Finocchiaro, <tres.finocchiaro@gmail.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
# Variables must be prefixed with "CPACK_" to be visible here
|
||||
set(lmms "${CPACK_PROJECT_NAME}")
|
||||
set(LMMS "${CPACK_PROJECT_NAME_UCASE}")
|
||||
set(ARCH "${CPACK_TARGET_ARCH}")
|
||||
set(APP "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/${LMMS}.AppDir")
|
||||
|
||||
# Target AppImage file
|
||||
set(APPIMAGE_FILE "${CPACK_BINARY_DIR}/${CPACK_PACKAGE_FILE_NAME}.AppImage")
|
||||
set(APPIMAGE_BEFORE_RENAME "${CPACK_BINARY_DIR}/${LMMS}-${ARCH}.AppImage")
|
||||
|
||||
set(DESKTOP_FILE "${APP}/usr/share/applications/${lmms}.desktop")
|
||||
|
||||
# Determine which packaging tool to use
|
||||
if(NOT CPACK_TOOL)
|
||||
# Pick up environmental variable
|
||||
if(DEFINED ENV{CPACK_TOOL})
|
||||
set(CPACK_TOOL "$ENV{CPACK_TOOL}")
|
||||
else()
|
||||
set(CPACK_TOOL "appimagetool")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Toggle command echoing & verbosity
|
||||
# 0 = no output, 1 = error/warning, 2 = normal, 3 = debug
|
||||
if(NOT CPACK_DEBUG)
|
||||
set(VERBOSITY 1)
|
||||
set(APPIMAGETOOL_VERBOSITY "")
|
||||
set(COMMAND_ECHO NONE)
|
||||
set(OUTPUT_QUIET OUTPUT_QUIET)
|
||||
else()
|
||||
set(VERBOSITY 2)
|
||||
set(APPIMAGETOOL_VERBOSITY "--verbose")
|
||||
set(COMMAND_ECHO STDOUT)
|
||||
unset(OUTPUT_QUIET)
|
||||
endif()
|
||||
|
||||
include(DownloadBinary)
|
||||
include(CreateSymlink)
|
||||
|
||||
# Cleanup CPack "External" json, txt files, old AppImage files
|
||||
file(GLOB cleanup "${CPACK_BINARY_DIR}/${lmms}-*.json"
|
||||
"${CPACK_BINARY_DIR}/${lmms}-*.AppImage"
|
||||
"${CPACK_BINARY_DIR}/install_manifest.txt")
|
||||
list(SORT cleanup)
|
||||
file(REMOVE ${cleanup})
|
||||
|
||||
# Download linuxdeploy, expose bundled appimagetool to PATH
|
||||
download_binary(LINUXDEPLOY_BIN
|
||||
"https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${ARCH}.AppImage"
|
||||
linuxdeploy-${ARCH}.AppImage
|
||||
FALSE)
|
||||
|
||||
# Symlink nested appimagetool
|
||||
set(_APPIMAGETOOL_LINK "${CPACK_CURRENT_BINARY_DIR}/appimagetool")
|
||||
if(NOT EXISTS "${_APPIMAGETOOL_LINK}")
|
||||
set(_APPIMAGETOOL "${CPACK_CURRENT_BINARY_DIR}/.linuxdeploy-${ARCH}.AppImage/squashfs-root/plugins/linuxdeploy-plugin-appimage/appimagetool-prefix/AppRun")
|
||||
message(STATUS "Creating a symbolic link ${_APPIMAGETOOL_LINK} which points to ${_APPIMAGETOOL}")
|
||||
create_symlink("${_APPIMAGETOOL}" "${_APPIMAGETOOL_LINK}")
|
||||
endif()
|
||||
|
||||
# Download linuxdeploy-plugin-qt
|
||||
download_binary(LINUXDEPLOY_PLUGIN_BIN
|
||||
"https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-${ARCH}.AppImage"
|
||||
linuxdeploy-plugin-qt-${ARCH}.AppImage
|
||||
FALSE)
|
||||
|
||||
message(STATUS "Creating AppDir ${APP}...")
|
||||
|
||||
file(REMOVE_RECURSE "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/include")
|
||||
file(MAKE_DIRECTORY "${APP}/usr")
|
||||
|
||||
# Setup AppDir structure (/usr/bin, /usr/lib, /usr/share... etc)
|
||||
file(GLOB files "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/*")
|
||||
list(SORT files)
|
||||
foreach(_file ${files})
|
||||
get_filename_component(_filename "${_file}" NAME)
|
||||
if(NOT _filename MATCHES ".AppDir")
|
||||
file(RENAME "${_file}" "${APP}/usr/${_filename}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Copy Suil modules
|
||||
if(CPACK_SUIL_MODULES)
|
||||
set(SUIL_MODULES_TARGET "${APP}/usr/lib/${CPACK_SUIL_MODULES_PREFIX}")
|
||||
file(MAKE_DIRECTORY "${SUIL_MODULES_TARGET}")
|
||||
file(COPY ${CPACK_SUIL_MODULES} DESTINATION "${SUIL_MODULES_TARGET}")
|
||||
endif()
|
||||
|
||||
# Copy stk/rawwaves
|
||||
if(CPACK_STK_RAWWAVE_ROOT)
|
||||
set(STK_RAWWAVE_TARGET "${APP}/usr/share/stk/rawwaves/")
|
||||
file(MAKE_DIRECTORY "${STK_RAWWAVE_TARGET}")
|
||||
file(GLOB RAWWAVES "${CPACK_STK_RAWWAVE_ROOT}/*.raw")
|
||||
file(COPY ${RAWWAVES} DESTINATION "${STK_RAWWAVE_TARGET}")
|
||||
endif()
|
||||
|
||||
# Ensure project's "qmake" executable is first on the PATH
|
||||
get_filename_component(QTBIN "${CPACK_QMAKE_EXECUTABLE}" DIRECTORY)
|
||||
set(ENV{PATH} "${QTBIN}:$ENV{PATH}")
|
||||
|
||||
# Ensure "linuxdeploy-<arch>.AppImage" and "appimagetool" binaries are first on the PATH
|
||||
set(ENV{PATH} "${CPACK_CURRENT_BINARY_DIR}:$ENV{PATH}")
|
||||
|
||||
# Promote finding our own libraries first
|
||||
set(ENV{LD_LIBRARY_PATH} "${APP}/usr/lib/${lmms}/:${APP}/usr/lib/${lmms}/optional:$ENV{LD_LIBRARY_PATH}")
|
||||
|
||||
# Skip slow searching of copyright files https://github.com/linuxdeploy/linuxdeploy/issues/278
|
||||
set(ENV{DISABLE_COPYRIGHT_FILES_DEPLOYMENT} 1)
|
||||
|
||||
# Patch desktop file
|
||||
file(APPEND "${DESKTOP_FILE}" "X-AppImage-Version=${CPACK_PROJECT_VERSION}\n")
|
||||
|
||||
# Prefer a hard-copy of .DirIcon over appimagetool's symlinking
|
||||
# 256x256 default for Cinnamon Desktop https://forums.linuxmint.com/viewtopic.php?p=2585952
|
||||
file(COPY "${APP}/usr/share/icons/hicolor/256x256/apps/${lmms}.png" DESTINATION "${APP}")
|
||||
file(RENAME "${APP}/${lmms}.png" "${APP}/.DirIcon")
|
||||
file(COPY "${APP}/usr/share/icons/hicolor/256x256/apps/${lmms}.png" DESTINATION "${APP}")
|
||||
|
||||
# Build list of libraries to inform linuxdeploy about
|
||||
# e.g. --library=foo.so --library=bar.so
|
||||
file(GLOB LIBS "${APP}/usr/lib/${lmms}/*.so")
|
||||
|
||||
# Inform linuxdeploy about LADSPA plugins; may depend on bundled fftw3f, etc.
|
||||
file(GLOB LADSPA "${APP}/usr/lib/${lmms}/ladspa/*.so")
|
||||
|
||||
# Inform linuxdeploy about remote plugins
|
||||
file(GLOB REMOTE_PLUGINS "${APP}/usr/lib/${lmms}/*Remote*")
|
||||
|
||||
# Collect, sort and dedupe all libraries
|
||||
list(APPEND LIBS ${LADSPA})
|
||||
list(APPEND LIBS ${REMOTE_PLUGINS})
|
||||
list(APPEND LIBS ${CPACK_SUIL_MODULES})
|
||||
list(REMOVE_DUPLICATES LIBS)
|
||||
list(SORT LIBS)
|
||||
|
||||
# Handle non-relinkable files (e.g. RemoveVstPlugin[32|64], but not NativeLinuxRemoteVstPlugin)
|
||||
list(FILTER LIBS EXCLUDE REGEX "\\/RemoteVst")
|
||||
|
||||
# Construct linuxdeploy parameters
|
||||
foreach(_lib IN LISTS LIBS)
|
||||
if(EXISTS "${_lib}")
|
||||
list(APPEND LIBRARIES "--library=${_lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Call linuxdeploy
|
||||
message(STATUS "Calling ${LINUXDEPLOY_BIN} --appdir \"${APP}\" ... [... libraries].")
|
||||
execute_process(COMMAND "${LINUXDEPLOY_BIN}"
|
||||
--appdir "${APP}"
|
||||
--desktop-file "${DESKTOP_FILE}"
|
||||
--custom-apprun "${CPACK_SOURCE_DIR}/cmake/linux/launch_lmms.sh"
|
||||
--plugin qt
|
||||
${LIBRARIES}
|
||||
--verbosity ${VERBOSITY}
|
||||
${OUTPUT_QUIET}
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
# Remove svg ambitiously placed by linuxdeploy
|
||||
file(REMOVE "${APP}/${lmms}.svg")
|
||||
|
||||
# Remove libraries that are normally sytem-provided
|
||||
file(GLOB EXCLUDE_LIBS
|
||||
"${APP}/usr/lib/libwine*"
|
||||
"${APP}/usr/lib/libcarla_native*"
|
||||
"${APP}/usr/lib/${lmms}/optional/libcarla*"
|
||||
"${APP}/usr/lib/libjack*")
|
||||
|
||||
list(SORT EXCLUDE_LIBS)
|
||||
foreach(_lib IN LISTS EXCLUDE_LIBS)
|
||||
if(EXISTS "${_lib}")
|
||||
file(REMOVE "${_lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# FIXME: Remove when linuxdeploy supports subfolders https://github.com/linuxdeploy/linuxdeploy/issues/305
|
||||
foreach(_lib IN LISTS LIBS)
|
||||
if(EXISTS "${_lib}")
|
||||
file(REMOVE "${_lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
# Move RemotePlugins into to LMMS_PLUGIN_DIR
|
||||
file(GLOB WINE_VST_LIBS
|
||||
"${APP}/usr/lib/${lmms}/RemoteVstPlugin*"
|
||||
"${APP}/usr/lib/${lmms}/32")
|
||||
foreach(_file IN LISTS WINE_VST_LIBS)
|
||||
if(EXISTS "${_file}")
|
||||
get_filename_component(_name "${_file}" NAME)
|
||||
file(RENAME "${_file}" "${APP}/usr/lib/${_name}")
|
||||
endif()
|
||||
endforeach()
|
||||
file(GLOB WINE_32_LIBS
|
||||
"${APP}/usr/lib/${lmms}/RemoteVstPlugin*")
|
||||
foreach(_lib IN LISTS WINE_64_LIBS)
|
||||
if(EXISTS "${_lib}")
|
||||
get_filename_component(_file "${_lib}" NAME)
|
||||
file(RENAME "${_lib}" "${APP}/usr/lib/${_file}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
file(REMOVE_RECURSE "${SUIL_MODULES_TARGET}" "${APP}/usr/lib/${lmms}/ladspa/")
|
||||
|
||||
# Bundle jack to avoid crash for systems without it
|
||||
# See https://github.com/LMMS/lmms/pull/4186
|
||||
execute_process(COMMAND ldd "${APP}/usr/bin/${lmms}"
|
||||
OUTPUT_VARIABLE LDD_OUTPUT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
string(REPLACE "\n" ";" LDD_LIST "${LDD_OUTPUT}")
|
||||
foreach(line ${LDD_LIST})
|
||||
if(line MATCHES "libjack\\.so")
|
||||
# Assume format "libjack.so.0 => /lib/x86_64-linux-gnu/libjack.so.0 (0x00007f48d0b0e000)"
|
||||
string(REPLACE " " ";" parts "${line}")
|
||||
list(LENGTH parts len)
|
||||
math(EXPR index "${len}-2")
|
||||
list(GET parts ${index} lib)
|
||||
# Get symlink target
|
||||
file(REAL_PATH "${lib}" libreal)
|
||||
get_filename_component(symname "${lib}" NAME)
|
||||
get_filename_component(realname "${libreal}" NAME)
|
||||
file(MAKE_DIRECTORY "${APP}/usr/lib/${lmms}/optional/")
|
||||
# Copy, but with original symlink name
|
||||
file(COPY "${libreal}" DESTINATION "${APP}/usr/lib/${lmms}/optional/")
|
||||
file(RENAME "${APP}/usr/lib/${lmms}/optional/${realname}" "${APP}/usr/lib/${lmms}/optional/${symname}")
|
||||
continue()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(CPACK_TOOL STREQUAL "appimagetool")
|
||||
# Create ".AppImage" file using appimagetool (default)
|
||||
|
||||
# appimage plugin needs ARCH set when running in extracted form from squashfs-root / CI
|
||||
set(ENV{ARCH} "${ARCH}")
|
||||
message(STATUS "Finishing the AppImage...")
|
||||
execute_process(COMMAND ${CPACK_TOOL} "${APP}" "${APPIMAGE_FILE}"
|
||||
${APPIMAGETOOL_VERBOSITY}
|
||||
${OUTPUT_QUIET}
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
message(STATUS "AppImage created: ${APPIMAGE_FILE}")
|
||||
elseif(CPACK_TOOL STREQUAL "makeself")
|
||||
# Create self-extracting ".run" script using makeself
|
||||
find_program(MAKESELF_BIN makeself REQUIRED)
|
||||
|
||||
message(STATUS "Finishing the .run file using ${MAKESELF_BIN}...")
|
||||
string(REPLACE ".AppImage" ".run" RUN_FILE "${APPIMAGE_FILE}")
|
||||
configure_file(
|
||||
"${CPACK_SOURCE_DIR}/cmake/linux/makeself_setup.sh.in" "${APP}/setup.sh" @ONLY
|
||||
FILE_PERMISSIONS
|
||||
OWNER_EXECUTE OWNER_WRITE OWNER_READ
|
||||
GROUP_EXECUTE GROUP_WRITE GROUP_READ
|
||||
WORLD_READ)
|
||||
|
||||
if(OUTPUT_QUIET)
|
||||
set(MAKESELF_QUIET "--quiet")
|
||||
set(ERROR_QUIET ERROR_QUIET)
|
||||
endif()
|
||||
|
||||
# makeself.sh [args] archive_dir file_name label startup_script [script_args]
|
||||
file(REMOVE "${RUN_FILE}")
|
||||
execute_process(COMMAND "${MAKESELF_BIN}"
|
||||
--keep-umask
|
||||
--nox11
|
||||
${MAKESELF_QUIET}
|
||||
"${APP}"
|
||||
"${RUN_FILE}"
|
||||
"${LMMS} Installer"
|
||||
"./setup.sh"
|
||||
${OUTPUT_QUIET}
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
# ensure the installer can be executed as a script file
|
||||
execute_process(COMMAND "${RUN_FILE}" --help
|
||||
${OUTPUT_QUIET}
|
||||
${ERROR_QUIET}
|
||||
COMMAND_ECHO ${COMMAND_ECHO}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
message(STATUS "Installer created: ${RUN_FILE}")
|
||||
else()
|
||||
message(FATAL_ERROR "Packaging tool CPACK_TOOL=\"${CPACK_TOOL}\" is not yet supported")
|
||||
endif()
|
||||
BIN
cmake/linux/icons/256x256/apps/lmms.png
Normal file
BIN
cmake/linux/icons/256x256/apps/lmms.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
@@ -21,4 +21,10 @@ else
|
||||
echo "Jack does not appear to be installed. That's OK, we'll use a dummy version instead." >&2
|
||||
export LD_LIBRARY_PATH=$DIR/usr/lib/lmms/optional:$LD_LIBRARY_PATH
|
||||
fi
|
||||
QT_X11_NO_NATIVE_MENUBAR=1 "$DIR"/usr/bin/lmms.real "$@"
|
||||
|
||||
# FIXME: Remove when linuxdeploy supports subfolders https://github.com/linuxdeploy/linuxdeploy/issues/305
|
||||
export LMMS_PLUGIN_DIR="$DIR/usr/lib/"
|
||||
export LADSPA_PATH="$DIR/usr/lib/"
|
||||
export SUIL_MODULE_DIR="$DIR/usr/lib/"
|
||||
|
||||
QT_X11_NO_NATIVE_MENUBAR=1 "$DIR"/usr/bin/lmms "$@"
|
||||
|
||||
35
cmake/linux/makeself_setup.sh.in
Normal file
35
cmake/linux/makeself_setup.sh.in
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Halt on first error
|
||||
set -e
|
||||
|
||||
DESTDIR="/opt/@CPACK_PROJECT_NAME@"
|
||||
BASHCOMPLETIONS="/usr/share/bash-completion/completions"
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
# Prepend "$HOME" so we can install to a writable location
|
||||
DESTDIR="${HOME}${DESTDIR}"
|
||||
BASHCOMPLETIONS="${HOME}/.local/share/bash-completion/completions"
|
||||
echo "Installing as a regular user to ${DESTDIR}/..."
|
||||
else
|
||||
echo "Installing as elevated user to ${DESTDIR}/..."
|
||||
fi
|
||||
|
||||
# Deploy @CPACK_PROJECT_NAME_UCASE@
|
||||
mkdir -p "${DESTDIR}"
|
||||
unalias cp &> /dev/null || true
|
||||
cp -rf ./* "${DESTDIR}"
|
||||
rm -f "${DESTDIR}/setup.sh"
|
||||
mv "${DESTDIR}/AppRun" "${DESTDIR}/@CPACK_PROJECT_NAME@"
|
||||
|
||||
# Install bash completions
|
||||
mkdir -p "${BASHCOMPLETIONS}"
|
||||
ln -sf "${DESTDIR}/usr/share/@CPACK_PROJECT_NAME@/bash-completion/completions/@CPACK_PROJECT_NAME@" "${BASHCOMPLETIONS}/@CPACK_PROJECT_NAME@"
|
||||
|
||||
# Test @CPACK_PROJECT_NAME_UCASE@
|
||||
echo "Installation complete... Testing \"@CPACK_PROJECT_NAME@\"..."
|
||||
"${DESTDIR}/@CPACK_PROJECT_NAME@" --allowroot --version &> /dev/null
|
||||
|
||||
# TODO: Register file associations, desktop icon, etc
|
||||
|
||||
echo "@CPACK_PROJECT_NAME_UCASE@ was installed successfully to ${DESTDIR}. To run:"
|
||||
echo " ${DESTDIR}/@CPACK_PROJECT_NAME@"
|
||||
@@ -1,213 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Creates Linux ".AppImage" for @PROJECT_NAME_UCASE@
|
||||
#
|
||||
# Depends: linuxdeployqt
|
||||
#
|
||||
# Notes: Will attempt to fetch linuxdeployqt automatically (x86_64 only)
|
||||
# See Also: https://github.com/probonopd/linuxdeployqt/blob/master/BUILDING.md
|
||||
|
||||
VERBOSITY=2 # 3=debug
|
||||
LOGFILE="@CMAKE_BINARY_DIR@/appimage.log"
|
||||
APPDIR="@CMAKE_BINARY_DIR@/@PROJECT_NAME_UCASE@.AppDir/"
|
||||
DESKTOPFILE="${APPDIR}usr/share/applications/lmms.desktop"
|
||||
STRIP=""
|
||||
|
||||
# Don't strip for Debug|RelWithDebInfo builds
|
||||
# shellcheck disable=SC2193
|
||||
if [[ "@CMAKE_BUILD_TYPE@" == *"Deb"* ]]; then
|
||||
STRIP="-no-strip"
|
||||
fi
|
||||
|
||||
# Console colors
|
||||
RED="\\x1B[1;31m"
|
||||
GREEN="\\x1B[1;32m"
|
||||
YELLOW="\\x1B[1;33m"
|
||||
PLAIN="\\x1B[0m"
|
||||
|
||||
function error {
|
||||
echo -e " ${PLAIN}[${RED}error${PLAIN}] ${1}"
|
||||
return 1
|
||||
}
|
||||
|
||||
function success {
|
||||
echo -e " ${PLAIN}[${GREEN}success${PLAIN}] ${1}"
|
||||
}
|
||||
|
||||
function skipped {
|
||||
echo -e " ${PLAIN}[${YELLOW}skipped${PLAIN}] ${1}"
|
||||
}
|
||||
|
||||
# Exit with error message if any command fails
|
||||
trap "error 'Failed to generate AppImage'; exit 1" ERR
|
||||
|
||||
# Run a command silently, but print output if it fails
|
||||
function run_and_log {
|
||||
echo -e "\n\n>>>>> $1" >> "$LOGFILE"
|
||||
output="$("$@" 2>&1)"
|
||||
status=$?
|
||||
echo "$output" >> "$LOGFILE"
|
||||
[[ $status != 0 ]] && echo "$output"
|
||||
return $status
|
||||
}
|
||||
|
||||
# Blindly assume system arch is appimage arch
|
||||
ARCH=$(uname -m)
|
||||
export ARCH
|
||||
|
||||
# Check for problematic install locations
|
||||
INSTALL=$(echo "@CMAKE_INSTALL_PREFIX@" | sed 's/\/*$//g')
|
||||
if [ "$INSTALL" == "/usr/local" ] || [ "$INSTALL" == "/usr" ] ; then
|
||||
error "Incompatible CMAKE_INSTALL_PREFIX for creating AppImage: @CMAKE_INSTALL_PREFIX@"
|
||||
fi
|
||||
|
||||
# Ensure linuxdeployqt uses the same qmake version as cmake
|
||||
PATH="$(dirname "@QT_QMAKE_EXECUTABLE@"):$PATH"
|
||||
export PATH
|
||||
|
||||
# Use linuxdeployqt from env or in PATH
|
||||
[[ $LINUXDEPLOYQT ]] || LINUXDEPLOYQT="$(which linuxdeployqt 2>/dev/null)" || true
|
||||
[[ $APPIMAGETOOL ]] || APPIMAGETOOL="$(which appimagetool 2>/dev/null)" || true
|
||||
|
||||
# Fetch portable linuxdeployqt if not in PATH
|
||||
if [[ -z $LINUXDEPLOYQT || -z $APPIMAGETOOL ]]; then
|
||||
filename="linuxdeployqt-continuous-$ARCH.AppImage"
|
||||
url="https://github.com/probonopd/linuxdeployqt/releases/download/continuous/$filename"
|
||||
echo " [.......] Downloading: ${url}"
|
||||
wget -N -q "$url" && err=0 || err=$?
|
||||
case "$err" in
|
||||
0) success "Downloaded $PWD/$filename" ;;
|
||||
# 8 == server issued 4xx error
|
||||
8) error "Download failed (perhaps no package available for $ARCH)" ;;
|
||||
*) error "Download failed" ;;
|
||||
esac
|
||||
|
||||
# Extract AppImage and replace LINUXDEPLOYQT variable with extracted binary
|
||||
# to support systems without fuse
|
||||
# Also, we need to set LD_LIBRARY_PATH, but linuxdepoyqt's AppRun unsets it
|
||||
# See https://github.com/probonopd/linuxdeployqt/pull/370/
|
||||
chmod +x "$filename"
|
||||
./"$filename" --appimage-extract >/dev/null
|
||||
success "Extracted $filename"
|
||||
|
||||
# Use the extracted linuxdeployqt and appimagetool
|
||||
PATH="$(pwd -P)/squashfs-root/usr/bin:$PATH"
|
||||
[[ $LINUXDEPLOYQT ]] || LINUXDEPLOYQT="$(which linuxdeployqt)"
|
||||
[[ $APPIMAGETOOL ]] || APPIMAGETOOL="$(which appimagetool)"
|
||||
fi
|
||||
|
||||
# Make skeleton AppDir
|
||||
echo -e "\nCreating ${APPDIR}..."
|
||||
rm -rf "${APPDIR}"
|
||||
mkdir -p "${APPDIR}usr"
|
||||
success "Created ${APPDIR}"
|
||||
|
||||
# Clone install to AppDir
|
||||
echo -e "\nCopying @CMAKE_INSTALL_PREFIX@ to ${APPDIR}..."
|
||||
cp -R "@CMAKE_INSTALL_PREFIX@/." "${APPDIR}usr"
|
||||
rm -rf "${APPDIR}usr/include"
|
||||
success "${APPDIR}"
|
||||
|
||||
# Copy rawwaves directory for stk/mallets
|
||||
mkdir -p "${APPDIR}usr/share/stk/"
|
||||
cp -R /usr/share/stk/rawwaves/ "${APPDIR}usr/share/stk/"
|
||||
|
||||
# Create a wrapper script which calls the lmms executable
|
||||
mv "${APPDIR}usr/bin/lmms" "${APPDIR}usr/bin/lmms.real"
|
||||
|
||||
cp "@CMAKE_CURRENT_SOURCE_DIR@/launch_lmms.sh" "${APPDIR}usr/bin/lmms"
|
||||
|
||||
chmod +x "${APPDIR}usr/bin/lmms"
|
||||
|
||||
# Per https://github.com/probonopd/linuxdeployqt/issues/129
|
||||
unset LD_LIBRARY_PATH
|
||||
|
||||
# Ensure linuxdeployqt can find shared objects
|
||||
export LD_LIBRARY_PATH="${APPDIR}"usr/lib/lmms/:"${APPDIR}"usr/lib/lmms/optional:"$LD_LIBRARY_PATH"
|
||||
|
||||
# Move executables so linuxdeployqt can find them
|
||||
ZYNLIB="${APPDIR}usr/lib/lmms/RemoteZynAddSubFx"
|
||||
VSTLIB32="${APPDIR}usr/lib/lmms/32/RemoteVstPlugin32.exe.so"
|
||||
VSTLIB64="${APPDIR}usr/lib/lmms/RemoteVstPlugin64.exe.so"
|
||||
|
||||
ZYNBIN="${APPDIR}usr/bin/RemoteZynAddSubFx"
|
||||
VSTBIN32="${APPDIR}usr/bin/RemoteVstPlugin32.exe.so"
|
||||
VSTBIN64="${APPDIR}usr/bin/RemoteVstPlugin64.exe.so"
|
||||
|
||||
mv "$ZYNLIB" "$ZYNBIN"
|
||||
mv "$VSTLIB32" "$VSTBIN32" || true
|
||||
mv "$VSTLIB64" "$VSTBIN64" || true
|
||||
|
||||
# Handle wine linking
|
||||
if [ -d "@WINE_32_LIBRARY_DIR@" ] && \
|
||||
ldd "$VSTBIN32" | grep "libwine\.so" | grep "not found"; then
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"@WINE_32_LIBRARY_DIRS@"
|
||||
fi
|
||||
if [ -d "@WINE_64_LIBRARY_DIR@" ] && \
|
||||
ldd "$VSTBIN64" | grep "libwine\.so" | grep "not found"; then
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"@WINE_64_LIBRARY_DIRS@"
|
||||
fi
|
||||
|
||||
# Patch the desktop file
|
||||
sed -i 's/.*Exec=.*/Exec=lmms.real/' "$DESKTOPFILE"
|
||||
echo "X-AppImage-Version=@VERSION@" >> "$DESKTOPFILE"
|
||||
|
||||
# Fix linking for soft-linked plugins
|
||||
for file in "${APPDIR}usr/lib/lmms/"*.so; do
|
||||
thisfile="${APPDIR}usr/lib/lmms/${file##*/}"
|
||||
executables="${executables} -executable=$thisfile"
|
||||
done
|
||||
executables="${executables} -executable=${ZYNBIN}"
|
||||
executables="${executables} -executable=${VSTBIN32}"
|
||||
executables="${executables} -executable=${VSTBIN64}"
|
||||
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/imp_1199.so"
|
||||
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/imbeq_1197.so"
|
||||
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale_1193.so"
|
||||
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale_1194.so"
|
||||
|
||||
echo -e "\nWriting verbose output to \"${LOGFILE}\""
|
||||
echo -n > "$LOGFILE"
|
||||
|
||||
# Bundle both qt and non-qt dependencies into appimage format
|
||||
echo -e "\nBundling and relinking system dependencies..."
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
run_and_log "$LINUXDEPLOYQT" "$DESKTOPFILE" $executables -bundle-non-qt-libs -verbose=$VERBOSITY $STRIP
|
||||
success "Bundled and relinked dependencies"
|
||||
|
||||
# Link to original location so lmms can find them
|
||||
ln -sr "$ZYNBIN" "$ZYNLIB"
|
||||
ln -sr "$VSTBIN32" "$VSTLIB32" || true
|
||||
ln -sr "$VSTBIN64" "$VSTLIB64" || true
|
||||
|
||||
# Remove wine library conflict
|
||||
rm -f "${APPDIR}/usr/lib/libwine.so.1"
|
||||
|
||||
# Use system-provided carla
|
||||
rm -f "${APPDIR}usr/lib/"libcarla*.so
|
||||
rm -f "${APPDIR}usr/lib/lmms/optional/"libcarla*.so
|
||||
|
||||
# Remove bundled jack in LD_LIBRARY_PATH if exists
|
||||
if [ -e "${APPDIR}/usr/lib/libjack.so.0" ]; then
|
||||
rm "${APPDIR}/usr/lib/libjack.so.0"
|
||||
fi
|
||||
|
||||
# Bundle jack out of LD_LIBRARY_PATH
|
||||
JACK_LIB=$(ldd "${APPDIR}/usr/bin/lmms.real" | sed -n 's/\tlibjack\.so\.0 => \(.\+\) (0x[0-9a-f]\+)/\1/p')
|
||||
if [ -e "$JACK_LIB" ]; then
|
||||
mkdir -p "${APPDIR}usr/lib/lmms/optional/"
|
||||
cp "$JACK_LIB" "${APPDIR}usr/lib/lmms/optional/"
|
||||
fi
|
||||
|
||||
# Point the AppRun to the shim launcher
|
||||
rm -f "${APPDIR}/AppRun"
|
||||
ln -sr "${APPDIR}/usr/bin/lmms" "${APPDIR}/AppRun"
|
||||
|
||||
# Add icon
|
||||
ln -srf "${APPDIR}/lmms.png" "${APPDIR}/.DirIcon"
|
||||
|
||||
# Create AppImage
|
||||
echo -e "\nFinishing the AppImage..."
|
||||
run_and_log "$APPIMAGETOOL" "${APPDIR}" "@APPIMAGE_FILE@"
|
||||
success "Created @APPIMAGE_FILE@"
|
||||
|
||||
echo -e "\nFinished"
|
||||
@@ -1,93 +1,78 @@
|
||||
# A wrapper around pkg-config-provided and cmake-provided bash completion that
|
||||
# will have dynamic behavior at INSTALL() time to allow both root-level
|
||||
# INSTALL() as well as user-level INSTALL().
|
||||
#
|
||||
# See also https://github.com/scop/bash-completion
|
||||
#
|
||||
# Copyright (c) 2018, Tres Finocchiaro, <tres.finocchiaro@gmail.com>
|
||||
# Copyright (c) 2024, Tres Finocchiaro, <tres.finocchiaro@gmail.com>
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
# Description:
|
||||
# Fail-safe bash-completion installation support
|
||||
# - Installs to ${CMAKE_INSTALL_PREFIX}/share/bash-completion/completions
|
||||
# - Attempts to calculate and install to system-wide location
|
||||
# - See also https://github.com/scop/bash-completion
|
||||
#
|
||||
# Usage:
|
||||
# INCLUDE(BashCompletion)
|
||||
# BASHCOMP_INSTALL(foo)
|
||||
# ... where "foo" is a shell script adjacent to the CMakeLists.txt
|
||||
#
|
||||
# How it determines BASHCOMP_PKG_PATH, in order:
|
||||
# 1. Uses BASHCOMP_PKG_PATH if already set (e.g. -DBASHCOMP_PKG_PATH=...)
|
||||
# a. If not, uses pkg-config's PKG_CHECK_MODULES to determine path
|
||||
# b. Fallback to cmake's FIND_PACKAGE(bash-completion) path
|
||||
# c. Fallback to hard-coded /usr/share/bash-completion/completions
|
||||
# 2. Final fallback to ${CMAKE_INSTALL_PREFIX}/share/bash-completion/completions if
|
||||
# detected path is unwritable.
|
||||
|
||||
# - Windows does not support bash completion
|
||||
# - macOS support should eventually be added for Homebrew (TODO)
|
||||
IF(WIN32)
|
||||
MESSAGE(STATUS "Bash completion is not supported on this platform.")
|
||||
ELSEIF(APPLE)
|
||||
MESSAGE(STATUS "Bash completion is not yet implemented for this platform.")
|
||||
ELSE()
|
||||
INCLUDE(FindUnixCommands)
|
||||
# Honor manual override if provided
|
||||
IF(NOT BASHCOMP_PKG_PATH)
|
||||
# First, use pkg-config, which is the most reliable
|
||||
FIND_PACKAGE(PkgConfig QUIET)
|
||||
IF(PKGCONFIG_FOUND)
|
||||
PKG_CHECK_MODULES(BASH_COMPLETION bash-completion)
|
||||
PKG_GET_VARIABLE(BASHCOMP_PKG_PATH bash-completion completionsdir)
|
||||
ELSE()
|
||||
# Second, use cmake (preferred but less common)
|
||||
FIND_PACKAGE(bash-completion QUIET)
|
||||
IF(BASH_COMPLETION_FOUND)
|
||||
SET(BASHCOMP_PKG_PATH "${BASH_COMPLETION_COMPLETIONSDIR}")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
# Honor manual override if provided
|
||||
if(NOT BASHCOMP_PKG_PATH)
|
||||
# First, use pkg-config, which is the most reliable
|
||||
find_package(PkgConfig QUIET)
|
||||
if(PKGCONFIG_FOUND)
|
||||
PKG_CHECK_MODULES(BASH_COMPLETION bash-completion)
|
||||
PKG_GET_VARIABLE(BASHCOMP_PKG_PATH bash-completion completionsdir)
|
||||
else()
|
||||
# Second, use cmake (preferred but less common)
|
||||
find_package(bash-completion QUIET)
|
||||
if(BASH_COMPLETION_FOUND)
|
||||
set(BASHCOMP_PKG_PATH "${BASH_COMPLETION_COMPLETIONSDIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Third, use a hard-coded fallback value
|
||||
IF("${BASHCOMP_PKG_PATH}" STREQUAL "")
|
||||
SET(BASHCOMP_PKG_PATH "/usr/share/bash-completion/completions")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
# Third, use a hard-coded fallback value
|
||||
if("${BASHCOMP_PKG_PATH}" STREQUAL "")
|
||||
set(BASHCOMP_PKG_PATH "/usr/share/bash-completion/completions")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Always provide a fallback for non-root INSTALL()
|
||||
SET(BASHCOMP_USER_PATH "${CMAKE_INSTALL_PREFIX}/share/bash-completion/completions")
|
||||
# Always provide a fallback for non-root INSTALL()
|
||||
# * "lmms" subfolder ensures we don't pollute /usr/local/share/ on default "make install"
|
||||
set(BASHCOMP_USER_PATH "share/${PROJECT_NAME}/bash-completion/completions")
|
||||
|
||||
# Cmake doesn't allow easy use of conditional logic at INSTALL() time
|
||||
# this is a problem because ${BASHCOMP_PKG_PATH} may not be writable and we
|
||||
# need sane fallback behavior for bundled INSTALL() (e.g. .AppImage, etc).
|
||||
#
|
||||
# The reason this can't be detected by cmake is that it's fairly common to
|
||||
# run "cmake" as a one user (i.e. non-root) and "make install" as another user
|
||||
# (i.e. root).
|
||||
#
|
||||
# - Creates a script called "install_${SCRIPT_NAME}_completion.sh" into the
|
||||
# working binary directory and invokes this script at install.
|
||||
# - Script handles INSTALL()-time conditional logic for sane ballback behavior
|
||||
# when ${BASHCOMP_PKG_PATH} is unwritable (i.e. non-root); Something cmake
|
||||
# can't handle on its own at INSTALL() time)
|
||||
MACRO(BASHCOMP_INSTALL SCRIPT_NAME)
|
||||
# A shell script for wrapping conditionl logic
|
||||
SET(BASHCOMP_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install_${SCRIPT_NAME}_completion.sh")
|
||||
macro(BASHCOMP_INSTALL SCRIPT_NAME)
|
||||
# Note: When running from CPack, message(...) will be supressed unless WARNING
|
||||
if(WIN32)
|
||||
message(STATUS "Bash completion is not supported on this platform.")
|
||||
else()
|
||||
# Install a copy of bash completion to the default install prefix
|
||||
# See also: https://github.com/LMMS/lmms/pull/7252/files#r1815749125
|
||||
install(FILES "${SCRIPT_NAME}" DESTINATION "${BASHCOMP_USER_PATH}")
|
||||
|
||||
# Next, blindly attempt a system-wide install, ignoring failure
|
||||
# See also: https://stackoverflow.com/q/58448332
|
||||
# * CPack doesn't use CMAKE_INSTALL_PREFIX, so the original will be missing when packaging
|
||||
# and this step will be skipped
|
||||
# * For non-root installs (e.g. ../target), this will silently fail
|
||||
set(BASHCOMP_ORIG "${CMAKE_INSTALL_PREFIX}/${BASHCOMP_USER_PATH}/${CMAKE_PROJECT_NAME}")
|
||||
set(BASHCOMP_LINK "${BASHCOMP_PKG_PATH}/${CMAKE_PROJECT_NAME}")
|
||||
|
||||
if(BASHCOMP_PKG_PATH)
|
||||
# TODO: CMake 3.21 Use "file(COPY_FILE ...)"
|
||||
install(CODE "
|
||||
if(EXISTS \"${BASHCOMP_ORIG}\")
|
||||
file(REMOVE \"${BASHCOMP_LINK}\")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
\"${BASHCOMP_ORIG}\"
|
||||
\"${BASHCOMP_LINK}\"
|
||||
ERROR_QUIET
|
||||
RESULT_VARIABLE result)
|
||||
if(result EQUAL 0)
|
||||
message(STATUS \"Bash completion-support has been installed to ${BASHCOMP_LINK}\")
|
||||
endif()
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
FILE(WRITE ${BASHCOMP_SCRIPT} "\
|
||||
#!${BASH}\n\
|
||||
set -e\n\
|
||||
if [ -w \"${BASHCOMP_PKG_PATH}\" ]; then\n\
|
||||
BASHCOMP_PKG_PATH=\"${BASHCOMP_PKG_PATH}\"\n\
|
||||
else \n\
|
||||
BASHCOMP_PKG_PATH=\"\$DESTDIR${BASHCOMP_USER_PATH}\"\n\
|
||||
fi\n\
|
||||
echo -e \"\\nInstalling bash completion...\\n\"\n\
|
||||
mkdir -p \"\$BASHCOMP_PKG_PATH\"\n\
|
||||
cp \"${CMAKE_CURRENT_SOURCE_DIR}/${SCRIPT_NAME}\" \"\$BASHCOMP_PKG_PATH\"\n\
|
||||
chmod a+r \"\$BASHCOMP_PKG_PATH/${SCRIPT_NAME}\"\n\
|
||||
echo -e \"Bash completion for ${SCRIPT_NAME} has been installed to \$BASHCOMP_PKG_PATH/${SCRIPT_NAME}\"\n\
|
||||
")
|
||||
INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x \"install_${SCRIPT_NAME}_completion.sh\" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )")
|
||||
INSTALL(CODE "EXECUTE_PROCESS(COMMAND \"./install_${SCRIPT_NAME}_completion.sh\" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} )")
|
||||
|
||||
MESSAGE(STATUS "Bash completion script for ${SCRIPT_NAME} will be installed to ${BASHCOMP_PKG_PATH} or fallback to ${BASHCOMP_USER_PATH} if unwritable.")
|
||||
ENDMACRO()
|
||||
ENDIF()
|
||||
|
||||
|
||||
34
cmake/modules/CreateSymlink.cmake
Normal file
34
cmake/modules/CreateSymlink.cmake
Normal file
@@ -0,0 +1,34 @@
|
||||
# Offer relative symlink support via "cmake -E create_symlink"
|
||||
# For verbose, set COMMAND_ECHO to STDOUT in calling script
|
||||
macro(create_symlink filepath sympath)
|
||||
if(CMAKE_COMMAND)
|
||||
set(_cmake_command "${CMAKE_COMMAND}")
|
||||
elseif(CPACK_CMAKE_COMMAND)
|
||||
set(_cmake_command "${CPACK_CMAKE_COMMAND}")
|
||||
else()
|
||||
message(FATAL_ERROR "Sorry, can't resolve variable CMAKE_COMMAND")
|
||||
endif()
|
||||
|
||||
if(NOT IS_ABSOLUTE "${sympath}")
|
||||
message(FATAL_ERROR "Sorry, this command only works with absolute paths")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED COMMAND_ECHO)
|
||||
set(_command_echo NONE)
|
||||
else()
|
||||
set(_command_echo "${COMMAND_ECHO}")
|
||||
endif()
|
||||
|
||||
# Calculate the relative path
|
||||
file(RELATIVE_PATH reldir "${sympath}/../" "${filepath}")
|
||||
get_filename_component(symname "${sympath}" NAME)
|
||||
|
||||
# Calculate the working directory
|
||||
get_filename_component(sympath_parent "${sympath}" DIRECTORY)
|
||||
|
||||
# Create the symbolic link
|
||||
execute_process(COMMAND "${_cmake_command}" -E create_symlink "${reldir}" "${symname}"
|
||||
WORKING_DIRECTORY "${sympath_parent}"
|
||||
COMMAND_ECHO ${_command_echo}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
endmacro()
|
||||
143
cmake/modules/DownloadBinary.cmake
Normal file
143
cmake/modules/DownloadBinary.cmake
Normal file
@@ -0,0 +1,143 @@
|
||||
# Downloads an executable from the provided URL for use in a build system
|
||||
# and optionally prepends it to the PATH
|
||||
#
|
||||
# Assumes:
|
||||
# - CMAKE_CURRENT_BINARY_DIR/[${_name}]
|
||||
# - CPACK_CURRENT_BINARY_DIR/[${_name}]
|
||||
# - Fallback to $ENV{TMPDIR}/[RANDOM]/[${_name}]
|
||||
# - For verbose, set COMMAND_ECHO to STDOUT in calling script
|
||||
#
|
||||
macro(download_binary RESULT_VARIABLE _url _name _prepend_to_path)
|
||||
if(NOT COMMAND_ECHO OR "${COMMAND_ECHO}" STREQUAL "NONE")
|
||||
set(_command_echo NONE)
|
||||
set(_output_quiet OUTPUT_QUIET)
|
||||
set(_error_quiet ERROR_QUIET)
|
||||
else()
|
||||
set(_command_echo "${COMMAND_ECHO}")
|
||||
set(_output_quiet "")
|
||||
set(_error_quiet "")
|
||||
endif()
|
||||
|
||||
# Check if fuse is needed
|
||||
if("${RESULT_VARIABLE}" MATCHES "\\.AppImage$" OR "${_name}" MATCHES "\\.AppImage$")
|
||||
message(STATUS "AppImage detected, we'll extract the AppImage before using")
|
||||
set(_${RESULT_VARIABLE}_IS_APPIMAGE TRUE)
|
||||
endif()
|
||||
|
||||
# Determine a suitable working directory
|
||||
if(CMAKE_CURRENT_BINARY_DIR)
|
||||
# Assume we're called from configure step
|
||||
set(_working_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
elseif(CPACK_CURRENT_BINARY_DIR)
|
||||
# Assume cpack (non-standard variable name, but used throughout)
|
||||
set(_working_dir "${CPACK_CURRENT_BINARY_DIR}")
|
||||
else()
|
||||
# Fallback to somewhere temporary, writable
|
||||
if($ENV{_tmpdir})
|
||||
# POSIX
|
||||
set(_tmpdir "$ENV{_tmpdir}")
|
||||
elseif($ENV{TEMP})
|
||||
# Windows
|
||||
set(_tmpdir "$ENV{TEMP}")
|
||||
else()
|
||||
# Linux, shame on you!
|
||||
find_program(MKTEMP mktemp)
|
||||
if(MKTEMP)
|
||||
execute_process(COMMAND mktemp
|
||||
OUTPUT_VARIABLE _working_dir
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
${_output_quiet}
|
||||
COMMAND_ECHO ${_command_echo})
|
||||
# mktemp formats it how we want it
|
||||
else()
|
||||
# Ummm... Linux you can do better!
|
||||
set(_tmpdir "/tmp")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT DEFINED _working_dir)
|
||||
string(RANDOM subdir)
|
||||
set(_working_dir "${_tmpdir}/tmp.${subdir}")
|
||||
endif()
|
||||
if(NOT EXISTS "${_working_dir}")
|
||||
file(MAKE_DIRECTORY "${_working_dir}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(_prepend_to_path)
|
||||
# Ensure the PATH is configured
|
||||
string(FIND "$ENV{PATH}" "${_working_dir}" _pathloc)
|
||||
if(NOT $_pathloc EQUAL 0)
|
||||
set(ENV{PATH} "${_working_dir}:$ENV{PATH}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# First ensure the binary doesn't already exist
|
||||
find_program(_${RESULT_VARIABLE} "${_name}" HINTS "${_working_dir}")
|
||||
|
||||
set(_binary_path "${_working_dir}/${_name}")
|
||||
if(NOT _${RESULT_VARIABLE})
|
||||
message(STATUS "Downloading ${_name} from ${_url}...")
|
||||
file(DOWNLOAD
|
||||
"${_url}"
|
||||
"${_binary_path}"
|
||||
STATUS DOWNLOAD_STATUS)
|
||||
# Check if download was successful.
|
||||
list(GET DOWNLOAD_STATUS 0 STATUS_CODE)
|
||||
list(GET DOWNLOAD_STATUS 1 ERROR_MESSAGE)
|
||||
if(NOT ${STATUS_CODE} EQUAL 0)
|
||||
file(REMOVE "${_binary_path}")
|
||||
message(FATAL_ERROR "Error downloading ${_url} ${ERROR_MESSAGE}")
|
||||
endif()
|
||||
|
||||
# Ensure the file is executable
|
||||
file(CHMOD "${_binary_path}" PERMISSIONS
|
||||
OWNER_EXECUTE OWNER_WRITE OWNER_READ
|
||||
GROUP_EXECUTE GROUP_WRITE GROUP_READ)
|
||||
|
||||
# Ensure it's found
|
||||
find_program(_${RESULT_VARIABLE} "${_name}" HINTS "${_working_dir}" REQUIRED)
|
||||
endif()
|
||||
|
||||
# We need to create a subdirectory for this binary and symlink it's AppRun to where it's expected
|
||||
if(_${RESULT_VARIABLE}_IS_APPIMAGE AND NOT IS_SYMLINK "${_${RESULT_VARIABLE}}")
|
||||
if(NOT COMMAND create_symlink)
|
||||
include(CreateSymlink)
|
||||
endif()
|
||||
|
||||
message(STATUS "Extracting ${_${RESULT_VARIABLE}} to ${_working_dir}/.${_name}/")
|
||||
|
||||
# extract appimage
|
||||
execute_process(COMMAND "${_${RESULT_VARIABLE}}" --appimage-extract
|
||||
WORKING_DIRECTORY "${_working_dir}"
|
||||
COMMAND_ECHO ${_command_echo}
|
||||
${_output_quiet}
|
||||
${_error_quiet}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
# move extracted files to dedicated location (e.g. ".linuxdeploy-x86_64.AppImage/squashfs-root/")
|
||||
file(MAKE_DIRECTORY "${_working_dir}/.${_name}/")
|
||||
file(RENAME "${_working_dir}/squashfs-root/" "${_working_dir}/.${_name}/squashfs-root/")
|
||||
|
||||
# remove the unusable binary
|
||||
file(REMOVE "${_${RESULT_VARIABLE}}")
|
||||
|
||||
# symlink the expected binary name to the AppRun file
|
||||
message(STATUS "Creating a symbolic link ${_${RESULT_VARIABLE}} which points to ${_working_dir}/.${_name}/squashfs-root/AppRun")
|
||||
create_symlink("${_working_dir}/.${_name}/squashfs-root/AppRun" "${_${RESULT_VARIABLE}}")
|
||||
endif()
|
||||
|
||||
# Test the binary
|
||||
# - TODO: Add support for bad binaries that set "$?" to an error code for no good reason
|
||||
# - TODO: Add support for Windows binaries expecting "/?" instead of "--help"
|
||||
message(STATUS "Testing that ${_name} works on this system...")
|
||||
set(_test_param "--help")
|
||||
|
||||
execute_process(COMMAND "${_${RESULT_VARIABLE}}" ${_test_param}
|
||||
COMMAND_ECHO ${_command_echo}
|
||||
${_output_quiet}
|
||||
${_error_quiet}
|
||||
COMMAND_ERROR_IS_FATAL ANY)
|
||||
|
||||
message(STATUS "The binary \"${_${RESULT_VARIABLE}}\" is now available")
|
||||
set(${RESULT_VARIABLE} "${_${RESULT_VARIABLE}}")
|
||||
endmacro()
|
||||
40
cmake/modules/FindSuilModules.cmake
Normal file
40
cmake/modules/FindSuilModules.cmake
Normal file
@@ -0,0 +1,40 @@
|
||||
# Copyright (c) 2024 Tres Finocchiaro
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
# This module defines
|
||||
# Suil_MODULES: List of full paths to Suil modules (e.g. "/usr/lib/suil-0/libsuil_x11.so;...")
|
||||
# Suil_MODULES_PREFIX: Only the directory name of the Suil_MODULES path (e.g. "suil-0")
|
||||
|
||||
pkg_check_modules(Suil QUIET suil-0)
|
||||
|
||||
if(Suil_FOUND)
|
||||
if(APPLE)
|
||||
set(_lib_ext "dylib")
|
||||
elseif(WIN32)
|
||||
set(_lib_ext "dll")
|
||||
else()
|
||||
set(_lib_ext "so")
|
||||
endif()
|
||||
|
||||
# Isolate -- if needed -- the first suil library path (e.g. "/usr/lib/libsuil-0.so")
|
||||
list(GET Suil_LINK_LIBRARIES 0 _lib)
|
||||
if(EXISTS "${_lib}")
|
||||
# Isolate -- if needed -- the first suil library name (e.g. "suil-0")
|
||||
list(GET Suil_LIBRARIES 0 _modules_prefix)
|
||||
get_filename_component(_lib_dir "${_lib}" DIRECTORY)
|
||||
# Construct modules path (e.g. "/usr/lib/suil-0")
|
||||
set(_modules_dir "${_lib_dir}/${_modules_prefix}")
|
||||
if(IS_DIRECTORY "${_modules_dir}")
|
||||
set(Suil_MODULES_PREFIX "${_modules_prefix}")
|
||||
file(GLOB Suil_MODULES "${_modules_dir}/*.${_lib_ext}")
|
||||
list(SORT Suil_MODULES)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SuilModules
|
||||
REQUIRED_VARS Suil_MODULES Suil_MODULES_PREFIX
|
||||
)
|
||||
@@ -53,6 +53,15 @@ SET(CPACK_NSIS_DEFINES "${CPACK_NSIS_DEFINES}" PARENT_SCOPE)
|
||||
SET(CPACK_PACKAGE_ICON "${CPACK_PACKAGE_ICON}" PARENT_SCOPE)
|
||||
SET(CPACK_NSIS_MUI_ICON "${CPACK_NSIS_MUI_ICON}" PARENT_SCOPE)
|
||||
|
||||
# Disable cpack's strip for historic reasons
|
||||
set(CPACK_STRIP_FILES_ORIG "${CPACK_STRIP_FILES}" PARENT_SCOPE)
|
||||
set(CPACK_STRIP_FILES FALSE PARENT_SCOPE)
|
||||
|
||||
if(CPACK_DEBUG)
|
||||
# CMake 3.19+
|
||||
set(CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS "-V4")
|
||||
endif()
|
||||
|
||||
# Windows resource compilers
|
||||
CONFIGURE_FILE("lmms.rc.in" "${CMAKE_BINARY_DIR}/lmms.rc")
|
||||
CONFIGURE_FILE("zynaddsubfx.rc.in" "${CMAKE_BINARY_DIR}/plugins/ZynAddSubFx/zynaddsubfx.rc")
|
||||
|
||||
@@ -181,11 +181,11 @@ set_target_properties(lmms PROPERTIES
|
||||
|
||||
set_target_properties(lmmsobjs PROPERTIES AUTOUIC_SEARCH_PATHS "gui/modals")
|
||||
|
||||
IF(NOT WIN32)
|
||||
IF(NOT WIN32 AND NOT LMMS_BUILD_APPLE)
|
||||
if(CMAKE_INSTALL_MANDIR)
|
||||
SET(INSTALL_MANDIR ${CMAKE_INSTALL_MANDIR})
|
||||
ELSE(CMAKE_INSTALL_MANDIR)
|
||||
SET(INSTALL_MANDIR ${CMAKE_INSTALL_PREFIX}/share/man)
|
||||
SET(INSTALL_MANDIR share/man)
|
||||
ENDIF(CMAKE_INSTALL_MANDIR)
|
||||
INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz"
|
||||
DESTINATION "${INSTALL_MANDIR}/man1/"
|
||||
|
||||
@@ -235,6 +235,11 @@ bool RemotePlugin::init(const QString &pluginExecutable,
|
||||
m_failed = false;
|
||||
}
|
||||
QString exec = QFileInfo(QDir("plugins:"), pluginExecutable).absoluteFilePath();
|
||||
|
||||
// We may have received a directory via a environment variable
|
||||
if (const char* env_path = std::getenv("LMMS_PLUGIN_DIR"))
|
||||
exec = QFileInfo(QDir(env_path), pluginExecutable).absoluteFilePath();
|
||||
|
||||
#ifdef LMMS_BUILD_APPLE
|
||||
// search current directory first
|
||||
QString curDir = QCoreApplication::applicationDirPath() + "/" + pluginExecutable;
|
||||
@@ -252,7 +257,7 @@ bool RemotePlugin::init(const QString &pluginExecutable,
|
||||
|
||||
if( ! QFile( exec ).exists() )
|
||||
{
|
||||
qWarning( "Remote plugin '%s' not found.",
|
||||
qWarning( "Remote plugin '%s' not found",
|
||||
exec.toUtf8().constData() );
|
||||
m_failed = true;
|
||||
invalidate();
|
||||
|
||||
@@ -467,7 +467,8 @@ AudioSoundIo::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
|
||||
reconnectSoundIo();
|
||||
|
||||
bool ok = connect( &m_backendModel, SIGNAL(dataChanged()), &m_setupUtil, SLOT(reconnectSoundIo()));
|
||||
[[maybe_unused]] bool ok = connect(&m_backendModel, &ComboBoxModel::dataChanged,
|
||||
&m_setupUtil, &AudioSoundIoSetupUtil::reconnectSoundIo);
|
||||
assert(ok);
|
||||
|
||||
m_backend->setModel( &m_backendModel );
|
||||
@@ -476,7 +477,8 @@ AudioSoundIo::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
|
||||
AudioSoundIo::setupWidget::~setupWidget()
|
||||
{
|
||||
bool ok = disconnect( &m_backendModel, SIGNAL(dataChanged()), &m_setupUtil, SLOT(reconnectSoundIo()));
|
||||
[[maybe_unused]] bool ok = disconnect(&m_backendModel, &ComboBoxModel::dataChanged,
|
||||
&m_setupUtil, &AudioSoundIoSetupUtil::reconnectSoundIo);
|
||||
assert(ok);
|
||||
if (m_soundio)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace lmms::gui {
|
||||
QString SampleLoader::openAudioFile(const QString& previousFile)
|
||||
{
|
||||
auto openFileDialog = FileDialog(nullptr, QObject::tr("Open audio file"));
|
||||
auto dir = !previousFile.isEmpty() ? PathUtil::toAbsolute(previousFile) : ConfigManager::inst()->userSamplesDir();
|
||||
auto dir = !previousFile.isEmpty() ? QFileInfo(PathUtil::toAbsolute(previousFile)).absolutePath() : ConfigManager::inst()->userSamplesDir();
|
||||
|
||||
// change dir to position of previously opened file
|
||||
openFileDialog.setDirectory(dir);
|
||||
|
||||
Reference in New Issue
Block a user