Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 22 additions & 109 deletions cmake/linux/LinuxDeploy.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ endif()

include(DownloadBinary)
include(CreateSymlink)
include(CopyDependency)

# Cleanup CPack "External" json, txt files, old AppImage files
file(GLOB cleanup "${CPACK_BINARY_DIR}/${lmms}-*.json"
Expand Down Expand Up @@ -87,11 +88,29 @@ foreach(_file ${files})
endif()
endforeach()

# Gather deps
list(APPEND DEPLOY_DEPS
--deploy-deps-only "${APP}/usr/lib/${lmms}/"
--deploy-deps-only "${APP}/usr/lib/${lmms}/ladspa/"
)

# If usr/bin/lmms is hard-linked to libjack, copy it to a new location
# See https://github.com/LMMS/lmms/issues/7689
copy_dependency("${APP}/usr/bin/lmms" "libjack.so" "${APP}/usr/lib/jack" JACK_LIB_RELOC)
if(JACK_LIB_RELOC)
list(APPEND DEPLOY_DEPS --deploy-deps-only "${JACK_LIB_RELOC}")
endif()

if(CPACK_HAVE_VST_32)
list(APPEND DEPLOY_DEPS --deploy-deps-only "${APP}/usr/lib/${lmms}/32/")
endif()

# Copy Suil modules
if(CPACK_SUIL_MODULES)
set(SUIL_MODULES_TARGET "${APP}/usr/lib/${CPACK_SUIL_MODULES_PREFIX}")
set(SUIL_MODULES_TARGET "${APP}/usr/lib/suil-0/")
file(MAKE_DIRECTORY "${SUIL_MODULES_TARGET}")
file(COPY ${CPACK_SUIL_MODULES} DESTINATION "${SUIL_MODULES_TARGET}")
list(APPEND DEPLOY_DEPS --deploy-deps-only "${APP}/usr/lib/suil-0/")
endif()

# Copy stk/rawwaves
Expand Down Expand Up @@ -125,47 +144,18 @@ file(COPY "${APP}/usr/share/icons/hicolor/256x256/apps/${lmms}.png" DESTINATION
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*")

# Inform linuxdeploy-plugin-qt about wayland plugin
set(ENV{EXTRA_PLATFORM_PLUGINS} "libqwayland-generic.so")
set(ENV{EXTRA_QT_MODULES} "waylandcompositor")

# 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()

list(APPEND SKIP_LIBRARIES "--exclude-library=*libgallium*")

# Call linuxdeploy
message(STATUS "Calling ${LINUXDEPLOY_BIN} --appdir \"${APP}\" ... [... libraries].")
execute_process(COMMAND "${LINUXDEPLOY_BIN}"
--appdir "${APP}"
--desktop-file "${DESKTOP_FILE}"
--plugin qt
${LIBRARIES}
${SKIP_LIBRARIES}
${DEPLOY_DEPS}
--exclude-library "*libgallium*"
--verbosity ${VERBOSITY}
WORKING_DIRECTORY "${CPACK_CURRENT_BINARY_DIR}"
${OUTPUT_QUIET}
Expand All @@ -189,83 +179,6 @@ foreach(_lib IN LISTS EXCLUDE_LIBS)
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/")

# Copy "exclude-list" lib(s) into specified location
macro(copy_excluded ldd_target name_match destination relocated_lib)
execute_process(COMMAND ldd
"${ldd_target}"
OUTPUT_VARIABLE ldd_output
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ECHO ${COMMAND_ECHO}
COMMAND_ERROR_IS_FATAL ANY)

# escape periods to avoid double-escaping
string(REPLACE "." "\\." name_match "${name_match}")

# cli output --> list
string(REPLACE "\n" ";" ldd_list "${ldd_output}")

foreach(line ${ldd_list})
if(line MATCHES "${name_match}")
# Assumes format "libname.so.0 => /lib/location/libname.so.0 (0x00007f48d0b0e000)"
string(REPLACE " " ";" parts "${line}")
list(LENGTH parts len)
math(EXPR index "${len}-2")
list(GET parts ${index} lib)
# Resolve any possible symlinks
file(REAL_PATH "${lib}" libreal)
get_filename_component(symname "${lib}" NAME)
get_filename_component(realname "${libreal}" NAME)
file(MAKE_DIRECTORY "${destination}")
# Copy, but with original symlink name
file(COPY "${libreal}" DESTINATION "${destination}")
file(RENAME "${destination}/${realname}" "${destination}/${symname}")
set("${relocated_lib}" "${destination}/${symname}")
break()
endif()
endforeach()
endmacro()

# copy libjack
copy_excluded("${APP}/usr/bin/${lmms}" "libjack.so" "${APP}/usr/lib/jack" relocated_jack)
if(relocated_jack)
# libdb's not excluded however we'll re-use the macro as a convenient path calculation
# See https://github.com/LMMS/lmms/issues/7689s
copy_excluded("${relocated_jack}" "libdb-" "${APP}/usr/lib/jack" relocated_libdb)
get_filename_component(libdb_name "${relocated_libdb}" NAME)
if(relocated_libdb AND EXISTS "${APP}/usr/lib/${libdb_name}")
# assume a copy already resides in usr/lib and symlink
file(REMOVE "${relocated_libdb}")
create_symlink("${APP}/usr/lib/${libdb_name}" "${relocated_libdb}")
endif()
endif()

# cleanup empty directories
file(REMOVE_RECURSE "${APP}/usr/lib/${lmms}/optional/")

Expand Down
1 change: 0 additions & 1 deletion cmake/linux/apprun-hooks/carla-hook.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ if command -v carla > /dev/null 2>&1; then
else
echo "[$ME] Carla does not appear to be installed, we'll remove it from the plugin listing." >&2
export "LMMS_EXCLUDE_PLUGINS=libcarla,${LMMS_EXCLUDE_PLUGINS}"
export "LMMS_EXCLUDE_LADSPA=libcarla,${LMMS_EXCLUDE_LADSPA}"
fi

# Additional workarounds for library conflicts
Expand Down
7 changes: 2 additions & 5 deletions cmake/linux/apprun-hooks/usr-lib-hooks.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#!/usr/bin/env bash

# Workaround libraries being incorrectly placed in usr/lib (e.g. instead of usr/lib/lmms, etc)
# FIXME: Remove when linuxdeploy supports subfolders https://github.com/linuxdeploy/linuxdeploy/issues/305
# Paths for plugin systems to pick-up
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
export LMMS_PLUGIN_DIR="$DIR/usr/lib/"
export LADSPA_PATH="$DIR/usr/lib/"
export SUIL_MODULE_DIR="$DIR/usr/lib/"
export SUIL_MODULE_DIR="$DIR/usr/lib/suil-0/" # See also ${SUIL_MODULES_TARGET}
76 changes: 76 additions & 0 deletions cmake/modules/CopyDependency.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Copy source_lib's dependency matching 'name_match' into specified location
# Sets variable named in relocated_lib to the destination
macro(copy_dependency source_lib name_match destination relocated_lib)
if(NOT COMMAND_ECHO OR "${COMMAND_ECHO}" STREQUAL "NONE")
set(_command_echo NONE)
else()
set(_command_echo "${COMMAND_ECHO}")
endif()

execute_process(COMMAND file -b --mime-type "${source_lib}" OUTPUT_VARIABLE file_type)

set(_is_linux_lib false)
set(_is_mac_lib false)

if("${file_type}" MATCHES "application/x-pie-executable")
# Linux ELF binary
set(_is_linux_lib true)
list(APPEND _lib_command ldd)
elseif("${file_type}" MATCHES "application/x-mach-binary")
# macOS Mach-O binary
set(_is_mac_lib true)
list(APPEND _lib_command otool -L)
else()
message(FATAL_ERROR "Copying dependencies for ${file_type} are not yet supported")
endif()

execute_process(COMMAND ${_lib_command}
"${source_lib}"
OUTPUT_VARIABLE raw_output
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ECHO ${_command_echo}
COMMAND_ERROR_IS_FATAL ANY)

# escape periods to avoid double-escaping
string(REPLACE "." "\\." name_match "${name_match}")

# cli output --> list
string(REPLACE "\n" ";" raw_list "${raw_output}")

foreach(line ${raw_list})
if(line MATCHES "${name_match}")
if(_is_linux_lib)
# Assumes format "libname.so.0 => /lib/location/libname.so.0 (0x00007f48d0b0e000)"
string(REGEX MATCH "=> ([^\\(]+)" dummy_var "${line}")
# Trim leading/trailing whitespace and add to our list
string(STRIP "${CMAKE_MATCH_1}" lib)
elseif(_is_mac_lib)
# Assumes format "@loader_path/../Frameworks/libname-0.0.dylib (compatibility version 0.0.0, current version 0.24.26)"
string(REGEX MATCH "^[ \t]+(.*) \\(" dummy_var "${line}")
string(STRIP "${CMAKE_MATCH_1}" lib)
get_filename_component(loader_path ${source_lib} DIRECTORY)
string(REPLACE "@loader_path" "${loader_path}" resolved_lib "${lib}")
string(REPLACE "@rpath" "${loader_path}" resolved_lib "${lib}")
# Special handling for '@executable_path'
if(line MATCHES "@executable_path")
# Find the position of '/Contents/'
string(FIND "${APP_PATH}" "/Contents/" APP_CONTENTS_POS)
# Extract the base path up to '/Contents/'
string(SUBSTRING "${loader_path}" 0 "${APP_CONTENTS_POS}" app_base_path)
string(REPLACE "@executable_path" "${app_base_path}/Contents/MacOS" resolved_lib "${lib}")
endif()
endif()

# Resolve any possible symlinks
file(REAL_PATH "${lib}" libreal)
get_filename_component(symname "${lib}" NAME)
get_filename_component(realname "${libreal}" NAME)
file(MAKE_DIRECTORY "${destination}")
# Copy, but with original symlink name
file(COPY "${libreal}" DESTINATION "${destination}")
file(RENAME "${destination}/${realname}" "${destination}/${symname}")
set("${relocated_lib}" "${destination}/${symname}")
break()
endif()
endforeach()
endmacro()
Loading