Skip to content

Commit

Permalink
Add support for CPack generation of TGZ, DEB, RPM and Windows installer
Browse files Browse the repository at this point in the history
On linux we now support auto generation of .deb and .rpm package files.
A desktop file is also added to make the emusc application show up in Linux
desktop environments.

On Windows the NSIS installer creates an installation program including
all files needed to run emusc, and develope on libemusc, on any modern
version of windows.

A pkg-config file was added to libemusc to simplify external use of the
library.
  • Loading branch information
skjelten committed Nov 13, 2024
1 parent ed662b1 commit 9ee81ae
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 49 deletions.
132 changes: 130 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,142 @@
cmake_minimum_required(VERSION 3.7...3.24)
# CMake & Cpack definitions for EmuSC project

# The project consists of a total of 5 CMakeList.txt files. This root file is
# primarily used for convinience (build both GUI client and library) and for
# Cpack generators covering both client and library.

cmake_minimum_required(VERSION 3.12...3.30)

project(
emusc
VERSION 0.2.0
HOMEPAGE_URL "https://github.com/skjelten/emusc"
LANGUAGES CXX)

option(emusc_WITH_EMUSC_CLIENT "Build GUI client application" TRUE)

add_subdirectory(libemusc)

if (emusc_WITH_EMUSC_CLIENT)
add_subdirectory(emusc)
add_dependencies(emusc-client emusc)
endif()

# CPack support
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Roland SC-55 synth emulator")
set(CPACK_PACKAGE_VENDOR "skjelten.org")
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/emusc/res/icons/32x32/emusc.png")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "EmuSC")
set(CPACK_PACKAGE_EXECUTABLES "emusc" "SC-55 synth emulator")
set(CPACK_PACKAGE_CONTACT "[email protected]")

set(CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${CMAKE_PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${CMAKE_PROJECT_VERSION_PATCH})

set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/emusc/COPYING")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")

# Source packages
set(CPACK_SOURCE_GENERATOR TGZ)
set(CPACK_SOURCE_IGNORE_FILES "${CPACK_SOURCE_IGNORE_FILES}")
# use .gitognore?
set(CPACK_SOURCE_PACKAGE_FILE_NAME "emusc-${PROJECT_VERSION}")
set(CPACK_SOURCE_STRIP_FILES ON)

# DEB and RPM specifc variables
if(UNIX AND NOT APPLE)
set(CPACK_COMPONENTS_GROUPING IGNORE)

set(CPACK_DEB_COMPONENT_INSTALL ON)
set(CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS ON)

# Note: This hack only works for CMAKE >= 3.20
# On CMAKE < 3.20 uncomment RPATH stuff in emusc/CMakeList.txt
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS "../lib/usr/lib")

# DEB common settings for all components
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Håkon Skjelten <${CPACK_PACKAGE_CONTACT}>")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/skjelten/emusc")
set(CPACK_DEBIAN_PACKAGE_SECTION "sound")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON)
set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY ">=")

# DEB component specific settings
set(CPACK_DEBIAN_BIN_PACKAGE_NAME "emusc")
set(CPACK_DEBIAN_BIN_FILE_NAME DEB-DEFAULT)
set(CPACK_DEBIAN_BIN_PACKAGE_DEPENDS "libemusc (>= ${PROJECT_VERSION})")

set(CPACK_DEBIAN_LIB_PACKAGE_NAME "libemusc")
set(CPACK_DEBIAN_LIB_FILE_NAME DEB-DEFAULT)

set(CPACK_DEBIAN_DEV_PACKAGE_NAME "libemusc-dev")
set(CPACK_DEBIAN_DEV_FILE_NAME DEB-DEFAULT)
set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "pkgconf")

# RPM common settings for all components
set(CPACK_RPM_COMPONENT_INSTALL ON)
set(CPACK_RPM_PACKAGE_LICENSE "GPLv3+")

# RPM component specific settings
set(CPACK_RPM_BIN_PACKAGE_NAME "emusc")
set(CPACK_RPM_BIN_FILE_NAME RPM-DEFAULT)
set(CPACK_RPM_BIN_PACKAGE_DEPENDS "libemusc (>= ${PROJECT_VERSION})")

