mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Clean up cross-compilation and features
Integrate cross-compilation and media-stack handling into the `build_like_command_arguments` decorator. This removes a lot of repetition in the code and standardizes how targets are selected for all similar commands. Now cross compilation targets, feature flags, and helper variables are stored in the CommandBase instance. This also avoids having to continuously pass these arguments down to functions called by the commands.
This commit is contained in:
parent
e9a7787a4d
commit
debc37a7d3
6 changed files with 181 additions and 172 deletions
|
@ -62,41 +62,19 @@ class MachCommands(CommandBase):
|
||||||
@CommandArgument('--very-verbose', '-vv',
|
@CommandArgument('--very-verbose', '-vv',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Print very verbose output')
|
help='Print very verbose output')
|
||||||
@CommandArgument('--uwp',
|
|
||||||
action='store_true',
|
|
||||||
help='Build for HoloLens (x64)')
|
|
||||||
@CommandArgument('--win-arm64', action='store_true', help="Use arm64 Windows target")
|
|
||||||
@CommandArgument('params', nargs='...',
|
@CommandArgument('params', nargs='...',
|
||||||
help="Command-line arguments to be passed through to Cargo")
|
help="Command-line arguments to be passed through to Cargo")
|
||||||
@CommandBase.build_like_command_arguments
|
@CommandBase.build_like_command_arguments
|
||||||
def build(self, release=False, dev=False, jobs=None, params=None, media_stack=None,
|
def build(self, release=False, dev=False, jobs=None, params=None, no_package=False,
|
||||||
no_package=False, verbose=False, very_verbose=False,
|
verbose=False, very_verbose=False, libsimpleservo=False, **kwargs):
|
||||||
target=None, android=False, libsimpleservo=False,
|
|
||||||
features=None, uwp=False, win_arm64=False, **kwargs):
|
|
||||||
# Force the UWP-enabled target if the convenience UWP flags are passed.
|
|
||||||
if uwp and not target:
|
|
||||||
if win_arm64:
|
|
||||||
target = 'aarch64-uwp-windows-msvc'
|
|
||||||
else:
|
|
||||||
target = 'x86_64-uwp-windows-msvc'
|
|
||||||
|
|
||||||
opts = params or []
|
opts = params or []
|
||||||
features = features or []
|
has_media_stack = "media-gstreamer" in self.features
|
||||||
|
|
||||||
target, android = self.pick_target_triple(target, android)
|
|
||||||
|
|
||||||
# Infer UWP build if only provided a target.
|
|
||||||
if not uwp:
|
|
||||||
uwp = target and 'uwp' in target
|
|
||||||
|
|
||||||
media_stack = self.pick_media_stack(media_stack, target)
|
|
||||||
features += media_stack
|
|
||||||
has_media_stack = media_stack[0] == "media-gstreamer"
|
|
||||||
|
|
||||||
target_path = base_path = servo.util.get_target_dir()
|
target_path = base_path = servo.util.get_target_dir()
|
||||||
if android:
|
if self.is_android_build:
|
||||||
|
assert self.cross_compile_target
|
||||||
target_path = path.join(target_path, "android")
|
target_path = path.join(target_path, "android")
|
||||||
base_path = path.join(target_path, target)
|
base_path = path.join(target_path, self.cross_compile_target)
|
||||||
|
|
||||||
release_path = path.join(base_path, "release", "servo")
|
release_path = path.join(base_path, "release", "servo")
|
||||||
dev_path = path.join(base_path, "debug", "servo")
|
dev_path = path.join(base_path, "debug", "servo")
|
||||||
|
@ -135,15 +113,15 @@ class MachCommands(CommandBase):
|
||||||
if very_verbose:
|
if very_verbose:
|
||||||
opts += ["-vv"]
|
opts += ["-vv"]
|
||||||
|
|
||||||
env = self.build_env(target=target, is_build=True, uwp=uwp, features=features)
|
env = self.build_env(is_build=True, features=self.features)
|
||||||
self.ensure_bootstrapped(target=target)
|
self.ensure_bootstrapped()
|
||||||
self.ensure_clobbered()
|
self.ensure_clobbered()
|
||||||
|
|
||||||
build_start = time()
|
build_start = time()
|
||||||
env["CARGO_TARGET_DIR"] = target_path
|
env["CARGO_TARGET_DIR"] = target_path
|
||||||
|
|
||||||
host = servo.platform.host_triple()
|
host = servo.platform.host_triple()
|
||||||
target_triple = target or servo.platform.host_triple()
|
target_triple = self.cross_compile_target or servo.platform.host_triple()
|
||||||
if 'apple-darwin' in host and target_triple == host:
|
if 'apple-darwin' in host and target_triple == host:
|
||||||
if 'CXXFLAGS' not in env:
|
if 'CXXFLAGS' not in env:
|
||||||
env['CXXFLAGS'] = ''
|
env['CXXFLAGS'] = ''
|
||||||
|
@ -166,7 +144,7 @@ class MachCommands(CommandBase):
|
||||||
|
|
||||||
env['PKG_CONFIG_ALLOW_CROSS'] = "1"
|
env['PKG_CONFIG_ALLOW_CROSS'] = "1"
|
||||||
|
|
||||||
if uwp:
|
if self.is_uwp_build:
|
||||||
# Ensure libstd is ready for the new UWP target.
|
# Ensure libstd is ready for the new UWP target.
|
||||||
check_call(["rustup", "component", "add", "rust-src"])
|
check_call(["rustup", "component", "add", "rust-src"])
|
||||||
|
|
||||||
|
@ -225,7 +203,7 @@ class MachCommands(CommandBase):
|
||||||
print(stderr.decode(encoding))
|
print(stderr.decode(encoding))
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
if android:
|
if self.is_android_build:
|
||||||
if "ANDROID_NDK" not in env:
|
if "ANDROID_NDK" not in env:
|
||||||
print("Please set the ANDROID_NDK environment variable.")
|
print("Please set the ANDROID_NDK environment variable.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -244,7 +222,7 @@ class MachCommands(CommandBase):
|
||||||
make_cmd = ["make"]
|
make_cmd = ["make"]
|
||||||
if jobs is not None:
|
if jobs is not None:
|
||||||
make_cmd += ["-j" + jobs]
|
make_cmd += ["-j" + jobs]
|
||||||
openssl_dir = path.join(target_path, target, "native", "openssl")
|
openssl_dir = path.join(target_path, self.cross_compile_target, "native", "openssl")
|
||||||
if not path.exists(openssl_dir):
|
if not path.exists(openssl_dir):
|
||||||
os.makedirs(openssl_dir)
|
os.makedirs(openssl_dir)
|
||||||
shutil.copy(path.join(self.android_support_dir(), "openssl.makefile"), openssl_dir)
|
shutil.copy(path.join(self.android_support_dir(), "openssl.makefile"), openssl_dir)
|
||||||
|
@ -261,7 +239,7 @@ class MachCommands(CommandBase):
|
||||||
print("Currently only support NDK 15. Please re-run `./mach bootstrap-android`.")
|
print("Currently only support NDK 15. Please re-run `./mach bootstrap-android`.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
env["RUST_TARGET"] = target
|
env["RUST_TARGET"] = self.cross_compile_target
|
||||||
with cd(openssl_dir):
|
with cd(openssl_dir):
|
||||||
status = call(
|
status = call(
|
||||||
make_cmd + ["-f", "openssl.makefile"],
|
make_cmd + ["-f", "openssl.makefile"],
|
||||||
|
@ -339,7 +317,7 @@ class MachCommands(CommandBase):
|
||||||
# Also worth remembering: autoconf uses C for its configuration,
|
# Also worth remembering: autoconf uses C for its configuration,
|
||||||
# even for C++ builds, so the C flags need to line up with the C++ flags.
|
# even for C++ builds, so the C flags need to line up with the C++ flags.
|
||||||
env['CFLAGS'] = ' '.join([
|
env['CFLAGS'] = ' '.join([
|
||||||
"--target=" + target,
|
"--target=" + self.cross_compile_target,
|
||||||
"--sysroot=" + env['ANDROID_SYSROOT'],
|
"--sysroot=" + env['ANDROID_SYSROOT'],
|
||||||
"--gcc-toolchain=" + gcc_toolchain,
|
"--gcc-toolchain=" + gcc_toolchain,
|
||||||
"-isystem", sysroot_include,
|
"-isystem", sysroot_include,
|
||||||
|
@ -349,7 +327,7 @@ class MachCommands(CommandBase):
|
||||||
"-D__ANDROID_API__=" + android_api,
|
"-D__ANDROID_API__=" + android_api,
|
||||||
])
|
])
|
||||||
env['CXXFLAGS'] = ' '.join([
|
env['CXXFLAGS'] = ' '.join([
|
||||||
"--target=" + target,
|
"--target=" + self.cross_compile_target,
|
||||||
"--sysroot=" + env['ANDROID_SYSROOT'],
|
"--sysroot=" + env['ANDROID_SYSROOT'],
|
||||||
"--gcc-toolchain=" + gcc_toolchain,
|
"--gcc-toolchain=" + gcc_toolchain,
|
||||||
"-I" + cpufeatures_include,
|
"-I" + cpufeatures_include,
|
||||||
|
@ -368,7 +346,7 @@ class MachCommands(CommandBase):
|
||||||
"-D__NDK_FPABI__=",
|
"-D__NDK_FPABI__=",
|
||||||
])
|
])
|
||||||
env['CPPFLAGS'] = ' '.join([
|
env['CPPFLAGS'] = ' '.join([
|
||||||
"--target=" + target,
|
"--target=" + self.cross_compile_target,
|
||||||
"--sysroot=" + env['ANDROID_SYSROOT'],
|
"--sysroot=" + env['ANDROID_SYSROOT'],
|
||||||
"-I" + arch_include,
|
"-I" + arch_include,
|
||||||
])
|
])
|
||||||
|
@ -431,26 +409,26 @@ class MachCommands(CommandBase):
|
||||||
|
|
||||||
status = self.run_cargo_build_like_command(
|
status = self.run_cargo_build_like_command(
|
||||||
"build", opts, env=env, verbose=verbose,
|
"build", opts, env=env, verbose=verbose,
|
||||||
target=target, android=android, libsimpleservo=libsimpleservo, uwp=uwp,
|
libsimpleservo=libsimpleservo, **kwargs
|
||||||
features=features, **kwargs
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Do some additional things if the build succeeded
|
# Do some additional things if the build succeeded
|
||||||
if status == 0:
|
if status == 0:
|
||||||
if android and not no_package:
|
if self.is_android_build and not no_package:
|
||||||
flavor = None
|
flavor = None
|
||||||
if "googlevr" in features:
|
if "googlevr" in self.features:
|
||||||
flavor = "googlevr"
|
flavor = "googlevr"
|
||||||
elif "oculusvr" in features:
|
elif "oculusvr" in self.features:
|
||||||
flavor = "oculusvr"
|
flavor = "oculusvr"
|
||||||
rv = Registrar.dispatch("package", context=self.context,
|
rv = Registrar.dispatch("package", context=self.context,
|
||||||
release=release, dev=dev, target=target, flavor=flavor)
|
release=release, dev=dev, target=self.cross_compile_target,
|
||||||
|
flavor=flavor)
|
||||||
if rv:
|
if rv:
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
servo_exe_dir = os.path.dirname(
|
servo_exe_dir = os.path.dirname(
|
||||||
self.get_binary_path(release, dev, target=target, simpleservo=libsimpleservo)
|
self.get_binary_path(release, dev, target=self.cross_compile_target, simpleservo=libsimpleservo)
|
||||||
)
|
)
|
||||||
assert os.path.exists(servo_exe_dir)
|
assert os.path.exists(servo_exe_dir)
|
||||||
|
|
||||||
|
@ -483,7 +461,7 @@ class MachCommands(CommandBase):
|
||||||
print("WARNING: could not find " + lib)
|
print("WARNING: could not find " + lib)
|
||||||
|
|
||||||
# UWP build has its own ANGLE library that it packages.
|
# UWP build has its own ANGLE library that it packages.
|
||||||
if not uwp:
|
if not self.is_uwp_build:
|
||||||
print("Packaging EGL DLLs")
|
print("Packaging EGL DLLs")
|
||||||
egl_libs = ["libEGL.dll", "libGLESv2.dll"]
|
egl_libs = ["libEGL.dll", "libGLESv2.dll"]
|
||||||
if not package_generated_shared_libraries(egl_libs, build_path, servo_exe_dir):
|
if not package_generated_shared_libraries(egl_libs, build_path, servo_exe_dir):
|
||||||
|
@ -492,7 +470,7 @@ class MachCommands(CommandBase):
|
||||||
# copy needed gstreamer DLLs in to servo.exe dir
|
# copy needed gstreamer DLLs in to servo.exe dir
|
||||||
if has_media_stack:
|
if has_media_stack:
|
||||||
print("Packaging gstreamer DLLs")
|
print("Packaging gstreamer DLLs")
|
||||||
if not package_gstreamer_dlls(env, servo_exe_dir, target_triple, uwp):
|
if not package_gstreamer_dlls(env, servo_exe_dir, target_triple, self.is_uwp_build):
|
||||||
status = 1
|
status = 1
|
||||||
|
|
||||||
# UWP app packaging already bundles all required DLLs for us.
|
# UWP app packaging already bundles all required DLLs for us.
|
||||||
|
@ -501,13 +479,14 @@ class MachCommands(CommandBase):
|
||||||
status = 1
|
status = 1
|
||||||
|
|
||||||
elif sys.platform == "darwin":
|
elif sys.platform == "darwin":
|
||||||
servo_path = self.get_binary_path(release, dev, target=target, simpleservo=libsimpleservo)
|
servo_path = self.get_binary_path(
|
||||||
|
release, dev, target=self.cross_compile_target, simpleservo=libsimpleservo)
|
||||||
servo_bin_dir = os.path.dirname(servo_path)
|
servo_bin_dir = os.path.dirname(servo_path)
|
||||||
assert os.path.exists(servo_bin_dir)
|
assert os.path.exists(servo_bin_dir)
|
||||||
|
|
||||||
if has_media_stack:
|
if has_media_stack:
|
||||||
print("Packaging gstreamer dylibs")
|
print("Packaging gstreamer dylibs")
|
||||||
if not package_gstreamer_dylibs(target, servo_path):
|
if not package_gstreamer_dylibs(self.cross_compile_target, servo_path):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# On Mac we use the relocatable dylibs from offical gstreamer
|
# On Mac we use the relocatable dylibs from offical gstreamer
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
|
from typing import Optional
|
||||||
import distro
|
import distro
|
||||||
import functools
|
import functools
|
||||||
import gzip
|
import gzip
|
||||||
|
@ -38,7 +39,7 @@ import servo.util as util
|
||||||
|
|
||||||
from xml.etree.ElementTree import XML
|
from xml.etree.ElementTree import XML
|
||||||
from servo.util import download_file, get_default_cache_dir
|
from servo.util import download_file, get_default_cache_dir
|
||||||
from mach.decorators import CommandArgument
|
from mach.decorators import CommandArgument, CommandArgumentGroup
|
||||||
from mach.registrar import Registrar
|
from mach.registrar import Registrar
|
||||||
|
|
||||||
BIN_SUFFIX = ".exe" if sys.platform == "win32" else ""
|
BIN_SUFFIX = ".exe" if sys.platform == "win32" else ""
|
||||||
|
@ -228,6 +229,10 @@ class CommandBase(object):
|
||||||
|
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
self.context = context
|
self.context = context
|
||||||
|
self.features = []
|
||||||
|
self.cross_compile_target = None
|
||||||
|
self.is_uwp_build = False
|
||||||
|
self.is_android_build = False
|
||||||
|
|
||||||
def get_env_bool(var, default):
|
def get_env_bool(var, default):
|
||||||
# Contents of env vars are strings by default. This returns the
|
# Contents of env vars are strings by default. This returns the
|
||||||
|
@ -285,8 +290,9 @@ class CommandBase(object):
|
||||||
self.config["android"].setdefault("sdk", "")
|
self.config["android"].setdefault("sdk", "")
|
||||||
self.config["android"].setdefault("ndk", "")
|
self.config["android"].setdefault("ndk", "")
|
||||||
self.config["android"].setdefault("toolchain", "")
|
self.config["android"].setdefault("toolchain", "")
|
||||||
|
|
||||||
# Set default android target
|
# Set default android target
|
||||||
self.handle_android_target("armv7-linux-androideabi")
|
self.setup_configuration_for_android_target("armv7-linux-androideabi")
|
||||||
|
|
||||||
_rust_toolchain = None
|
_rust_toolchain = None
|
||||||
|
|
||||||
|
@ -516,12 +522,13 @@ class CommandBase(object):
|
||||||
'vcdir': vcinstalldir,
|
'vcdir': vcinstalldir,
|
||||||
}
|
}
|
||||||
|
|
||||||
def build_env(self, hosts_file_path=None, target=None, is_build=False, test_unit=False, uwp=False, features=None):
|
def build_env(self, hosts_file_path=None, is_build=False, test_unit=False, features=None):
|
||||||
"""Return an extended environment dictionary."""
|
"""Return an extended environment dictionary."""
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
|
|
||||||
if not features or "media-dummy" not in features:
|
if not features or "media-dummy" not in features:
|
||||||
servo.platform.get().set_gstreamer_environment_variables_if_necessary(env, cross_compilation_target=target)
|
servo.platform.get().set_gstreamer_environment_variables_if_necessary(
|
||||||
|
env, cross_compilation_target=self.cross_compile_target)
|
||||||
|
|
||||||
if sys.platform == "win32" and type(env['PATH']) == six.text_type:
|
if sys.platform == "win32" and type(env['PATH']) == six.text_type:
|
||||||
# On win32, the virtualenv's activate_this.py script sometimes ends up
|
# On win32, the virtualenv's activate_this.py script sometimes ends up
|
||||||
|
@ -532,7 +539,8 @@ class CommandBase(object):
|
||||||
# it in any case.
|
# it in any case.
|
||||||
env['PATH'] = env['PATH'].encode('ascii', 'ignore')
|
env['PATH'] = env['PATH'].encode('ascii', 'ignore')
|
||||||
extra_path = []
|
extra_path = []
|
||||||
if "msvc" in (target or servo.platform.host_triple()):
|
effective_target = self.cross_compile_target or servo.platform.host_triple()
|
||||||
|
if "msvc" in effective_target:
|
||||||
extra_path += [path.join(self.msvc_package_dir("cmake"), "bin")]
|
extra_path += [path.join(self.msvc_package_dir("cmake"), "bin")]
|
||||||
extra_path += [path.join(self.msvc_package_dir("llvm"), "bin")]
|
extra_path += [path.join(self.msvc_package_dir("llvm"), "bin")]
|
||||||
extra_path += [path.join(self.msvc_package_dir("ninja"), "bin")]
|
extra_path += [path.join(self.msvc_package_dir("ninja"), "bin")]
|
||||||
|
@ -540,20 +548,20 @@ class CommandBase(object):
|
||||||
|
|
||||||
env.setdefault("CC", "clang-cl.exe")
|
env.setdefault("CC", "clang-cl.exe")
|
||||||
env.setdefault("CXX", "clang-cl.exe")
|
env.setdefault("CXX", "clang-cl.exe")
|
||||||
if uwp:
|
if self.is_uwp_build:
|
||||||
env.setdefault("TARGET_CFLAGS", "")
|
env.setdefault("TARGET_CFLAGS", "")
|
||||||
env.setdefault("TARGET_CXXFLAGS", "")
|
env.setdefault("TARGET_CXXFLAGS", "")
|
||||||
env["TARGET_CFLAGS"] += " -DWINAPI_FAMILY=WINAPI_FAMILY_APP"
|
env["TARGET_CFLAGS"] += " -DWINAPI_FAMILY=WINAPI_FAMILY_APP"
|
||||||
env["TARGET_CXXFLAGS"] += " -DWINAPI_FAMILY=WINAPI_FAMILY_APP"
|
env["TARGET_CXXFLAGS"] += " -DWINAPI_FAMILY=WINAPI_FAMILY_APP"
|
||||||
|
|
||||||
arch = (target or servo.platform.host_triple()).split('-')[0]
|
arch = effective_target.split('-')[0]
|
||||||
vcpkg_arch = {
|
vcpkg_arch = {
|
||||||
"x86_64": "x64-windows",
|
"x86_64": "x64-windows",
|
||||||
"i686": "x86-windows",
|
"i686": "x86-windows",
|
||||||
"aarch64": "arm64-windows",
|
"aarch64": "arm64-windows",
|
||||||
}
|
}
|
||||||
target_arch = vcpkg_arch[arch]
|
target_arch = vcpkg_arch[arch]
|
||||||
if uwp:
|
if self.is_uwp_build:
|
||||||
target_arch += "-uwp"
|
target_arch += "-uwp"
|
||||||
openssl_base_dir = path.join(self.msvc_package_dir("openssl"), target_arch)
|
openssl_base_dir = path.join(self.msvc_package_dir("openssl"), target_arch)
|
||||||
|
|
||||||
|
@ -657,9 +665,10 @@ class CommandBase(object):
|
||||||
env['CCACHE'] = self.config["build"]["ccache"]
|
env['CCACHE'] = self.config["build"]["ccache"]
|
||||||
|
|
||||||
# Ensure Rust uses hard floats and SIMD on ARM devices
|
# Ensure Rust uses hard floats and SIMD on ARM devices
|
||||||
if target:
|
if self.cross_compile_target and (
|
||||||
if target.startswith('arm') or target.startswith('aarch64'):
|
self.cross_compile_target.startswith('arm')
|
||||||
env['RUSTFLAGS'] = env.get('RUSTFLAGS', "") + " -C target-feature=+neon"
|
or self.cross_compile_target.startswith('aarch64')):
|
||||||
|
env['RUSTFLAGS'] = env.get('RUSTFLAGS', "") + " -C target-feature=+neon"
|
||||||
|
|
||||||
env['RUSTFLAGS'] = env.get('RUSTFLAGS', "") + " -W unused-extern-crates"
|
env['RUSTFLAGS'] = env.get('RUSTFLAGS', "") + " -W unused-extern-crates"
|
||||||
|
|
||||||
|
@ -708,107 +717,151 @@ class CommandBase(object):
|
||||||
return env
|
return env
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def build_like_command_arguments(decorated_function):
|
def build_like_command_arguments(original_function):
|
||||||
decorators = [
|
decorators = [
|
||||||
|
CommandArgumentGroup('Cross Compilation'),
|
||||||
CommandArgument(
|
CommandArgument(
|
||||||
'--target', '-t',
|
'--target', '-t',
|
||||||
|
group="Cross Compilation",
|
||||||
default=None,
|
default=None,
|
||||||
help='Cross compile for given target platform',
|
help='Cross compile for given target platform',
|
||||||
),
|
),
|
||||||
CommandArgument(
|
CommandArgument(
|
||||||
'--media-stack',
|
'--android', default=None, action='store_true',
|
||||||
default=None,
|
help='Build for Android. If --target is not specified, this '
|
||||||
choices=["gstreamer", "dummy"],
|
'will choose a default target architecture.',
|
||||||
help='Which media stack to use',
|
|
||||||
),
|
),
|
||||||
CommandArgument(
|
CommandArgument(
|
||||||
'--android',
|
'--uwp',
|
||||||
default=None,
|
group="Cross Compilation",
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Build for Android',
|
help='Build for HoloLens (x64)'),
|
||||||
|
CommandArgument('--win-arm64', action='store_true', help="Use arm64 Windows target"),
|
||||||
|
CommandArgumentGroup('Feature Selection'),
|
||||||
|
CommandArgument(
|
||||||
|
'--features', default=None, group="Feature Selection", nargs='+',
|
||||||
|
help='Space-separated list of features to also build',
|
||||||
|
),
|
||||||
|
CommandArgument(
|
||||||
|
'--media-stack', default=None, group="Feature Selection",
|
||||||
|
choices=["gstreamer", "dummy"], help='Which media stack to use',
|
||||||
),
|
),
|
||||||
CommandArgument(
|
CommandArgument(
|
||||||
'--libsimpleservo',
|
'--libsimpleservo',
|
||||||
default=None,
|
default=None,
|
||||||
|
group="Feature Selection",
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Build the libsimpleservo library instead of the servo executable',
|
help='Build the libsimpleservo library instead of the servo executable',
|
||||||
),
|
),
|
||||||
CommandArgument(
|
|
||||||
'--features',
|
|
||||||
default=None,
|
|
||||||
help='Space-separated list of features to also build',
|
|
||||||
nargs='+',
|
|
||||||
),
|
|
||||||
CommandArgument(
|
CommandArgument(
|
||||||
'--debug-mozjs',
|
'--debug-mozjs',
|
||||||
default=None,
|
default=False,
|
||||||
|
group="Feature Selection",
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Enable debug assertions in mozjs',
|
help='Enable debug assertions in mozjs',
|
||||||
),
|
),
|
||||||
CommandArgument(
|
CommandArgument(
|
||||||
'--with-debug-assertions',
|
'--with-debug-assertions',
|
||||||
default=None,
|
default=False,
|
||||||
|
group="Feature Selection",
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Enable debug assertions in release',
|
help='Enable debug assertions in release',
|
||||||
),
|
),
|
||||||
CommandArgument(
|
CommandArgument(
|
||||||
'--with-frame-pointer',
|
'--with-frame-pointer',
|
||||||
default=None,
|
default=None, group="Feature Selection",
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Build with frame pointer enabled, used by the background hang monitor.',
|
help='Build with frame pointer enabled, used by the background hang monitor.',
|
||||||
),
|
),
|
||||||
CommandArgument('--with-layout-2020', '--layout-2020', default=None, action='store_true'),
|
CommandArgument(
|
||||||
CommandArgument('--with-layout-2013', '--layout-2013', default=None, action='store_true'),
|
'--with-layout-2020', '--layout-2020',
|
||||||
CommandArgument('--without-wgl', default=None, action='store_true'),
|
group="Feature Selection", default=None, action='store_true'),
|
||||||
|
CommandArgument(
|
||||||
|
'--with-layout-2013', '--layout-2013', group="Feature Selection", default=None, action='store_true'),
|
||||||
|
CommandArgument('--without-wgl', group="Feature Selection", default=None, action='store_true'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def configuration_decorator(self, *args, **kwargs):
|
||||||
|
self.configure_cross_compilation(
|
||||||
|
kwargs['target'], kwargs['android'],
|
||||||
|
kwargs['uwp'], kwargs['win_arm64'])
|
||||||
|
|
||||||
|
self.features = kwargs.get("features", None) or []
|
||||||
|
self.configure_media_stack(kwargs['media_stack'])
|
||||||
|
original_function(self, *args, **kwargs)
|
||||||
|
|
||||||
|
decorators.reverse()
|
||||||
|
decorated_function = configuration_decorator
|
||||||
for decorator in decorators:
|
for decorator in decorators:
|
||||||
decorated_function = decorator(decorated_function)
|
decorated_function = decorator(decorated_function)
|
||||||
return decorated_function
|
return decorated_function
|
||||||
|
|
||||||
def pick_target_triple(self, target, android):
|
def configure_cross_compilation(
|
||||||
|
self,
|
||||||
|
cross_compile_target: Optional[str],
|
||||||
|
android: Optional[str],
|
||||||
|
uwp: Optional[str],
|
||||||
|
win_arm64: Optional[str]):
|
||||||
|
# Force the UWP-enabled target if the convenience UWP flags are passed.
|
||||||
|
if uwp and not cross_compile_target:
|
||||||
|
if win_arm64:
|
||||||
|
cross_compile_target = 'aarch64-uwp-windows-msvc'
|
||||||
|
else:
|
||||||
|
cross_compile_target = 'x86_64-uwp-windows-msvc'
|
||||||
|
|
||||||
if android is None:
|
if android is None:
|
||||||
android = self.config["build"]["android"]
|
android = self.config["build"]["android"]
|
||||||
if target and android:
|
if android:
|
||||||
assert self.handle_android_target(target)
|
if not cross_compile_target:
|
||||||
if android and not target:
|
cross_compile_target = self.config["android"]["target"]
|
||||||
target = self.config["android"]["target"]
|
assert cross_compile_target
|
||||||
if target and not android:
|
assert self.setup_configuration_for_android_target(cross_compile_target)
|
||||||
android = self.handle_android_target(target)
|
elif cross_compile_target:
|
||||||
return target, android
|
# If a target was specified, it might also be an android target,
|
||||||
|
# so set up the configuration in that case.
|
||||||
|
self.setup_configuration_for_android_target(cross_compile_target)
|
||||||
|
|
||||||
# A guess about which platforms should use the gstreamer media stack
|
self.cross_compile_target = cross_compile_target
|
||||||
def pick_media_stack(self, media_stack, target):
|
self.is_uwp_build = uwp or (cross_compile_target and "uwp" in cross_compile_target)
|
||||||
|
self.is_android_build = (cross_compile_target and "android" in cross_compile_target)
|
||||||
|
|
||||||
|
if self.cross_compile_target:
|
||||||
|
print(f"Targeting '{self.cross_compile_target}' for cross-compilation")
|
||||||
|
|
||||||
|
def configure_media_stack(self, media_stack: Optional[str]):
|
||||||
|
"""Determine what media stack to use based on the value of the build target
|
||||||
|
platform and the value of the '--media-stack' command-line argument.
|
||||||
|
The chosen media stack is written into the `features` instance variable."""
|
||||||
if not media_stack:
|
if not media_stack:
|
||||||
if self.config["build"]["media-stack"] != "auto":
|
if self.config["build"]["media-stack"] != "auto":
|
||||||
media_stack = self.config["build"]["media-stack"]
|
media_stack = self.config["build"]["media-stack"]
|
||||||
|
assert media_stack
|
||||||
elif (
|
elif (
|
||||||
not target
|
not self.cross_compile_target
|
||||||
or ("armv7" in target and "android" in target)
|
or ("armv7" in self.cross_compile_target and self.is_android_build)
|
||||||
or "x86_64" in target
|
or "x86_64" in self.cross_compile_target
|
||||||
or "uwp" in target
|
or "uwp" in self.cross_compile_target
|
||||||
):
|
):
|
||||||
media_stack = "gstreamer"
|
media_stack = "gstreamer"
|
||||||
else:
|
else:
|
||||||
media_stack = "dummy"
|
media_stack = "dummy"
|
||||||
return ["media-" + media_stack]
|
self.features += ["media-" + media_stack]
|
||||||
|
|
||||||
def run_cargo_build_like_command(
|
def run_cargo_build_like_command(
|
||||||
self, command, cargo_args,
|
self, command, cargo_args,
|
||||||
env=None, verbose=False,
|
env=None, verbose=False,
|
||||||
target=None, android=False, libsimpleservo=False,
|
libsimpleservo=False,
|
||||||
features=None, debug_mozjs=False, with_debug_assertions=False,
|
debug_mozjs=False, with_debug_assertions=False,
|
||||||
with_frame_pointer=False, without_wgl=False,
|
with_frame_pointer=False, without_wgl=False,
|
||||||
with_layout_2020=False, with_layout_2013=False,
|
with_layout_2020=False, with_layout_2013=False,
|
||||||
uwp=False, media_stack=None,
|
**_kwargs
|
||||||
):
|
):
|
||||||
env = env or self.build_env()
|
env = env or self.build_env()
|
||||||
target, android = self.pick_target_triple(target, android)
|
|
||||||
|
|
||||||
args = []
|
args = []
|
||||||
if "--manifest-path" not in cargo_args:
|
if "--manifest-path" not in cargo_args:
|
||||||
if libsimpleservo or android:
|
if libsimpleservo or self.is_android_build:
|
||||||
if android:
|
if self.is_android_build:
|
||||||
api = "jniapi"
|
api = "jniapi"
|
||||||
else:
|
else:
|
||||||
api = "capi"
|
api = "capi"
|
||||||
|
@ -819,19 +872,17 @@ class CommandBase(object):
|
||||||
"--manifest-path",
|
"--manifest-path",
|
||||||
path.join(self.context.topdir, "ports", port, "Cargo.toml"),
|
path.join(self.context.topdir, "ports", port, "Cargo.toml"),
|
||||||
]
|
]
|
||||||
if target:
|
if self.cross_compile_target:
|
||||||
args += ["--target", target]
|
args += ["--target", self.cross_compile_target]
|
||||||
|
|
||||||
if features is None: # If we're passed a list, mutate it even if it's empty
|
|
||||||
features = []
|
|
||||||
|
|
||||||
|
features = list(self.features)
|
||||||
if "-p" not in cargo_args: # We're building specific package, that may not have features
|
if "-p" not in cargo_args: # We're building specific package, that may not have features
|
||||||
if self.config["build"]["debug-mozjs"] or debug_mozjs:
|
if self.config["build"]["debug-mozjs"] or debug_mozjs:
|
||||||
features.append("debugmozjs")
|
features.append("debugmozjs")
|
||||||
|
|
||||||
features.append("native-bluetooth")
|
features.append("native-bluetooth")
|
||||||
|
|
||||||
if uwp:
|
if self.is_uwp_build:
|
||||||
features.append("no-wgl")
|
features.append("no-wgl")
|
||||||
features.append("uwp")
|
features.append("uwp")
|
||||||
else:
|
else:
|
||||||
|
@ -856,7 +907,7 @@ class CommandBase(object):
|
||||||
assert "--features" not in cargo_args
|
assert "--features" not in cargo_args
|
||||||
args += ["--features", " ".join(features)]
|
args += ["--features", " ".join(features)]
|
||||||
|
|
||||||
if target and 'uwp' in target:
|
if self.is_uwp_build:
|
||||||
cargo_args += ["-Z", "build-std"]
|
cargo_args += ["-Z", "build-std"]
|
||||||
return self.call_rustup_run(["cargo", command] + args + cargo_args, env=env, verbose=verbose)
|
return self.call_rustup_run(["cargo", command] + args + cargo_args, env=env, verbose=verbose)
|
||||||
|
|
||||||
|
@ -880,7 +931,10 @@ class CommandBase(object):
|
||||||
return sdk_adb
|
return sdk_adb
|
||||||
return "emulator"
|
return "emulator"
|
||||||
|
|
||||||
def handle_android_target(self, target):
|
def setup_configuration_for_android_target(self, target: str):
|
||||||
|
"""If cross-compilation targets Android, configure the Android
|
||||||
|
build by writing the appropriate toolchain configuration values
|
||||||
|
into the stored configuration."""
|
||||||
if target == "armv7-linux-androideabi":
|
if target == "armv7-linux-androideabi":
|
||||||
self.config["android"]["platform"] = "android-21"
|
self.config["android"]["platform"] = "android-21"
|
||||||
self.config["android"]["target"] = target
|
self.config["android"]["target"] = target
|
||||||
|
@ -908,13 +962,12 @@ class CommandBase(object):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def ensure_bootstrapped(self, target=None, rustup_components=None):
|
def ensure_bootstrapped(self, rustup_components=None):
|
||||||
if self.context.bootstrapped:
|
if self.context.bootstrapped:
|
||||||
return
|
return
|
||||||
|
|
||||||
target_platform = target or servo.platform.host_triple()
|
|
||||||
|
|
||||||
# Always check if all needed MSVC dependencies are installed
|
# Always check if all needed MSVC dependencies are installed
|
||||||
|
target_platform = self.cross_compile_target or servo.platform.host_triple()
|
||||||
if "msvc" in target_platform:
|
if "msvc" in target_platform:
|
||||||
Registrar.dispatch("bootstrap", context=self.context)
|
Registrar.dispatch("bootstrap", context=self.context)
|
||||||
|
|
||||||
|
@ -943,10 +996,13 @@ class CommandBase(object):
|
||||||
if component.encode("utf-8") not in installed:
|
if component.encode("utf-8") not in installed:
|
||||||
check_call(["rustup", "component", "add", "--toolchain", toolchain, component])
|
check_call(["rustup", "component", "add", "--toolchain", toolchain, component])
|
||||||
|
|
||||||
if target and "uwp" not in target and target.encode("utf-8") not in check_output(
|
needs_toolchain_install = self.cross_compile_target \
|
||||||
["rustup", "target", "list", "--installed", "--toolchain", toolchain]
|
and not self.is_uwp_build \
|
||||||
):
|
and self.cross_compile_target.encode("utf-8") not in check_output(
|
||||||
check_call(["rustup", "target", "add", "--toolchain", toolchain, target])
|
["rustup", "target", "list", "--installed", "--toolchain", toolchain]
|
||||||
|
)
|
||||||
|
if needs_toolchain_install:
|
||||||
|
check_call(["rustup", "target", "add", "--toolchain", toolchain, self.cross_compile_target])
|
||||||
|
|
||||||
self.context.bootstrapped = True
|
self.context.bootstrapped = True
|
||||||
|
|
||||||
|
|
|
@ -35,21 +35,13 @@ class MachCommands(CommandBase):
|
||||||
'params', default=None, nargs='...',
|
'params', default=None, nargs='...',
|
||||||
help="Command-line arguments to be passed through to cargo check")
|
help="Command-line arguments to be passed through to cargo check")
|
||||||
@CommandBase.build_like_command_arguments
|
@CommandBase.build_like_command_arguments
|
||||||
def check(self, params, features=[], media_stack=None, target=None,
|
def check(self, params, **kwargs):
|
||||||
android=False, **kwargs):
|
|
||||||
if not params:
|
if not params:
|
||||||
params = []
|
params = []
|
||||||
|
|
||||||
features = features or []
|
self.ensure_bootstrapped()
|
||||||
|
|
||||||
target, android = self.pick_target_triple(target, android)
|
|
||||||
|
|
||||||
features += self.pick_media_stack(media_stack, target)
|
|
||||||
|
|
||||||
self.ensure_bootstrapped(target=target)
|
|
||||||
self.ensure_clobbered()
|
self.ensure_clobbered()
|
||||||
|
status = self.run_cargo_build_like_command("check", params, **kwargs)
|
||||||
status = self.run_cargo_build_like_command("check", params, features=features, **kwargs)
|
|
||||||
if status == 0:
|
if status == 0:
|
||||||
print('Finished checking, binary NOT updated. Consider ./mach build before ./mach run')
|
print('Finished checking, binary NOT updated. Consider ./mach build before ./mach run')
|
||||||
|
|
||||||
|
@ -128,21 +120,13 @@ class MachCommands(CommandBase):
|
||||||
'params', default=None, nargs='...',
|
'params', default=None, nargs='...',
|
||||||
help="Command-line arguments to be passed through to cargo-fix")
|
help="Command-line arguments to be passed through to cargo-fix")
|
||||||
@CommandBase.build_like_command_arguments
|
@CommandBase.build_like_command_arguments
|
||||||
def cargo_fix(self, params, features=[], media_stack=None, target=None,
|
def cargo_fix(self, params, **kwargs):
|
||||||
android=False, **kwargs):
|
|
||||||
if not params:
|
if not params:
|
||||||
params = []
|
params = []
|
||||||
|
|
||||||
features = features or []
|
self.ensure_bootstrapped()
|
||||||
|
|
||||||
target, android = self.pick_target_triple(target, android)
|
|
||||||
|
|
||||||
features += self.pick_media_stack(media_stack, target)
|
|
||||||
|
|
||||||
self.ensure_bootstrapped(target=target)
|
|
||||||
self.ensure_clobbered()
|
self.ensure_clobbered()
|
||||||
|
return self.run_cargo_build_like_command("fix", params, **kwargs)
|
||||||
return self.run_cargo_build_like_command("fix", params, features=features, **kwargs)
|
|
||||||
|
|
||||||
@Command('cargo-clippy',
|
@Command('cargo-clippy',
|
||||||
description='Run "cargo clippy"',
|
description='Run "cargo clippy"',
|
||||||
|
@ -151,21 +135,13 @@ class MachCommands(CommandBase):
|
||||||
'params', default=None, nargs='...',
|
'params', default=None, nargs='...',
|
||||||
help="Command-line arguments to be passed through to cargo-clippy")
|
help="Command-line arguments to be passed through to cargo-clippy")
|
||||||
@CommandBase.build_like_command_arguments
|
@CommandBase.build_like_command_arguments
|
||||||
def cargo_clippy(self, params, features=[], media_stack=None, target=None,
|
def cargo_clippy(self, params, **kwargs):
|
||||||
android=False, **kwargs):
|
|
||||||
if not params:
|
if not params:
|
||||||
params = []
|
params = []
|
||||||
|
|
||||||
features = features or []
|
self.ensure_bootstrapped()
|
||||||
|
|
||||||
target, android = self.pick_target_triple(target, android)
|
|
||||||
|
|
||||||
features += self.pick_media_stack(media_stack, target)
|
|
||||||
|
|
||||||
self.ensure_bootstrapped(target=target)
|
|
||||||
self.ensure_clobbered()
|
self.ensure_clobbered()
|
||||||
|
return self.run_cargo_build_like_command("clippy", params, **kwargs)
|
||||||
return self.run_cargo_build_like_command("clippy", params, features=features, **kwargs)
|
|
||||||
|
|
||||||
@Command('grep',
|
@Command('grep',
|
||||||
description='`git grep` for selected directories.',
|
description='`git grep` for selected directories.',
|
||||||
|
@ -224,9 +200,11 @@ class MachCommands(CommandBase):
|
||||||
if not path.isfile(logfile):
|
if not path.isfile(logfile):
|
||||||
print(logfile + " doesn't exist")
|
print(logfile + " doesn't exist")
|
||||||
return -1
|
return -1
|
||||||
env = self.build_env(target=target)
|
|
||||||
|
self.cross_compile_target = target
|
||||||
|
env = self.build_env()
|
||||||
ndk_stack = path.join(env["ANDROID_NDK"], "ndk-stack")
|
ndk_stack = path.join(env["ANDROID_NDK"], "ndk-stack")
|
||||||
self.handle_android_target(target)
|
self.setup_configuration_for_android_target(target)
|
||||||
sym_path = path.join(
|
sym_path = path.join(
|
||||||
"target",
|
"target",
|
||||||
target,
|
target,
|
||||||
|
@ -244,8 +222,9 @@ class MachCommands(CommandBase):
|
||||||
@CommandArgument('--target', action='store', default="armv7-linux-androideabi",
|
@CommandArgument('--target', action='store', default="armv7-linux-androideabi",
|
||||||
help="Build target")
|
help="Build target")
|
||||||
def ndk_gdb(self, release, target):
|
def ndk_gdb(self, release, target):
|
||||||
env = self.build_env(target)
|
self.cross_compile_target = target
|
||||||
self.handle_android_target(target)
|
self.setup_configuration_for_android_target(target)
|
||||||
|
env = self.build_env()
|
||||||
ndk_gdb = path.join(env["ANDROID_NDK"], "ndk-gdb")
|
ndk_gdb = path.join(env["ANDROID_NDK"], "ndk-gdb")
|
||||||
adb_path = path.join(env["ANDROID_SDK"], "platform-tools", "adb")
|
adb_path = path.join(env["ANDROID_SDK"], "platform-tools", "adb")
|
||||||
sym_paths = [
|
sym_paths = [
|
||||||
|
|
|
@ -147,19 +147,20 @@ class PackageCommands(CommandBase):
|
||||||
action='append',
|
action='append',
|
||||||
help='Create an APPX package')
|
help='Create an APPX package')
|
||||||
@CommandArgument('--ms-app-store', default=None, action='store_true')
|
@CommandArgument('--ms-app-store', default=None, action='store_true')
|
||||||
def package(self, release=False, dev=False, android=None, debug=False,
|
def package(self, release=False, dev=False, android=None, target=None,
|
||||||
debugger=None, target=None, flavor=None, maven=False, uwp=None, ms_app_store=False):
|
flavor=None, maven=False, uwp=None, ms_app_store=False):
|
||||||
if android is None:
|
if android is None:
|
||||||
android = self.config["build"]["android"]
|
android = self.config["build"]["android"]
|
||||||
if target and android:
|
if target and android:
|
||||||
print("Please specify either --target or --android.")
|
print("Please specify either --target or --android.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if not android:
|
if not android:
|
||||||
android = self.handle_android_target(target)
|
android = self.setup_configuration_for_android_target(target)
|
||||||
else:
|
else:
|
||||||
target = self.config["android"]["target"]
|
target = self.config["android"]["target"]
|
||||||
|
|
||||||
env = self.build_env(target=target)
|
self.cross_compile_target = target
|
||||||
|
env = self.build_env()
|
||||||
binary_path = self.get_binary_path(
|
binary_path = self.get_binary_path(
|
||||||
release, dev, target=target, android=android,
|
release, dev, target=target, android=android,
|
||||||
simpleservo=uwp is not None
|
simpleservo=uwp is not None
|
||||||
|
@ -423,9 +424,10 @@ class PackageCommands(CommandBase):
|
||||||
print("Please specify either --target or --android.")
|
print("Please specify either --target or --android.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if not android:
|
if not android:
|
||||||
android = self.handle_android_target(target)
|
android = self.setup_configuration_for_android_target(target)
|
||||||
|
self.cross_compile_target = target
|
||||||
|
|
||||||
env = self.build_env(target=target)
|
env = self.build_env()
|
||||||
try:
|
try:
|
||||||
binary_path = self.get_binary_path(release, dev, android=android)
|
binary_path = self.get_binary_path(release, dev, android=android)
|
||||||
except BuildNotFound:
|
except BuildNotFound:
|
||||||
|
|
|
@ -242,8 +242,7 @@ class PostBuildCommands(CommandBase):
|
||||||
'params', nargs='...',
|
'params', nargs='...',
|
||||||
help="Command-line arguments to be passed through to cargo doc")
|
help="Command-line arguments to be passed through to cargo doc")
|
||||||
@CommandBase.build_like_command_arguments
|
@CommandBase.build_like_command_arguments
|
||||||
def doc(self, params, features, target=None, android=False,
|
def doc(self, params, **kwargs):
|
||||||
media_stack=None, **kwargs):
|
|
||||||
self.ensure_bootstrapped(rustup_components=["rust-docs"])
|
self.ensure_bootstrapped(rustup_components=["rust-docs"])
|
||||||
rustc_path = check_output(
|
rustc_path = check_output(
|
||||||
["rustup" + BIN_SUFFIX, "which", "--toolchain", self.rust_toolchain(), "rustc"]
|
["rustup" + BIN_SUFFIX, "which", "--toolchain", self.rust_toolchain(), "rustc"]
|
||||||
|
@ -271,15 +270,8 @@ class PostBuildCommands(CommandBase):
|
||||||
else:
|
else:
|
||||||
copy2(full_name, destination)
|
copy2(full_name, destination)
|
||||||
|
|
||||||
features = features or []
|
env = self.build_env(is_build=True)
|
||||||
|
returncode = self.run_cargo_build_like_command("doc", params, env=env, **kwargs)
|
||||||
target, android = self.pick_target_triple(target, android)
|
|
||||||
|
|
||||||
features += self.pick_media_stack(media_stack, target)
|
|
||||||
|
|
||||||
env = self.build_env(target=target, is_build=True, features=features)
|
|
||||||
|
|
||||||
returncode = self.run_cargo_build_like_command("doc", params, features=features, env=env, **kwargs)
|
|
||||||
if returncode:
|
if returncode:
|
||||||
return returncode
|
return returncode
|
||||||
|
|
||||||
|
|
|
@ -470,10 +470,11 @@ class MachCommands(CommandBase):
|
||||||
avd = "servo-x86"
|
avd = "servo-x86"
|
||||||
target = "i686-linux-android"
|
target = "i686-linux-android"
|
||||||
print("Assuming --target " + target)
|
print("Assuming --target " + target)
|
||||||
|
self.cross_compile_target = target
|
||||||
|
|
||||||
env = self.build_env(target=target)
|
env = self.build_env()
|
||||||
os.environ["PATH"] = env["PATH"]
|
os.environ["PATH"] = env["PATH"]
|
||||||
assert self.handle_android_target(target)
|
assert self.setup_configuration_for_android_target(target)
|
||||||
apk = self.get_apk_path(release)
|
apk = self.get_apk_path(release)
|
||||||
|
|
||||||
py = path.join(self.context.topdir, "etc", "run_in_headless_android_emulator.py")
|
py = path.join(self.context.topdir, "etc", "run_in_headless_android_emulator.py")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue