rbutil: Deploy support in cmake.

Add a "deploy" target that will create a distributable file.

- Linux: AppImage.
- Windows: zip file.
- MacOS: dmg.

Change-Id: Id8ae9c021bc5bbb1abf066205b57d943c3f3b327
This commit is contained in:
Dominik Riebeling 2021-12-23 11:12:31 +01:00
parent 4eb3f05042
commit 774b35cccf
4 changed files with 205 additions and 2 deletions

View file

@ -48,6 +48,8 @@ else()
find_package(Qt6 REQUIRED COMPONENTS Core Core5Compat Widgets Svg Multimedia Network LinguistTools
OPTIONAL_COMPONENTS Test)
endif()
get_target_property(_qmake_executable Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION)
get_filename_component(QT_BINDIR "${_qmake_executable}" DIRECTORY)
message("-- Found Qt${QT_VERSION_MAJOR}: ${Qt${QT_VERSION_MAJOR}_DIR}")
# If we're on Linux, try to find the used libs in the system.
@ -197,6 +199,13 @@ set_property(TARGET RockboxUtility PROPERTY AUTOMOC ON)
set_property(TARGET RockboxUtility PROPERTY AUTORCC ON)
set_property(TARGET RockboxUtility PROPERTY AUTOUIC ON)
include(${CMAKE_CURRENT_LIST_DIR}/cmake/deploy.cmake)
deploy_qt(RockboxUtility
${QT_BINDIR}
${CMAKE_CURRENT_LIST_DIR}/../docs/logo/rockbox-clef.svg
${CMAKE_CURRENT_LIST_DIR}/rbutilqt/RockboxUtility.desktop
${CMAKE_CURRENT_LIST_DIR}/rbutilqt/dmgbuild.cfg)
add_library(rbbase
${CMAKE_CURRENT_LIST_DIR}/../tools/iriver.c
${CMAKE_CURRENT_LIST_DIR}/../tools/iriver.h

141
utils/cmake/deploy.cmake Normal file
View file

@ -0,0 +1,141 @@
#
# __________ __ ___.
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
# \/ \/ \/ \/ \/
#
# All files in this archive are subject to the GNU General Public License.
# See the file COPYING in the source tree root for full license agreement.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# include this file to
# - get a new target "deploy"
# - get a function "deploy_qt()" which will add a deploy target that creates a
# zip / AppImage / dmg and depends on "deploy".
if(NOT have_deploy)
add_custom_target(deploy)
set(have_deploy ON)
endif()
# Linux: Build AppImage
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(LINUXDEPLOY ${CMAKE_CURRENT_BINARY_DIR}/linuxdeploy-x86_64.AppImage)
add_custom_command(
OUTPUT ${LINUXDEPLOY}
COMMAND ${CMAKE_COMMAND}
-DOUTDIR=${CMAKE_CURRENT_BINARY_DIR}
-DURL=https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
-P ${CMAKE_CURRENT_LIST_DIR}/download.cmake
COMMAND ${CMAKE_COMMAND}
-DOUTDIR=${CMAKE_CURRENT_BINARY_DIR}
-DURL=https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
-P ${CMAKE_CURRENT_LIST_DIR}/download.cmake
)
function(deploy_qt target qtbindir iconfile desktopfile dmgbuildcfg)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
message(WARNING "Deploying a Debug build.")
endif()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}.AppImage
COMMENT "Creating AppImage ${target}"
COMMAND OUTPUT=${CMAKE_CURRENT_BINARY_DIR}/${target}.AppImage
${LINUXDEPLOY}
--icon-file=${iconfile}
--desktop-file=${desktopfile}
--executable=$<TARGET_FILE:${target}>
--appdir=AppImage-${target}
--output=appimage
--verbosity=2
DEPENDS ${target}
${LINUXDEPLOY}
)
add_custom_target(deploy_${target}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${target}.AppImage)
add_dependencies(deploy deploy_${target})
endfunction()
endif()
# MacOS: Build dmg
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
function(deploy_qt target qtbindir iconfile desktopfile dmgbuildcfg)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
message(WARNING "Deploying a Debug build.")
endif()
set(DMGBUILD ${CMAKE_CURRENT_BINARY_DIR}/venv/bin/dmgbuild)
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${qtbindir}")
add_custom_command(
COMMENT "Setting up dmgbuild virtualenv"
OUTPUT ${DMGBUILD}
COMMAND python3 -m venv ${CMAKE_CURRENT_BINARY_DIR}/venv
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/venv/bin/python -m pip install -q dmgbuild biplist
)
add_custom_command(
# TODO: find a better way to figure the app bundle name.
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}.dmg
COMMENT "Running macdeployqt and creating dmg ${target}"
COMMAND ${MACDEPLOYQT_EXECUTABLE} ${target}.app
COMMAND ${DMGBUILD} -s ${dmgbuildcfg}
-Dappbundle=${target}.app
${target} ${CMAKE_CURRENT_BINARY_DIR}/${target}.dmg
DEPENDS ${target}
${DMGBUILD}
)
add_custom_target(deploy_${target}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${target}.dmg)
add_dependencies(deploy deploy_${target})
endfunction()
endif()
# Windows. Copy to dist folder, run windeployqt on the binary, compress to zip.
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
function(deploy_qt target qtbindir iconfile desktopfile dmgbuildcfg)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
message(WARNING "Deploying a Debug build.")
endif()
set(_targetfile ${target}.exe) # TODO: Use property. OUTPUT_NAME seems to fail.
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${qtbindir}")
set(deploydir ${CMAKE_CURRENT_BINARY_DIR}/deploy-${target})
if(WINDEPLOYQT_EXECUTABLE)
add_custom_command(
COMMENT "Creating deploy folder and running windeployqt"
OUTPUT ${deploydir}/${_targetfile}
COMMAND ${CMAKE_COMMAND} -E make_directory ${deploydir}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_targetfile} ${deploydir}
COMMAND ${WINDEPLOYQT_EXECUTABLE}
$<IF:$<CONFIG:Debug>,--debug,--release> # on MinGW, release is mistaken as debug.
${deploydir}/${_targetfile}
DEPENDS ${target}
)
else()
add_custom_command(
COMMENT "Creating deploy folder"
OUTPUT ${deploydir}/${_targetfile}
COMMAND ${CMAKE_COMMAND} -E make_directory ${deploydir}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_targetfile} ${deploydir}
DEPENDS ${target}
)
endif()
add_custom_command(
COMMENT "Compressing to zip"
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}.zip
WORKING_DIRECTORY ${deploydir}
COMMAND ${CMAKE_COMMAND} -E tar c ${CMAKE_CURRENT_BINARY_DIR}/${target}.zip
--format=zip .
DEPENDS ${deploydir}/${_targetfile}
)
add_custom_target(deploy_${target}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${target}.zip)
add_dependencies(deploy deploy_${target})
endfunction()
endif()

