diff --git a/.azure/azure-pipelines-android.yml b/.azure/azure-pipelines-android.yml deleted file mode 100644 index 9fdd6aefb..000000000 --- a/.azure/azure-pipelines-android.yml +++ /dev/null @@ -1,556 +0,0 @@ - -trigger: - paths: - include: - - '*' - exclude: - - '.azure/azure-pipelines-alpine.yml' - - '.azure/azure-pipelines-mac.yml' - - '.azure/azure-pipelines-vcpkg.yml' - - '.azure/azure-pipelines-win.yml' - - '.azure/Dockerfile.azure-alpine' - - '.circleci/config.yml' - - '.github/workflows/linux.yml' - - '.github/workflows/sonarcloud.yml' - - '.cirrus.yml' - - 'README.md' - -parameters: -- name: UseCache - displayName: Use Dependency Cache - type: boolean - default: true - values: - - true - - false - -schedules: -- cron: "0 0 * * 1" - displayName: 'Weekly Monday Midnight build without caching' - branches: - include: - - master - always: true - -variables: - ICONV_VERSION: '1.17' - # libffi 3.4.4 fails due to https://github.com/libffi/libffi/issues/760 - FFI_VERSION: 'ce077e5565366171aa1b4438749b0922fce887a4' - GETTEXT_VERSION: '0.22.5' - GLIB_VERSION: '2.72' - GLIB_EXTRAVERSION: '4' - OBOE_VERSION: '1.9.0' - SNDFILE_VERSION: '1.2.2' - INSTPATCH_VERSION: '1.1.6' - VORBIS_VERSION: '1.3.7' - OGG_VERSION: '1.3.5' - OPUS_VERSION: '1.5.2' - FLAC_VERSION: '1.4.3' - PCRE_VERSION: '8.45' - - # Android NDK sources and standalone toolchain is put here - DEV: '$(System.DefaultWorkingDirectory)/android-build-root' - - # This is a symlink pointing to the real Android NDK - # Must be the same as $ANDROID_NDK_HOME see: - # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md - # We cannot use $ANDROID_NDK_HOME because this is an environment variable, but here, we need a compile-time constant. - NDK: '/usr/local/lib/android/sdk/ndk/27.3.13750724' - - # All the built binaries, libs and their headers will be installed here - PREFIX: '$(DEV)/opt/android' - - # Prevent installing to lib64/ - # This becomes important, if you would build on e.g. openSUSE - LIBPATH0: '$(PREFIX)/lib' - - # The path of standalone NDK toolchain - # Refer to https://developer.android.com/ndk/guides/standalone_toolchain.html - NDK_TOOLCHAIN: '$(NDK)/toolchains/llvm/prebuilt/linux-x86_64/' - - # Don't mix up .pc files from your host and build target - PKG_CONFIG_PATH: '$(LIBPATH0)/pkgconfig' - # setting PKG_CONFIG_PATH alone does not seem to be enough to avoid mixing up with the host, also set PKG_CONFIG_LIBDIR - PKG_CONFIG_LIBDIR: '$(PKG_CONFIG_PATH)' - - # Set Android target API level - # when compiling with clang use at least 28 as this makes sure that android provides the posix_spawn functions, so the compilation of gettext will (should) work out of the box - # it's probably a bug of gettext, if posix_spawn is not available it replaces it with its own implementation. Autotools of gettext set HAVE_POSIX_SPAWN==0 (which is correct) but for some reason REPLACE_POSIX_SPAWN==0 (which is wrong, as it should be 1). - # - # NOTE: API 24 is required because it provides fseeko() and ftello() required by libflac - ANDROID_API: '24' - - # Tell configure what flags Android requires. - # Turn Wimplicit-function-declaration into errors. Else autotools will be fooled when checking for available functions (that in fact are NOT available) and compilation will fail later on. - CFLAGS: "-fPIE -fPIC -I$(PREFIX)/include --sysroot=$(NDK_TOOLCHAIN)/sysroot -I$(NDK_TOOLCHAIN)/sysroot/usr/include -Werror=implicit-function-declaration" - CXXFLAGS: $(CFLAGS) - CPPFLAGS: $(CXXFLAGS) - DEBIAN_FRONTEND: 'noninteractive' - - ARTIFACT_NAME: 'fluidsynth-android$(ANDROID_API)' - -jobs: -- job: Android - strategy: - matrix: - ARM: - ARCH: 'arm' - ANDROID_ARCH: 'armv7a' - ANDROID_ABI_CMAKE: 'armeabi-v7a' - ANDROID_TARGET_ABI: "eabi" - ANDROID_ABI_MESON: 'arm' - # the --target to be used by autotools - AUTOTOOLS_TARGET: "$(ARCH)-linux-android$(ANDROID_TARGET_ABI)" - AARCH64: - ARCH: 'aarch64' - ANDROID_ARCH: 'aarch64' - ANDROID_ABI_CMAKE: 'arm64-v8a' - ANDROID_TARGET_ABI: - ANDROID_ABI_MESON: 'aarch64' - AUTOTOOLS_TARGET: "$(ARCH)-none-linux-android" - i686: - ARCH: 'i686' - ANDROID_ARCH: 'i686' - ANDROID_ABI_CMAKE: 'x86' - ANDROID_TARGET_ABI: - ANDROID_ABI_MESON: 'x86' - AUTOTOOLS_TARGET: "$(ARCH)-pc-linux-android" - x86_64: - ARCH: 'x86_64' - ANDROID_ARCH: 'x86_64' - ANDROID_ABI_CMAKE: 'x86_64' - ANDROID_TARGET_ABI: - ANDROID_ABI_MESON: 'x86_64' - AUTOTOOLS_TARGET: "$(ARCH)-pc-linux-android" - - pool: - vmImage: 'ubuntu-22.04' - - steps: - - checkout: self - submodules: true - - - script: | - set -ex - mkdir -p $(DEV) - displayName: 'mkdir $(DEV)' - - - script: | - sudo apt-get update -y - displayName: 'Update apt' - - - script: | - set -ex - sudo -E apt-get -y --no-install-suggests --no-install-recommends install wget tar bzip2 xz-utils ca-certificates - displayName: 'apt-get install wget tar' - - - script: | - set -ex - - wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz - tar zxf libiconv-${ICONV_VERSION}.tar.gz - - wget -O libffi-${FFI_VERSION}.tar.gz https://github.com/libffi/libffi/archive/${FFI_VERSION}.tar.gz # https://github.com/libffi/libffi/releases/download/v${FFI_VERSION}/libffi-${FFI_VERSION}.tar.gz - tar zxf libffi-${FFI_VERSION}.tar.gz - - wget http://ftp.gnu.org/pub/gnu/gettext/gettext-${GETTEXT_VERSION}.tar.gz - tar zxf gettext-${GETTEXT_VERSION}.tar.gz - - wget http://ftp.gnome.org/pub/gnome/sources/glib/${GLIB_VERSION}/glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION}.tar.xz - tar xf glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION}.tar.xz - - wget -O oboe-${OBOE_VERSION}.tar.gz https://github.com/google/oboe/archive/${OBOE_VERSION}.tar.gz - tar zxf oboe-${OBOE_VERSION}.tar.gz - - wget https://github.com/libsndfile/libsndfile/releases/download/${SNDFILE_VERSION}/libsndfile-${SNDFILE_VERSION}.tar.xz - tar xf libsndfile-${SNDFILE_VERSION}.tar.xz - - wget -O libinstpatch-${INSTPATCH_VERSION}.tar.gz https://github.com/swami/libinstpatch/archive/refs/tags/v${INSTPATCH_VERSION}.tar.gz - tar zxf libinstpatch-${INSTPATCH_VERSION}.tar.gz - - wget https://github.com/xiph/vorbis/releases/download/v${VORBIS_VERSION}/libvorbis-${VORBIS_VERSION}.tar.gz - tar zxf libvorbis-${VORBIS_VERSION}.tar.gz - - wget https://github.com/xiph/ogg/releases/download/v${OGG_VERSION}/libogg-${OGG_VERSION}.tar.gz - tar zxf libogg-${OGG_VERSION}.tar.gz - - wget -O flac-${FLAC_VERSION}.tar.gz https://github.com/xiph/flac/archive/refs/tags/${FLAC_VERSION}.tar.gz - tar xf flac-${FLAC_VERSION}.tar.gz - - wget -O opus-${OPUS_VERSION}.tar.gz https://github.com/xiph/opus/archive/refs/tags/v${OPUS_VERSION}.tar.gz - tar xf opus-${OPUS_VERSION}.tar.gz - - wget -O pcre-${PCRE_VERSION}.tar.bz2 https://sourceforge.net/projects/pcre/files/pcre/${PCRE_VERSION}/pcre-${PCRE_VERSION}.tar.bz2/download - tar jxf pcre-${PCRE_VERSION}.tar.bz2 - cd pcre-${PCRE_VERSION} - # CMake checks for existence of strtoq() using the C compiler - and yes, it does exist! - # Later on, it's actually used by the C++ compiler, where it does not exist. - # Rename the function so CMake won't find it. - sed -i 's/strtoq/strtoqqqq/g' CMakeLists.txt - displayName: 'Download Dependencies' - workingDirectory: $(DEV) - - - task: Cache@2 - inputs: - key: '$(ARCH) | "$(NDK)" | $(DEV)/*.tar.* | ver1' - path: '$(PREFIX)' - cacheHitVar: 'CACHE_RESTORED' - displayName: 'Cache fluidsynth dependency libraries' - condition: and(not(in(variables['Build.Reason'], 'Schedule')), ${{ parameters.useCache }}) - - - script: | - set -ex - - sudo apt remove --purge --auto-remove cmake - wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null - sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main' - displayName: 'Use recent CMake Version' - condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true')) - enabled: 'false' - - - script: | - set -ex - sudo -E apt-get -y --no-install-suggests --no-install-recommends install gettext cmake zlib1g-dev autogen automake autoconf libtool pkg-config autotools-dev build-essential meson ninja-build python3-distutils - displayName: 'apt-get install build-tools' - condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true')) - - - script: | - set -e - - # The cross-compile toolchain we use - export ANDROID_TARGET=${ARCH}-linux-android${ANDROID_TARGET_ABI} - echo "##vso[task.setvariable variable=ANDROID_TARGET]$ANDROID_TARGET" - - export ANDROID_TARGET_API=${ANDROID_ARCH}-linux-android${ANDROID_TARGET_ABI}${ANDROID_API} - echo "##vso[task.setvariable variable=ANDROID_TARGET_API]$ANDROID_TARGET_API" - - # Add the standalone toolchain to the search path. - export PATH=$PATH:${PREFIX}/bin:${PREFIX}/lib:${PREFIX}/include:${NDK_TOOLCHAIN}/bin - echo "##vso[task.setvariable variable=PATH]$PATH" - - LIBPATH1=$(NDK_TOOLCHAIN)/sysroot/usr/lib - LIBPATH2=$(NDK_TOOLCHAIN)/sysroot/usr/lib/$(ARCH)-linux-android$(ANDROID_TARGET_ABI)/$(ANDROID_API) - LIBPATH3=$(NDK_TOOLCHAIN)/sysroot/usr/lib/$(ARCH)-linux-android$(ANDROID_TARGET_ABI) - - # Add max. page size to linker flag, see https://developer.android.com/guide/practices/page-sizes - export LDFLAGS="-pie -Wl,-z,max-page-size=16384 -Wl,-rpath-link=${LIBPATH1} -L${LIBPATH1} -Wl,-rpath-link=${LIBPATH2} -L${LIBPATH2} -Wl,-rpath-link=${LIBPATH3} -L${LIBPATH3} -Wl,-rpath-link=${LIBPATH0} -L${LIBPATH0}" - echo "##vso[task.setvariable variable=LDFLAGS]$LDFLAGS" - - # Tell configure what tools to use. - export AR=llvm-ar - echo "##vso[task.setvariable variable=AR]$AR" - export AS=${ANDROID_TARGET_API}-clang - echo "##vso[task.setvariable variable=AS]$AS" - export CC=${ANDROID_TARGET_API}-clang - echo "##vso[task.setvariable variable=CC]$CC" - export CXX=${ANDROID_TARGET_API}-clang++ - echo "##vso[task.setvariable variable=CXX]$CXX" - export LD=ld.lld - echo "##vso[task.setvariable variable=LD]$LD" - export STRIP=llvm-strip - echo "##vso[task.setvariable variable=STRIP]$STRIP" - export RANLIB=llvm-ranlib - echo "##vso[task.setvariable variable=RANLIB]$RANLIB" - - displayName: 'Set environment variables' - - - script: | - set -ex - - pushd libiconv-${ICONV_VERSION} - ./configure \ - --host=${AUTOTOOLS_TARGET} \ - --prefix=${PREFIX} \ - --libdir=${LIBPATH0} \ - --disable-rpath \ - --enable-static \ - --disable-shared \ - --with-pic \ - --disable-maintainer-mode \ - --disable-silent-rules \ - --disable-gtk-doc \ - --disable-introspection \ - --disable-nls - make -j$((`nproc`+1)) - make install - popd - - displayName: 'Compile libiconv-$(ICONV_VERSION)' - workingDirectory: $(DEV) - condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true')) - - - script: | - set -ex - pushd libiconv-${ICONV_VERSION} - cat config.log - displayName: 'libiconv config.log' - workingDirectory: $(DEV) - condition: and(failed(), ne(variables.CACHE_RESTORED, 'true')) - - - script: | - set -ex - - pushd libffi-${FFI_VERSION} - NOCONFIGURE=true autoreconf -v -i - # install headers into the conventional ${PREFIX}/include rather than ${PREFIX}/lib/libffi-3.2.1/include. - #sed -e '/^includesdir/ s/$(libdir).*$/$(includedir)/' -i include/Makefile.in - #sed -e '/^includedir/ s/=.*$/=@includedir@/' -e 's/^Cflags: -I${includedir}/Cflags:/' -i libffi.pc.in - ./configure --host=${AUTOTOOLS_TARGET} --prefix=${PREFIX} --libdir=${LIBPATH0} --enable-static --disable-shared - make -j$((`nproc`+1)) - make install - popd - displayName: 'Compile libffi-$(FFI_VERSION)' - workingDirectory: $(DEV) - condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true')) - - - script: | - set -ex - - pushd gettext-${GETTEXT_VERSION} - ./configure \ - --host=${AUTOTOOLS_TARGET} \ - --prefix=${PREFIX} \ - --libdir=${LIBPATH0} \ - --disable-rpath \ - --disable-libasprintf \ - --disable-java \ - --disable-native-java \ - --disable-openmp \ - --disable-curses \ - --enable-static \ - --disable-shared \ - --with-pic \ - --disable-maintainer-mode \ - --disable-silent-rules \ - --disable-gtk-doc \ - --disable-introspection - make -j$((`nproc`+1)) - make install - popd - displayName: 'Compile gettext-$(GETTEXT_VERSION)' - workingDirectory: $(DEV) - condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true')) - - - template: cmake-android.yml - parameters: - sourceDir: 'pcre-$(PCRE_VERSION)' - cmakeArgs: '-DPCRE_SUPPORT_UNICODE_PROPERTIES=1 -DPCRE_SUPPORT_UTF=1 -DPCRE_BUILD_PCRECPP=0 -DPCRE_BUILD_TESTS=0' - - - script: | - set -ex - export PKGCFG=`which pkg-config` - pushd glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION} - - cat << EOF > cross_file.ini - [host_machine] - system = 'android' - cpu_family = '${ANDROID_ABI_MESON}' - cpu = '${ANDROID_ARCH}' - endian = 'little' - - [binaries] - c = '${NDK_TOOLCHAIN}/bin/${CC}' - cpp = '${NDK_TOOLCHAIN}/bin/${CXX}' - ar = '${NDK_TOOLCHAIN}/bin/${AR}' - as = '${NDK_TOOLCHAIN}/bin/${AS}' - ld = '${NDK_TOOLCHAIN}/bin/${LD}' - strip = '${NDK_TOOLCHAIN}/bin/${STRIP}' - ranlib = '${NDK_TOOLCHAIN}/bin/${RANLIB}' - pkgconfig = '${PKGCFG}' - - [properties] - prefix = '${PREFIX}' - c_args = '${CFLAGS}' - cpp_args = '${CXXFLAGS}' - pkg_config_libdir = '${PKG_CONFIG_LIBDIR}' - c_link_args = '${LDFLAGS}' - - [project options] - libmount = 'disabled' - xattr = false - selinux = 'disabled' - nls = 'disabled' - glib_debug = 'disabled' - glib_assert = false - glib_checks = false - libelf = 'disabled' - EOF - - cat cross_file.ini - - # When CC and CXX are set, then meson detects them as host compiler (not cross compiler), - # so they tries to run arm binaries in x86. That's why sanity check is failing, and that's - # why we have to use env -i. - # And we must explicitly set PKG_CONFIG_LIBDIR, because pkg_config_libdir is only recognized by meson >= 0.54 - env -i bash -c "export PATH && export PKG_CONFIG_LIBDIR=$(PKG_CONFIG_LIBDIR) && meson setup build --cross-file cross_file.ini --prefix=$(PREFIX)" - ninja -C build - ninja -C build install - popd - displayName: 'Compile glib-$(GLIB_VERSION).$(GLIB_EXTRAVERSION) (meson)' - workingDirectory: $(DEV) - condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true')) - - - script: | - pushd glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION} - ls -la build - cat build/meson-logs/meson-log.txt - popd - displayName: 'Meson LOG' - workingDirectory: $(DEV) - condition: and(succeededOrFailed(), ne(variables.CACHE_RESTORED, 'true')) - - - template: cmake-android.yml - parameters: - sourceDir: 'libogg-$(OGG_VERSION)' - cmakeArgs: '-DINSTALL_DOCS=0' - - - template: cmake-android.yml - parameters: - sourceDir: 'libvorbis-$(VORBIS_VERSION)' - - # flac uses c99 macros, but doesnt specify a standard, so we need to do it explicitly. - # On i686, they invoke yasm with -fstack-protector-strong flag... turn off asm optimizations. - - template: cmake-android.yml - parameters: - sourceDir: 'flac-$(FLAC_VERSION)' - cmakeArgs: '-DCMAKE_C_STANDARD=99 -DCMAKE_C_STANDARD_REQUIRED=1 -DWITH_ASM=0 -DBUILD_CXXLIBS=0 -DBUILD_PROGRAMS=0 -DBUILD_EXAMPLES=0 -DBUILD_DOCS=0 -DINSTALL_MANPAGES=0' - - # another broken xiph project that doesn't specify the C standard and keeps complaining of you don't have C99 - - template: cmake-android.yml - parameters: - sourceDir: 'opus-$(OPUS_VERSION)' - cmakeArgs: '-DBUILD_PROGRAMS=0 -DOPUS_MAY_HAVE_NEON=1 -DCMAKE_C_STANDARD=99 -DCMAKE_C_STANDARD_REQUIRED=1' - - - template: cmake-android.yml - parameters: - sourceDir: 'libsndfile-$(SNDFILE_VERSION)' - cmakeArgs: '-DBUILD_PROGRAMS=0 -DBUILD_EXAMPLES=0' - - - template: cmake-android.yml - parameters: - sourceDir: 'oboe-$(OBOE_VERSION)' - installCommand: 'cp liboboe.* ${PREFIX}/lib/ && cp -ur ../include/oboe ${PREFIX}/include' - - - script: | - set -ex - - # create a custom pkgconfig file for oboe to allow fluidsynth to find it - cat << EOF > ${PKG_CONFIG_PATH}/oboe-1.0.pc - prefix=${PREFIX} - exec_prefix=\${prefix} - libdir=\${prefix}/lib - includedir=\${prefix}/include - - Name: Oboe - Description: Oboe library - Version: ${OBOE_VERSION} - Libs: -L\${libdir} -loboe -landroid -llog - Cflags: -I\${includedir} - EOF - - cat ${PKG_CONFIG_PATH}/oboe-1.0.pc - - displayName: 'Create fake oboe.pc' - workingDirectory: $(DEV) - condition: and(succeeded(), ne(variables.CACHE_RESTORED, 'true')) - - - template: cmake-android.yml - parameters: - sourceDir: 'libinstpatch-$(INSTPATCH_VERSION)' - - # finally, compile fluidsynth - - template: cmake-android.yml - parameters: - workDir: '$(System.DefaultWorkingDirectory)' - sourceDir: '.' - condition: succeeded() - cmakeArgs: '-Denable-opensles=1 -Denable-floats=1 -Denable-oboe=1 -Denable-dbus=0 -Denable-oss=0 -Denable-openmp=0' - installCommand: '' - - - script: | - set -x - export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$(PREFIX)/lib:$(NDK_TOOLCHAIN)/sysroot/usr/lib/$(ARCH)-linux-android$(ANDROID_TARGET_ABI)/$(ANDROID_API) - pushd build - make -j$((`nproc`+1)) check - ldd test/test_sample_cache - popd - displayName: 'Execute fluidsynth unit test' - condition: and(succeeded(), in(variables['ARCH'], 'x86_64', 'i686')) - enabled: 'false' - - - script: | - set -ex - pushd build - make install - popd - displayName: 'Install fluidsynth' - - - template: cmake-android.yml - parameters: - workDir: '$(System.DefaultWorkingDirectory)/doc/android/fluidsynth-assetloader/' - sourceDir: '.' - condition: succeeded() - installCommand: 'cp *.so ${PREFIX}/lib/' - - - script: | - ls -Rg $(PREFIX) - displayName: 'Show cross-compiled files in $(PREFIX)' - condition: or(succeeded(), failed()) - - - script: | - set -ex - # use ANDROID_ABI_CMAKE so libs can be simply copied to the archive contents in src/main/jniLibs - mkdir -p $(Build.ArtifactStagingDirectory)/lib/$(ANDROID_ABI_CMAKE) - cd $(Build.ArtifactStagingDirectory)/lib/$(ANDROID_ABI_CMAKE) - cp -LR $(PREFIX)/lib/* . - ls -Rg . - rm -rf *.dll *.alias gettext/ libtextstyle.* *.a *.la - rm -f *.so.* - mkdir -p $(Build.ArtifactStagingDirectory)/include - cd $(Build.ArtifactStagingDirectory)/include - cp -a $(PREFIX)/include/fluidsynth* . - displayName: 'Collecting artifacts' - - - script: | - set -ex - ls libFLAC.so - ls libfluidsynth-assetloader.so - ls libfluidsynth.so - ls libgio-2.0.so - ls libglib-2.0.so - ls libgmodule-2.0.so - ls libgobject-2.0.so - ls libgthread-2.0.so - ls libinstpatch-1.0.so - ls liboboe.so - ls libogg.so - ls libopus.so - ls libsndfile.so - ls libvorbis.so - ls libvorbisenc.so - ls libvorbisfile.so - ls libpcre.so - ls libpcreposix.so - displayName: 'Verify all libs exist' - workingDirectory: '$(PREFIX)/lib' - - - script: | - set -ex - chmod +x contrib/check_elf_alignment.sh - contrib/check_elf_alignment.sh "$(PREFIX)/lib" - displayName: 'Assert 16K page alignment' - - - task: PublishBuildArtifacts@1 - displayName: 'Publishing Artefacts for Android API$(ANDROID_API) $(ANDROID_ABI_CMAKE)' - inputs: - PathtoPublish: '$(Build.ArtifactStagingDirectory)' - ArtifactName: '$(ARTIFACT_NAME)' - publishLocation: 'Container' - - - script: | - set -ex - # as very last step before creating the pipeline cache, remove fluidsynth - pushd build - make uninstall - popd - displayName: 'Uninstall fluidsynth' diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 000000000..7f498ae36 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,791 @@ +name: FluidSynth Android + +on: + pull_request: + push: + paths-ignore: + - '.azure/**' + - '.github/workflows/api_doc_build.yml' + - '.github/workflows/codeql-analysis.yml' + - '.github/workflows/codespell.yml' + - '.github/workflows/linux.yml' + - '.github/workflows/sonarcloud.yml' + - '.github/workflows/solaris.yml' + - '.github/workflows/windows.yml' + - '.github/workflows/ios.yml' + - '.cirrus.yml' + - 'README.md' + schedule: + # Weekly Monday Midnight build without caching + - cron: '0 0 * * 1' + +env: + ICONV_VERSION: '1.17' + # libffi 3.4.4 fails due to https://github.com/libffi/libffi/issues/760 + FFI_VERSION: 'ce077e5565366171aa1b4438749b0922fce887a4' + GETTEXT_VERSION: '0.22.5' + GLIB_VERSION: '2.72' + GLIB_EXTRAVERSION: '4' + OBOE_VERSION: '1.9.0' + SNDFILE_VERSION: '1.2.2' + INSTPATCH_VERSION: '1.1.6' + VORBIS_VERSION: '1.3.7' + OGG_VERSION: '1.3.5' + OPUS_VERSION: '1.5.2' + FLAC_VERSION: '1.4.3' + PCRE_VERSION: '8.45' + + # Android NDK sources and standalone toolchain is put here + DEV: '${{ github.workspace }}/android-build-root' + + # Set Android target API level + # when compiling with clang use at least 28 as this makes sure that android provides the posix_spawn functions, so the compilation of gettext will (should) work out of the box + # it's probably a bug of gettext, if posix_spawn is not available it replaces it with its own implementation. Autotools of gettext set HAVE_POSIX_SPAWN==0 (which is correct) but for some reason REPLACE_POSIX_SPAWN==0 (which is wrong, as it should be 1). + # + # NOTE: API 24 is required because it provides fseeko() and ftello() required by libflac + ANDROID_API: '24' + + DEBIAN_FRONTEND: 'noninteractive' + + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-22.04 + strategy: + matrix: + include: + - arch: 'arm' + android_arch: 'armv7a' + android_abi_cmake: 'armeabi-v7a' + android_target_abi: 'eabi' + android_abi_meson: 'arm' + autotools_target: 'arm-linux-androideabi' + - arch: 'aarch64' + android_arch: 'aarch64' + android_abi_cmake: 'arm64-v8a' + android_target_abi: '' + android_abi_meson: 'aarch64' + autotools_target: 'aarch64-none-linux-android' + - arch: 'i686' + android_arch: 'i686' + android_abi_cmake: 'x86' + android_target_abi: '' + android_abi_meson: 'x86' + autotools_target: 'i686-pc-linux-android' + - arch: 'x86_64' + android_arch: 'x86_64' + android_abi_cmake: 'x86_64' + android_target_abi: '' + android_abi_meson: 'x86_64' + autotools_target: 'x86_64-pc-linux-android' + + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + submodules: true + + - name: Setup build directories + run: | + set -ex + mkdir -p ${{ env.DEV }} + + - name: Update apt + run: sudo apt-get update -y + + - name: Install wget and tar + run: | + set -ex + sudo -E apt-get -y --no-install-suggests --no-install-recommends install wget tar bzip2 xz-utils ca-certificates + + - name: Download Dependencies + run: | + set -ex + + wget http://ftpmirror.gnu.org/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz + tar zxf libiconv-${ICONV_VERSION}.tar.gz + + wget -O libffi-${FFI_VERSION}.tar.gz https://github.com/libffi/libffi/archive/${FFI_VERSION}.tar.gz + tar zxf libffi-${FFI_VERSION}.tar.gz + + wget http://ftpmirror.gnu.org/gnu/gettext/gettext-${GETTEXT_VERSION}.tar.gz + tar zxf gettext-${GETTEXT_VERSION}.tar.gz + + wget http://ftp.gnome.org/pub/gnome/sources/glib/${GLIB_VERSION}/glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION}.tar.xz + tar xf glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION}.tar.xz + + wget -O oboe-${OBOE_VERSION}.tar.gz https://github.com/google/oboe/archive/${OBOE_VERSION}.tar.gz + tar zxf oboe-${OBOE_VERSION}.tar.gz + + wget https://github.com/libsndfile/libsndfile/releases/download/${SNDFILE_VERSION}/libsndfile-${SNDFILE_VERSION}.tar.xz + tar xf libsndfile-${SNDFILE_VERSION}.tar.xz + + wget -O libinstpatch-${INSTPATCH_VERSION}.tar.gz https://github.com/swami/libinstpatch/archive/refs/tags/v${INSTPATCH_VERSION}.tar.gz + tar zxf libinstpatch-${INSTPATCH_VERSION}.tar.gz + + wget https://github.com/xiph/vorbis/releases/download/v${VORBIS_VERSION}/libvorbis-${VORBIS_VERSION}.tar.gz + tar zxf libvorbis-${VORBIS_VERSION}.tar.gz + + wget https://github.com/xiph/ogg/releases/download/v${OGG_VERSION}/libogg-${OGG_VERSION}.tar.gz + tar zxf libogg-${OGG_VERSION}.tar.gz + + wget -O flac-${FLAC_VERSION}.tar.gz https://github.com/xiph/flac/archive/refs/tags/${FLAC_VERSION}.tar.gz + tar xf flac-${FLAC_VERSION}.tar.gz + + wget -O opus-${OPUS_VERSION}.tar.gz https://github.com/xiph/opus/archive/refs/tags/v${OPUS_VERSION}.tar.gz + tar xf opus-${OPUS_VERSION}.tar.gz + + wget -O pcre-${PCRE_VERSION}.tar.bz2 https://sourceforge.net/projects/pcre/files/pcre/${PCRE_VERSION}/pcre-${PCRE_VERSION}.tar.bz2/download + tar jxf pcre-${PCRE_VERSION}.tar.bz2 + cd pcre-${PCRE_VERSION} + # CMake checks for the existence of strtoq() using the C compiler - and yes, it does exist! + # Later on, it's actually used by the C++ compiler, where it does not exist. + # Rename the function so CMake won't find it. + sed -i 's/strtoq/strtoqqqq/g' CMakeLists.txt + working-directory: ${{ env.DEV }} + + - name: Cache fluidsynth dependency libraries + id: cache-deps + if: github.event_name != 'schedule' + uses: actions/cache@v4 + with: + key: ${{ matrix.arch }}-android${{ env.ANDROID_API }}-${{ env.NDK }}-${{ env.DEV }}/*.tar.* + path: ${{ env.PREFIX }} + + - name: Install build tools + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + sudo -E apt-get -y --no-install-suggests --no-install-recommends install gettext cmake zlib1g-dev autogen automake autoconf libtool pkg-config autotools-dev build-essential meson ninja-build python3-distutils + + - name: Set environment variables + run: | + set -e + NDK="${ANDROID_NDK_HOME}" + echo "NDK=$NDK" >> $GITHUB_ENV + + # All the built binaries, libs and their headers will be installed here + PREFIX="${{ env.DEV }}/opt/android" + echo "PREFIX=$PREFIX" >> $GITHUB_ENV + + # Prevent installing to lib64/ + # This becomes important, if you would build on e.g. openSUSE + LIBPATH0="${PREFIX}/lib" + echo "LIBPATH0=$LIBPATH0" >> $GITHUB_ENV + + # The path of standalone NDK toolchain + # Refer to https://developer.android.com/ndk/guides/standalone_toolchain.html + NDK_TOOLCHAIN="${NDK}/toolchains/llvm/prebuilt/linux-x86_64/" + echo "NDK_TOOLCHAIN=$NDK_TOOLCHAIN" >> $GITHUB_ENV + + # Don't mix up .pc files from your host and build target + PKG_CONFIG_PATH="${LIBPATH0}/pkgconfig" + echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" >> $GITHUB_ENV + + # setting PKG_CONFIG_PATH alone does not seem to be enough to avoid mixing up with the host, also set PKG_CONFIG_LIBDIR + PKG_CONFIG_LIBDIR="${PKG_CONFIG_PATH}" + echo "PKG_CONFIG_LIBDIR=$PKG_CONFIG_LIBDIR" >> $GITHUB_ENV + + # Tell configure what flags Android requires. + # Turn Wimplicit-function-declaration into errors. Else autotools will be fooled when checking for available functions (that in fact are NOT available) and compilation will fail later on. + CFLAGS="-fPIE -fPIC -I${PREFIX}/include --sysroot=${NDK_TOOLCHAIN}/sysroot -I${NDK_TOOLCHAIN}/sysroot/usr/include -Werror=implicit-function-declaration" + echo "CFLAGS=$CFLAGS" >> $GITHUB_ENV + CXXFLAGS=${CFLAGS} + echo "CXXFLAGS=$CXXFLAGS" >> $GITHUB_ENV + CPPFLAGS=${CXXFLAGS} + echo "CPPFLAGS=$CPPFLAGS" >> $GITHUB_ENV + ARTIFACT_NAME="fluidsynth-android${ANDROID_API}" + echo "ARTIFACT_NAME=$ARTIFACT_NAME" >> $GITHUB_ENV + + # The cross-compile toolchain we use + ANDROID_TARGET="${{ matrix.arch }}-linux-android${{ matrix.android_target_abi }}" + echo "ANDROID_TARGET=$ANDROID_TARGET" >> $GITHUB_ENV + + ANDROID_TARGET_API="${{ matrix.android_arch }}-linux-android${{ matrix.android_target_abi }}${ANDROID_API}" + echo "ANDROID_TARGET_API=$ANDROID_TARGET_API" >> $GITHUB_ENV + + # Add the standalone toolchain to the search path. + echo "${PREFIX}/bin" >> $GITHUB_PATH + echo "${PREFIX}/lib" >> $GITHUB_PATH + echo "${PREFIX}/include" >> $GITHUB_PATH + echo "${NDK_TOOLCHAIN}/bin" >> $GITHUB_PATH + + # Linker flags + LIBPATH1="${NDK_TOOLCHAIN}/sysroot/usr/lib" + LIBPATH2="${NDK_TOOLCHAIN}/sysroot/usr/lib/${{ matrix.arch }}-linux-android${{ matrix.android_target_abi }}/${ANDROID_API}" + LIBPATH3="${NDK_TOOLCHAIN}/sysroot/usr/lib/${{ matrix.arch }}-linux-android${{ matrix.android_target_abi }}" + + # Add max. page size to linker flag, see https://developer.android.com/guide/practices/page-sizes + echo "LDFLAGS=-pie -Wl,-z,max-page-size=16384 -Wl,-rpath-link=${LIBPATH1} -L${LIBPATH1} -Wl,-rpath-link=${LIBPATH2} -L${LIBPATH2} -Wl,-rpath-link=${LIBPATH3} -L${LIBPATH3} -Wl,-rpath-link=${LIBPATH0} -L${LIBPATH0}" >> $GITHUB_ENV + + # Tell configure what tools to use. + echo "AR=llvm-ar" >> $GITHUB_ENV + echo "AS=${ANDROID_TARGET_API}-clang" >> $GITHUB_ENV + echo "CC=${ANDROID_TARGET_API}-clang" >> $GITHUB_ENV + echo "CXX=${ANDROID_TARGET_API}-clang++" >> $GITHUB_ENV + echo "LD=ld.lld" >> $GITHUB_ENV + echo "STRIP=llvm-strip" >> $GITHUB_ENV + echo "RANLIB=llvm-ranlib" >> $GITHUB_ENV + + - name: Compile libiconv-${{ env.ICONV_VERSION }} + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd libiconv-${ICONV_VERSION} + ./configure \ + --host=${{ matrix.autotools_target }} \ + --prefix=${PREFIX} \ + --libdir=${LIBPATH0} \ + --disable-rpath \ + --enable-static \ + --disable-shared \ + --with-pic \ + --disable-maintainer-mode \ + --disable-silent-rules \ + --disable-gtk-doc \ + --disable-introspection \ + --disable-nls + make -j$((`nproc`+1)) + make install + popd + working-directory: ${{ env.DEV }} + + - name: libiconv config.log + if: ${{ failure() && steps.cache-deps.outputs.cache-hit != 'true' }} + working-directory: ${{ env.DEV }} + run: | + set -ex + pushd "libiconv-${ICONV_VERSION}" + cat config.log + popd + + - name: Compile libffi + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd libffi-${FFI_VERSION} + NOCONFIGURE=true autoreconf -v -i + # install headers into the conventional ${PREFIX}/include rather than ${PREFIX}/lib/libffi-3.2.1/include. + #sed -e '/^includesdir/ s/$(libdir).*$/$(includedir)/' -i include/Makefile.in + #sed -e '/^includedir/ s/=.*$/=@includedir@/' -e 's/^Cflags: -I${includedir}/Cflags:/' -i libffi.pc.in + ./configure --host=${{ matrix.autotools_target }} --prefix=${PREFIX} --libdir=${LIBPATH0} --enable-static --disable-shared + make -j$((`nproc`+1)) + make install + popd + working-directory: ${{ env.DEV }} + + - name: Compile gettext + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd gettext-${GETTEXT_VERSION} + ./configure \ + --host=${{ matrix.autotools_target }} \ + --prefix=${PREFIX} \ + --libdir=${LIBPATH0} \ + --disable-rpath \ + --disable-libasprintf \ + --disable-java \ + --disable-native-java \ + --disable-openmp \ + --disable-curses \ + --enable-static \ + --disable-shared \ + --with-pic \ + --disable-maintainer-mode \ + --disable-silent-rules \ + --disable-gtk-doc \ + --disable-introspection + make -j$((`nproc`+1)) + make install + popd + working-directory: ${{ env.DEV }} + + - name: Compile pcre + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd pcre-${PCRE_VERSION} + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_API} \ + -DANDROID_ABI=${{ matrix.android_abi_cmake }} \ + -DANDROID_TOOLCHAIN=${CC} \ + -DANDROID_NDK=${NDK} \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_STAGING_PREFIX=${PREFIX} \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + -DPCRE_SUPPORT_UNICODE_PROPERTIES=1 -DPCRE_SUPPORT_UTF=1 -DPCRE_BUILD_PCRECPP=0 -DPCRE_BUILD_TESTS=0 .. + make -j$((`nproc`+1)) + make install + popd + popd + working-directory: ${{ env.DEV }} + + - name: Compile glib (meson) + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + export PKGCFG=`which pkg-config` + pushd glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION} + + cat << EOF > cross_file.ini + [host_machine] + system = 'android' + cpu_family = '${{ matrix.android_abi_meson }}' + cpu = '${{ matrix.android_arch }}' + endian = 'little' + + [binaries] + c = '${NDK_TOOLCHAIN}/bin/${CC}' + cpp = '${NDK_TOOLCHAIN}/bin/${CXX}' + ar = '${NDK_TOOLCHAIN}/bin/${AR}' + as = '${NDK_TOOLCHAIN}/bin/${AS}' + ld = '${NDK_TOOLCHAIN}/bin/${LD}' + strip = '${NDK_TOOLCHAIN}/bin/${STRIP}' + ranlib = '${NDK_TOOLCHAIN}/bin/${RANLIB}' + pkgconfig = '${PKGCFG}' + + [properties] + prefix = '${PREFIX}' + c_args = '${CFLAGS}' + cpp_args = '${CXXFLAGS}' + pkg_config_libdir = '${PKG_CONFIG_LIBDIR}' + c_link_args = '${LDFLAGS}' + + [project options] + libmount = 'disabled' + xattr = false + selinux = 'disabled' + nls = 'disabled' + glib_debug = 'disabled' + glib_assert = false + glib_checks = false + libelf = 'disabled' + EOF + + cat cross_file.ini + + # When CC and CXX are set, then meson detects them as host compiler (not cross compiler), + # so they tries to run arm binaries in x86. That's why sanity check is failing, and that's + # why we have to use env -i. + # And we must explicitly set PKG_CONFIG_LIBDIR, because pkg_config_libdir is only recognized by meson >= 0.54 + env -i bash -c "export PATH && export PKG_CONFIG_LIBDIR=${PKG_CONFIG_LIBDIR} && meson setup build --cross-file cross_file.ini --prefix=${PREFIX}" + ninja -C build + ninja -C build install + popd + working-directory: ${{ env.DEV }} + + - name: Meson LOG + if: ${{ failure() && steps.cache-deps.outputs.cache-hit != 'true' }} + working-directory: ${{ env.DEV }} + shell: bash + run: | + pushd glib-${GLIB_VERSION}.${GLIB_EXTRAVERSION} + ls -la build + cat build/meson-logs/meson-log.txt + popd + + - name: Compile libogg + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd libogg-${OGG_VERSION} + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_API} \ + -DANDROID_ABI=${{ matrix.android_abi_cmake }} \ + -DANDROID_TOOLCHAIN=${CC} \ + -DANDROID_NDK=${NDK} \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_STAGING_PREFIX=${PREFIX} \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + -DINSTALL_DOCS=0 .. + make -j$((`nproc`+1)) + make install + popd + popd + working-directory: ${{ env.DEV }} + + - name: Compile libvorbis + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd libvorbis-${VORBIS_VERSION} + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_API} \ + -DANDROID_ABI=${{ matrix.android_abi_cmake }} \ + -DANDROID_TOOLCHAIN=${CC} \ + -DANDROID_NDK=${NDK} \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_STAGING_PREFIX=${PREFIX} \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + .. + make -j$((`nproc`+1)) + make install + popd + popd + working-directory: ${{ env.DEV }} + + - name: Compile flac + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd flac-${FLAC_VERSION} + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_API} \ + -DANDROID_ABI=${{ matrix.android_abi_cmake }} \ + -DANDROID_TOOLCHAIN=${CC} \ + -DANDROID_NDK=${NDK} \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_STAGING_PREFIX=${PREFIX} \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + -DCMAKE_C_STANDARD=99 -DCMAKE_C_STANDARD_REQUIRED=1 -DWITH_ASM=0 -DBUILD_CXXLIBS=0 -DBUILD_PROGRAMS=0 -DBUILD_EXAMPLES=0 -DBUILD_DOCS=0 -DINSTALL_MANPAGES=0 .. + make -j$((`nproc`+1)) + make install + popd + popd + working-directory: ${{ env.DEV }} + + - name: Compile opus + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd opus-${OPUS_VERSION} + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_API} \ + -DANDROID_ABI=${{ matrix.android_abi_cmake }} \ + -DANDROID_TOOLCHAIN=${CC} \ + -DANDROID_NDK=${NDK} \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_STAGING_PREFIX=${PREFIX} \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + -DBUILD_PROGRAMS=0 -DOPUS_MAY_HAVE_NEON=1 -DCMAKE_C_STANDARD=99 -DCMAKE_C_STANDARD_REQUIRED=1 .. + make -j$((`nproc`+1)) + make install + popd + popd + working-directory: ${{ env.DEV }} + + - name: Compile libsndfile + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd libsndfile-${SNDFILE_VERSION} + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_API} \ + -DANDROID_ABI=${{ matrix.android_abi_cmake }} \ + -DANDROID_TOOLCHAIN=${CC} \ + -DANDROID_NDK=${NDK} \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_STAGING_PREFIX=${PREFIX} \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + -DBUILD_PROGRAMS=0 -DBUILD_EXAMPLES=0 .. + make -j$((`nproc`+1)) + make install + popd + popd + working-directory: ${{ env.DEV }} + + - name: Compile oboe + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd oboe-${OBOE_VERSION} + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_API} \ + -DANDROID_ABI=${{ matrix.android_abi_cmake }} \ + -DANDROID_TOOLCHAIN=${CC} \ + -DANDROID_NDK=${NDK} \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_STAGING_PREFIX=${PREFIX} \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + .. + make -j$((`nproc`+1)) + cp liboboe.* ${PREFIX}/lib/ && cp -ur ../include/oboe ${PREFIX}/include + popd + popd + working-directory: ${{ env.DEV }} + + - name: Create fake oboe.pc + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + cat << EOF > ${PKG_CONFIG_PATH}/oboe-1.0.pc + prefix=${PREFIX} + exec_prefix=\${prefix} + libdir=\${prefix}/lib + includedir=\${prefix}/include + + Name: Oboe + Description: Oboe library + Version: ${OBOE_VERSION} + Libs: -L\${libdir} -loboe -landroid -llog + Cflags: -I\${includedir} + EOF + + cat ${PKG_CONFIG_PATH}/oboe-1.0.pc + working-directory: ${{ env.DEV }} + + - name: Compile libinstpatch + if: steps.cache-deps.outputs.cache-hit != 'true' + run: | + set -ex + + pushd libinstpatch-${INSTPATCH_VERSION} + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_API} \ + -DANDROID_ABI=${{ matrix.android_abi_cmake }} \ + -DANDROID_TOOLCHAIN=${CC} \ + -DANDROID_NDK=${NDK} \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_STAGING_PREFIX=${PREFIX} \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + .. + make -j$((`nproc`+1)) + make install + popd + popd + working-directory: ${{ env.DEV }} + + - name: Compile fluidsynth + run: | + set -ex + + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_API} \ + -DANDROID_ABI=${{ matrix.android_abi_cmake }} \ + -DANDROID_TOOLCHAIN=${CC} \ + -DANDROID_NDK=${NDK} \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_STAGING_PREFIX=${PREFIX} \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + -Denable-opensles=1 -Denable-floats=1 -Denable-oboe=1 -Denable-dbus=0 -Denable-oss=0 -Denable-openmp=0 .. + make -j$((`nproc`+1)) + popd + + - name: Install fluidsynth + run: | + set -ex + pushd build + make install + popd + + - name: Compile fluidsynth-assetloader + run: | + set -ex + + pushd doc/android/fluidsynth-assetloader + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE=${NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_API} \ + -DANDROID_ABI=${{ matrix.android_abi_cmake }} \ + -DANDROID_TOOLCHAIN=${CC} \ + -DANDROID_NDK=${NDK} \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_STAGING_PREFIX=${PREFIX} \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + .. + make -j$((`nproc`+1)) + cp *.so ${PREFIX}/lib/ + popd + popd + + - name: Show cross-compiled files + run: ls -Rg ${PREFIX} + + - name: Collect artifacts + run: | + set -ex + mkdir -p ${{ runner.temp }}/artifacts/lib/${{ matrix.android_abi_cmake }} + cd ${{ runner.temp }}/artifacts/lib/${{ matrix.android_abi_cmake }} + cp -LR ${PREFIX}/lib/* . + ls -Rg . + rm -rf *.dll *.alias gettext/ libtextstyle.* *.a *.la + rm -f *.so.* + mkdir -p ${{ runner.temp }}/artifacts/include + cd ${{ runner.temp }}/artifacts/include + cp -a ${PREFIX}/include/fluidsynth* . + + - name: Verify all libs exist + run: | + set -ex + ls libFLAC.so + ls libfluidsynth-assetloader.so + ls libfluidsynth.so + ls libgio-2.0.so + ls libglib-2.0.so + ls libgmodule-2.0.so + ls libgobject-2.0.so + ls libgthread-2.0.so + ls libinstpatch-1.0.so + ls liboboe.so + ls libogg.so + ls libopus.so + ls libsndfile.so + ls libvorbis.so + ls libvorbisenc.so + ls libvorbisfile.so + ls libpcre.so + ls libpcreposix.so + working-directory: ${{ env.DEV }}/opt/android/lib + + - name: Assert 16K page alignment + run: | + set -ex + chmod +x contrib/check_elf_alignment.sh + contrib/check_elf_alignment.sh "${PREFIX}/lib" + + - name: Publish artifacts + uses: actions/upload-artifact@v4 + with: + name: fluidsynth-android${{ env.ANDROID_API }}-${{ matrix.android_abi_cmake }} + path: ${{ runner.temp }}/artifacts + + - name: Uninstall fluidsynth + run: | + set -ex + pushd build + make uninstall + popd diff --git a/.github/workflows/github_actions_cmake-android_action.yml b/.github/workflows/github_actions_cmake-android_action.yml new file mode 100644 index 000000000..7b0b6646c --- /dev/null +++ b/.github/workflows/github_actions_cmake-android_action.yml @@ -0,0 +1,94 @@ +# usage +# - name: Build via composite action steps +# uses: ./.github/actions/cmake-android +# with: +# sourceDir: . +# workDir: . +# cmakeArgs: "" +# installCommand: "make install" +# cache_restored: ${{ steps.cache.outputs.cache-hit }} +name: "CMake Android (Steps)" +description: "Android CMake build steps mirroring the Azure template" +inputs: + cmakeArgs: + description: "Extra CMake arguments" + required: false + default: "" + sourceDir: + description: "Path to the source directory (contains CMakeLists.txt)" + required: false + default: "" + workDir: + description: "Working directory (equivalent to $(DEV) in Azure)" + required: false + default: "." + installCommand: + description: "Install command to run after build" + required: false + default: "make install" + cache_restored: + description: "Mimic Azure condition: skip compile when cache restored ('true' to skip)" + required: false + default: "false" + +runs: + using: "composite" + steps: + - name: Compile ${{ inputs.sourceDir }} + if: ${{ inputs.cache_restored != 'true' }} + working-directory: ${{ inputs.workDir }} + shell: bash + run: | + set -ex + + # Defaults and sanity checks + if [[ -z "${NDK:-}" && -n "${ANDROID_NDK_LATEST_HOME:-}" ]]; then + export NDK="$ANDROID_NDK_LATEST_HOME" + fi + : "${NDK:?NDK is required or provide ANDROID_NDK_LATEST_HOME on the runner}" + : "${ANDROID_API:?ANDROID_API is required}" + : "${ANDROID_ABI_CMAKE:?ANDROID_ABI_CMAKE is required}" + : "${CC:=clang}" + : "${PREFIX:?PREFIX is required}" + : "${CFLAGS:=}" + : "${LDFLAGS:=}" + + pushd "${{ inputs.sourceDir }}" + mkdir -p build + pushd build + + cmake -G "Unix Makefiles" \ + -DCMAKE_MAKE_PROGRAM=make \ + -DCMAKE_TOOLCHAIN_FILE="${NDK}/build/cmake/android.toolchain.cmake" \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DANDROID_NATIVE_API_LEVEL="${ANDROID_API}" \ + -DANDROID_ABI="${ANDROID_ABI_CMAKE}" \ + -DANDROID_TOOLCHAIN="${CC}" \ + -DANDROID_NDK="${NDK}" \ + -DANDROID_COMPILER_FLAGS="${CFLAGS// /;}" \ + -DANDROID_LINKER_FLAGS="${LDFLAGS// /;}" \ + -DANDROID_STL="c++_shared" \ + -DCMAKE_REQUIRED_FLAGS="${CFLAGS}" \ + -DCMAKE_REQUIRED_LINK_OPTIONS="${LDFLAGS// /;}" \ + -DCMAKE_INSTALL_PREFIX="${PREFIX}" \ + -DCMAKE_STAGING_PREFIX="${PREFIX}" \ + -DCMAKE_VERBOSE_MAKEFILE=1 \ + -DBUILD_SHARED_LIBS=1 \ + -DLIB_SUFFIX= \ + ${{ inputs.cmakeArgs }} .. + + make -j$((`nproc`+1)) + ${{ inputs.installCommand }} + popd + popd + + - name: Print ${{ inputs.sourceDir }} CMake Error Log + if: ${{ always() }} + working-directory: ${{ inputs.workDir }} + shell: bash + run: | + set +e + ls -la "${{ inputs.sourceDir }}/build/CMakeFiles/" || true + cat "${{ inputs.sourceDir }}/build/CMakeFiles/CMakeError.log" || true + cat "${{ inputs.sourceDir }}/build/CMakeFiles/CMakeOutput.log" || true + true