DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (6863f516ba38)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.


js_option('--with-android-ndk', nargs=1,
          help='location where the Android NDK can be found')

js_option('--with-android-toolchain', nargs=1,
          help='location of the Android toolchain')

option('--with-android-googlevr-sdk', nargs=1,
       help='location of the Android GoogleVR SDK')


@depends(target)
def min_android_version(target):
    if target.cpu in ['aarch64', 'x86_64']:
        # 64-bit support was added in API 21.
        return '21'
    return '16'


js_option('--with-android-version',
          nargs=1,
          help='android platform version{|}',
          default=min_android_version)


@depends('--with-android-version', min_android_version)
@imports(_from='__builtin__', _import='ValueError')
def android_version(value, min_version):
    if not value:
        # Someone has passed --without-android-version.
        die('--with-android-version cannot be disabled.')

    try:
        version = int(value[0])
    except ValueError:
        die('--with-android-version expects an integer value')

    if version < int(min_version):
        die('--with-android-version must be at least %s (got %s)',
            min_version, value[0])

    return version


add_old_configure_assignment('android_version', android_version)


@depends('--with-android-ndk')
def ndk(value):
    if not value:
        die('You must specify --with-android-ndk=/path/to/ndk when '
            'building for Android')
    return value[0]


set_config('ANDROID_NDK', ndk)
add_old_configure_assignment('android_ndk', ndk)


@depends(ndk)
@checking('for android ndk version')
@imports(_from='__builtin__', _import='open')
def ndk_version(ndk):
    if not ndk:
        # Building 'js/src' for non-Android.
        return
    with open(os.path.join(ndk, 'source.properties'), 'r') as f:
        for line in f:
            if not line.startswith('Pkg.Revision'):
                continue
            (_, version) = line.split('=')
            if version:
                return version.strip()
            die('Unexpected Pkg.Revision line in source.properties')
    die('Cannot determine NDK version from source.properties')


@depends(ndk_version)
def ndk_major_version(ndk_version):
    if not ndk_version:
        # Building 'js/src' for non-Android.
        return
    (major, minor, revision) = ndk_version.split('.')
    if major:
        return major
    die('Unexpected NDK version string: ' + ndk_version)


set_config('ANDROID_NDK_MAJOR_VERSION', ndk_major_version)


@depends(ndk_version)
def ndk_minor_version(ndk_version):
    if not ndk_version:
        # Building 'js/src' for non-Android.
        return
    (major, minor, revision) = ndk_version.split('.')
    if minor:
        return minor
    die('Unexpected NDK version string: ' + ndk_version)


set_config('ANDROID_NDK_MINOR_VERSION', ndk_minor_version)


@depends(target, android_version, ndk)
@checking('for android platform directory')
@imports(_from='os.path', _import='isdir')
def android_platform(target, android_version, ndk):
    if target.os != 'Android':
        return

    if 'aarch64' == target.cpu:
        target_dir_name = 'arm64'
    else:
        target_dir_name = target.cpu

    # Not all Android releases have their own platform release. We use
    # the next lower platform version in these cases.
    if android_version in (11, 10):
        platform_version = 9
    elif android_version in (20, 22):
        platform_version = android_version - 1
    else:
        platform_version = android_version

    platform_dir = os.path.join(ndk,
                                'platforms',
                                'android-%s' % platform_version,
                                'arch-%s' % target_dir_name)

    if not isdir(platform_dir):
        die("Android platform directory not found. With the current "
            "configuration, it should be in %s" % platform_dir)

    return platform_dir


add_old_configure_assignment('android_platform', android_platform)


@depends(android_platform, ndk, target)
@checking('for android sysroot directory')
@imports(_from='os.path', _import='isdir')
def android_sysroot(android_platform, ndk, target):
    if target.os != 'Android':
        return

    # NDK r15 has both unified and non-unified headers, but we only support
    # non-unified for that NDK, so look for that first.
    search_dirs = [
        # (<if this directory exists>, <return this directory>)
        (os.path.join(android_platform, 'usr', 'include'), android_platform),
        (os.path.join(ndk, 'sysroot'), os.path.join(ndk, 'sysroot')),
    ]

    for test_dir, sysroot_dir in search_dirs:
        if isdir(test_dir):
            return sysroot_dir

    die("Android sysroot directory not found in %s." %
        str([sysroot_dir for test_dir, sysroot_dir in search_dirs]))


