Skip to content

Commit 807751d

Browse files
authored
AppImage: Un-pollute /usr/lib (#8053)
Refactor to un-pollute `$APP/usr/lib` * Adds `usr/lib/suil-0` and `usr/lib/lmms/32` to `--deploy-deps-only` flags * Simplifies libjack handling * Removes outdated `LMMS_EXCLUDE_LADSPA` entry (carla no longer shares a parent folder with LADSPA plugins)
1 parent db6fc29 commit 807751d

File tree

4 files changed

+100
-115
lines changed

4 files changed

+100
-115
lines changed

cmake/linux/LinuxDeploy.cmake

Lines changed: 22 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ endif()
4949

5050
include(DownloadBinary)
5151
include(CreateSymlink)
52+
include(CopyDependency)
5253

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

91+
# Gather deps
92+
list(APPEND DEPLOY_DEPS
93+
--deploy-deps-only "${APP}/usr/lib/${lmms}/"
94+
--deploy-deps-only "${APP}/usr/lib/${lmms}/ladspa/"
95+
)
96+
97+
# If usr/bin/lmms is hard-linked to libjack, copy it to a new location
98+
# See https://github.com/LMMS/lmms/issues/7689
99+
copy_dependency("${APP}/usr/bin/lmms" "libjack.so" "${APP}/usr/lib/jack" JACK_LIB_RELOC)
100+
if(JACK_LIB_RELOC)
101+
list(APPEND DEPLOY_DEPS --deploy-deps-only "${JACK_LIB_RELOC}")
102+
endif()
103+
104+
if(CPACK_HAVE_VST_32)
105+
list(APPEND DEPLOY_DEPS --deploy-deps-only "${APP}/usr/lib/${lmms}/32/")
106+
endif()
107+
90108
# Copy Suil modules
91109
if(CPACK_SUIL_MODULES)
92-
set(SUIL_MODULES_TARGET "${APP}/usr/lib/${CPACK_SUIL_MODULES_PREFIX}")
110+
set(SUIL_MODULES_TARGET "${APP}/usr/lib/suil-0/")
93111
file(MAKE_DIRECTORY "${SUIL_MODULES_TARGET}")
94112
file(COPY ${CPACK_SUIL_MODULES} DESTINATION "${SUIL_MODULES_TARGET}")
113+
list(APPEND DEPLOY_DEPS --deploy-deps-only "${APP}/usr/lib/suil-0/")
95114
endif()
96115

97116
# Copy stk/rawwaves
@@ -125,47 +144,18 @@ file(COPY "${APP}/usr/share/icons/hicolor/256x256/apps/${lmms}.png" DESTINATION
125144
file(RENAME "${APP}/${lmms}.png" "${APP}/.DirIcon")
126145
file(COPY "${APP}/usr/share/icons/hicolor/256x256/apps/${lmms}.png" DESTINATION "${APP}")
127146

128-
# Build list of libraries to inform linuxdeploy about
129-
# e.g. --library=foo.so --library=bar.so
130-
file(GLOB LIBS "${APP}/usr/lib/${lmms}/*.so")
131-
132-
# Inform linuxdeploy about LADSPA plugins; may depend on bundled fftw3f, etc.
133-
file(GLOB LADSPA "${APP}/usr/lib/${lmms}/ladspa/*.so")
134-
135-
# Inform linuxdeploy about remote plugins
136-
file(GLOB REMOTE_PLUGINS "${APP}/usr/lib/${lmms}/*Remote*")
137-
138147
# Inform linuxdeploy-plugin-qt about wayland plugin
139148
set(ENV{EXTRA_PLATFORM_PLUGINS} "libqwayland-generic.so")
140149
set(ENV{EXTRA_QT_MODULES} "waylandcompositor")
141150

142-
# Collect, sort and dedupe all libraries
143-
list(APPEND LIBS ${LADSPA})
144-
list(APPEND LIBS ${REMOTE_PLUGINS})
145-
list(APPEND LIBS ${CPACK_SUIL_MODULES})
146-
list(REMOVE_DUPLICATES LIBS)
147-
list(SORT LIBS)
148-
149-
# Handle non-relinkable files (e.g. RemoveVstPlugin[32|64], but not NativeLinuxRemoteVstPlugin)
150-
list(FILTER LIBS EXCLUDE REGEX "\\/RemoteVst")
151-
152-
# Construct linuxdeploy parameters
153-
foreach(_lib IN LISTS LIBS)
154-
if(EXISTS "${_lib}")
155-
list(APPEND LIBRARIES "--library=${_lib}")
156-
endif()
157-
endforeach()
158-
159-
list(APPEND SKIP_LIBRARIES "--exclude-library=*libgallium*")
160-
161151
# Call linuxdeploy
162152
message(STATUS "Calling ${LINUXDEPLOY_BIN} --appdir \"${APP}\" ... [... libraries].")
163153
execute_process(COMMAND "${LINUXDEPLOY_BIN}"
164154
--appdir "${APP}"
165155
--desktop-file "${DESKTOP_FILE}"
166156
--plugin qt
167-
${LIBRARIES}
168-
${SKIP_LIBRARIES}
157+
${DEPLOY_DEPS}
158+
--exclude-library "*libgallium*"
169159
--verbosity ${VERBOSITY}
170160
WORKING_DIRECTORY "${CPACK_CURRENT_BINARY_DIR}"
171161
${OUTPUT_QUIET}
@@ -189,83 +179,6 @@ foreach(_lib IN LISTS EXCLUDE_LIBS)
189179
endif()
190180
endforeach()
191181

192-
# FIXME: Remove when linuxdeploy supports subfolders https://github.com/linuxdeploy/linuxdeploy/issues/305
193-
foreach(_lib IN LISTS LIBS)
194-
if(EXISTS "${_lib}")
195-
file(REMOVE "${_lib}")
196-
endif()
197-
endforeach()
198-
# Move RemotePlugins into to LMMS_PLUGIN_DIR
199-
file(GLOB WINE_VST_LIBS
200-
"${APP}/usr/lib/${lmms}/RemoteVstPlugin*"
201-
"${APP}/usr/lib/${lmms}/32")
202-
foreach(_file IN LISTS WINE_VST_LIBS)
203-
if(EXISTS "${_file}")
204-
get_filename_component(_name "${_file}" NAME)
205-
file(RENAME "${_file}" "${APP}/usr/lib/${_name}")
206-
endif()
207-
endforeach()
208-
file(GLOB WINE_32_LIBS
209-
"${APP}/usr/lib/${lmms}/RemoteVstPlugin*")
210-
foreach(_lib IN LISTS WINE_64_LIBS)
211-
if(EXISTS "${_lib}")
212-
get_filename_component(_file "${_lib}" NAME)
213-
file(RENAME "${_lib}" "${APP}/usr/lib/${_file}")
214-
endif()
215-
endforeach()
216-
217-
file(REMOVE_RECURSE "${SUIL_MODULES_TARGET}" "${APP}/usr/lib/${lmms}/ladspa/")
218-
219-
# Copy "exclude-list" lib(s) into specified location
220-
macro(copy_excluded ldd_target name_match destination relocated_lib)
221-
execute_process(COMMAND ldd
222-
"${ldd_target}"
223-
OUTPUT_VARIABLE ldd_output
224-
OUTPUT_STRIP_TRAILING_WHITESPACE
225-
COMMAND_ECHO ${COMMAND_ECHO}
226-
COMMAND_ERROR_IS_FATAL ANY)
227-
228-
# escape periods to avoid double-escaping
229-
string(REPLACE "." "\\." name_match "${name_match}")
230-
231-
# cli output --> list
232-
string(REPLACE "\n" ";" ldd_list "${ldd_output}")
233-
234-
foreach(line ${ldd_list})
235-
if(line MATCHES "${name_match}")
236-
# Assumes format "libname.so.0 => /lib/location/libname.so.0 (0x00007f48d0b0e000)"
237-
string(REPLACE " " ";" parts "${line}")
238-
list(LENGTH parts len)
239-
math(EXPR index "${len}-2")
240-
list(GET parts ${index} lib)
241-
# Resolve any possible symlinks
242-
file(REAL_PATH "${lib}" libreal)
243-
get_filename_component(symname "${lib}" NAME)
244-
get_filename_component(realname "${libreal}" NAME)
245-
file(MAKE_DIRECTORY "${destination}")
246-
# Copy, but with original symlink name
247-
file(COPY "${libreal}" DESTINATION "${destination}")
248-
file(RENAME "${destination}/${realname}" "${destination}/${symname}")
249-
set("${relocated_lib}" "${destination}/${symname}")
250-
break()
251-
endif()
252-
endforeach()
253-
endmacro()
254-
255-
# copy libjack
256-
copy_excluded("${APP}/usr/bin/${lmms}" "libjack.so" "${APP}/usr/lib/jack" relocated_jack)
257-
if(relocated_jack)
258-
# libdb's not excluded however we'll re-use the macro as a convenient path calculation
259-
# See https://github.com/LMMS/lmms/issues/7689s
260-
copy_excluded("${relocated_jack}" "libdb-" "${APP}/usr/lib/jack" relocated_libdb)
261-
get_filename_component(libdb_name "${relocated_libdb}" NAME)
262-
if(relocated_libdb AND EXISTS "${APP}/usr/lib/${libdb_name}")
263-
# assume a copy already resides in usr/lib and symlink
264-
file(REMOVE "${relocated_libdb}")
265-
create_symlink("${APP}/usr/lib/${libdb_name}" "${relocated_libdb}")
266-
endif()
267-
endif()
268-
269182
# cleanup empty directories
270183
file(REMOVE_RECURSE "${APP}/usr/lib/${lmms}/optional/")
271184

cmake/linux/apprun-hooks/carla-hook.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ if command -v carla > /dev/null 2>&1; then
2525
else
2626
echo "[$ME] Carla does not appear to be installed, we'll remove it from the plugin listing." >&2
2727
export "LMMS_EXCLUDE_PLUGINS=libcarla,${LMMS_EXCLUDE_PLUGINS}"
28-
export "LMMS_EXCLUDE_LADSPA=libcarla,${LMMS_EXCLUDE_LADSPA}"
2928
fi
3029

3130
# Additional workarounds for library conflicts
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
#!/usr/bin/env bash
22

3-
# Workaround libraries being incorrectly placed in usr/lib (e.g. instead of usr/lib/lmms, etc)
4-
# FIXME: Remove when linuxdeploy supports subfolders https://github.com/linuxdeploy/linuxdeploy/issues/305
3+
# Paths for plugin systems to pick-up
54
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
6-
export LMMS_PLUGIN_DIR="$DIR/usr/lib/"
7-
export LADSPA_PATH="$DIR/usr/lib/"
8-
export SUIL_MODULE_DIR="$DIR/usr/lib/"
5+
export SUIL_MODULE_DIR="$DIR/usr/lib/suil-0/" # See also ${SUIL_MODULES_TARGET}

cmake/modules/CopyDependency.cmake

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copy source_lib's dependency matching 'name_match' into specified location
2+
# Sets variable named in relocated_lib to the destination
3+
macro(copy_dependency source_lib name_match destination relocated_lib)
4+
if(NOT COMMAND_ECHO OR "${COMMAND_ECHO}" STREQUAL "NONE")
5+
set(_command_echo NONE)
6+
else()
7+
set(_command_echo "${COMMAND_ECHO}")
8+
endif()
9+
10+
execute_process(COMMAND file -b --mime-type "${source_lib}" OUTPUT_VARIABLE file_type)
11+
12+
set(_is_linux_lib false)
13+
set(_is_mac_lib false)
14+
15+
if("${file_type}" MATCHES "application/x-pie-executable")
16+
# Linux ELF binary
17+
set(_is_linux_lib true)
18+
list(APPEND _lib_command ldd)
19+
elseif("${file_type}" MATCHES "application/x-mach-binary")
20+
# macOS Mach-O binary
21+
set(_is_mac_lib true)
22+
list(APPEND _lib_command otool -L)
23+
else()
24+
message(FATAL_ERROR "Copying dependencies for ${file_type} are not yet supported")
25+
endif()
26+
27+
execute_process(COMMAND ${_lib_command}
28+
"${source_lib}"
29+
OUTPUT_VARIABLE raw_output
30+
OUTPUT_STRIP_TRAILING_WHITESPACE
31+
COMMAND_ECHO ${_command_echo}
32+
COMMAND_ERROR_IS_FATAL ANY)
33+
34+
# escape periods to avoid double-escaping
35+
string(REPLACE "." "\\." name_match "${name_match}")
36+
37+
# cli output --> list
38+
string(REPLACE "\n" ";" raw_list "${raw_output}")
39+
40+
foreach(line ${raw_list})
41+
if(line MATCHES "${name_match}")
42+
if(_is_linux_lib)
43+
# Assumes format "libname.so.0 => /lib/location/libname.so.0 (0x00007f48d0b0e000)"
44+
string(REGEX MATCH "=> ([^\\(]+)" dummy_var "${line}")
45+
# Trim leading/trailing whitespace and add to our list
46+
string(STRIP "${CMAKE_MATCH_1}" lib)
47+
elseif(_is_mac_lib)
48+
# Assumes format "@loader_path/../Frameworks/libname-0.0.dylib (compatibility version 0.0.0, current version 0.24.26)"
49+
string(REGEX MATCH "^[ \t]+(.*) \\(" dummy_var "${line}")
50+
string(STRIP "${CMAKE_MATCH_1}" lib)
51+
get_filename_component(loader_path ${source_lib} DIRECTORY)
52+
string(REPLACE "@loader_path" "${loader_path}" resolved_lib "${lib}")
53+
string(REPLACE "@rpath" "${loader_path}" resolved_lib "${lib}")
54+
# Special handling for '@executable_path'
55+
if(line MATCHES "@executable_path")
56+
# Find the position of '/Contents/'
57+
string(FIND "${APP_PATH}" "/Contents/" APP_CONTENTS_POS)
58+
# Extract the base path up to '/Contents/'
59+
string(SUBSTRING "${loader_path}" 0 "${APP_CONTENTS_POS}" app_base_path)
60+
string(REPLACE "@executable_path" "${app_base_path}/Contents/MacOS" resolved_lib "${lib}")
61+
endif()
62+
endif()
63+
64+
# Resolve any possible symlinks
65+
file(REAL_PATH "${lib}" libreal)
66+
get_filename_component(symname "${lib}" NAME)
67+
get_filename_component(realname "${libreal}" NAME)
68+
file(MAKE_DIRECTORY "${destination}")
69+
# Copy, but with original symlink name
70+
file(COPY "${libreal}" DESTINATION "${destination}")
71+
file(RENAME "${destination}/${realname}" "${destination}/${symname}")
72+
set("${relocated_lib}" "${destination}/${symname}")
73+
break()
74+
endif()
75+
endforeach()
76+
endmacro()

0 commit comments

Comments
 (0)