Bug 1811871 - Check collapsed attribute rather than computed opacity value to tell...
[gecko.git] / build / moz.configure / android-ndk.configure
blob2480556ff9e5c3e0618858713cf9618e206735a9
1 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
2 # vim: set filetype=python:
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 @depends(toolchains_base_dir, "--help")
9 @imports(_from="os.path", _import="isdir")
10 @imports(_from="mozboot.android", _import="NDK_VERSION")
11 def default_android_ndk_root(toolchains_base_dir, _):
12     for ndk in ("android-ndk-%s" % NDK_VERSION, "android-ndk"):
13         path = os.path.join(toolchains_base_dir, ndk)
14         if isdir(path):
15             return path
18 option(
19     "--with-android-ndk",
20     nargs=1,
21     default=default_android_ndk_root,
22     help="location where the Android NDK can be found{|}",
25 option("--with-android-toolchain", nargs=1, help="location of the Android toolchain")
27 option(
28     "--with-android-lldb-server", nargs=1, help="location of the Android LLDB server"
31 option(
32     "--with-android-googlevr-sdk", nargs=1, help="location of the Android GoogleVR SDK"
36 @depends(target)
37 def min_android_version(target):
38     if target.cpu in ["aarch64", "x86_64"]:
39         # 64-bit support was added in API 21.
40         return "21"
41     return "16"
44 option(
45     "--with-android-version",
46     nargs=1,
47     help="android platform version{|}",
48     default=min_android_version,
52 @depends("--with-android-version", min_android_version)
53 @imports(_from="__builtin__", _import="ValueError")
54 def android_version(value, min_version):
55     if not value:
56         # Someone has passed --without-android-version.
57         die("--with-android-version cannot be disabled.")
59     try:
60         version = int(value[0])
61     except ValueError:
62         die("--with-android-version expects an integer value")
64     if version < int(min_version):
65         die(
66             "--with-android-version must be at least %s (got %s)", min_version, value[0]
67         )
69     return version
72 add_old_configure_assignment("android_version", android_version)
75 @depends("--with-android-ndk")
76 @imports(_from="os.path", _import="isdir")
77 def ndk(value):
78     if value:
79         if not isdir(value[0]):
80             die(
81                 "The path you specified with --with-android-ndk (%s) is not "
82                 "a directory" % value[0]
83             )
84         return value[0]
86     die(
87         "You must specify --with-android-ndk=/path/to/ndk when targeting Android, "
88         "or try |mach bootstrap|."
89     )
92 set_config("ANDROID_NDK", ndk)
93 add_old_configure_assignment("android_ndk", ndk)
96 @depends(ndk)
97 @checking("for android ndk version")
98 @imports(_from="__builtin__", _import="open")
99 @imports(_from="mozboot.android", _import="NDK_VERSION")
100 @imports(_from="mozboot.android", _import="get_ndk_version")
101 @imports(_from="mozboot.android", _import="GetNdkVersionError")
102 def ndk_version(ndk):
103     if not ndk:
104         # Building 'js/src' for non-Android.
105         return
107     try:
108         major, minor, human = get_ndk_version(ndk)
109     except GetNdkVersionError as e:
110         die(str(e))
112     if NDK_VERSION != human:
113         die(
114             "The only supported version of the NDK is %s (have %s)\n"
115             "Please run |mach bootstrap| "
116             "to install the correct NDK." % (NDK_VERSION, human)
117         )
118     return namespace(
119         major=major,
120         minor=minor,
121     )
124 set_config("ANDROID_NDK_MAJOR_VERSION", ndk_version.major)
125 set_config("ANDROID_NDK_MINOR_VERSION", ndk_version.minor)
128 @depends(target, android_version, ndk)
129 @checking("for android platform directory")
130 @imports(_from="os.path", _import="isdir")
131 def android_platform(target, android_version, ndk):
132     if target.os != "Android":
133         return
135     if "aarch64" == target.cpu:
136         target_dir_name = "arm64"
137     else:
138         target_dir_name = target.cpu
140     # Not all Android releases have their own platform release. We use
141     # the next lower platform version in these cases.
142     if android_version in (11, 10):
143         platform_version = 9
144     elif android_version in (20, 22):
145         platform_version = android_version - 1
146     else:
147         platform_version = android_version
149     platform_dir = os.path.join(
150         ndk, "platforms", "android-%s" % platform_version, "arch-%s" % target_dir_name
151     )
153     if not isdir(platform_dir):
154         die(
155             "Android platform directory not found. With the current "
156             "configuration, it should be in %s" % platform_dir
157         )
159     return platform_dir
162 set_config("ANDROID_PLATFORM", android_platform)
165 @depends(android_platform, ndk, target)
166 @checking("for android sysroot directory")
167 @imports(_from="os.path", _import="isdir")
168 def android_sysroot(android_platform, ndk, target):
169     if target.os != "Android":
170         return
172     # NDK r15 has both unified and non-unified headers, but we only support
173     # non-unified for that NDK, so look for that first.
174     search_dirs = [
175         # (<if this directory exists>, <return this directory>)
176         (os.path.join(android_platform, "usr", "include"), android_platform),
177         (os.path.join(ndk, "sysroot"), os.path.join(ndk, "sysroot")),
178     ]
180     for test_dir, sysroot_dir in search_dirs:
181         if isdir(test_dir):
182             return sysroot_dir
184     die(
185         "Android sysroot directory not found in %s."
186         % str([sysroot_dir for test_dir, sysroot_dir in search_dirs])
187     )
190 add_old_configure_assignment("android_sysroot", android_sysroot)
193 @depends(android_platform, ndk, target)
194 @checking("for android system directory")
195 @imports(_from="os.path", _import="isdir")
196 def android_system(android_platform, ndk, target):
197     if target.os != "Android":
198         return
200     # NDK r15 has both unified and non-unified headers, but we only support
201     # non-unified for that NDK, so look for that first.
202     search_dirs = [
203         os.path.join(android_platform, "usr", "include"),
204         os.path.join(ndk, "sysroot", "usr", "include", target.toolchain),
205     ]
207     for system_dir in search_dirs:
208         if isdir(system_dir):
209             return system_dir
211     die("Android system directory not found in %s." % str(search_dirs))
214 add_old_configure_assignment("android_system", android_system)
217 @depends(target, host, ndk, "--with-android-toolchain")
218 @checking("for the Android toolchain directory", lambda x: x or "not found")
219 @imports(_from="os.path", _import="isdir")
220 @imports(_from="mozbuild.shellutil", _import="quote")
221 def android_toolchain(target, host, ndk, toolchain):
222     if not ndk:
223         return
224     if toolchain:
225         return toolchain[0]
226     else:
227         if target.cpu == "arm" and target.endianness == "little":
228             target_base = "arm-linux-androideabi"
229         elif target.cpu == "x86":
230             target_base = "x86"
231         elif target.cpu == "x86_64":
232             target_base = "x86_64"
233         elif target.cpu == "aarch64" and target.endianness == "little":
234             target_base = "aarch64-linux-android"
235         else:
236             die("Target cpu is not supported.")
238         toolchain_format = "%s/toolchains/%s-4.9/prebuilt/%s-%s"
239         host_kernel = "windows" if host.kernel == "WINNT" else host.kernel.lower()
241         toolchain = toolchain_format % (ndk, target_base, host_kernel, host.cpu)
242         log.debug("Trying %s" % quote(toolchain))
243         if not isdir(toolchain) and host.cpu == "x86_64":
244             toolchain = toolchain_format % (ndk, target_base, host_kernel, "x86")
245             log.debug("Trying %s" % quote(toolchain))
246         if not isdir(toolchain) and host.kernel == "Darwin" and host.cpu == "aarch64":
247             toolchain = toolchain_format % (ndk, target_base, host_kernel, "x86_64")
248             log.debug("Trying %s" % quote(toolchain))
249         if isdir(toolchain):
250             return toolchain
251         die("You have to specify --with-android-toolchain=" "/path/to/ndk/toolchain.")
254 set_config("ANDROID_TOOLCHAIN", android_toolchain)
257 @depends(target, host, ndk, "--with-android-lldb-server")
258 @checking("for the Android LLDB server", lambda x: x or "not found")
259 @imports(_from="os", _import="listdir")
260 @imports(_from="os.path", _import="isdir")
261 @imports(_from="os.path", _import="isfile")
262 @imports(_from="mozbuild.shellutil", _import="quote")
263 def android_lldb_server(target, host, ndk, lldb):
264     if not ndk:
265         return
266     if lldb:
267         return lldb[0]
268     else:
269         clang_format = "toolchains/llvm/prebuilt/%s-%s/lib64/clang"
270         llvm_lib = "lib/linux"
272         host_kernel = "windows" if host.kernel == "WINNT" else host.kernel.lower()
273         clang_path = os.path.join(ndk, clang_format % (host_kernel, host.cpu))
274         if not isdir(clang_path) and host.kernel == "Darwin" and host.cpu == "aarch64":
275             clang_path = os.path.join(ndk, clang_format % (host_kernel, "x86_64"))
276         log.debug("Listing subdirectories of %s" % quote(clang_path))
277         clang_subdirs = [
278             x for x in listdir(clang_path) if isdir(os.path.join(clang_path, x))
279         ]
280         log.debug("Got %r" % clang_subdirs)
281         if len(clang_subdirs) != 1:
282             die(
283                 "Could not resolve lldb-server in %s. Please specify --with-android-lldb-server=/path/to/android/lldb-server"
284                 % quote(clang_path)
285             )
286         log.debug("Found version %s" % quote(clang_subdirs[0]))
288         if target.cpu == "x86":
289             target_cpu = "i386"
290         else:
291             target_cpu = target.cpu
293         full_path = os.path.join(
294             clang_path, clang_subdirs[0], llvm_lib, target_cpu, "lldb-server"
295         )
296         log.debug("Trying %s" % quote(full_path))
298         if isfile(full_path):
299             return full_path
300         die("Please specify --with-android-lldb-server=/path/to/android/lldb-server")
303 set_config("ANDROID_LLDB_SERVER", android_lldb_server)
306 @depends(target)
307 def android_toolchain_prefix_base(target):
308     if target.cpu == "x86":
309         # Ideally, the --target should just have the right x86 variant
310         # in the first place.
311         return "i686-linux-android"
312     return target.toolchain
315 option(
316     env="STLPORT_CPPFLAGS",
317     nargs=1,
318     help="Options compiler should pass for standard C++ library",
322 @depends("STLPORT_CPPFLAGS", ndk)
323 @imports(_from="os.path", _import="isdir")
324 def stlport_cppflags(value, ndk):
325     if value and len(value):
326         return value.split()
327     if not ndk:
328         return
330     ndk_base = os.path.join(ndk, "sources", "cxx-stl")
331     cxx_base = os.path.join(ndk_base, "llvm-libc++")
332     cxx_include = os.path.join(cxx_base, "libcxx", "include")
333     cxxabi_base = os.path.join(ndk_base, "llvm-libc++abi")
334     cxxabi_include = os.path.join(cxxabi_base, "libcxxabi", "include")
336     if not isdir(cxx_include):
337         # NDK r13 removes the inner "libcxx" directory.
338         cxx_include = os.path.join(cxx_base, "include")
339         if not isdir(cxx_include):
340             die("Couldn't find path to libc++ includes in the android ndk")
342     if not isdir(cxxabi_include):
343         # NDK r13 removes the inner "libcxxabi" directory.
344         cxxabi_include = os.path.join(cxxabi_base, "include")
345         if not isdir(cxxabi_include):
346             die("Couldn't find path to libc++abi includes in the android ndk")
348     # Add android/support/include/ for prototyping long double math
349     # functions, locale-specific C library functions, multibyte support,
350     # etc.
351     return [
352         # You'd think we'd want to use -stdlib=libc++, but this doesn't work
353         # (cf. https://bugzilla.mozilla.org/show_bug.cgi?id=1510897#c2)
354         # Using -stdlib=libc++ and removing some of the -I below also doesn't
355         # work because not everything that is in cxx_include comes in the C++
356         # header directory that comes with clang.
357         "-stdlib=libstdc++",
358         "-I%s" % cxx_include,
359         "-I%s" % os.path.join(ndk, "sources", "android", "support", "include"),
360         "-I%s" % cxxabi_include,
361     ]
364 add_old_configure_assignment("stlport_cppflags", stlport_cppflags)
367 @depends(android_system, android_sysroot, android_toolchain, android_version)
368 def extra_toolchain_flags(
369     android_system, android_sysroot, toolchain_dir, android_version
371     if not android_sysroot:
372         return []
373     flags = [
374         "-isystem",
375         android_system,
376         "-isystem",
377         os.path.join(android_sysroot, "usr", "include"),
378         "--gcc-toolchain={}".format(toolchain_dir),
379         "-D__ANDROID_API__=%d" % android_version,
380     ]
381     return flags
384 @depends(android_toolchain_prefix_base, android_toolchain)
385 def android_toolchain_prefix(prefix_base, toolchain):
386     if toolchain:
387         return "%s/bin/%s-" % (toolchain, prefix_base)
390 imply_option(
391     "--with-toolchain-prefix", android_toolchain_prefix, reason="--with-android-ndk"
395 @depends(
396     extra_toolchain_flags,
397     stlport_cppflags,
398     android_toolchain,
399     android_toolchain_prefix_base,
401 @imports(_from="os.path", _import="isdir")
402 def bindgen_cflags_android(toolchain_flags, stlport_flags, toolchain, toolchain_prefix):
403     if not toolchain_flags:
404         return
406     gcc_include = os.path.join(toolchain, "lib", "gcc", toolchain_prefix, "4.9.x")
407     if not isdir(gcc_include):
408         gcc_include = os.path.join(toolchain, "lib", "gcc", toolchain_prefix, "4.9")
410     return (
411         toolchain_flags
412         + stlport_flags
413         + [
414             "-I%s" % os.path.join(gcc_include, "include"),
415             "-I%s" % os.path.join(gcc_include, "include-fixed"),
416         ]
417     )
420 @depends("--with-android-googlevr-sdk", target)
421 @checking("for GoogleVR SDK", lambda x: x.result)
422 @imports(_from="os.path", _import="exists")
423 @imports(_from="os.path", _import="abspath")
424 def googlevr_sdk(value, target):
425     if not value:
426         return namespace(result="Not specified")
427     path = abspath(value[0])
428     if not exists(path):
429         die("Could not find GoogleVR SDK %s", path)
430     include = "%s/libraries/headers/" % path
431     if "arm" == target.cpu:
432         arch = "armeabi-v7a"
433     elif "aarch64" == target.cpu:
434         arch = "arm64-v8a"
435     elif "x86" == target.cpu:
436         arch = "x86"
437     else:
438         die("Unsupported GoogleVR cpu architecture %s" % target.cpu)
440     libs = "{0}/libraries/jni/{1}/".format(path, arch)
442     if not exists(libs):
443         die(
444             "Could not find GoogleVR NDK at %s. Did you try running "
445             "'./gradlew :extractNdk' in %s?",
446             libs,
447             path,
448         )
450     return namespace(
451         result=path,
452         include=include,
453         libs=libs,
454         enabled=True,
455     )
458 set_define("MOZ_ANDROID_GOOGLE_VR", googlevr_sdk.enabled)
459 set_config("MOZ_ANDROID_GOOGLE_VR", googlevr_sdk.enabled)
460 set_config("MOZ_ANDROID_GOOGLE_VR_INCLUDE", googlevr_sdk.include)
461 set_config("MOZ_ANDROID_GOOGLE_VR_LIBS", googlevr_sdk.libs)