add_old_configure_assignment('android_sysroot', android_sysroot)


@depends(android_platform, ndk, target)
@checking('for android system directory')
@imports(_from='os.path', _import='isdir')
def android_system(android_platform, ndk, target):
    if target.os != 'Android':
        return

    # NDK r15 has both unified and non-unified headers, but we only support
    # non-unified for that NDK, so look for that first.
    search_dirs = [
        os.path.join(android_platform, 'usr', 'include'),
        os.path.join(ndk, 'sysroot', 'usr', 'include', target.toolchain),
    ]

    for system_dir in search_dirs:
        if isdir(system_dir):
            return system_dir

    die("Android system directory not found in %s." % str(search_dirs))


add_old_configure_assignment('android_system', android_system)


@depends(target, host, ndk, '--with-android-toolchain')
@checking('for the Android toolchain directory', lambda x: x or 'not found')
@imports(_from='os.path', _import='isdir')
@imports(_from='mozbuild.shellutil', _import='quote')
def android_toolchain(target, host, ndk, toolchain):
    if not ndk:
        return
    if toolchain:
        return toolchain[0]
    else:
        if target.cpu == 'arm' and target.endianness == 'little':
            target_base = 'arm-linux-androideabi'
        elif target.cpu == 'x86':
            target_base = 'x86'
        elif target.cpu == 'x86_64':
            target_base = 'x86_64'
        elif target.cpu == 'aarch64' and target.endianness == 'little':
            target_base = 'aarch64-linux-android'
        else:
            die('Target cpu is not supported.')

        toolchain_format = '%s/toolchains/%s-4.9/prebuilt/%s-%s'

        toolchain = toolchain_format % (ndk, target_base,
                                        host.kernel.lower(), host.cpu)
        log.debug('Trying %s' % quote(toolchain))
        if not isdir(toolchain) and host.cpu == 'x86_64':
            toolchain = toolchain_format % (ndk, target_base,
                                            host.kernel.lower(), 'x86')
            log.debug('Trying %s' % quote(toolchain))
        if isdir(toolchain):
            return toolchain
        die('You have to specify --with-android-toolchain='
            '/path/to/ndk/toolchain.')


set_config('ANDROID_TOOLCHAIN', android_toolchain)


@depends(target)
def android_toolchain_prefix_base(target):
    if target.cpu == 'x86':
        # Ideally, the --target should just have the right x86 variant
        # in the first place.
        return 'i686-linux-android'
    return target.toolchain


js_option(env='STLPORT_CPPFLAGS',
          nargs=1,
          help='Options compiler should pass for standard C++ library')


@depends('STLPORT_CPPFLAGS', ndk)
@imports(_from='os.path', _import='isdir')
def stlport_cppflags(value, ndk):
    if value and len(value):
        return value.split()
    if not ndk:
        return

    ndk_base = os.path.join(ndk, 'sources', 'cxx-stl')
    cxx_base = os.path.join(ndk_base, 'llvm-libc++')
    cxx_include = os.path.join(cxx_base, 'libcxx', 'include')
    cxxabi_base = os.path.join(ndk_base, 'llvm-libc++abi')
    cxxabi_include = os.path.join(cxxabi_base, 'libcxxabi', 'include')

    if not isdir(cxx_include):
        # NDK r13 removes the inner "libcxx" directory.
        cxx_include = os.path.join(cxx_base, 'include')
        if not isdir(cxx_include):
            die("Couldn't find path to libc++ includes in the android ndk")

    if not isdir(cxxabi_include):
        # NDK r13 removes the inner "libcxxabi" directory.
        cxxabi_include = os.path.join(cxxabi_base, 'include')
        if not isdir(cxxabi_include):
            die("Couldn't find path to libc++abi includes in the android ndk")

    # Add android/support/include/ for prototyping long double math
    # functions, locale-specific C library functions, multibyte support,
    # etc.
    return [
        # You'd think we'd want to use -stdlib=libc++, but this doesn't work
        # (cf. https://bugzilla.mozilla.org/show_bug.cgi?id=1510897#c2)
        # Using -stdlib=libc++ and removing some of the -I below also doesn't
        # work because not everything that is in cxx_include comes in the C++
        # header directory that comes with clang.
        '-stdlib=libstdc++',
        '-I%s' % cxx_include,
        '-I%s' % os.path.join(ndk, 'sources', 'android', 'support', 'include'),
        '-I%s' % cxxabi_include]