set(CPACK_RPM_LIB_PACKAGE_NAME "libemusc")
set(CPACK_RPM_LIB_FILE_NAME RPM-DEFAULT)

set(CPACK_RPM_DEV_PACKAGE_NAME "libemusc-devel")
set(CPACK_RPM_DEV_FILE_NAME RPM-DEFAULT)
set(CPACK_RPM_DEV_PACKAGE_DEPENDS "pkgconf")
set(CPACK_RPM_DEV_PACKAGE_ARCHITECTURE "noarch")

# Windows (NSIS) specific variables
elseif(WIN32)
set(CPACK_NSIS_PACKAGE_NAME "EmuSC")
set(CPACK_NSIS_DISPLAY_NAME "EmuSC ${CMAKE_PROJECT_VERSION}")
set(CPACK_NSIS_HELP_LINK "https://github.com/skjelten/emusc/wiki")
set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/skjelten/emusc")
set(CPACK_NSIS_CONTACT "https://github.com/skjelten/emusc")
set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/emusc/res/icons\\\\emusc.ico")
set(CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP "${CMAKE_CURRENT_SOURCE_DIR}/emusc/res/images/installers\\\\nsis_welcome.bmp")
set(CPACK_NSIS_MUI_HEADERIMAGE "${CMAKE_CURRENT_SOURCE_DIR}/emusc/res/images/installers\\\\nsis_header.bmp")
set(CPACK_NSIS_MODIFY_PATH OFF)
set(CPACK_NSIS_BRANDING_TEXT "EmuSC v${CMAKE_PROJECT_VERSION}")

elseif(APPLE)
set(CPACK_DMG_VOLUME_NAME "EmuSC")
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_CURRENT_SOURCE_DIR}/emusc/res/images/installers/dmg_background.png")

endif()

include(CPack)

cpack_add_component(bin
DISPLAY_NAME "EmuSC"
DESCRIPTION "Application for reading MIDI input and generating SC-55 audio PCM"
INSTALL_TYPES "User"
GROUP Runtime)
cpack_add_component(lib
DISPLAY_NAME "EmuSC Library"
DESCRIPTION "Library used to build and run programs generating SC-55 audio (libemusc)"
DISABLED
INSTALL_TYPES "Developer"
GROUP Development)
cpack_add_component(dev
DISPLAY_NAME "C++ Headers"
DESCRIPTION "C++ header files needed for developers to create new software using the EmuSC Library (libemusc)"
DISABLED
INSTALL_TYPES "Developer"
GROUP Development
DEPENDS lib)

cpack_add_component_group(Runtime
DISPLAY_NAME "Runtime"
DESCRIPTION "End user software for emulating the SoundCanvas"
EXPANDED)

cpack_add_component_group(Development
DISPLAY_NAME "Development"
DESCRIPTION "Development files for creating new applications based on EmuSC (libemusc)"
EXPANDED)
96 changes: 58 additions & 38 deletions emusc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
cmake_minimum_required(VERSION 3.8...3.24)
cmake_minimum_required(VERSION 3.12...3.30)

project(emusc-client VERSION 0.2.0 LANGUAGES CXX)
project(
emusc-client
VERSION 0.2.0
HOMEPAGE_URL "https://github.com/skjelten/emusc"
LANGUAGES CXX)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

include(GNUInstallDirs)

set(USE_MACOS_BUNDLE "no")

set(ALSA_AUDIO "no")
Expand Down Expand Up @@ -102,6 +104,10 @@ find_library(COREMIDI_LIBRARY CoreMIDI)

endif()

# Hack to make CPACK_DEBIAN_BIN_PACKAGE_SHLIBDEPS work properly (CMAKE < 3.20)
#set(CMAKE_INSTALL_RPATH "../lib/usr/lib")
#set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

add_subdirectory(src)

if(APPLE)
Expand All @@ -117,46 +123,60 @@ endif()
set(WAV_AUDIO "yes")
target_compile_definitions(emusc-client PUBLIC __WAV_AUDIO__)

