mirror of
https://github.com/clangen/musikcube.git
synced 2025-01-11 21:39:27 +00:00
Improve cross-compile support (#634)
* Update minimum CMake version requirement to get rid of warning. * Include CMake compile commands for easier diagnostics. * More improvements to arm toolchain selection while cross-compiling third-party dependencies. * Use x-tools provided cmake toolchains * Add a script to download and extract deb dependencies for crosscompile. * Link against libstdc++ statically when cross-compiling to ARM to improve portability. * Update GeneratePackage.cmake to generate better filenames. * Ensure symbols are stripped properly when cross-compiling * Remove old scripts that are no longer required * Add script to install x-tools * Add some docs that describe how to setup a crosscompile environment. * Add docs for building standlone on Linux * Update CHANGELOG * Update version hash.
This commit is contained in:
parent
e422c4a928
commit
4f44829cda
@ -4,6 +4,7 @@ macro(find_vendor_library target_var library_name)
|
||||
endmacro(find_vendor_library)
|
||||
|
||||
macro(find_header header_name)
|
||||
set(TEMP "")
|
||||
find_path(TEMP ${header_name} HINTS ${PROJECT_INCLUDE_DIRECTORIES} REQUIRED NO_CACHE)
|
||||
if (${TEMP} MATCHES "TEMP-NOTFOUND")
|
||||
message(STATUS "[dependency-detection] ${BoldRed}'${header_name}' COULD NOT BE FOUND!${ColorReset}")
|
||||
|
@ -57,12 +57,14 @@ if (${GENERATE_DEB} MATCHES "true" AND CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "casey langen")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${PACKAGE_ARCHITECTURE})
|
||||
set(CPACK_DEBIAN_FILE_NAME "musikcube_${musikcube_VERSION_MAJOR}.${musikcube_VERSION_MINOR}.${musikcube_VERSION_PATCH}_${FRIENDLY_ARCHITECTURE_NAME}.deb")
|
||||
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "BSD-3-Clause")
|
||||
set(CPACK_RPM_PACKAGE_URL "https://www.musikcube.com")
|
||||
set(CPACK_RPM_PACKAGE_VERSION "${musikcube_VERSION_MAJOR}.${musikcube_VERSION_MINOR}.${musikcube_VERSION_PATCH}")
|
||||
set(CPACK_RPM_REQUIRES_EXCLUDE_FROM "^/.*$")
|
||||
if (${PACKAGE_ARCHITECTURE} MATCHES "amd64")
|
||||
set(CPACK_RPM_FILE_NAME "musikcube_${musikcube_VERSION_MAJOR}.${musikcube_VERSION_MINOR}.${musikcube_VERSION_PATCH}_${FRIENDLY_ARCHITECTURE_NAME}.rpm")
|
||||
if (${PACKAGE_ARCHITECTURE} MATCHES "amd64")
|
||||
# debs use `amd64`, but rpm uses `x86_64`. both seem to agree on other architecture values.
|
||||
message(STATUS "[GeneratePackage] ${BoldYellow}set RPM architecture to x86_64${ColorReset}")
|
||||
set(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64")
|
||||
|
4
.cmake/RaspberryPiToolchain-armv6.cmake
Normal file
4
.cmake/RaspberryPiToolchain-armv6.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
include("/build/x-tools/armv6-rpi-linux-gnueabihf/armv6-rpi-linux-gnueabihf.toolchain.cmake")
|
||||
set(CROSS_COMPILE_SYSROOT /build/x-tools/armv6-rpi-linux-gnueabihf/armv6-rpi-linux-gnueabihf/sysroot)
|
||||
set(CROSS_COMPILE_PKG_CONFIG_PATH "${CROSS_COMPILE_SYSROOT}/usr/lib/arm-linux-gnueabi/pkgconfig")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++")
|
4
.cmake/RaspberryPiToolchain-armv8.cmake
Normal file
4
.cmake/RaspberryPiToolchain-armv8.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
include("/build/x-tools/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf.toolchain.cmake")
|
||||
set(CROSS_COMPILE_SYSROOT /build/x-tools/armv8-rpi3-linux-gnueabihf/armv8-rpi3-linux-gnueabihf/sysroot)
|
||||
set(CROSS_COMPILE_PKG_CONFIG_PATH "${CROSS_COMPILE_SYSROOT}/usr/lib/arm-linux-gnueabi/pkgconfig")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++")
|
@ -1,15 +0,0 @@
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
|
||||
set(CROSS_COMPILE_SYSROOT /build/rpi/sysroot)
|
||||
set(CROSS_COMPILE_PKG_CONFIG_PATH "${CROSS_COMPILE_SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig")
|
||||
|
||||
set(CMAKE_SYSROOT ${CROSS_COMPILE_SYSROOT})
|
||||
|
||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -20,6 +20,7 @@ dist
|
||||
bin
|
||||
bin32
|
||||
bin64
|
||||
compile_commands.json
|
||||
ipch
|
||||
build
|
||||
local-circle-ci.yml
|
||||
|
@ -9,6 +9,11 @@
|
||||
* fixed 64-bit RPM architecture value (was `amd64`, but should be `x86_64`)
|
||||
* updated musikdroid to latest version of Android Studio and external
|
||||
dependencies (anecdotally improving Opus playback reliability)
|
||||
* updated to openssl@3.1.2, libcurl@8.2.1, libmicrohttpd@0.9.77 and
|
||||
libopenmpt@0.7.1 on unix platforms
|
||||
* re-wrote raspberry-pi/arm cross-compiling functionality to be more generic and
|
||||
use more well-maintained toolkits.
|
||||
* added `armv6` builds for Raspberry Pi Zero (and other similar devices)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
#cmake -DGENERATE_DEB=true -DPACKAGE_ARCHITECTURE=i386|amd64|armhf -DDEB_PLATFORM=ubuntu -DDEB_DISTRO=eoan -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release .
|
||||
#cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_STANDALONE=true .
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(musikcube)
|
||||
set (musikcube_VERSION_MAJOR 3)
|
||||
@ -48,10 +48,6 @@ else()
|
||||
message(STATUS "[cross-compile] not enabled!")
|
||||
endif()
|
||||
|
||||
message(STATUS "[vendor-link-directories] ${VENDOR_LINK_DIRECTORIES}")
|
||||
message(STATUS "[vendor-include-directories] ${VENDOR_INCLUDE_DIRECTORIES}")
|
||||
message(STATUS "[os-system-libs] ${DEFAULT_OS_SYSTEM_LIBS}")
|
||||
|
||||
list(
|
||||
APPEND
|
||||
PROJECT_INCLUDE_DIRECTORIES
|
||||
@ -66,6 +62,11 @@ include_directories(${PROJECT_INCLUDE_DIRECTORIES})
|
||||
|
||||
link_directories("${musikcube_SOURCE_DIR}/bin/plugins")
|
||||
|
||||
message(STATUS "[vendor-link-directories] ${VENDOR_LINK_DIRECTORIES}")
|
||||
message(STATUS "[vendor-include-directories] ${VENDOR_INCLUDE_DIRECTORIES}")
|
||||
message(STATUS "[os-system-libs] ${DEFAULT_OS_SYSTEM_LIBS}")
|
||||
message(STATUS "[project-include-directories] ${PROJECT_INCLUDE_DIRECTORIES}")
|
||||
|
||||
# these are used to (1) disable the standalone ASIO from trying to use
|
||||
# boost, and (2) instruct websocketpp to use standalone (not boost) ASIO
|
||||
add_definitions(
|
||||
|
69
doc/build-standalone-unix.md
Normal file
69
doc/build-standalone-unix.md
Normal file
@ -0,0 +1,69 @@
|
||||
# Overview
|
||||
|
||||
By default when you build `musikcube` it's almost exclusively tied to your Linux distribution and version. If you try to copy the binaries compiled from `Ubuntu` to `Fedora`, for example, they probably won't work.
|
||||
|
||||
It turns out that building a single C++ app once that works across many Linux distributions and versions can be very challenging, especially when there are external dependencies involved. The difficulties have been documented and discussed countless times and include, but are not limited to:
|
||||
|
||||
1. Incompatible `GLIBC`/`GLIBCXX` versions
|
||||
3. Incompatible versions of required dependencies
|
||||
4. Incompatible locations of required dependencies (e.g. `/lib` vs `/usr/lib` vs `/usr/local/lib`)
|
||||
5. Incompatible filenames for required depdencies (eg `libfoo.so.3` vs `libfoo.so`)
|
||||
6. General unavailability of required dependencies (i.e. "dependency `foo` doesn't exist in `Ubuntu`'s `apt`")
|
||||
|
||||
In an ideal world we wouldn't have to worry about these problems, and `musikcube` would be available via all major Linux distribution package management systems. In practice, however, it's not. It can take tremendous time and effort to get packages accepted upstream by maintainers. For example, see the [DebianMentorsFaq](https://wiki.debian.org/DebianMentorsFaq).
|
||||
|
||||
So, for now, we've developed a process that allows us to compile "generic" binaries once per CPU architecture that should generally work across most modern Linux distributions without hassle. In short, we do the following:
|
||||
|
||||
1. Compile using an operating system with versions of `GLIBC` and `GLIBCXX` that should work on any Linux distribution from 2018 to now. We currently use `Debian Buster`.
|
||||
2. Include modern versions of fundamental dependencies (`openssl`, `curl`, `ffmpeg` and others), compiled from source, ommitting any unused/extraneous functionality.
|
||||
3. Ensure the app is "relocatable" on the filesystem; all libraries are loaded via relative paths so you can put the `musikcube` directory wherever you want and it'll still run. This is done by manually rewriting `rpath` values for shared libraries and executables where necessary.
|
||||
|
||||
The rest of this document will describe how we produce these builds, which are what we distribute on our [Github project page](https://github.com/clangen/musikcube/releases) for all releases.
|
||||
|
||||
Regular build instructions can be found on the [Github project page, here](https://github.com/clangen/musikcube/wiki/building), and have fewer weird prerequisites.
|
||||
|
||||
# Instructions
|
||||
|
||||
## Install `Debian Buster`
|
||||
|
||||
It's probably easiest to just install a `docker` image and use that, but an install straight to physical hardware (or a virtual machine) will work just fine.
|
||||
|
||||
## Install dependencies
|
||||
|
||||
### From `apt-get`:
|
||||
- `sudo apt update`
|
||||
- `sudo apt dist-upgrade`
|
||||
- `sudo apt install build-essential g++ gcc git libasound2-dev libev-dev libncurses-dev libopus-dev libopus-dev libopus0 libpulse-dev libsndio-dev libssl-dev libsystemd-dev libvorbis-dev libvorbis-dev libvorbis0a libvorbisenc2 portaudio19-dev rpm wget zlib1g-dev`
|
||||
|
||||
### Compile from source:
|
||||
|
||||
Install the following from source, as the distro-provided packages are too old:
|
||||
- `cmake` v3.27.4+
|
||||
- `pipewire` v0.3.x (optional -- only if you want to use `pipewire`)
|
||||
|
||||
## Provision your build directory
|
||||
|
||||
A couple build steps assume that you'll be building from the `/build` directory. This can either be a physical directory or a symlink to elsewhere. This is currently a hard-requirement, but may not be in the future. Sorry.
|
||||
|
||||
- `cd /build`
|
||||
- `git clone https://github.com/clangen/musikcube.git --recursive`
|
||||
|
||||
## Compile third-party dependencies
|
||||
|
||||
As mentioned above, a number of larger third-party dependencies are compiled from source, stripping unused functionality to ensure they are as small and efficient as possible. Doing this manually is really annoying, so it's all been automated behind a script.
|
||||
|
||||
- `cd /build`
|
||||
- `./musikcube/script/build-vendor-libraries.sh`
|
||||
|
||||
This process may take a while, but when it completes you'll be left with a `/build/vendor-${arch}` directory that will contain all build artifacts. The `musikcube` app compile will reference this directory during its build process.
|
||||
|
||||
## Compile `musikcube`
|
||||
|
||||
Now that we have all required dependencies available it's time to compile the app itself. As mentioned above we want the resulting binary to be relocatable on the filesystem, so some special pre- and post-processing must happen. Specifically: we need to gather copies of all dependencies and rewrite their `rpaths` if necessary. We also need to collect and include resource files like themes and localization files, then create `.deb`, `.rpm`, and `.tar.bz2` archives for distribution. As in the previous step all of this complexity has been hidden behind a script.
|
||||
|
||||
- `cd /build/musikcube`
|
||||
- `./script/archive-standalone-nix.sh x.y.z`
|
||||
- `x.y.z` is the version of `musikcube` we'd like to appear in the filename. You can use anything you want, e.g. `0.0.0`
|
||||
- The build process will automatically discover and use the `/build/vendor-${arch}` directory created in the previous step.
|
||||
|
||||
After the script has completed you should have a set of "relocatable" binaries in `/build/musikcube/dist/x.y.z/` that will work on most Linux distributions released in 2018 or later.
|
48
doc/crosscompile-rpi.md
Normal file
48
doc/crosscompile-rpi.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Prerequisites
|
||||
|
||||
Cross compiling depends on:
|
||||
|
||||
- A working "standalone" build environment ([see here](build-standalone-unix.md))
|
||||
- A working Raspberry Pi `Buster` environment, either via `chroot` ([see here](rpi-buster-chroot.md)) or on a physical device
|
||||
|
||||
# Gather dependencies from a Raspbian install
|
||||
|
||||
The cross-compile toolchain ships with a minimal system "image" that does not include all of the third-party dependencies we need to compile musikcube.
|
||||
|
||||
To obtain these dependencies we need to boot into the chroot environment and execute a script to download and collect the latest versions of the headers and libraries so we can add them to the cross-compile toolchain.
|
||||
|
||||
1. Enter the `chroot` environment (or boot your device)
|
||||
2. `apt-get update`
|
||||
3. `sudo apt-get dist-upgrade`
|
||||
4. `cd /build/sysroot`
|
||||
5. `node /build/musikcube/script/create-crosscompile-sysroot.js`
|
||||
|
||||
After this process completes you will be left with a file called `sysroot.tar`.
|
||||
|
||||
# Install the cross-compile toolchain
|
||||
|
||||
The cross-compile toochains that ship with Debian and Ubuntu generally do not fully support `armv6`, which means we cannot use them to generate builds for older Raspberry Pi devices.
|
||||
|
||||
Instead, we'll install a better maintained toolchain from the following github project: https://github.com/tttapa/docker-arm-cross-toolchain
|
||||
|
||||
1. `cd /build`
|
||||
2. `cp /path/to/generated/sysroot/sysroot.tar .`
|
||||
3. `node /build/musikcube/script/install-crosscompile-tools.js`
|
||||
|
||||
This will download the cross-compile tools to the current directory, extract them, then use the `sysroot.tar` to populate the tools' environments.
|
||||
|
||||
# Use cross-compile toolchain to compile dependencies
|
||||
|
||||
In order to facilite easy, efficient distribution of musikcube binaries, we compile various dependencies ourselves, omitting unused features and ensuring the entire package is "relocatable," meaning users can run them from anywhere (i.e. they don't need to be installed to `/usr/` or `/usr/local/` to work properly).
|
||||
|
||||
1. `cd /build`
|
||||
2. `CROSSCOMPILE=rpi-armv6 ./musikcube/script/build-vendor-libraries.sh`
|
||||
|
||||
When this has finished, you'll be left with a `vendor-rpi-armv6` directory that the main app compile will reference.
|
||||
|
||||
# Build the main app
|
||||
|
||||
Now that we have all of our dependencies available it's time to compile the main app.
|
||||
|
||||
1. `cd /build/musikcube`
|
||||
2. `CROSSCOMPILE=rpi-armv6 ./script/archive-standalone-nix.sh 3.0.2`
|
71
doc/rpi-buster-chroot.md
Normal file
71
doc/rpi-buster-chroot.md
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
# Forward
|
||||
- stolen from here: https://medium.com/@crmoratelli/architectural-chroot-for-faster-compilation-and-deployment-on-raspberry-pi-76224327659d
|
||||
|
||||
# Install dependencies
|
||||
- `sudo apt install qemu-kvm qemu-user-static binfmt-support qemu-user-static qemu-utils kpartx e2fsprogs`
|
||||
|
||||
# Create a new directory
|
||||
- `mkdir rpi-buster-chroot`
|
||||
|
||||
# Download image
|
||||
- `wget https://downloads.raspberrypi.org/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2023-05-03/2023-05-03-raspios-buster-armhf-lite.img.xz`
|
||||
|
||||
# Extract image
|
||||
- `xz -d -v 2023-05-03-raspios-buster-armhf-lite.img.xz`
|
||||
|
||||
# Expand the image
|
||||
- `qemu-img resize -f raw 2023-05-03-raspios-buster-armhf-lite.img 16G`
|
||||
|
||||
# Expand the partition within the image
|
||||
- `fdisk 2023-05-03-raspios-buster-armhf-lite.img`
|
||||
- `Command: p` [prints the partition table. note partition #2's "Start" value.]
|
||||
- `Command: d` [delete a partition]
|
||||
- `Command: 2` [delete the Linux partition, which should be #2]
|
||||
- `Command: n` [add new partition]
|
||||
- `Command: p` [primary partition]
|
||||
- `Command: 2` [partition number]
|
||||
- `Command: ` [enter start value from first step]
|
||||
- `Command: ` [press enter to accept default value]
|
||||
- `Command: N` [to *NOT* remove the ext4 signature]
|
||||
- `Command: w` [write table to file]
|
||||
|
||||
# Create a mount point
|
||||
- `mkdir os-mount`
|
||||
|
||||
# Mount both disk imagen partitions via loopback
|
||||
- `sudo kpartx -a -v 2023-05-03-raspios-buster-armhf-lite.img`
|
||||
|
||||
output, note device names:
|
||||
```
|
||||
add map loop4p1 (253:0): 0 524288 linear 7:4 8192
|
||||
add map loop4p2 (253:1): 0 33021952 linear 7:4 532480 <== THIS IS OUR ACTUAL OS
|
||||
```
|
||||
|
||||
# Mount the second partition to the filesystem
|
||||
- `sudo mount /dev/mapper/loop4p2 ./os-mount`
|
||||
|
||||
# Resize the ext filesystem
|
||||
- `sudo /sbin/resize2fs /dev/mapper/loop4p2`
|
||||
|
||||
# Inject qemu and setup special mount points
|
||||
- `sudo cp /usr/bin/qemu-arm-static ./os-mount/usr/bin`
|
||||
- `sudo mount -o bind /dev ./os-mount/dev`
|
||||
- `sudo mount -o bind /proc ./os-mount/proc`
|
||||
- `sudo mount -o bind /sys ./os-mount/sys`
|
||||
|
||||
# Magic: register `qemu-arm-static` as the arm interpreter in the kernel
|
||||
> Must be root, no `sudo`
|
||||
- `su`
|
||||
- `echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:' > /proc/sys/fs/binfmt_misc/register`
|
||||
- `exit`
|
||||
|
||||
# Enter the chroot
|
||||
- `sudo chroot ./os-mount`
|
||||
|
||||
# Shutdown
|
||||
- `sudo umount ./os-mount/dev`
|
||||
- `sudo umount ./os-mount/proc`
|
||||
- `sudo umount ./os-mount/sys`
|
||||
- `sudo umount ./os-mount`
|
||||
- `sudo kpartx -d -v 2023-05-03-raspios-buster-armhf-lite.img`
|
@ -19,19 +19,26 @@ if [[ $OS == "Darwin" ]]; then
|
||||
JOBS="-j$(sysctl -n hw.ncpu)"
|
||||
fi
|
||||
|
||||
ARCH=$(uname -m)
|
||||
DEB_ARCH=$ARCH
|
||||
VENDOR=$ARCH
|
||||
if [[ -n $CROSSCOMPILE ]]; then
|
||||
FRIENDLY_OS_NAME="linux_${CROSSCOMPILE}"
|
||||
STRIP="strip"
|
||||
FRIENDLY_ARCH_NAME=$(uname -m)
|
||||
DEB_ARCH=$FRIENDLY_ARCH_NAME
|
||||
VENDOR=$FRIENDLY_ARCH_NAME
|
||||
if [[ $CROSSCOMPILE == rpi-* ]]; then
|
||||
FRIENDLY_OS_NAME="linux_rpi"
|
||||
XTOOLS_NAME="armv8-rpi3-linux-gnueabihf"
|
||||
VENDOR=${CROSSCOMPILE}
|
||||
ARCH="armhf"
|
||||
FRIENDLY_ARCH_NAME="armv8"
|
||||
DEB_ARCH="armhf"
|
||||
elif [[ $ARCH == "x86_64" ]]; then
|
||||
if [[ $CROSSCOMPILE == "rpi-armv6" ]]; then
|
||||
XTOOLS_NAME="armv6-rpi-linux-gnueabihf"
|
||||
FRIENDLY_ARCH_NAME="armv6"
|
||||
fi
|
||||
STRIP="/build/x-tools/${XTOOLS_NAME}/${XTOOLS_NAME}/bin/strip"
|
||||
elif [[ $FRIENDLY_ARCH_NAME == "x86_64" ]]; then
|
||||
DEB_ARCH="amd64"
|
||||
fi
|
||||
|
||||
OS_ARCH="${FRIENDLY_OS_NAME}_${ARCH}"
|
||||
OS_ARCH="${FRIENDLY_OS_NAME}_${FRIENDLY_ARCH_NAME}"
|
||||
OUTNAME="musikcube_${OS_ARCH}_$VERSION"
|
||||
OUTDIR="dist/$VERSION/$OUTNAME"
|
||||
SCRIPTDIR=`dirname "$0"`
|
||||
@ -44,15 +51,17 @@ fi
|
||||
|
||||
OS_SPECIFIC_BUILD_FLAGS=""
|
||||
if [[ $OS == "Linux" ]]; then
|
||||
OS_SPECIFIC_BUILD_FLAGS="-DGENERATE_DEB=true -DPACKAGE_ARCHITECTURE=${DEB_ARCH} -DCMAKE_INSTALL_PREFIX=/usr"
|
||||
if [[ $CROSSCOMPILE == "rpi" ]]; then
|
||||
OS_SPECIFIC_BUILD_FLAGS="-DGENERATE_DEB=true -DPACKAGE_ARCHITECTURE=${DEB_ARCH} -DFRIENDLY_ARCHITECTURE_NAME=${OS_ARCH} -DCMAKE_INSTALL_PREFIX=/usr"
|
||||
if [[ $CROSSCOMPILE == rpi-* ]]; then
|
||||
# for now we don't support pipewire when cross compiling...
|
||||
OS_SPECIFIC_BUILD_FLAGS="$OS_SPECIFIC_BUILD_FLAGS -DENABLE_PIPEWIRE=false"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $CROSSCOMPILE == "rpi" ]]; then
|
||||
CMAKE_TOOLCHAIN="-DCMAKE_TOOLCHAIN_FILE=.cmake/RaspberryPiToolchain.cmake"
|
||||
if [[ $CROSSCOMPILE == "rpi-armv8" ]]; then
|
||||
CMAKE_TOOLCHAIN="-DCMAKE_TOOLCHAIN_FILE=.cmake/RaspberryPiToolchain-armv8.cmake"
|
||||
elif [[ $CROSSCOMPILE == "rpi-armv6" ]]; then
|
||||
CMAKE_TOOLCHAIN="-DCMAKE_TOOLCHAIN_FILE=.cmake/RaspberryPiToolchain-armv6.cmake"
|
||||
fi
|
||||
|
||||
rm vendor
|
||||
@ -72,20 +81,27 @@ else
|
||||
${SCRIPTDIR}/clean-nix.sh
|
||||
rm -rf bin/ 2> /dev/null
|
||||
./script/stage-vendor-libraries.sh || exit $?
|
||||
cmake ${CMAKE_TOOLCHAIN} -DCMAKE_BUILD_TYPE=Release -DBUILD_STANDALONE=true -DENABLE_PCH=true ${OS_SPECIFIC_BUILD_FLAGS} . || exit $?
|
||||
cmake ${CMAKE_TOOLCHAIN} -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_STANDALONE=true -DENABLE_PCH=true ${OS_SPECIFIC_BUILD_FLAGS} . || exit $?
|
||||
make ${JOBS} || exit $?
|
||||
fi
|
||||
|
||||
./script/patch-rpath.sh $(pwd) || exit $?
|
||||
|
||||
rm -rf dist/$VERSION/*${OS_ARCH}_$VERSION* 2> /dev/null
|
||||
printf "stripping binaries..."
|
||||
$STRIP bin/musikcube
|
||||
$STRIP bin/musikcubed
|
||||
$STRIP bin/libmusikcore.${DLL_EXT}
|
||||
$STRIP bin/lib/*
|
||||
$STRIP bin/libmusikcore.${DLL_EXT}
|
||||
$STRIP bin/plugins/*.${DLL_EXT}
|
||||
|
||||
printf "staging binaries..."
|
||||
rm -rf dist/$VERSION/*${OS_ARCH}_$VERSION* 2> /dev/null
|
||||
mkdir -p $OUTDIR/lib
|
||||
mkdir -p $OUTDIR/plugins
|
||||
mkdir -p $OUTDIR/locales
|
||||
mkdir -p $OUTDIR/themes
|
||||
mkdir -p $OUTDIR/share/terminfo
|
||||
|
||||
cp bin/musikcube $OUTDIR
|
||||
cp bin/musikcubed $OUTDIR
|
||||
cp bin/libmusikcore.${DLL_EXT} $OUTDIR
|
||||
@ -95,7 +111,7 @@ cp bin/locales/*.json $OUTDIR/locales
|
||||
cp bin/themes/*.json $OUTDIR/themes
|
||||
cp -rfp bin/share/terminfo/* $OUTDIR/share/terminfo/
|
||||
|
||||
if [[ $CROSSCOMPILE == "rpi" ]]; then
|
||||
if [[ $CROSSCOMPILE == rpi-* ]]; then
|
||||
printf "\n\n\n ***** CROSSCOMPILE DETECTED, **NOT** SCANNING DEPENDENCIES! *****\n\n\n"
|
||||
sleep 1
|
||||
else
|
||||
@ -104,13 +120,6 @@ else
|
||||
node ./script/scan-standalone dist/$VERSION/$OUTNAME || exit $?
|
||||
fi
|
||||
|
||||
strip $OUTDIR/musikcube
|
||||
strip $OUTDIR/musikcubed
|
||||
strip $OUTDIR/libmusikcore.${DLL_EXT}
|
||||
strip $OUTDIR/lib/*
|
||||
strip $OUTDIR/libmusikcore.${DLL_EXT}
|
||||
strip $OUTDIR/plugins/*.${DLL_EXT}
|
||||
|
||||
cd dist/$VERSION/
|
||||
tar cvf $OUTNAME.tar $OUTNAME
|
||||
bzip2 $OUTNAME.tar
|
||||
|
@ -27,12 +27,12 @@ RPATH="@rpath"
|
||||
OS=$(uname)
|
||||
ARCH=$(uname -m)
|
||||
SCRIPTDIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
OPENSSL_VERSION="3.1.0"
|
||||
CURL_VERSION="8.0.1"
|
||||
LIBMICROHTTPD_VERSION="0.9.76"
|
||||
OPENSSL_VERSION="3.1.2"
|
||||
CURL_VERSION="8.2.1"
|
||||
LIBMICROHTTPD_VERSION="0.9.77"
|
||||
FFMPEG_VERSION="6.0"
|
||||
LAME_VERSION="3.100"
|
||||
LIBOPENMPT_VERSION="0.6.9"
|
||||
LIBOPENMPT_VERSION="0.7.1"
|
||||
TAGLIB_VERSION="1.13"
|
||||
GME_VERSION="0.6.3"
|
||||
OUTDIR="$(pwd)/vendor/bin"
|
||||
@ -48,29 +48,81 @@ if [[ $OS == "Darwin" ]]; then
|
||||
OPENSSL_TYPE="darwin64-${ARCH}-cc"
|
||||
fi
|
||||
|
||||
# update cross-compile vars, if specified.
|
||||
if [[ $CROSSCOMPILE == "rpi" ]]; then
|
||||
OPENSSL_VERSION="1.1.1n"
|
||||
ARM_ROOT="/build/rpi/sysroot"
|
||||
export CPPFLAGS="-I${ARM_ROOT}/usr/include"
|
||||
export CXXFLAGS="$CXXFLAGS -I${ARM_ROOT}/usr/include"
|
||||
export LDFLAGS="$LDFLAGS --sysroot=${ARM_ROOT} -L${ARM_ROOT}/lib/arm-linux-gnueabihf/"
|
||||
OPENSSL_TYPE="linux-generic32"
|
||||
OPENSSL_CROSSCOMPILE_PREFIX="--cross-compile-prefix=arm-linux-gnueabihf-"
|
||||
GENERIC_CONFIGURE_FLAGS="--build=x86_64-pc-linux-gnu --host=arm-linux-gnueabihf --with-sysroot=${ARM_ROOT}"
|
||||
FFMPEG_CONFIGURE_FLAGS="--arch=${ARCH} --target-os=linux --cross-prefix=arm-linux-gnueabihf-"
|
||||
CMAKE_COMPILER_TOOLCHAIN="-DCMAKE_TOOLCHAIN_FILE=/build/musikcube/.cmake/RaspberryPiToolchain.cmake"
|
||||
PKG_CONFIG_PATH="${LIBDIR}/pkgconfig/:${ARM_ROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig/"
|
||||
printf "\n\ndetected CROSSCOMPILE=${CROSSCOMPILE}\n"
|
||||
printf " CFLAGS=${CFLAGS}\n CXXFLAGS=${CXXFLAGS}\n LDFLAGS=${LDFLAGS}\n GENERIC_CONFIGURE_FLAGS=${GENERIC_CONFIGURE_FLAGS}\n"
|
||||
printf " OPENSSL_TYPE=${OPENSSL_TYPE}\n OPENSSL_CROSSCOMPILE_PREFIX=${OPENSSL_CROSSCOMPILE_PREFIX}\n"
|
||||
printf " FFMPEG_CONFIGURE_FLAGS=${FFMPEG_CONFIGURE_FLAGS}\n PKG_CONFIG_PATH=${PKG_CONFIG_PATH}\n\n"
|
||||
sleep 3
|
||||
fi
|
||||
BUILD_ROOT="/build"
|
||||
|
||||
function clean() {
|
||||
rm -rf vendor
|
||||
mkdir vendor
|
||||
function set_makefile_env_vars() {
|
||||
if [[ -n $CROSSCOMPILE ]]; then
|
||||
printf "updating AR, CC, CXX, LD for Makefile cross-compile\n"
|
||||
OLD_AR=$AR
|
||||
OLD_CC=$CC
|
||||
OLD_CXX=$CXX
|
||||
OLD_LD=$LD
|
||||
export AR="${XTOOLS_TOOLCHAIN_NAME}-ar"
|
||||
export CC="${XTOOLS_TOOLCHAIN_NAME}-gcc"
|
||||
export CXX="${XTOOLS_TOOLCHAIN_NAME}-g++"
|
||||
export LD="${XTOOLS_TOOLCHAIN_NAME}-ld"
|
||||
fi
|
||||
}
|
||||
|
||||
function unset_makefile_env_vars() {
|
||||
if [[ -n $CROSSCOMPILE ]]; then
|
||||
printf "restoring AR, CC, CXX, LDD for autotools/cmake cross-compile\n"
|
||||
AR=$OLD_AR
|
||||
CC=$OLD_CC
|
||||
CXX=$OLD_CXX
|
||||
LD=$OLD_LD
|
||||
fi
|
||||
}
|
||||
|
||||
function configure_crosscompile_if_necessary() {
|
||||
# update cross-compile vars, if specified.
|
||||
if [[ $CROSSCOMPILE == rpi-* ]]; then
|
||||
# cross-compile toolchains found here: https://github.com/tttapa/docker-arm-cross-toolchain. note
|
||||
# that the toolchain uses a newer version of libstdc++ than supported by our oldest platform,
|
||||
# so we link with "-static-libstdc++".
|
||||
# see: https://github.com/tttapa/docker-arm-cross-toolchain/issues/5#issuecomment-1665744288
|
||||
|
||||
OPENSSL_TYPE="linux-generic32"
|
||||
|
||||
XTOOLS_TOOLCHAIN_NAME="armv8-rpi3-linux-gnueabihf"
|
||||
CMAKE_COMPILER_TOOLCHAIN="--toolchain ${BUILD_ROOT}/musikcube/.cmake/RaspberryPiToolchain-armv8.cmake"
|
||||
|
||||
if [[ $CROSSCOMPILE == "rpi-armv6" ]]; then
|
||||
XTOOLS_TOOLCHAIN_NAME="armv6-rpi-linux-gnueabihf"
|
||||
CMAKE_COMPILER_TOOLCHAIN="--toolchain ${BUILD_ROOT}/musikcube/.cmake/RaspberryPiToolchain-armv6.cmake"
|
||||
fi
|
||||
|
||||
XTOOLS_SYSROOT="${BUILD_ROOT}/x-tools/${XTOOLS_TOOLCHAIN_NAME}/${XTOOLS_TOOLCHAIN_NAME}/sysroot/"
|
||||
XTOOLS_LDFLAGS="--sysroot=${XTOOLS_SYSROOT}"
|
||||
XTOOLS_BIN_PATH="${BUILD_ROOT}/x-tools/${XTOOLS_TOOLCHAIN_NAME}/bin"
|
||||
XTOOLS_PKG_CONFIG_PATH="${XTOOLS_SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig/"
|
||||
VENDOR_PKG_CONFIG_PATH="${LIBDIR}/pkgconfig/"
|
||||
|
||||
# in general these are all we need for autotools
|
||||
export PATH="${XTOOLS_BIN_PATH}:$PATH"
|
||||
export LDFLAGS="$LDFLAGS ${XTOOLS_LDFLAGS}"
|
||||
export CXXFLAGS="$CXXFLAGS -static-libstdc++"
|
||||
export PKG_CONFIG_PATH="${VENDOR_PKG_CONFIG_PATH}:${XTOOLS_PKG_CONFIG_PATH}"
|
||||
|
||||
OPENSSL_CROSSCOMPILE_PREFIX="--cross-compile-prefix=${XTOOLS_TOOLCHAIN_NAME}-"
|
||||
GENERIC_CONFIGURE_FLAGS="--build=x86_64-pc-linux-gnu --host=${XTOOLS_TOOLCHAIN_NAME} --with-sysroot=${XTOOLS_SYSROOT}"
|
||||
FFMPEG_CONFIGURE_FLAGS="--arch=${ARCH} --target-os=linux --enable-cross-compile --sysroot=${XTOOLS_SYSROOT} --cross-prefix=${XTOOLS_TOOLCHAIN_NAME}-"
|
||||
fi
|
||||
}
|
||||
|
||||
function print_build_configuration() {
|
||||
show_banner "build configuration"
|
||||
printf " - XTOOLS_TOOLCHAIN_NAME=${XTOOLS_TOOLCHAIN_NAME}\n"
|
||||
printf " - CMAKE_COMPILER_TOOLCHAIN=${CMAKE_COMPILER_TOOLCHAIN}\n"
|
||||
printf " - CFLAGS=${CFLAGS}\n"
|
||||
printf " - CXXFLAGS=${CXXFLAGS}\n"
|
||||
printf " - LDFLAGS=${LDFLAGS}\n"
|
||||
printf " - GENERIC_CONFIGURE_FLAGS=${GENERIC_CONFIGURE_FLAGS}\n"
|
||||
printf " - OPENSSL_TYPE=${OPENSSL_TYPE}\n"
|
||||
printf " - OPENSSL_CROSSCOMPILE_PREFIX=${OPENSSL_CROSSCOMPILE_PREFIX}\n"
|
||||
printf " - FFMPEG_CONFIGURE_FLAGS=${FFMPEG_CONFIGURE_FLAGS}\n"
|
||||
printf " - PKG_CONFIG_PATH=${PKG_CONFIG_PATH}\n"
|
||||
sleep 3
|
||||
}
|
||||
|
||||
#
|
||||
@ -97,17 +149,27 @@ function fetch_packages() {
|
||||
copy_or_download https://ftp.gnu.org/gnu/libmicrohttpd libmicrohttpd-${LIBMICROHTTPD_VERSION}.tar.gz
|
||||
copy_or_download https://ffmpeg.org/releases ffmpeg-${FFMPEG_VERSION}.tar.bz2
|
||||
copy_or_download https://downloads.sourceforge.net/project/lame/lame/${LAME_VERSION} lame-${LAME_VERSION}.tar.gz
|
||||
copy_or_download https://lib.openmpt.org/files/libopenmpt/src libopenmpt-${LIBOPENMPT_VERSION}+release.makefile.tar.gz
|
||||
copy_or_download https://lib.openmpt.org/files/libopenmpt/src libopenmpt-${LIBOPENMPT_VERSION}+release.autotools.tar.gz
|
||||
copy_or_download https://github.com/taglib/taglib/releases/download/v${TAGLIB_VERSION} taglib-${TAGLIB_VERSION}.tar.gz
|
||||
copy_or_download https://bitbucket.org/mpyne/game-music-emu/downloads game-music-emu-${GME_VERSION}.tar.gz
|
||||
}
|
||||
|
||||
function show_banner {
|
||||
printf "\n\n********************************************************************************\n"
|
||||
printf "*\n"
|
||||
printf "* $1\n"
|
||||
printf "*\n"
|
||||
printf "********************************************************************************\n\n"
|
||||
}
|
||||
|
||||
#
|
||||
# openssl
|
||||
#
|
||||
|
||||
function build_openssl() {
|
||||
tar xvfz openssl-${OPENSSL_VERSION}.tar.gz
|
||||
show_banner "building openssl..."
|
||||
tar xvfz openssl-${OPENSSL_VERSION}.tar.gz > /dev/null
|
||||
cd openssl-${OPENSSL_VERSION}
|
||||
perl ./Configure --prefix=${OUTDIR} no-ssl3 no-ssl3-method no-zlib ${OPENSSL_TYPE} ${OPENSSL_CROSSCOMPILE_PREFIX} || exit $?
|
||||
make -j8
|
||||
@ -131,8 +193,9 @@ function build_openssl() {
|
||||
#
|
||||
|
||||
function build_curl() {
|
||||
show_banner "building libcurl..."
|
||||
rm -rf curl-${CURL_VERSION}
|
||||
tar xvfz curl-${CURL_VERSION}.tar.gz
|
||||
tar xvfz curl-${CURL_VERSION}.tar.gz > /dev/null
|
||||
cd curl-${CURL_VERSION}
|
||||
./configure --enable-shared \
|
||||
--with-pic \
|
||||
@ -175,8 +238,9 @@ function build_curl() {
|
||||
#
|
||||
|
||||
function build_libmicrohttpd() {
|
||||
show_banner "building libmicrohttpd..."
|
||||
rm -rf libmicrohttpd-${LIBMICROHTTPD_VERSION}
|
||||
tar xvfz libmicrohttpd-${LIBMICROHTTPD_VERSION}.tar.gz
|
||||
tar xvfz libmicrohttpd-${LIBMICROHTTPD_VERSION}.tar.gz > /dev/null
|
||||
cd libmicrohttpd-${LIBMICROHTTPD_VERSION}
|
||||
./configure --enable-shared --with-pic --enable-https=no --disable-curl --prefix=${OUTDIR} ${GENERIC_CONFIGURE_FLAGS}
|
||||
make -j8 || exit $?
|
||||
@ -189,9 +253,16 @@ function build_libmicrohttpd() {
|
||||
#
|
||||
|
||||
function build_ffmpeg() {
|
||||
show_banner "building ffmpeg..."
|
||||
# fix for cross-compile: https://github.com/NixOS/nixpkgs/pull/76915/files
|
||||
rm -rf ffmpeg-${FFMPEG_VERSION}
|
||||
tar xvfj ffmpeg-${FFMPEG_VERSION}.tar.bz2
|
||||
tar xvfj ffmpeg-${FFMPEG_VERSION}.tar.bz2 > /dev/null
|
||||
|
||||
OLD_LDFLAGS=$LDFLAGS
|
||||
OLD_CFLAGS=$CFLAGS
|
||||
export LDFLAGS="$LDFLAGS -lm"
|
||||
export CFLAGS="$CFLAGS -I${XTOOLS_SYSROOT}/usr/include/opus"
|
||||
|
||||
cd ffmpeg-${FFMPEG_VERSION}
|
||||
./configure \
|
||||
--prefix=${OUTDIR} \
|
||||
@ -370,6 +441,10 @@ function build_ffmpeg() {
|
||||
--build-suffix=-musikcube || exit $?
|
||||
make ${JOBS} || exit $?
|
||||
make install
|
||||
|
||||
export LDFLAGS=$OLD_LDFLAGS
|
||||
export CFLAGS=$OLD_CFLAGS
|
||||
|
||||
cd ..
|
||||
}
|
||||
|
||||
@ -378,8 +453,9 @@ function build_ffmpeg() {
|
||||
#
|
||||
|
||||
function build_lame() {
|
||||
show_banner "building lame..."
|
||||
rm -rf lame-${LAME_VERSION}
|
||||
tar xvfz lame-${LAME_VERSION}.tar.gz
|
||||
tar xvfz lame-${LAME_VERSION}.tar.gz > /dev/null
|
||||
cd lame-${LAME_VERSION}
|
||||
# https://sourceforge.net/p/lame/mailman/message/36081038/
|
||||
perl -i.bak -0pe "s|lame_init_old\n||" include/libmp3lame.sym
|
||||
@ -394,30 +470,45 @@ function build_lame() {
|
||||
#
|
||||
|
||||
function build_libopenmpt() {
|
||||
rm -rf libopenmpt-${LIBOPENMPT_VERSION}+release.autotools
|
||||
tar xvfz libopenmpt-${LIBOPENMPT_VERSION}+release.autotools.tar.gz
|
||||
cd libopenmpt-${LIBOPENMPT_VERSION}+release.autotools
|
||||
./configure \
|
||||
--disable-dependency-tracking \
|
||||
--enable-shared \
|
||||
--disable-openmpt123 \
|
||||
--disable-examples \
|
||||
--disable-tests \
|
||||
--disable-doxygen-doc \
|
||||
--disable-doxygen-html \
|
||||
--without-mpg123 \
|
||||
--without-ogg \
|
||||
--without-vorbis \
|
||||
--without-vorbisfile \
|
||||
--without-portaudio \
|
||||
--without-portaudiocpp \
|
||||
--without-sndfile \
|
||||
--without-flac \
|
||||
${GENERIC_CONFIGURE_FLAGS} \
|
||||
--prefix=${OUTDIR} || exit $?
|
||||
make ${JOBS} || exit $?
|
||||
make install
|
||||
cd ..
|
||||
show_banner "building libopenmpt..."
|
||||
# macOS needs to use the autotools version, but Linux uses the Makefile
|
||||
# version for cross-compile support.
|
||||
if [[ $OS == "Darwin" ]]; then
|
||||
rm -rf libopenmpt-${LIBOPENMPT_VERSION}+release.autotools
|
||||
tar xvfz libopenmpt-${LIBOPENMPT_VERSION}+release.autotools.tar.gz > /dev/null
|
||||
cd libopenmpt-${LIBOPENMPT_VERSION}+release.autotools
|
||||
./configure \
|
||||
--disable-dependency-tracking \
|
||||
--enable-shared \
|
||||
--disable-openmpt123 \
|
||||
--disable-examples \
|
||||
--disable-tests \
|
||||
--disable-doxygen-doc \
|
||||
--disable-doxygen-html \
|
||||
--without-mpg123 \
|
||||
--without-ogg \
|
||||
--without-vorbis \
|
||||
--without-vorbisfile \
|
||||
--without-portaudio \
|
||||
--without-portaudiocpp \
|
||||
--without-sndfile \
|
||||
--without-flac \
|
||||
${GENERIC_CONFIGURE_FLAGS} \
|
||||
--prefix=${OUTDIR} || exit $?
|
||||
make ${JOBS} || exit $?
|
||||
make install
|
||||
cd ..
|
||||
else
|
||||
set_makefile_env_vars
|
||||
rm -rf libopenmpt-0.7.0+release/
|
||||
tar xvfz libopenmpt-${LIBOPENMPT_VERSION}+release.makefile.tar.gz > /dev/null
|
||||
cd libopenmpt-${LIBOPENMPT_VERSION}+release
|
||||
OPENMPT_OPTIONS="EXAMPLES=0 NO_FLAC=1 NO_MINIMP3=1 NO_MINIZ=1 NO_MPG123=1 NO_OGG=1 NO_PORTAUDIO=1 NO_PORTAUDIOCPP=1 NO_PULSEAUDIO=1 NO_SDL2=1 NO_SNDFILE=1 NO_STBVORBIS=1 NO_VORBIS=1 NO_VORBISFILE=1 OPENMPT123=0 SHARED_LIB=1 STATIC_LIB=0 TEST=0 PREFIX=${OUTDIR}"
|
||||
make ${OPENMPT_OPTIONS} ${JOBS} VERBOSE=1 || exit $?
|
||||
make ${OPENMPT_OPTIONS} install
|
||||
unset_makefile_env_vars
|
||||
cd ..
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
@ -425,12 +516,14 @@ function build_libopenmpt() {
|
||||
#
|
||||
|
||||
function build_gme() {
|
||||
show_banner "building gme (game-music-emu)..."
|
||||
rm -rf game-music-emu-${GME_VERSION}
|
||||
tar xvfz game-music-emu-${GME_VERSION}.tar.gz
|
||||
tar xvfz game-music-emu-${GME_VERSION}.tar.gz > /dev/null
|
||||
cd game-music-emu-${GME_VERSION}
|
||||
cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=${OUTDIR} \
|
||||
${CMAKE_COMPILER_TOOLCHAIN} \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OUTDIR} \
|
||||
-DENABLE_UBSAN=OFF \
|
||||
-DBUILD_SHARED_LIBS=1 \
|
||||
. || exit $?
|
||||
@ -444,12 +537,14 @@ function build_gme() {
|
||||
#
|
||||
|
||||
function build_taglib() {
|
||||
show_banner "building taglib..."
|
||||
rm -rf taglib-${TAGLIB_VERSION}
|
||||
tar xvfz taglib-${TAGLIB_VERSION}.tar.gz
|
||||
tar xvfz taglib-${TAGLIB_VERSION}.tar.gz > /dev/null
|
||||
cd taglib-${TAGLIB_VERSION}
|
||||
cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=${OUTDIR} \
|
||||
${CMAKE_COMPILER_TOOLCHAIN} \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OUTDIR} \
|
||||
-DBUILD_SHARED_LIBS=1 \
|
||||
. || exit $?
|
||||
make ${JOBS} || exit $?
|
||||
@ -502,28 +597,39 @@ function delete_unused_libraries() {
|
||||
cd ../../
|
||||
}
|
||||
|
||||
clean
|
||||
mkdir vendor
|
||||
cd vendor
|
||||
function main() {
|
||||
rm -rf vendor
|
||||
mkdir vendor
|
||||
cd vendor
|
||||
touch ".config-${ARCH}-${CROSSCOMPILE}"
|
||||
|
||||
stage_prebuilt_libraries
|
||||
fetch_packages
|
||||
build_openssl
|
||||
build_curl
|
||||
build_libmicrohttpd
|
||||
build_ffmpeg
|
||||
build_lame
|
||||
build_libopenmpt
|
||||
build_gme
|
||||
build_taglib
|
||||
delete_unused_libraries
|
||||
relink_dynamic_libraries
|
||||
configure_crosscompile_if_necessary
|
||||
print_build_configuration
|
||||
|
||||
cd ..
|
||||
if [[ $CROSSCOMPILE == "rpi" ]]; then
|
||||
mv vendor vendor-${CROSSCOMPILE}
|
||||
else
|
||||
mv vendor vendor-$(uname -m)
|
||||
fi
|
||||
stage_prebuilt_libraries
|
||||
fetch_packages
|
||||
|
||||
build_ffmpeg
|
||||
build_openssl
|
||||
build_curl
|
||||
build_libopenmpt
|
||||
build_libmicrohttpd
|
||||
build_lame
|
||||
build_gme
|
||||
build_taglib
|
||||
|
||||
delete_unused_libraries
|
||||
relink_dynamic_libraries
|
||||
|
||||
cd ..
|
||||
|
||||
if [[ $CROSSCOMPILE == rpi-* ]]; then
|
||||
mv vendor vendor-${CROSSCOMPILE}
|
||||
else
|
||||
mv vendor vendor-$(uname -m)
|
||||
fi
|
||||
}
|
||||
|
||||
main
|
||||
|
||||
printf "\n\ndone!\n\n"
|
||||
|
196
script/create-crosscompile-sysroot.js
Normal file
196
script/create-crosscompile-sysroot.js
Normal file
@ -0,0 +1,196 @@
|
||||
const { promisify } = require('util');
|
||||
const exec = promisify(require('child_process').exec);
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* This script will download and extract all transitive dependencies
|
||||
* for the packages specified by PACKAGE_NAMES. This is used to populate
|
||||
* a cross-compile sysroot with the libraries required to compile the
|
||||
* app itself.
|
||||
*/
|
||||
const PACKAGE_NAMES = [
|
||||
'libasound2-dev',
|
||||
'libev-dev',
|
||||
'libncurses-dev',
|
||||
'libopus-dev',
|
||||
'libpulse-dev',
|
||||
'libsndio-dev',
|
||||
'libsystemd-dev',
|
||||
'libvorbis-dev',
|
||||
'portaudio19-dev',
|
||||
'zlib1g-dev',
|
||||
];
|
||||
|
||||
/**
|
||||
* These are packages that are either provided by the cross-compiler
|
||||
* tools, or otherwise introduce conflicts while building and linking.
|
||||
* If any of the packages depend on these, we explicitly ignore them.
|
||||
*/
|
||||
const EXCLUDE = [
|
||||
'debconf',
|
||||
'dpkg',
|
||||
'gcc-10-base',
|
||||
'gcc-13-base',
|
||||
'gcc-8-base',
|
||||
'install-info',
|
||||
'libc-dev-bin',
|
||||
'libc6-dev',
|
||||
'libc6',
|
||||
'libcrypt1',
|
||||
'libdebian-installer4',
|
||||
'libdpkg-perl',
|
||||
'libgcc-s1',
|
||||
'libgcc1',
|
||||
'libselinux1-dev',
|
||||
'libselinux1',
|
||||
'libstdc++6',
|
||||
'linux-libc-dev',
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of files known to be provided by deb archives that we don't
|
||||
* want or need; we'll delete these after we're done downloading and
|
||||
* extracting files.
|
||||
*/
|
||||
const CLEANUP_FILES = [
|
||||
'control.tar.gz',
|
||||
'control.tar.bz2',
|
||||
'control.tar.xz',
|
||||
'control.tar.zst',
|
||||
'data.tar.gz',
|
||||
'data.tar.bz2',
|
||||
'data.tar.xz',
|
||||
'data.tar.zst',
|
||||
'debian-binary',
|
||||
];
|
||||
|
||||
/**
|
||||
* Uses `apt-cache` to resolve a list of package dependencies for
|
||||
* the specified package.
|
||||
*/
|
||||
const getPackageDependencies = async (packageName) => {
|
||||
const rawOutput = (
|
||||
await exec(
|
||||
`apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances ${packageName}`
|
||||
)
|
||||
).stdout.split('\n');
|
||||
const packages = rawOutput
|
||||
.filter((e) => e.indexOf('Depends:') >= 0)
|
||||
.map((e) => e.replace('Depends:', '').trim())
|
||||
.filter(
|
||||
(e) => !(e.startsWith('Pre ') || e.startsWith('<') || e.startsWith('|'))
|
||||
);
|
||||
return packages;
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses `apt download` to get a list of download URLs from
|
||||
* the specified list of packages.
|
||||
*/
|
||||
const getPackageDownloadUrls = async (packages) => {
|
||||
const rawOutput = (
|
||||
await exec(`apt download --print-uris ${packages.join(' ')}`)
|
||||
).stdout.split('\n');
|
||||
const downloadUrls = rawOutput
|
||||
.filter((e) => e.trim().length > 0)
|
||||
.map((e) => e.split(' ')[0].trim().replace(/'/g, ''));
|
||||
return downloadUrls;
|
||||
};
|
||||
|
||||
/**
|
||||
* Downloads and extracts a list of deb URLs
|
||||
*/
|
||||
const downloadAndExtract = async (downloadUrls) => {
|
||||
for (let i = 0; i < downloadUrls.length; i++) {
|
||||
const fn = decodeURIComponent(downloadUrls[i].split('/').pop());
|
||||
console.log(
|
||||
`processing [${i + 1}/${downloadUrls.length}]`,
|
||||
downloadUrls[i]
|
||||
);
|
||||
await exec(`wget ${downloadUrls[i]}`);
|
||||
await exec(`ar x ./${fn}`);
|
||||
if (fs.existsSync('data.tar.zst')) {
|
||||
await exec(`tar --use-compress-program=unzstd -xvf data.tar.zst`);
|
||||
} else if (fs.existsSync('data.tar.xz')) {
|
||||
await exec(`tar -xvf data.tar.xz`);
|
||||
} else if (fs.existsSync('data.tar.gz')) {
|
||||
await exec(`tar xvfz data.tar.gz`);
|
||||
} else if (fs.existsSync('data.tar.bz2')) {
|
||||
await exec(`tar xvfj data.tar.bz2`);
|
||||
} else {
|
||||
console.error('unknown file type');
|
||||
process.exit(-1);
|
||||
}
|
||||
for (let j = 0; j < CLEANUP_FILES.length; j++) {
|
||||
if (fs.existsSync(CLEANUP_FILES[j])) {
|
||||
await exec(`rm ${CLEANUP_FILES[j]}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds all symlinks with absolute paths in our generated
|
||||
* sysroot, and converts them to relative paths. This ensures
|
||||
* the sysroot is "relocatable" and can be used with
|
||||
* crosscompile toolchains.
|
||||
*/
|
||||
const convertAbsoluteToRelativeSymlinks = async () => {
|
||||
const root = process.cwd();
|
||||
const symlinks = (await exec('find . -type l')).stdout
|
||||
.split('\n')
|
||||
.filter((e) => e.length > 0);
|
||||
for (let i = 0; i < symlinks.length; i++) {
|
||||
const dest = fs.readlinkSync(symlinks[i]);
|
||||
if (dest[0] === '/') {
|
||||
const absoluteTo = path.join(root, dest);
|
||||
const absoluteFrom = path.join(root, symlinks[i]);
|
||||
const relative = path.relative(path.dirname(absoluteFrom), absoluteTo);
|
||||
console.log(
|
||||
`relinking\n * fn: ${absoluteFrom}\n * from: ${absoluteTo}\n * to: ${relative}`
|
||||
);
|
||||
fs.unlinkSync(symlinks[i]);
|
||||
fs.symlinkSync(relative, symlinks[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete any debs we downloaded
|
||||
*/
|
||||
const rmDebs = async () => {
|
||||
try {
|
||||
console.log('cleaning up downloads');
|
||||
await exec('rm *.deb');
|
||||
} catch (e) {
|
||||
/* nothing */
|
||||
}
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
await rmDebs();
|
||||
let dependencies = [];
|
||||
for (let i = 0; i < PACKAGE_NAMES.length; i++) {
|
||||
console.log(
|
||||
`scanning [${i + 1}/${PACKAGE_NAMES.length}]`,
|
||||
PACKAGE_NAMES[i]
|
||||
);
|
||||
dependencies = [
|
||||
...dependencies,
|
||||
...(await getPackageDependencies(PACKAGE_NAMES[i])),
|
||||
];
|
||||
}
|
||||
const deduped = new Set([...PACKAGE_NAMES, ...dependencies]);
|
||||
for (let i = 0; i < EXCLUDE.length; i++) {
|
||||
deduped.delete(EXCLUDE[i]);
|
||||
}
|
||||
console.log(`resolved ${deduped.size} transitive dependencies`);
|
||||
const downloadUrls = await getPackageDownloadUrls(Array.from(deduped));
|
||||
await downloadAndExtract(downloadUrls);
|
||||
await convertAbsoluteToRelativeSymlinks();
|
||||
await rmDebs();
|
||||
await exec('tar cvf sysroot.tar .', { maxBuffer: 1024 * 1024 * 8 }); /* 8mb */
|
||||
};
|
||||
|
||||
main();
|
43
script/install-crosscompile-toolkits.js
Normal file
43
script/install-crosscompile-toolkits.js
Normal file
@ -0,0 +1,43 @@
|
||||
const { promisify } = require('util');
|
||||
const exec = promisify(require('child_process').exec);
|
||||
const fs = require('fs');
|
||||
|
||||
const TOOLCHAINS = ['armv6-rpi-linux-gnueabihf', 'armv8-rpi3-linux-gnueabihf'];
|
||||
|
||||
const run = async (command) => {
|
||||
console.log(' > ', command);
|
||||
await exec(command, { maxBuffer: 1024 * 1024 * 8 }); /* 8mb */
|
||||
};
|
||||
|
||||
const install = async (toolchain) => {
|
||||
const archiveFn = `x-tools-${toolchain}.tar.xz`;
|
||||
const toolsRootDir = `x-tools/${toolchain}`;
|
||||
const sysrootDir = `${toolsRootDir}/${toolchain}/sysroot`;
|
||||
const downloadUrl = `https://github.com/tttapa/docker-arm-cross-toolchain/releases/download/0.1.2/${archiveFn}`;
|
||||
console.log(' * downloading...');
|
||||
await run(`wget ${downloadUrl}`);
|
||||
console.log(' * extracting...');
|
||||
await run(`tar xvf ${archiveFn}`);
|
||||
console.log(' * updating permissions...');
|
||||
await run(`chmod u+w ${sysrootDir} -R`);
|
||||
console.log(' * installing sysroot...');
|
||||
await run(`tar xvf sysroot.tar --directory=${sysrootDir}`);
|
||||
console.log(' * cleaning up...');
|
||||
await run(`rm ${archiveFn} 2> /dev/null`);
|
||||
};
|
||||
|
||||
main = async () => {
|
||||
for (let i = 0; i < TOOLCHAINS.length; i++) {
|
||||
console.log(`installing [${i + 1}/${TOOLCHAINS.length}] ${TOOLCHAINS[i]}`);
|
||||
await install(TOOLCHAINS[i]);
|
||||
}
|
||||
};
|
||||
|
||||
if (!fs.existsSync('./sysroot.tar')) {
|
||||
console.error(
|
||||
'[ERROR]: sysroot.tar not found in the current directory, process will not continue'
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
main();
|
@ -10,53 +10,54 @@ const filetype = mac ? '.dylib' : '.so';
|
||||
const ignoredLibraries = mac
|
||||
? new Set([])
|
||||
: new Set([
|
||||
'libalsaout.so',
|
||||
'libmpris.so',
|
||||
'libpipewireout.so',
|
||||
'libpulseout.so',
|
||||
'libsndioout.so',
|
||||
]);
|
||||
'libalsaout.so',
|
||||
'libmpris.so',
|
||||
'libpipewireout.so',
|
||||
'libpulseout.so',
|
||||
'libsndioout.so',
|
||||
]);
|
||||
|
||||
/* we assume these dependencies will always be available on the user's
|
||||
target machine. */
|
||||
const validLibraries = mac
|
||||
? new Set([
|
||||
'/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit',
|
||||
'/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices',
|
||||
'/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox',
|
||||
'/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon',
|
||||
'/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio',
|
||||
'/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation',
|
||||
'/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics',
|
||||
'/System/Library/Frameworks/CoreMedia.framework/Versions/A/CoreMedia',
|
||||
'/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo',
|
||||
'/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation',
|
||||
'/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration',
|
||||
'/usr/lib/libc++.1.dylib',
|
||||
'/usr/lib/libobjc.A.dylib',
|
||||
'/usr/lib/libSystem.B.dylib',
|
||||
'/usr/lib/libz.1.dylib',
|
||||
'/opt/homebrew/opt/portaudio/lib/libportaudio.2.dylib',
|
||||
'/usr/local/opt/portaudio/lib/libportaudio.2.dylib',
|
||||
])
|
||||
'/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit',
|
||||
'/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices',
|
||||
'/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox',
|
||||
'/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon',
|
||||
'/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio',
|
||||
'/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation',
|
||||
'/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics',
|
||||
'/System/Library/Frameworks/CoreMedia.framework/Versions/A/CoreMedia',
|
||||
'/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo',
|
||||
'/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation',
|
||||
'/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration',
|
||||
'/usr/lib/libc++.1.dylib',
|
||||
'/usr/lib/libobjc.A.dylib',
|
||||
'/usr/lib/libSystem.B.dylib',
|
||||
'/usr/lib/libz.1.dylib',
|
||||
'/opt/homebrew/opt/portaudio/lib/libportaudio.2.dylib',
|
||||
'/usr/local/opt/portaudio/lib/libportaudio.2.dylib',
|
||||
])
|
||||
: new Set([
|
||||
'/lib/ld-linux-armhf.so.3',
|
||||
'/lib64/ld-linux-x86-64.so.2',
|
||||
'/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so',
|
||||
'libc.so.6',
|
||||
'libdl.so.2',
|
||||
'libgcc_s.so.1',
|
||||
'libm.so.6',
|
||||
'libpthread.so.0',
|
||||
'librt.so.1',
|
||||
'libstdc++.so.6',
|
||||
'libz.so.1',
|
||||
'linux-vdso.so.1',
|
||||
'libportaudio.so.2',
|
||||
'libasound.so.2',
|
||||
'libjack.so.0',
|
||||
'libdb-5.3.so',
|
||||
]);
|
||||
'/lib/ld-linux-armhf.so.3',
|
||||
'/lib64/ld-linux-x86-64.so.2',
|
||||
'/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so',
|
||||
'/usr/lib/arm-linux-gnueabi/libarmmem-${PLATFORM}.so',
|
||||
'libc.so.6',
|
||||
'libdl.so.2',
|
||||
'libgcc_s.so.1',
|
||||
'libm.so.6',
|
||||
'libpthread.so.0',
|
||||
'librt.so.1',
|
||||
'libstdc++.so.6',
|
||||
'libz.so.1',
|
||||
'linux-vdso.so.1',
|
||||
'libportaudio.so.2',
|
||||
'libasound.so.2',
|
||||
'libjack.so.0',
|
||||
'libdb-5.3.so',
|
||||
]);
|
||||
|
||||
let errors = 0;
|
||||
|
||||
|
@ -22,7 +22,7 @@ if [[ "$PLATFORM" == 'Darwin' ]]; then
|
||||
cp vendor/bin/lib/libcurl.4.dylib ./bin/lib
|
||||
cp vendor/bin/lib/libmicrohttpd.12.dylib ./bin/lib
|
||||
cp vendor/bin/lib/libmp3lame.0.dylib ./bin/lib
|
||||
cp vendor/bin/lib/libopenmpt.0.dylib ./bin/lib
|
||||
cp vendor/bin/lib/libopenmpt.4.dylib ./bin/lib
|
||||
cp vendor/bin/lib/libgme.0.6.3.dylib ./bin/lib
|
||||
cp vendor/bin/lib/libtag.1.19.0.dylib ./bin/lib
|
||||
|
||||
@ -36,19 +36,25 @@ elif [[ "$PLATFORM" == 'Linux' ]]; then
|
||||
cp vendor/bin/lib/libavformat-musikcube.so.60 ./bin/lib
|
||||
cp vendor/bin/lib/libavutil-musikcube.so.58 ./bin/lib
|
||||
cp vendor/bin/lib/libswresample-musikcube.so.4 ./bin/lib
|
||||
cp vendor/bin/lib/libcrypto.so.3 ./bin/lib
|
||||
cp vendor/bin/lib/libssl.so.3 ./bin/lib
|
||||
cp vendor/bin/lib/libcrypto.so.3 ./bin/lib 2> /dev/null
|
||||
cp vendor/bin/lib/libssl.so.3 ./bin/lib 2> /dev/null
|
||||
cp vendor/bin/lib/libcrypto.so.1.1 ./bin/lib 2> /dev/null
|
||||
cp vendor/bin/lib/libssl.so.1.1 ./bin/lib 2> /dev/null
|
||||
cp vendor/bin/lib/libcurl.so.4 ./bin/lib
|
||||
cp vendor/bin/lib/libmp3lame.so.0 ./bin/lib
|
||||
cp vendor/bin/lib/libmicrohttpd.so.12 ./bin/lib
|
||||
cp vendor/bin/lib/libopenmpt.so.0 ./bin/lib
|
||||
cp vendor/bin/lib/libopenmpt.so.4 ./bin/lib
|
||||
cp vendor/bin/lib/libgme.so.0 ./bin/lib
|
||||
cp vendor/bin/lib/libtag.so.1 ./bin/lib
|
||||
|
||||
SYSTEM_ROOT=""
|
||||
SYSTEM_TYPE="x86_64-linux-gnu"
|
||||
if [[ $CROSSCOMPILE == "rpi" ]]; then
|
||||
SYSTEM_ROOT="/build/rpi/sysroot"
|
||||
if [[ $CROSSCOMPILE == rpi-* ]]; then
|
||||
XTOOLS_ARCH="armv8-rpi3-linux-gnueabihf"
|
||||
if [[ $CROSSCOMPILE == "rpi-armv6" ]]; then
|
||||
XTOOLS_ARCH="armv6-rpi-linux-gnueabihf"
|
||||
fi
|
||||
SYSTEM_ROOT="/build/x-tools/${XTOOLS_ARCH}/${XTOOLS_ARCH}/sysroot"
|
||||
SYSTEM_TYPE="arm-linux-gnueabihf"
|
||||
fi
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
HOST=$1
|
||||
if [[ -z $HOST ]]; then
|
||||
printf "usage: sync-pi-sysroot.sh <pi_hostname>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# https://mechatronicsblog.com/cross-compile-and-deploy-qt-5-12-for-raspberry-pi/
|
||||
mkdir -p sysroot/usr
|
||||
mkdir -p sysroot/opt
|
||||
rsync -avz pi@$HOST:/lib sysroot
|
||||
rsync -avz pi@$HOST:/usr/include sysroot/usr
|
||||
rsync -avz pi@$HOST:/usr/lib sysroot/usr
|
||||
rsync -avz pi@$HOST:/opt/vc sysroot/opt
|
||||
|
||||
# https://raw.githubusercontent.com/riscv/riscv-poky/master/scripts/sysroot-relativelinks.py
|
||||
$SCRIPT_DIR/update-pi-sysroot-symlinks.py ./sysroot
|
@ -1,31 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Take a sysroot directory and turn all the absolute symlinks into
|
||||
# relative ones such that the sysroot is usable within another system.
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage is " + sys.argv[0] + "<directory>")
|
||||
sys.exit(1)
|
||||
|
||||
topdir = sys.argv[1]
|
||||
topdir = os.path.abspath(topdir)
|
||||
|
||||
def handlelink(filep, subdir):
|
||||
link = os.readlink(filep)
|
||||
if link[0] != "/":
|
||||
return
|
||||
if link.startswith(topdir):
|
||||
return
|
||||
#print("Replacing %s with %s for %s" % (link, topdir+link, filep))
|
||||
print("Replacing %s with %s for %s" % (link, os.path.relpath(topdir+link, subdir), filep))
|
||||
os.unlink(filep)
|
||||
os.symlink(os.path.relpath(topdir+link, subdir), filep)
|
||||
|
||||
for subdir, dirs, files in os.walk(topdir):
|
||||
for f in files:
|
||||
filep = os.path.join(subdir, f)
|
||||
if os.path.islink(filep):
|
||||
#print("Considering %s" % filep)
|
||||
handlelink(filep, subdir)
|
@ -40,8 +40,8 @@
|
||||
#define MUSIKCUBE_VERSION_MINOR 0
|
||||
#define MUSIKCUBE_VERSION_PATCH 2
|
||||
#define MUSIKCUBE_VERSION "3.0.2"
|
||||
#define MUSIKCUBE_VERSION_COMMIT_HASH "#3dad0594"
|
||||
#define MUSIKCUBE_VERSION_WITH_COMMIT_HASH "3.0.2-#3dad0594"
|
||||
#define MUSIKCUBE_VERSION_COMMIT_HASH "#7191e5ad"
|
||||
#define MUSIKCUBE_VERSION_WITH_COMMIT_HASH "3.0.2-#7191e5ad"
|
||||
|
||||
namespace musik {
|
||||
namespace cube {
|
||||
|
Loading…
Reference in New Issue
Block a user