add_old_configure_assignment('stlport_cppflags', stlport_cppflags)


@depends(android_system, android_sysroot, android_toolchain, android_version)
def extra_toolchain_flags(android_system, android_sysroot, toolchain_dir,
                          android_version):
    if not android_sysroot:
        return []
    flags = ['-isystem',
             android_system,
             '-isystem',
             os.path.join(android_sysroot, 'usr', 'include'),
             '-gcc-toolchain',
             toolchain_dir,
             '-D__ANDROID_API__=%d' % android_version]
    return flags


@depends(android_toolchain_prefix_base, android_toolchain)
def android_toolchain_prefix(prefix_base, toolchain):
    if toolchain:
        return '%s/bin/%s-' % (toolchain, prefix_base)


imply_option('--with-toolchain-prefix', android_toolchain_prefix,
             reason='--with-android-ndk')


@depends(extra_toolchain_flags, stlport_cppflags, android_toolchain,
         android_toolchain_prefix_base)
@imports(_from='os.path', _import='isdir')
def bindgen_cflags_android(toolchain_flags, stlport_flags, toolchain,
                           toolchain_prefix):
    if not toolchain_flags:
        return

    gcc_include = os.path.join(
        toolchain, 'lib', 'gcc', toolchain_prefix, '4.9.x')
    if not isdir(gcc_include):
        gcc_include = os.path.join(
            toolchain, 'lib', 'gcc', toolchain_prefix, '4.9')

    return toolchain_flags + stlport_flags + [
        '-I%s' % os.path.join(gcc_include, 'include'),
        '-I%s' % os.path.join(gcc_include, 'include-fixed'),
    ]


@depends(host, ndk)
@imports(_from='os.path', _import='exists')
@imports(_from='os.path', _import='isdir')
def android_clang_compiler(host, ndk):
    if not ndk:
        return

    llvm_format = '%s/toolchains/llvm/prebuilt/%s-%s/bin'
    llvm_path = llvm_format % (ndk, host.kernel.lower(), host.cpu)
    if not isdir(llvm_path) and host.cpu == 'x86_64':
        llvm_path = llvm_format % (ndk, host.kernel.lower(), 'x86')

    if not isdir(llvm_path):
        die("Couldn't find path to LLVM toolchain at %s" % llvm_path)

    clang = '%s/clang' % llvm_path
    if not exists(clang):
        die("Couln't find clang in LLVM toolchain at %s" % clang)

    return clang


@depends('--with-android-googlevr-sdk', target)
@checking('for GoogleVR SDK', lambda x: x.result)
@imports(_from='os.path', _import='exists')
@imports(_from='os.path', _import='abspath')
def googlevr_sdk(value, target):
    if not value:
        return namespace(
            result='Not specified'
        )
    path = abspath(value[0])
    if not exists(path):
        die('Could not find GoogleVR SDK %s', path)
    include = '%s/libraries/headers/' % path
    if 'arm' == target.cpu:
        arch = 'armeabi-v7a'
    elif 'aarch64' == target.cpu:
        arch = 'arm64-v8a'
    elif 'x86' == target.cpu:
        arch = 'x86'
    else:
        die('Unsupported GoogleVR cpu architecture %s' % target.cpu)

    libs = '{0}/libraries/jni/{1}/'.format(path, arch)

    if not exists(libs):
        die('Could not find GoogleVR NDK at %s. Did you try running '
            '\'./gradlew :extractNdk\' in %s?', libs, path)

    return namespace(
        result=path,
        include=include,
        libs=libs,
        enabled=True,
    )


set_define('MOZ_ANDROID_GOOGLE_VR', googlevr_sdk.enabled)
set_config('MOZ_ANDROID_GOOGLE_VR', googlevr_sdk.enabled)
set_config('MOZ_ANDROID_GOOGLE_VR_INCLUDE', googlevr_sdk.include)
set_config('MOZ_ANDROID_GOOGLE_VR_LIBS', googlevr_sdk.libs)