View file

@ -0,0 +1,47 @@
#
# __________ __ ___.
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
# \/ \/ \/ \/ \/
#
# All files in this archive are subject to the GNU General Public License.
# See the file COPYING in the source tree root for full license agreement.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# This is a separate cmake script, to be invoked as
# cmake -P -DURL=<url-to-download> -DOUTDIR=<output-folder>
# Downloads the file and store it in OUTDIR, using the file basename as output
# filename.
# The downloaded file gets its executable flag set.
function(gettempdir basedir tmpdir)
# Create a random filename in current directory.
# Result stored in tmpdir.
string(RANDOM LENGTH 24 _tmp)
while(EXISTS "${basedir}/${_tmp}.tmp")
string(RANDOM LENGTH 24 _tmp)
endwhile()
set("${tmpdir}" "${basedir}/${_tmp}.tmp" PARENT_SCOPE)
endfunction()
get_filename_component(fname "${URL}" NAME)
if(EXISTS "${OUTDIR}/${fname}")
message("-- Found ${fname}")
else()
message("-- Downloading ${URL} ...")
gettempdir(${OUTDIR} tmp)
# cmake CHOWN is 3.19+, thus download to a temporary folder, then copy.
file(DOWNLOAD "${URL}" "${tmp}/${fname}")
file(COPY "${tmp}/${fname}" DESTINATION "${OUTDIR}"
FILE_PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ)
file(REMOVE_RECURSE "${tmp}")
endif()

View file

@ -1,9 +1,15 @@
# Configuration for creating a dmg with dmgbuild
# (https://github.com/al45tair/dmgbuild)
# Needs biplist as additional package.
import os
import biplist
files = [ 'RockboxUtility.app' ]
_appbundle = defines['appbundle']
_plist = biplist.readPlist(os.path.join(_appbundle, 'Contents/Info.plist'))
_iconfile = os.path.join(_appbundle, 'Contents/Resources', _plist['CFBundleIconFile'])
files = [ _appbundle ]
icon = _iconfile
background = '#c6d6f5'
icon = os.path.join(defines['basepath'], 'rbutilqt/icons/rbutilqt.icns')