Skip to content

Commit

Permalink
Merge branch 'v0.23.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxKellermann committed Sep 26, 2023
2 parents 5cea03b + 49130c2 commit 39476be
Show file tree
Hide file tree
Showing 16 changed files with 399 additions and 295 deletions.
4 changes: 2 additions & 2 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ ver 0.24 (not yet released)
* switch to C++20
- GCC 10 or clang 11 (or newer) recommended
* static partition configuration
* Android
- require Android 7 or newer
* Windows
- build with libsamplerate
- remove JACK DLL support
Expand All @@ -56,6 +54,8 @@ ver 0.23.14 (not yet released)
- wasapi: fix problem setting volume
* more libfmt 10 fixes
* fix auto-detected systemd unit directory
* Android
- require Android 7 or newer

ver 0.23.13 (2023/05/22)
* input
Expand Down
128 changes: 7 additions & 121 deletions android/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,131 +20,13 @@
print("NDK not found in", ndk_path, file=sys.stderr)
sys.exit(1)

android_abis = {
'armeabi-v7a': {
'arch': 'arm-linux-androideabi',
'ndk_arch': 'arm',
'llvm_triple': 'armv7-linux-androideabi',
'cflags': '-fpic -mfpu=neon -mfloat-abi=softfp',
},

'arm64-v8a': {
'arch': 'aarch64-linux-android',
'ndk_arch': 'arm64',
'llvm_triple': 'aarch64-linux-android',
'cflags': '-fpic',
},

'x86': {
'arch': 'i686-linux-android',
'ndk_arch': 'x86',
'llvm_triple': 'i686-linux-android',
'cflags': '-fPIC -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32',
},

'x86_64': {
'arch': 'x86_64-linux-android',
'ndk_arch': 'x86_64',
'llvm_triple': 'x86_64-linux-android',
'cflags': '-fPIC -m64',
},
}

# select the NDK target
abi_info = android_abis[android_abi]
arch = abi_info['arch']

# the path to the MPD sources
mpd_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]) or '.', '..'))
sys.path[0] = os.path.join(mpd_path, 'python')

# output directories
from build.dirs import lib_path, tarball_path, src_path
from build.meson import configure as run_meson

arch_path = os.path.join(lib_path, arch)
build_path = os.path.join(arch_path, 'build')

# build host configuration
build_arch = 'linux-x86_64'

# set up the NDK toolchain

class AndroidNdkToolchain:
def __init__(self, tarball_path, src_path, build_path,
use_cxx):
self.tarball_path = tarball_path
self.src_path = src_path
self.build_path = build_path

ndk_arch = abi_info['ndk_arch']
android_api_level = '24'

install_prefix = os.path.join(arch_path, 'root')

self.arch = arch
self.actual_arch = arch
self.install_prefix = install_prefix

llvm_path = os.path.join(ndk_path, 'toolchains', 'llvm', 'prebuilt', build_arch)
llvm_triple = abi_info['llvm_triple'] + android_api_level

common_flags = '-Os -g'
common_flags += ' ' + abi_info['cflags']

llvm_bin = os.path.join(llvm_path, 'bin')
self.cc = os.path.join(llvm_bin, 'clang')
self.cxx = os.path.join(llvm_bin, 'clang++')
common_flags += ' -target ' + llvm_triple

common_flags += ' -fvisibility=hidden -fdata-sections -ffunction-sections'

self.ar = os.path.join(llvm_bin, 'llvm-ar')
self.arflags = 'rcs'
self.ranlib = os.path.join(llvm_bin, 'llvm-ranlib')
self.nm = os.path.join(llvm_bin, 'llvm-nm')
self.strip = os.path.join(llvm_bin, 'llvm-strip')

self.cflags = common_flags
self.cxxflags = common_flags
self.cppflags = ' -isystem ' + os.path.join(install_prefix, 'include')
self.ldflags = ' -L' + os.path.join(install_prefix, 'lib') + \
' -Wl,--exclude-libs=ALL' + \
' ' + common_flags
self.ldflags = common_flags
self.libs = ''

self.is_arm = ndk_arch == 'arm'
self.is_armv7 = self.is_arm and 'armv7' in self.cflags
self.is_aarch64 = ndk_arch == 'arm64'
self.is_windows = False

libstdcxx_flags = ''
libstdcxx_cxxflags = ''
libstdcxx_ldflags = ''
libstdcxx_libs = '-static-libstdc++'

if self.is_armv7:
# On 32 bit ARM, clang generates no ".eh_frame" section;
# instead, the LLVM unwinder library is used for unwinding
# the stack after a C++ exception was thrown
libstdcxx_libs += ' -lunwind'

if use_cxx:
self.cxxflags += ' ' + libstdcxx_cxxflags
self.ldflags += ' ' + libstdcxx_ldflags
self.libs += ' ' + libstdcxx_libs

self.env = dict(os.environ)

