build.py 5.23 KB
Newer Older
Max Kellermann's avatar
Max Kellermann committed
1 2
#!/usr/bin/env python3

3
import os, os.path
4
import sys, subprocess
Max Kellermann's avatar
Max Kellermann committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

if len(sys.argv) < 3:
    print("Usage: build.py SDK_PATH NDK_PATH [configure_args...]", file=sys.stderr)
    sys.exit(1)

sdk_path = sys.argv[1]
ndk_path = sys.argv[2]
configure_args = sys.argv[3:]

if not os.path.isfile(os.path.join(sdk_path, 'tools', 'android')):
    print("SDK not found in", ndk_path, file=sys.stderr)
    sys.exit(1)

if not os.path.isdir(ndk_path):
    print("NDK not found in", ndk_path, file=sys.stderr)
    sys.exit(1)

22
# select the NDK target
23
arch = 'arm-linux-androideabi'
24

Max Kellermann's avatar
Max Kellermann committed
25
# the path to the MPD sources
26
mpd_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]) or '.', '..'))
27
sys.path[0] = os.path.join(mpd_path, 'python')
Max Kellermann's avatar
Max Kellermann committed
28 29

# output directories
30
from build.dirs import lib_path, tarball_path, src_path
31

32
arch_path = os.path.join(lib_path, arch)
33
build_path = os.path.join(arch_path, 'build')
Max Kellermann's avatar
Max Kellermann committed
34 35 36 37 38 39

# build host configuration
build_arch = 'linux-x86_64'

# set up the NDK toolchain

40
class AndroidNdkToolchain:
41 42 43 44 45 46
    def __init__(self, tarball_path, src_path, build_path,
                 use_cxx, use_clang):
        self.tarball_path = tarball_path
        self.src_path = src_path
        self.build_path = build_path

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
        self.ndk_arch = 'arm'
        android_abi = 'armeabi-v7a'
        ndk_platform = 'android-14'

        # select the NDK compiler
        gcc_version = '4.9'
        llvm_version = '3.6'

        ndk_platform_path = os.path.join(ndk_path, 'platforms', ndk_platform)
        sysroot = os.path.join(ndk_platform_path, 'arch-' + self.ndk_arch)

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

        self.arch = arch
        self.install_prefix = install_prefix
        self.sysroot = sysroot

        toolchain_path = os.path.join(ndk_path, 'toolchains', arch + '-' + gcc_version, 'prebuilt', build_arch)
        llvm_path = os.path.join(ndk_path, 'toolchains', 'llvm-' + llvm_version, 'prebuilt', build_arch)
        llvm_triple = 'armv7-none-linux-androideabi'

        common_flags = '-march=armv7-a -mfloat-abi=softfp'

        toolchain_bin = os.path.join(toolchain_path, 'bin')
        if use_clang:
            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 + ' -integrated-as -gcc-toolchain ' + toolchain_path
        else:
            self.cc = os.path.join(toolchain_bin, arch + '-gcc')
            self.cxx = os.path.join(toolchain_bin, arch + '-g++')

        self.ar = os.path.join(toolchain_bin, arch + '-ar')
        self.nm = os.path.join(toolchain_bin, arch + '-nm')
        self.strip = os.path.join(toolchain_bin, arch + '-strip')

        self.cflags = '-Os -g ' + common_flags
        self.cxxflags = '-Os -g ' + common_flags
        self.cppflags = '--sysroot=' + self.sysroot + ' -isystem ' + os.path.join(install_prefix, 'include')
87
        self.ldflags = '--sysroot=' + self.sysroot + ' -L' + os.path.join(install_prefix, 'lib')
88 89
        self.libs = ''

90 91 92 93
        self.is_arm = self.ndk_arch == 'arm'
        self.is_armv7 = self.is_arm and 'armv7' in self.cflags
        self.is_windows = False

94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
        libstdcxx_path = os.path.join(ndk_path, 'sources/cxx-stl/gnu-libstdc++', gcc_version)
        libstdcxx_cppflags = '-isystem ' + os.path.join(libstdcxx_path, 'include') + ' -isystem ' + os.path.join(libstdcxx_path, 'libs', android_abi, 'include')
        if use_clang:
            libstdcxx_cppflags += ' -D__STRICT_ANSI__'
        libstdcxx_ldadd = os.path.join(libstdcxx_path, 'libs', android_abi, 'libgnustl_static.a')

        if use_cxx:
            self.libs += ' ' + libstdcxx_ldadd
            self.cppflags += ' ' + libstdcxx_cppflags

        self.env = dict(os.environ)

        # redirect pkg-config to use our root directory instead of the
        # default one on the build host
        self.env['PKG_CONFIG_LIBDIR'] = os.path.join(install_prefix, 'lib/pkgconfig')
Max Kellermann's avatar
Max Kellermann committed
109 110

# a list of third-party libraries to be used by MPD on Android
111
from build.libs import *
Max Kellermann's avatar
Max Kellermann committed
112
thirdparty_libs = [
113 114 115 116 117 118 119 120 121
    libogg,
    libvorbis,
    opus,
    flac,
    libid3tag,
    libmad,
    ffmpeg,
    curl,
    boost,
Max Kellermann's avatar
Max Kellermann committed
122 123 124 125
]

# build the third-party libraries
for x in thirdparty_libs:
126 127
    toolchain = AndroidNdkToolchain(tarball_path, src_path, build_path,
                                    use_cxx=x.use_cxx, use_clang=x.use_clang)
128 129
    if not x.is_installed(toolchain):
        x.build(toolchain)
Max Kellermann's avatar
Max Kellermann committed
130 131

# configure and build MPD
132 133
toolchain = AndroidNdkToolchain(tarball_path, src_path, build_path,
                                use_cxx=True, use_clang=True)
Max Kellermann's avatar
Max Kellermann committed
134 135 136

configure = [
    os.path.join(mpd_path, 'configure'),
137 138 139 140 141 142 143 144 145 146 147 148
    'CC=' + toolchain.cc,
    'CXX=' + toolchain.cxx,
    'CFLAGS=' + toolchain.cflags,
    'CXXFLAGS=' + toolchain.cxxflags,
    'CPPFLAGS=' + toolchain.cppflags,
    'LDFLAGS=' + toolchain.ldflags,
    'LIBS=' + toolchain.libs,
    'AR=' + toolchain.ar,
    'STRIP=' + toolchain.strip,
    '--host=' + toolchain.arch,
    '--prefix=' + toolchain.install_prefix,
    '--with-sysroot=' + toolchain.sysroot,
Max Kellermann's avatar
Max Kellermann committed
149 150 151 152
    '--with-android-sdk=' + sdk_path,

    '--enable-silent-rules',

153
    '--disable-icu',
Max Kellermann's avatar
Max Kellermann committed
154 155 156

] + configure_args

157 158
subprocess.check_call(configure, env=toolchain.env)
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], env=toolchain.env)