install(TARGETS emusc-client DESTINATION ${CMAKE_INSTALL_BINDIR})
include(GNUInstallDirs)

install(TARGETS emusc-client DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT bin)
install(FILES AUTHORS ChangeLog COPYING NEWS README.md
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/emusc)
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/emusc COMPONENT bin)

if(UNIX AND NOT APPLE)
install(FILES res/emusc.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications COMPONENT bin)
foreach(EMUSC_ICON_RESOLUTION 16x16;32x32;128x128;256x256;512x512)
install(FILES res/icons/${EMUSC_ICON_RESOLUTION}/emusc.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${EMUSC_ICON_RESOLUTION}/apps COMPONENT bin)
endforeach(EMUSC_ICON_RESOLUTION)
endif(UNIX AND NOT APPLE)

message(STATUS "")
message(STATUS " EmuSC client interface summary: ")
message(STATUS "-===============================-")
message(STATUS "")
message("\n"
" EmuSC client summary:\n"
"-=====================-\n")

if(APPLE)
message(STATUS "Platform: macOS")
message(STATUS " * Build bundle: ${USE_MACOS_BUNDLE}")
message(" Platform: macOS")
elseif(UNIX)
message(STATUS "Platform: UNIX")
message(" Platform: UNIX")
elseif(WIN32)
message(STATUS "Platform: Windows")
message(STATUS " * Debug console: ${WIN32_EXECUTABLE}")
message(" Platform: Windows\n"
" * Debug console: ${WIN32_EXECUTABLE}")
else()
message(STATUS "Platform: unkown")
message(" Platform: unkown")
endif()

message("\n"
" Qt version: Qt${QT_VERSION_MAJOR}\n"
" QtCharts: ${USE_QTCHARTS}\n"
"\n"
" Audio APIs:\n"
" * ALSA : ${ALSA_AUDIO}\n"
" * Core : ${CORE_AUDIO}\n"
" * Jack : ${JACK_AUDIO}\n"
" * Null : yes\n"
" * Pulse : ${PULSE_AUDIO}\n"
" * Qt : ${QT_AUDIO}\n"
" * WAV : ${WAV_AUDIO}\n"
" * Win32 : ${WIN32_AUDIO}\n"
"\n"
" MIDI APIs:\n"
" * ALSA : ${ALSA_MIDI}\n"
" * Core : ${CORE_MIDI}\n"
" * Win32 : ${WIN32_MIDI}\n"
"\n"
" Make sure all needed APIs are found before you continue\n"
"\n")

# CPack support
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)

if(CMAKE_CURRENT_BINARY_DIR STREQUAL CMAKE_BINARY_DIR)
include(CPack)
endif()

message(STATUS "")
message(STATUS "Qt version: Qt${QT_VERSION_MAJOR}")
message(STATUS "QtCharts: ${USE_QTCHARTS}")

message(STATUS "")
message(STATUS "Audio APIs:")
message(STATUS " * ALSA : ${ALSA_AUDIO}")
message(STATUS " * Core : ${CORE_AUDIO}")
message(STATUS " * Jack : ${JACK_AUDIO}")
message(STATUS " * Null : yes")
message(STATUS " * Pulse : ${PULSE_AUDIO}")
message(STATUS " * Qt : ${QT_AUDIO}")
message(STATUS " * WAV : ${WAV_AUDIO}")
message(STATUS " * Win32 : ${WIN32_AUDIO}")
message(STATUS "")
message(STATUS "MIDI APIs:")
message(STATUS " * ALSA : ${ALSA_MIDI}")
message(STATUS " * Core : ${CORE_MIDI}")
message(STATUS " * Win32 : ${WIN32_MIDI}")
message(STATUS "")
message(STATUS "Make sure all needed APIs are found before you continue")
message(STATUS "")
10 changes: 10 additions & 0 deletions emusc/res/emusc.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Desktop Entry]
Name=EmuSC
Comment=Roland SC-55 synth emulator
Exec=emusc
Icon=emusc
NoDisplay=false
Terminal=false
Type=Application
Categories=AudioVideo;Audio;Midi;
Keywords=Midi;Music;Synth;Emulator;SoundCanvas;SC-55;
Binary file added emusc/res/images/installers/nsis_header.bmp
Binary file not shown.
Binary file added emusc/res/images/installers/nsis_welcome.bmp
Binary file not shown.
22 changes: 21 additions & 1 deletion emusc/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.8...3.24)
cmake_minimum_required(VERSION 3.8...3.30)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
Expand Down Expand Up @@ -100,4 +100,24 @@ if (APPLE)
elseif(WIN32)
set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/../res/emusc-win32.rc")
target_sources(emusc-client PRIVATE ${APP_ICON_RESOURCE_WINDOWS})