# redirect pkg-config to use our root directory instead of the
# default one on the build host
import shutil
bin_dir = os.path.join(install_prefix, 'bin')
os.makedirs(bin_dir, exist_ok=True)
self.pkg_config = shutil.copy(os.path.join(mpd_path, 'build', 'pkg-config.sh'),
os.path.join(bin_dir, 'pkg-config'))
self.env['PKG_CONFIG'] = self.pkg_config
from build.toolchain import AndroidNdkToolchain

# a list of third-party libraries to be used by MPD on Android
from build.libs import *
Expand All @@ -165,13 +47,17 @@ def __init__(self, tarball_path, src_path, build_path,

# build the third-party libraries
for x in thirdparty_libs:
toolchain = AndroidNdkToolchain(tarball_path, src_path, build_path,
toolchain = AndroidNdkToolchain(mpd_path, lib_path,
tarball_path, src_path,
ndk_path, android_abi,
use_cxx=x.use_cxx)
if not x.is_installed(toolchain):
x.build(toolchain)

# configure and build MPD
toolchain = AndroidNdkToolchain(tarball_path, src_path, build_path,
toolchain = AndroidNdkToolchain(mpd_path, lib_path,
tarball_path, src_path,
ndk_path, android_abi,
use_cxx=True)

configure_args += [
Expand Down
40 changes: 27 additions & 13 deletions python/build/autotools.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
import os.path, subprocess, sys
from typing import Collection, Iterable, Optional, Sequence, Union
from collections.abc import Mapping

from build.makeproject import MakeProject
from .toolchain import AnyToolchain

class AutotoolsProject(MakeProject):
def __init__(self, url, md5, installed, configure_args=[],
autogen=False,
autoreconf=False,
cppflags='',
ldflags='',
libs='',
subdirs=None,
def __init__(self, url: Union[str, Sequence[str]], md5: str, installed: str,
configure_args: Iterable[str]=[],
autogen: bool=False,
autoreconf: bool=False,
per_arch_cflags: Optional[Mapping[str, str]]=None,
cppflags: str='',
ldflags: str='',
libs: str='',
subdirs: Optional[Collection[str]]=None,
**kwargs):
MakeProject.__init__(self, url, md5, installed, **kwargs)
self.configure_args = configure_args
self.autogen = autogen
self.autoreconf = autoreconf
self.per_arch_cflags = per_arch_cflags
self.cppflags = cppflags
self.ldflags = ldflags
self.libs = libs
self.subdirs = subdirs

def configure(self, toolchain):
def configure(self, toolchain: AnyToolchain) -> str:
src = self.unpack(toolchain)
if self.autogen:
if sys.platform == 'darwin':
Expand All @@ -35,23 +41,31 @@ def configure(self, toolchain):

build = self.make_build_path(toolchain)

arch_cflags = ''
if self.per_arch_cflags is not None and toolchain.host_triplet is not None:
arch_cflags = self.per_arch_cflags.get(toolchain.host_triplet, '')

configure = [
os.path.join(src, 'configure'),
'CC=' + toolchain.cc,
'CXX=' + toolchain.cxx,
'CFLAGS=' + toolchain.cflags,
'CXXFLAGS=' + toolchain.cxxflags,
'CFLAGS=' + toolchain.cflags + ' ' + arch_cflags,
'CXXFLAGS=' + toolchain.cxxflags + ' ' + arch_cflags,
'CPPFLAGS=' + toolchain.cppflags + ' ' + self.cppflags,
'LDFLAGS=' + toolchain.ldflags + ' ' + self.ldflags,
'LIBS=' + toolchain.libs + ' ' + self.libs,
'AR=' + toolchain.ar,
'ARFLAGS=' + toolchain.arflags,
'RANLIB=' + toolchain.ranlib,
'STRIP=' + toolchain.strip,
'--host=' + toolchain.arch,
'--prefix=' + toolchain.install_prefix,
'--disable-silent-rules',
] + self.configure_args
]

if toolchain.host_triplet is not None:
configure.append('--host=' + toolchain.host_triplet)

configure.extend(self.configure_args)

try:
print(configure)
Expand All @@ -68,7 +82,7 @@ def configure(self, toolchain):

return build

def _build(self, toolchain):
def _build(self, toolchain: AnyToolchain) -> None:
build = self.configure(toolchain)
if self.subdirs is not None:
for subdir in self.subdirs:
Expand Down
63 changes: 35 additions & 28 deletions python/build/cmake.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import os
import re
import subprocess
from typing import cast, Optional, Sequence, TextIO, Union
from collections.abc import Mapping

from build.project import Project
from .toolchain import AnyToolchain

def __write_cmake_compiler(f, language, compiler):
def __write_cmake_compiler(f: TextIO, language: str, compiler: str) -> None:
s = compiler.split(' ', 1)
if len(s) == 2:
print(f'set(CMAKE_{language}_COMPILER_LAUNCHER {s[0]})', file=f)
compiler = s[1]
print(f'set(CMAKE_{language}_COMPILER {compiler})', file=f)

def __write_cmake_toolchain_file(f, toolchain):
if '-darwin' in toolchain.actual_arch:
def __write_cmake_toolchain_file(f: TextIO, toolchain: AnyToolchain) -> None:
if toolchain.is_darwin:
cmake_system_name = 'Darwin'
elif toolchain.is_windows:
cmake_system_name = 'Windows'
Expand All @@ -21,10 +24,10 @@ def __write_cmake_toolchain_file(f, toolchain):

f.write(f"""
set(CMAKE_SYSTEM_NAME {cmake_system_name})
set(CMAKE_SYSTEM_PROCESSOR {toolchain.actual_arch.split('-', 1)[0]})
set(CMAKE_SYSTEM_PROCESSOR {toolchain.host_triplet.split('-', 1)[0]})
set(CMAKE_C_COMPILER_TARGET {toolchain.actual_arch})
set(CMAKE_CXX_COMPILER_TARGET {toolchain.actual_arch})
set(CMAKE_C_COMPILER_TARGET {toolchain.host_triplet})
set(CMAKE_CXX_COMPILER_TARGET {toolchain.host_triplet})
set(CMAKE_C_FLAGS_INIT "{toolchain.cflags} {toolchain.cppflags}")
set(CMAKE_CXX_FLAGS_INIT "{toolchain.cxxflags} {toolchain.cppflags}")
Expand Down Expand Up @@ -52,36 +55,39 @@ def __write_cmake_toolchain_file(f, toolchain):
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
""")

def configure(toolchain, src, build, args=(), env=None):
cross_args = []
def configure(toolchain: AnyToolchain, src: str, build: str, args: list[str]=[], env: Optional[Mapping[str, str]]=None) -> None:
cross_args: list[str] = []

if toolchain.is_windows:
cross_args.append('-DCMAKE_RC_COMPILER=' + toolchain.windres)

# Several targets need a sysroot to prevent pkg-config from
# looking for libraries on the build host (TODO: fix this
# properly); but we must not do that on Android because the NDK
# has a sysroot already
if '-android' not in toolchain.actual_arch and '-darwin' not in toolchain.actual_arch:
cross_args.append('-DCMAKE_SYSROOT=' + toolchain.install_prefix)

os.makedirs(build, exist_ok=True)
cmake_toolchain_file = os.path.join(build, 'cmake_toolchain_file')
with open(cmake_toolchain_file, 'w') as f:
__write_cmake_toolchain_file(f, toolchain)
cross_args.append('-DCMAKE_RC_COMPILER=' + cast(str, toolchain.windres))

configure = [
'cmake',
src,

'-DCMAKE_TOOLCHAIN_FILE=' + cmake_toolchain_file,

'-DCMAKE_INSTALL_PREFIX=' + toolchain.install_prefix,
'-DCMAKE_BUILD_TYPE=release',

'-GNinja',
] + cross_args + args

if toolchain.host_triplet is not None:
# cross-compiling: write a toolchain file
os.makedirs(build, exist_ok=True)

# Several targets need a sysroot to prevent pkg-config from
# looking for libraries on the build host (TODO: fix this
# properly); but we must not do that on Android because the NDK
# has a sysroot already
if not toolchain.is_android and not toolchain.is_darwin:
cross_args.append('-DCMAKE_SYSROOT=' + toolchain.install_prefix)

cmake_toolchain_file = os.path.join(build, 'cmake_toolchain_file')
with open(cmake_toolchain_file, 'w') as f:
__write_cmake_toolchain_file(f, toolchain)

configure.append('-DCMAKE_TOOLCHAIN_FILE=' + cmake_toolchain_file)

if env is None:
env = toolchain.env
else:
Expand All @@ -91,16 +97,17 @@ def configure(toolchain, src, build, args=(), env=None):
subprocess.check_call(configure, env=env, cwd=build)

class CmakeProject(Project):
def __init__(self, url, md5, installed, configure_args=[],
windows_configure_args=[],
env=None,
def __init__(self, url: Union[str, Sequence[str]], md5: str, installed: str,
configure_args: list[str]=[],
windows_configure_args: list[str]=[],
env: Optional[Mapping[str, str]]=None,
**kwargs):
Project.__init__(self, url, md5, installed, **kwargs)
self.configure_args = configure_args
self.windows_configure_args = windows_configure_args
self.env = env

def configure(self, toolchain):
def configure(self, toolchain: AnyToolchain) -> str:
src = self.unpack(toolchain)
build = self.make_build_path(toolchain)
configure_args = self.configure_args
Expand All @@ -109,7 +116,7 @@ def configure(self, toolchain):
configure(toolchain, src, build, configure_args, self.env)
return build

def _build(self, toolchain):
def _build(self, toolchain: AnyToolchain) -> None:
build = self.configure(toolchain)
subprocess.check_call(['ninja', '-v', 'install'],
cwd=build, env=toolchain.env)
Loading

0 comments on commit 39476be

Please sign in to comment.