Skip to content

Commit 10dc9f4

Browse files
committed
Linux: Update Deployment
1 parent 4ae36ba commit 10dc9f4

11 files changed

+305
-104
lines changed

cmake/CustomOptions.cmake

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,13 @@ set(QGC_MACOS_ENTITLEMENTS_PATH "${CMAKE_SOURCE_DIR}/deploy/macos/qgroundcontrol
6969
# option(QGC_MACOS_UNIVERSAL_BUILD "Build MacOS Universal Build (arm64;x86_64)" ON) # MACOS
7070

7171
# Linux
72-
set(QGC_APPIMAGE_ICON_PATH "${CMAKE_SOURCE_DIR}/resources/icons/qgroundcontrol.png" CACHE FILEPATH "AppImage Icon Path")
72+
option(QGC_CREATE_APPIMAGE "Build an AppImage after build" ON)
73+
set(QGC_APPIMAGE_ICON_256_PATH "${CMAKE_SOURCE_DIR}/deploy/linux/QGroundControl_256.png" CACHE FILEPATH "AppImage Icon 256x256 Path")
74+
set(QGC_APPIMAGE_ICON_SCALABLE_PATH "${CMAKE_SOURCE_DIR}/deploy/linux/QGroundControl.svg" CACHE FILEPATH "AppImage Icon SVG Path")
75+
set(QGC_APPIMAGE_APPRUN_PATH "${CMAKE_SOURCE_DIR}/deploy/linux/AppRun" CACHE FILEPATH "AppImage AppRun Path")
76+
set(QGC_APPIMAGE_DESKTOP_ENTRY_PATH "${CMAKE_SOURCE_DIR}/deploy/linux/org.mavlink.qgroundcontrol.desktop.in" CACHE FILEPATH "AppImage Desktop Entry Path")
77+
set(QGC_APPIMAGE_METADATA_PATH "${CMAKE_SOURCE_DIR}/deploy/linux/org.mavlink.qgroundcontrol.appdata.xml.in" CACHE FILEPATH "AppImage Metadata Path")
78+
set(QGC_APPIMAGE_APPDATA_DEVELOPER "qgroundcontrol" CACHE STRING "AppImage Metadata Developer")
7379

7480
# Windows
7581
set(QGC_WINDOWS_INSTALL_HEADER_PATH "${CMAKE_SOURCE_DIR}/deploy/windows/installheader.bmp" CACHE FILEPATH "Windows Install Header Path")

cmake/install/CreateAppImage.cmake

Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,70 @@
1-
message(STATUS "Creating AppImage")
2-
# TODO: https://github.com/AppImageCommunity/AppImageUpdate
1+
# TODO: # go-appimage, updateinformation w/ GitHub Releases, signing
2+
3+
message(STATUS "QGC: Creating AppImage")
34

45
set(APPDIR_PATH "${CMAKE_BINARY_DIR}/AppDir")
5-
set(APPIMAGETOOL_PATH "${CMAKE_BINARY_DIR}/appimagetool-x86_64.AppImage")
6-
set(LD_PATH "${CMAKE_BINARY_DIR}/linuxdeploy-${CMAKE_SYSTEM_PROCESSOR}.AppImage")
7-
# set(LD_APPIMAGEPLUGIN_PATH "${CMAKE_BINARY_DIR}/linuxdeploy-plugin-appimage-${CMAKE_SYSTEM_PROCESSOR}.AppImage")
8-
# set(LD_QTPLUGIN_PATH "${CMAKE_BINARY_DIR}/linuxdeploy-plugin-qt-${CMAKE_SYSTEM_PROCESSOR}.AppImage")
9-
# set(LD_GSTPLUGIN_PATH "${CMAKE_BINARY_DIR}/linuxdeploy-plugin-gstreamer.sh")
10-
11-
if(NOT EXISTS "${APPIMAGETOOL_PATH}")
12-
file(DOWNLOAD https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${CMAKE_SYSTEM_PROCESSOR}.AppImage "${APPIMAGETOOL_PATH}")
13-
# file(DOWNLOAD https://github.com/probonopd/go-appimage/releases/download/832/appimagetool-823-${CMAKE_SYSTEM_PROCESSOR}.AppImage "${APPIMAGETOOL_PATH}") # TODO: Use Continuous Release
14-
execute_process(COMMAND chmod a+x "${APPIMAGETOOL_PATH}")
15-
endif()
16-
if(NOT EXISTS "${LD_PATH}")
17-
file(DOWNLOAD https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${CMAKE_SYSTEM_PROCESSOR}.AppImage "${LD_PATH}")
18-
execute_process(COMMAND chmod a+x "${LD_PATH}")
6+
set(APPIMAGE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_PROCESSOR}.AppImage")
7+
8+
#===========================================================================#
9+
# Download Tools
10+
11+
function(download_tool VAR URL)
12+
cmake_path(GET URL FILENAME _name)
13+
set(_dest "${CMAKE_BINARY_DIR}/tools/${_name}")
14+
if(NOT EXISTS "${_dest}")
15+
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/tools")
16+
message(STATUS "QGC: Downloading ${_name} to ${_dest}")
17+
file(DOWNLOAD "${URL}" "${_dest}" STATUS _status)
18+
list(GET _status 0 _result)
19+
if(NOT _result EQUAL 0)
20+
message(FATAL_ERROR "Failed to download ${URL} to ${_dest}: ${_status}")
21+
endif()
22+
file(CHMOD "${_dest}" FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
23+
endif()
24+
set(${VAR}_PATH "${_dest}" PARENT_SCOPE)
25+
endfunction()
26+
27+
download_tool(LINUXDEPLOY https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${CMAKE_SYSTEM_PROCESSOR}.AppImage)
28+
download_tool(APPIMAGETOOL https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${CMAKE_SYSTEM_PROCESSOR}.AppImage)
29+
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
30+
download_tool(APPIMAGELINT https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-${CMAKE_SYSTEM_PROCESSOR}.AppImage)
1931
endif()
20-
# if(NOT EXISTS "${LD_APPIMAGEPLUGIN_PATH}")
21-
# file(DOWNLOAD https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-${CMAKE_SYSTEM_PROCESSOR}.AppImage "${LD_APPIMAGEPLUGIN_PATH}")
22-
# execute_process(COMMAND chmod a+x "${LD_APPIMAGEPLUGIN_PATH}")
23-
# endif()
24-
# if(NOT EXISTS "${LD_QTPLUGIN_PATH}")
25-
# file(DOWNLOAD https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-${CMAKE_SYSTEM_PROCESSOR}.AppImage "${LD_QTPLUGIN_PATH}")
26-
# execute_process(COMMAND chmod a+x "${LD_QTPLUGIN_PATH}")
27-
# endif()
28-
# if(NOT EXISTS "${LD_GSTPLUGIN_PATH}")
29-
# file(DOWNLOAD https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gstreamer/master/linuxdeploy-plugin-gstreamer.sh "${LD_GSTPLUGIN_PATH}")
30-
# execute_process(COMMAND chmod a+x "${LD_GSTPLUGIN_PATH}")
31-
# endif()
32-
33-
execute_process(COMMAND ${LD_PATH}
34-
--appdir ${APPDIR_PATH}
35-
--executable ${APPDIR_PATH}/usr/bin/QGroundControl
36-
--desktop-file ${APPDIR_PATH}/usr/share/applications/org.mavlink.qgroundcontrol.desktop
37-
--custom-apprun ${CMAKE_BINARY_DIR}/AppRun)
38-
# --plugin qt --plugin gstreamer
39-
# --exclude-library "libgst*"
32+
33+
#===========================================================================#
34+
# Bundle the runtime
35+
36+
execute_process(
37+
COMMAND "${LINUXDEPLOY_PATH}"
38+
--appdir "${APPDIR_PATH}"
39+
--executable "${APPDIR_PATH}/usr/bin/${CMAKE_PROJECT_NAME}"
40+
--desktop-file "${APPDIR_PATH}/usr/share/applications/${QGC_PACKAGE_NAME}.desktop"
41+
--custom-apprun "${CMAKE_BINARY_DIR}/AppRun"
42+
--icon-file "${APPDIR_PATH}/usr/share/icons/hicolor/256x256/apps/${CMAKE_PROJECT_NAME}.png"
43+
COMMAND_ECHO STDOUT
44+
COMMAND_ERROR_IS_FATAL ANY
45+
)
46+
47+
#===========================================================================#
48+
# Build the final AppImage
4049

4150
set(ENV{ARCH} ${CMAKE_SYSTEM_PROCESSOR})
42-
# set(ENV{VERSION} 5.0)
43-
execute_process(COMMAND ${APPIMAGETOOL_PATH} ${APPDIR_PATH})
51+
set(ENV{VERSION} ${CMAKE_PROJECT_VERSION})
52+
execute_process(
53+
COMMAND "${APPIMAGETOOL_PATH}" "${APPDIR_PATH}" "${APPIMAGE_PATH}"
54+
COMMAND_ECHO STDOUT
55+
COMMAND_ERROR_IS_FATAL ANY
56+
)
57+
58+
#===========================================================================#
59+
# Lint
60+
61+
if(EXISTS "${APPIMAGELINT_PATH}")
62+
execute_process(
63+
COMMAND "${APPIMAGELINT_PATH}" "${APPIMAGE_PATH}"
64+
RESULT_VARIABLE LINT_RESULT
65+
COMMAND_ECHO STDOUT
66+
)
67+
if(NOT LINT_RESULT EQUAL 0)
68+
message(WARNING "QGC: appimagelint reported problems; see log above")
69+
endif()
70+
endif()

cmake/install/Install.cmake

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,33 +38,43 @@ if(ANDROID)
3838
# cmake_print_variables(QGC_ANDROID_DEPLOY_FILE)
3939
elseif(LINUX)
4040
configure_file(
41-
${CMAKE_SOURCE_DIR}/deploy/linux/org.mavlink.qgroundcontrol.desktop.in
42-
${CMAKE_BINARY_DIR}/org.mavlink.qgroundcontrol.desktop
41+
"${QGC_APPIMAGE_DESKTOP_ENTRY_PATH}"
42+
"${CMAKE_BINARY_DIR}/${QGC_PACKAGE_NAME}.desktop"
4343
@ONLY
4444
)
4545
install(
46-
FILES ${CMAKE_BINARY_DIR}/org.mavlink.qgroundcontrol.desktop
47-
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
46+
FILES "${CMAKE_BINARY_DIR}/${QGC_PACKAGE_NAME}.desktop"
47+
DESTINATION "${CMAKE_INSTALL_DATADIR}/applications"
4848
)
4949
install(
50-
FILES ${QGC_APPIMAGE_ICON_PATH}
51-
DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/128x128/apps/
50+
FILES "${QGC_APPIMAGE_ICON_256_PATH}"
51+
DESTINATION "${CMAKE_INSTALL_DATADIR}/icons/hicolor/256x256/apps/"
5252
RENAME ${CMAKE_PROJECT_NAME}.png
5353
)
54+
install(
55+
FILES "${QGC_APPIMAGE_ICON_SCALABLE_PATH}"
56+
DESTINATION "${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps/"
57+
RENAME ${CMAKE_PROJECT_NAME}.svg
58+
)
5459
configure_file(
55-
${CMAKE_SOURCE_DIR}/deploy/linux/org.mavlink.qgroundcontrol.metainfo.xml.in
56-
${CMAKE_BINARY_DIR}/metainfo/org.mavlink.qgroundcontrol.metainfo.xml
60+
"${QGC_APPIMAGE_METADATA_PATH}"
61+
"${CMAKE_BINARY_DIR}/${QGC_PACKAGE_NAME}.appdata.xml"
5762
@ONLY
5863
)
5964
install(
60-
FILES ${CMAKE_BINARY_DIR}/metainfo/org.mavlink.qgroundcontrol.metainfo.xml
61-
DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo/
65+
PROGRAMS "${CMAKE_BINARY_DIR}/${QGC_PACKAGE_NAME}.appdata.xml"
66+
DESTINATION "${CMAKE_INSTALL_DATADIR}/metainfo/"
6267
)
6368
install(
64-
FILES ${CMAKE_SOURCE_DIR}/deploy/linux/AppRun
65-
DESTINATION ${CMAKE_BINARY_DIR}
69+
FILES "${QGC_APPIMAGE_APPRUN_PATH}"
70+
DESTINATION "${CMAKE_BINARY_DIR}/"
6671
)
67-
install(CODE "set(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")")
72+
install(CODE "
73+
set(CMAKE_PROJECT_NAME ${CMAKE_PROJECT_NAME})
74+
set(CMAKE_PROJECT_VERSION ${CMAKE_PROJECT_VERSION})
75+
set(QGC_PACKAGE_NAME ${QGC_PACKAGE_NAME})
76+
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR})
77+
")
6878
install(SCRIPT "${CMAKE_SOURCE_DIR}/cmake/install/CreateAppImage.cmake")
6979
elseif(WIN32)
7080
install(CODE "set(CMAKE_PROJECT_NAME ${CMAKE_PROJECT_NAME})")

custom-example/cmake/CustomOverrides.cmake

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
set(QGC_APP_NAME "Custom-QGroundControl" CACHE STRING "App Name" FORCE)
22

33
set(QGC_MACOS_ICON_PATH "${CMAKE_SOURCE_DIR}/custom/res" CACHE PATH "MacOS Icon Path" FORCE)
4-
set(QGC_APPIMAGE_ICON_PATH "${CMAKE_SOURCE_DIR}/custom/res/icons/custom_qgroundcontrol.png" CACHE FILEPATH "AppImage Icon Path" FORCE)
4+
5+
if(EXISTS "${CMAKE_SOURCE_DIR}/custom/res/icons/custom_qgroundcontrol.svg")
6+
set(QGC_APPIMAGE_ICON_SCALABLE_PATH "${CMAKE_SOURCE_DIR}/custom/res/icons/custom_qgroundcontrol.svg" CACHE FILEPATH "AppImage Icon SVG Path" FORCE)
7+
endif()
58

69
if(EXISTS ${CMAKE_SOURCE_DIR}/custom/deploy/windows/installheader.bmp)
710
set(QGC_WINDOWS_INSTALL_HEADER_PATH "${CMAKE_SOURCE_DIR}/custom/deploy/windows/installheader.bmp" CACHE FILEPATH "Windows Install Header Path" FORCE)
Lines changed: 12 additions & 0 deletions
Loading

deploy/linux/QGroundControl.svg

Lines changed: 11 additions & 0 deletions
Loading
31.6 KB
Loading

deploy/linux/_AppRun

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/bin/sh
2+
3+
HERE="$(dirname "$(readlink -f "${0}")")"
4+
5+
MAIN=$(grep -r "^Exec=.*" "$HERE"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1)
6+
7+
############################################################################################
8+
# Use bundled paths
9+
############################################################################################
10+
11+
export PATH="${HERE}"/usr/bin/:"${HERE}"/usr/sbin/:"${HERE}"/usr/games/:"${HERE}"/bin/:"${HERE}"/sbin/:"${PATH}"
12+
export XDG_DATA_DIRS="${HERE}"/usr/share/:"${XDG_DATA_DIRS}"
13+
14+
############################################################################################
15+
# Use bundled Python
16+
############################################################################################
17+
18+
export PYTHONHOME="${HERE}"/usr/
19+
20+
############################################################################################
21+
# Use bundled Tcl/Tk
22+
############################################################################################
23+
24+
if [ -e "${HERE}"/usr/share/tcltk/tcl8.6 ] ; then
25+
export TCL_LIBRARY="${HERE}"/usr/share/tcltk/tcl8.6:$TCL_LIBRARY:$TK_LIBRARY
26+
export TK_LIBRARY="${HERE}"/usr/share/tcltk/tk8.6:$TK_LIBRARY:$TCL_LIBRARY
27+
fi
28+
29+
############################################################################################
30+
# Make it look more native on Gtk+ based systems
31+
############################################################################################
32+
33+
case "${XDG_CURRENT_DESKTOP}" in
34+
*GNOME*|*gnome*)
35+
export QT_QPA_PLATFORMTHEME=gtk2
36+
esac
37+
38+
############################################################################################
39+
# If .ui files are in the AppDir, then chances are that we need to cd into usr/
40+
# because we may have had to patch the absolute paths away in the binary
41+
############################################################################################
42+
43+
UIFILES=$(find "$HERE" -name "*.ui")
44+
if [ ! -z "$UIFILES" ] ; then
45+
cd "$HERE/usr"
46+
fi
47+
48+
############################################################################################
49+
# Use bundled GStreamer
50+
# NOTE: May need to remove libgstvaapi.so
51+
############################################################################################
52+
53+
if [ ! -z $(find "${HERE}" -name "libgstcoreelements.so" -type f) ] ; then
54+
export GST_PLUGIN_PATH=$(dirname $(readlink -f $(find "${HERE}" -name "libgstcoreelements.so" -type f | head -n 1)))
55+
export GST_PLUGIN_SCANNER=$(find "${HERE}" -name "gst-plugin-scanner" -type f | head -n 1)
56+
export GST_PLUGIN_SYSTEM_PATH=$GST_PLUGIN_PATH
57+
env | grep GST
58+
fi
59+
60+
############################################################################################
61+
# Run experimental bundle that bundles everything if a private ld-linux-x86-64.so.2 is there
62+
# This allows the bundle to run even on older systems than the one it was built on
63+
############################################################################################
64+
65+
cd "$HERE/usr" # Not all applications will need this; TODO: Make this opt-in
66+
67+
# Try to find a binary with the same name as the AppImage or the symlink through which
68+
# it was invoked, without any suffix
69+
if [ -z "$ARGV0" ] ; then
70+
# AppRun is being executed outside of an AppImage
71+
ARGV0="$0"
72+
fi
73+
BINARY_NAME=$(basename "$ARGV0")
74+
if [ "$BINARY_NAME" = "AppRun" ] ; then
75+
unset BINARY_NAME
76+
fi
77+
78+
BINARY_NAME="${BINARY_NAME%.*}" # remove everything after the last "."
79+
MAIN_BIN=$(find "$HERE/usr/bin" -name "$BINARY_NAME" | head -n 1)
80+
81+
# Fall back to finding the main binary based on the Exec= line in the desktop file
82+
if [ -z "$MAIN_BIN" ] ; then
83+
MAIN_BIN=$(find "$HERE/usr/bin" -name "$MAIN" | head -n 1)
84+
fi
85+
86+
LD_LINUX=$(find "$HERE" -name 'ld-*.so.*' | head -n 1)
87+
88+
if [ -e "$LD_LINUX" ] ; then
89+
export GCONV_PATH="$HERE/usr/lib/gconv"
90+
export FONTCONFIG_FILE="$HERE/etc/fonts/fonts.conf"
91+
export GTK_PATH=$(find "$HERE/lib" -name gtk-* -type d)
92+
export GTK_THEME=Default # This one should be bundled so that it can work on systems without Gtk
93+
export GDK_PIXBUF_MODULEDIR=$(find "$HERE" -name loaders -type d -path '*gdk-pixbuf*')
94+
export GDK_PIXBUF_MODULE_FILE=$(find "$HERE" -name loaders.cache -type f -path '*gdk-pixbuf*') # Patched to contain no paths
95+
export XDG_DATA_DIRS="${HERE}"/usr/share/:"${XDG_DATA_DIRS}"
96+
export PERLLIB="${HERE}"/usr/share/perl5/:"${HERE}"/usr/lib/perl5/:"${PERLLIB}"
97+
export GSETTINGS_SCHEMA_DIR="${HERE}"/usr/share/glib-2.0/runtime-schemas/:"${HERE}"/usr/share/glib-2.0/schemas/:"${GSETTINGS_SCHEMA_DIR}"
98+
export QT_PLUGIN_PATH="$(readlink -f "$(dirname "$(find "${HERE}" -type d -path '*/plugins/platforms' 2>/dev/null)" 2>/dev/null)" 2>/dev/null)"
99+
case $line in
100+
"ld-linux"*) exec "${LD_LINUX}" --inhibit-cache "${MAIN_BIN}" "$@" ;;
101+
*) exec "${LD_LINUX}" "${MAIN_BIN}" "$@" ;;
102+
esac
103+
else
104+
exec "${MAIN_BIN}" "$@"
105+
fi

0 commit comments

Comments
 (0)