# On Windows we need to deploy QT together with all other dependent shared
# libraries (DLLs) to create a self contained installer package.
# This seems to be surprisingly hard to do properly with cmake on Windows,
# but we hack around this problem by calling a shell script in the utils
# directory to extract the relevant files and then add them to the install.
# Note that this hack only works for MSYS2 based installation environments in
# Windows, i.e. Visual Studio users needs to find another solution to this
# problem. There is also no logic to select the correct DLLs, e.g. debug vs
# release etc. A better solution might be to use
# $<TARGET_RUNTIME_DLLS:${TARGET}> in the future (requires CMake > 3.21).
if(MINGW)
# Copy all DLLs and QT plugins that emusc.exe and libemusc.dll depends on
# in a separate directory
add_custom_command(TARGET emusc-client POST_BUILD
COMMAND bash -c "${CMAKE_CURRENT_SOURCE_DIR}/../utils/msys_copy_all_dlls.sh ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../DLLs")

# Include all DLLs and QT plugins to bin
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../DLLs/" DESTINATION bin COMPONENT bin)
endif()
endif()
63 changes: 63 additions & 0 deletions emusc/utils/msys_copy_all_dlls.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/bin/bash
# Shell script for deploying QT and extracting all other relevant DLL files on
# a Windows system running in a MSYS2 environment.
# Part of the EmuSC project: https://github.com/skjelten/emusc

DEPLOYCMD=""

if command -v windeployqt.exe &> /dev/null
then
DEPLOYCMD="windeployqt.exe"
fi

if [ -z $DEPLOYCMD ]
then
if command -v windeployqt6.exe &> /dev/null
then
DEPLOYCMD="windeployqt6.exe"
else
echo "Error: windeployqt.exe / windeployqt6.exe is not in PATH. Install the Qt tools package, e.g. 'pacman -S mingw-w64-ucrt-x86_64-qt6-tools' if you are using Qt6."
exit 1
fi
fi

if ! command -v ldd &> /dev/null
then
echo "Error: ldd is not in PATH. Install GCC or fix your PATH variable."
exit 1
fi

if [ $# -ne 2 ]; then
echo "Usage: msys_copy_all_dlls.sh SRC_DIRECTORY_WITH_EMUSC.EXE DEST_DIRECTORY"
exit 1
fi

if [ ! -d "$1" ]; then
echo "Error: $1 is not a valid directory"
exit 1
fi

if [ ! -f "$1/emusc.exe" ]; then
echo "Error: $1 is not a valid directory (missing emusc.exe)"
exit 1
fi

if [ ! -d "$2" ]; then
mkdir $2
if [ ! -d "$2" ]; then
echo "Error: The directory $2 does not exist and unable create it."
exit 1
fi
fi

# 1. Deply QT

echo "$DEPLOYCMD --no-translations --dir $2 --no-compiler-runtime --no-translations --verbose 1 $1/emusc.exe" | bash

# 2. Copy libemusc.dll
cp $1/../../libemusc/src/libemusc.dll $2

# 3. Find and copy all other DLL-files needed to run emusc.exe
# Note that the ldd command must to be run in the folder with all the DLLs
cd $2
ldd $1/emusc.exe | grep -iv system32 | grep -iv windows | grep -iv qt5 | grep -iv qt6 | grep -iv "not found" | cut -f2 -d\> | cut -f1 -d\( | tr '\\' / | while read a; do cp "$a" "$2"; done
Loading

0 comments on commit 9ee81ae

Please sign in to comment.