mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Merge 1f3e3af432
into c94605b13e
This commit is contained in:
commit
38f85a9314
5 changed files with 203 additions and 68 deletions
|
@ -17,7 +17,7 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from time import time
|
from time import time
|
||||||
from typing import Optional, List
|
from typing import Optional, List, Dict
|
||||||
|
|
||||||
import notifypy
|
import notifypy
|
||||||
|
|
||||||
|
@ -37,9 +37,12 @@ from servo.command_base import BuildType, CommandBase, call, check_call
|
||||||
from servo.gstreamer import windows_dlls, windows_plugins, package_gstreamer_dylibs
|
from servo.gstreamer import windows_dlls, windows_plugins, package_gstreamer_dylibs
|
||||||
from servo.platform.build_target import BuildTarget
|
from servo.platform.build_target import BuildTarget
|
||||||
|
|
||||||
|
from python.servo.platform.build_target import SanitizerKind
|
||||||
|
|
||||||
SUPPORTED_ASAN_TARGETS = [
|
SUPPORTED_ASAN_TARGETS = [
|
||||||
"aarch64-apple-darwin",
|
"aarch64-apple-darwin",
|
||||||
"aarch64-unknown-linux-gnu",
|
"aarch64-unknown-linux-gnu",
|
||||||
|
"aarch64-unknown-linux-ohos",
|
||||||
"x86_64-apple-darwin",
|
"x86_64-apple-darwin",
|
||||||
"x86_64-unknown-linux-gnu",
|
"x86_64-unknown-linux-gnu",
|
||||||
]
|
]
|
||||||
|
@ -90,7 +93,7 @@ class MachCommands(CommandBase):
|
||||||
no_package=False,
|
no_package=False,
|
||||||
verbose=False,
|
verbose=False,
|
||||||
very_verbose=False,
|
very_verbose=False,
|
||||||
with_asan=False,
|
sanitizer: SanitizerKind = SanitizerKind.NONE,
|
||||||
flavor=None,
|
flavor=None,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
|
@ -109,6 +112,8 @@ class MachCommands(CommandBase):
|
||||||
opts += ["-v"]
|
opts += ["-v"]
|
||||||
if very_verbose:
|
if very_verbose:
|
||||||
opts += ["-vv"]
|
opts += ["-vv"]
|
||||||
|
self.config["build"]["sanitizer"] = sanitizer
|
||||||
|
assert sanitizer.is_tsan()
|
||||||
|
|
||||||
env = self.build_env()
|
env = self.build_env()
|
||||||
self.ensure_bootstrapped()
|
self.ensure_bootstrapped()
|
||||||
|
@ -117,52 +122,8 @@ class MachCommands(CommandBase):
|
||||||
host = servo.platform.host_triple()
|
host = servo.platform.host_triple()
|
||||||
target_triple = self.target.triple()
|
target_triple = self.target.triple()
|
||||||
|
|
||||||
if with_asan:
|
if sanitizer is not None:
|
||||||
if target_triple not in SUPPORTED_ASAN_TARGETS:
|
self.build_sanitizer_env(env, opts, kwargs, target_triple, sanitizer)
|
||||||
print(
|
|
||||||
"AddressSanitizer is currently not supported on this platform\n",
|
|
||||||
"See https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html",
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# do not use crown (clashes with different rust version)
|
|
||||||
env["RUSTC"] = "rustc"
|
|
||||||
|
|
||||||
# Enable usage of unstable rust flags
|
|
||||||
env["RUSTC_BOOTSTRAP"] = "1"
|
|
||||||
|
|
||||||
# Enable asan
|
|
||||||
env["RUSTFLAGS"] = env.get("RUSTFLAGS", "") + " -Zsanitizer=address"
|
|
||||||
opts += ["-Zbuild-std"]
|
|
||||||
kwargs["target_override"] = target_triple
|
|
||||||
|
|
||||||
# Note: We want to use the same clang/LLVM version as rustc.
|
|
||||||
rustc_llvm_version = get_rustc_llvm_version()
|
|
||||||
if rustc_llvm_version is None:
|
|
||||||
raise RuntimeError("Unable to determine necessary clang version for ASAN support")
|
|
||||||
llvm_major: int = rustc_llvm_version[0]
|
|
||||||
target_clang = f"clang-{llvm_major}"
|
|
||||||
target_cxx = f"clang++-{llvm_major}"
|
|
||||||
if shutil.which(target_clang) is None or shutil.which(target_cxx) is None:
|
|
||||||
raise RuntimeError(f"--with-asan requires `{target_clang}` and `{target_cxx}` to be in PATH")
|
|
||||||
env.setdefault("TARGET_CC", target_clang)
|
|
||||||
env.setdefault("TARGET_CXX", target_cxx)
|
|
||||||
# TODO: We should also parse the LLVM version from the clang compiler we chose.
|
|
||||||
# It's unclear if the major version being the same is sufficient.
|
|
||||||
|
|
||||||
# We need to use `TARGET_CFLAGS`, since we don't want to compile host dependencies with ASAN,
|
|
||||||
# since that causes issues when building build-scripts / proc macros.
|
|
||||||
env.setdefault("TARGET_CFLAGS", "")
|
|
||||||
env.setdefault("TARGET_CXXFLAGS", "")
|
|
||||||
env["TARGET_CFLAGS"] += " -fsanitize=address"
|
|
||||||
env["TARGET_CXXFLAGS"] += " -fsanitize=address"
|
|
||||||
env["TARGET_LDFLAGS"] = "-static-libasan"
|
|
||||||
# By default build mozjs from source to enable ASAN with mozjs.
|
|
||||||
env.setdefault("MOZJS_FROM_SOURCE", "1")
|
|
||||||
|
|
||||||
# asan replaces system allocator with asan allocator
|
|
||||||
# we need to make sure that we do not replace it with jemalloc
|
|
||||||
self.features.append("servo_allocator/use-system-allocator")
|
|
||||||
|
|
||||||
build_start = time()
|
build_start = time()
|
||||||
|
|
||||||
|
@ -187,10 +148,12 @@ class MachCommands(CommandBase):
|
||||||
status = self.run_cargo_build_like_command("rustc", opts, env=env, verbose=verbose, **kwargs)
|
status = self.run_cargo_build_like_command("rustc", opts, env=env, verbose=verbose, **kwargs)
|
||||||
|
|
||||||
if status == 0:
|
if status == 0:
|
||||||
built_binary = self.get_binary_path(build_type, asan=with_asan)
|
built_binary = self.get_binary_path(build_type, sanitizer=sanitizer)
|
||||||
|
|
||||||
if not no_package and self.target.needs_packaging():
|
if not no_package and self.target.needs_packaging():
|
||||||
rv = Registrar.dispatch("package", context=self.context, build_type=build_type, flavor=flavor)
|
rv = Registrar.dispatch(
|
||||||
|
"package", context=self.context, build_type=build_type, flavor=flavor, sanitizer=sanitizer
|
||||||
|
)
|
||||||
if rv:
|
if rv:
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
@ -247,6 +210,72 @@ class MachCommands(CommandBase):
|
||||||
opts += params
|
opts += params
|
||||||
return check_call(["cargo", "clean"] + opts, env=self.build_env(), verbose=verbose)
|
return check_call(["cargo", "clean"] + opts, env=self.build_env(), verbose=verbose)
|
||||||
|
|
||||||
|
def build_sanitizer_env(
|
||||||
|
self, env: Dict, opts: List[str], kwargs, target_triple, sanitizer: Optional[SanitizerKind] = None
|
||||||
|
):
|
||||||
|
if sanitizer is None:
|
||||||
|
return None
|
||||||
|
# do not use crown (clashes with different rust version)
|
||||||
|
env["RUSTC"] = "rustc"
|
||||||
|
# Enable usage of unstable rust flags
|
||||||
|
env["RUSTC_BOOTSTRAP"] = "1"
|
||||||
|
# std library should also be instrumented
|
||||||
|
opts += ["-Zbuild-std"]
|
||||||
|
# We need to always set the target triple, even when building for host.
|
||||||
|
kwargs["target_override"] = target_triple
|
||||||
|
# When sanitizers are used we also want framepointers to help with backtraces.
|
||||||
|
if "force-frame-pointers" not in env["RUSTFLAGS"]:
|
||||||
|
env["RUSTFLAGS"] += " -C force-frame-pointers=yes"
|
||||||
|
|
||||||
|
# Note: We want to use the same clang/LLVM version as rustc.
|
||||||
|
rustc_llvm_version = get_rustc_llvm_version()
|
||||||
|
if rustc_llvm_version is None:
|
||||||
|
raise RuntimeError("Unable to determine necessary clang version for Sanitizer support")
|
||||||
|
llvm_major: int = rustc_llvm_version[0]
|
||||||
|
target_clang = f"clang-{llvm_major}"
|
||||||
|
target_cxx = f"clang++-{llvm_major}"
|
||||||
|
if shutil.which(target_clang) is None or shutil.which(target_cxx) is None:
|
||||||
|
env.setdefault("TARGET_CC", 'clang')
|
||||||
|
env.setdefault("TARGET_CXX", 'clang++')
|
||||||
|
else:
|
||||||
|
# libasan can be compatible across multiple compiler versions and has a
|
||||||
|
# runtime check, which would fail if we used incompatible compilers, so
|
||||||
|
# we can try and fallback to the default clang.
|
||||||
|
env.setdefault("TARGET_CC", target_clang)
|
||||||
|
env.setdefault("TARGET_CXX", target_cxx)
|
||||||
|
# By default, build mozjs from source to enable Sanitizers in mozjs.
|
||||||
|
env.setdefault("MOZJS_FROM_SOURCE", "1")
|
||||||
|
|
||||||
|
# We need to use `TARGET_CFLAGS`, since we don't want to compile host dependencies with ASAN,
|
||||||
|
# since that causes issues when building build-scripts / proc macros.
|
||||||
|
# The actual flags will be appended below depending on the sanitizer kind.
|
||||||
|
env.setdefault("TARGET_CFLAGS", "")
|
||||||
|
env.setdefault("TARGET_CXXFLAGS", "")
|
||||||
|
env.setdefault("RUSTFLAGS", "")
|
||||||
|
|
||||||
|
if sanitizer is sanitizer.ASAN:
|
||||||
|
if target_triple not in SUPPORTED_ASAN_TARGETS:
|
||||||
|
print(
|
||||||
|
"AddressSanitizer is currently not supported on this platform\n",
|
||||||
|
"See https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html",
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Enable asan
|
||||||
|
env["RUSTFLAGS"] += " -Zsanitizer=address"
|
||||||
|
env["TARGET_CFLAGS"] += " -fsanitize=address"
|
||||||
|
env["TARGET_CXXFLAGS"] += " -fsanitize=address"
|
||||||
|
|
||||||
|
# asan replaces system allocator with asan allocator
|
||||||
|
# we need to make sure that we do not replace it with jemalloc
|
||||||
|
self.features.append("servo_allocator/use-system-allocator")
|
||||||
|
elif sanitizer is SanitizerKind.TSAN:
|
||||||
|
env["RUSTFLAGS"] += " -Zsanitizer=thread"
|
||||||
|
env["TARGET_CFLAGS"] += " -fsanitize=thread"
|
||||||
|
env["TARGET_CXXFLAGS"] += " -fsanitize=thread"
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
def notify(self, title: str, message: str):
|
def notify(self, title: str, message: str):
|
||||||
"""Generate desktop notification when build is complete and the
|
"""Generate desktop notification when build is complete and the
|
||||||
elapsed build time was longer than 30 seconds.
|
elapsed build time was longer than 30 seconds.
|
||||||
|
|
|
@ -43,6 +43,8 @@ from servo.util import download_file, get_default_cache_dir
|
||||||
import servo.platform
|
import servo.platform
|
||||||
import servo.util as util
|
import servo.util as util
|
||||||
|
|
||||||
|
from python.servo.platform.build_target import SanitizerKind
|
||||||
|
|
||||||
NIGHTLY_REPOSITORY_URL = "https://servo-builds2.s3.amazonaws.com/"
|
NIGHTLY_REPOSITORY_URL = "https://servo-builds2.s3.amazonaws.com/"
|
||||||
ASAN_LEAK_SUPPRESSION_FILE = "support/suppressed_leaks_for_asan.txt"
|
ASAN_LEAK_SUPPRESSION_FILE = "support/suppressed_leaks_for_asan.txt"
|
||||||
|
|
||||||
|
@ -305,6 +307,7 @@ class CommandBase(object):
|
||||||
self.config["build"].setdefault("incremental", None)
|
self.config["build"].setdefault("incremental", None)
|
||||||
self.config["build"].setdefault("webgl-backtrace", False)
|
self.config["build"].setdefault("webgl-backtrace", False)
|
||||||
self.config["build"].setdefault("dom-backtrace", False)
|
self.config["build"].setdefault("dom-backtrace", False)
|
||||||
|
self.config["build"].setdefault("sanitizer", SanitizerKind.NONE)
|
||||||
|
|
||||||
self.config.setdefault("android", {})
|
self.config.setdefault("android", {})
|
||||||
self.config["android"].setdefault("sdk", "")
|
self.config["android"].setdefault("sdk", "")
|
||||||
|
@ -327,9 +330,9 @@ class CommandBase(object):
|
||||||
def get_top_dir(self):
|
def get_top_dir(self):
|
||||||
return self.context.topdir
|
return self.context.topdir
|
||||||
|
|
||||||
def get_binary_path(self, build_type: BuildType, asan: bool = False):
|
def get_binary_path(self, build_type: BuildType, sanitizer=None):
|
||||||
base_path = util.get_target_dir()
|
base_path = util.get_target_dir()
|
||||||
if asan or self.target.is_cross_build():
|
if sanitizer is not None or self.target.is_cross_build():
|
||||||
base_path = path.join(base_path, self.target.triple())
|
base_path = path.join(base_path, self.target.triple())
|
||||||
binary_name = self.target.binary_name()
|
binary_name = self.target.binary_name()
|
||||||
binary_path = path.join(base_path, build_type.directory_name(), binary_name)
|
binary_path = path.join(base_path, build_type.directory_name(), binary_name)
|
||||||
|
@ -536,7 +539,23 @@ class CommandBase(object):
|
||||||
help="Build in release mode without debug assertions",
|
help="Build in release mode without debug assertions",
|
||||||
),
|
),
|
||||||
CommandArgument("--profile", group="Build Type", help="Build with custom Cargo profile"),
|
CommandArgument("--profile", group="Build Type", help="Build with custom Cargo profile"),
|
||||||
CommandArgument("--with-asan", action="store_true", help="Build with AddressSanitizer"),
|
CommandArgumentGroup("Sanitizer"),
|
||||||
|
CommandArgument(
|
||||||
|
"--with-asan",
|
||||||
|
group="Sanitizer",
|
||||||
|
dest="sanitizer",
|
||||||
|
action="store_const",
|
||||||
|
const=SanitizerKind.ASAN,
|
||||||
|
help="Build with AddressSanitizer",
|
||||||
|
),
|
||||||
|
CommandArgument(
|
||||||
|
"--with-tsan",
|
||||||
|
group="Sanitizer",
|
||||||
|
dest="sanitizer",
|
||||||
|
action="store_const",
|
||||||
|
const=SanitizerKind.TSAN,
|
||||||
|
help="Build with ThreadSanitizer",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
if build_configuration:
|
if build_configuration:
|
||||||
|
@ -648,13 +667,13 @@ class CommandBase(object):
|
||||||
kwargs["servo_binary"] = (
|
kwargs["servo_binary"] = (
|
||||||
kwargs.get("bin")
|
kwargs.get("bin")
|
||||||
or self.get_nightly_binary_path(kwargs.get("nightly"))
|
or self.get_nightly_binary_path(kwargs.get("nightly"))
|
||||||
or self.get_binary_path(kwargs.get("build_type"), asan=kwargs.get("with_asan"))
|
or self.get_binary_path(kwargs.get("build_type"), sanitizer=kwargs.get("sanitizer"))
|
||||||
)
|
)
|
||||||
kwargs.pop("bin")
|
kwargs.pop("bin")
|
||||||
kwargs.pop("nightly")
|
kwargs.pop("nightly")
|
||||||
if not build_type:
|
if not build_type:
|
||||||
kwargs.pop("build_type")
|
kwargs.pop("build_type")
|
||||||
kwargs.pop("with_asan")
|
kwargs.pop("sanitizer")
|
||||||
|
|
||||||
return original_function(self, *args, **kwargs)
|
return original_function(self, *args, **kwargs)
|
||||||
|
|
||||||
|
@ -803,15 +822,16 @@ class CommandBase(object):
|
||||||
"--manifest-path",
|
"--manifest-path",
|
||||||
path.join(self.context.topdir, "ports", "servoshell", "Cargo.toml"),
|
path.join(self.context.topdir, "ports", "servoshell", "Cargo.toml"),
|
||||||
]
|
]
|
||||||
if target_override:
|
|
||||||
args += ["--target", target_override]
|
if self.target.is_cross_build():
|
||||||
elif self.target.is_cross_build():
|
|
||||||
args += ["--target", self.target.triple()]
|
args += ["--target", self.target.triple()]
|
||||||
if type(self.target) in [AndroidTarget, OpenHarmonyTarget]:
|
if type(self.target) in [AndroidTarget, OpenHarmonyTarget]:
|
||||||
# Note: in practice `cargo rustc` should just be used unconditionally.
|
# Note: in practice `cargo rustc` should just be used unconditionally.
|
||||||
assert command != "build", "For Android / OpenHarmony `cargo rustc` must be used instead of cargo build"
|
assert command != "build", "For Android / OpenHarmony `cargo rustc` must be used instead of cargo build"
|
||||||
if command == "rustc":
|
if command == "rustc":
|
||||||
args += ["--lib", "--crate-type=cdylib"]
|
args += ["--lib", "--crate-type=cdylib"]
|
||||||
|
elif target_override:
|
||||||
|
args += ["--target", target_override]
|
||||||
|
|
||||||
features = []
|
features = []
|
||||||
|
|
||||||
|
|
|
@ -237,7 +237,7 @@ def find_non_system_dependencies_with_otool(binary_path: str) -> Set[str]:
|
||||||
|
|
||||||
# No need to do any processing for system libraries. They should be
|
# No need to do any processing for system libraries. They should be
|
||||||
# present on all macOS systems.
|
# present on all macOS systems.
|
||||||
if not is_macos_system_library(dependency):
|
if not (is_macos_system_library(dependency) or 'librustc-stable_rt' in dependency):
|
||||||
output.add(dependency)
|
output.add(dependency)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
from typing import List
|
from typing import List, Optional
|
||||||
from github import Github
|
from github import Github
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -41,6 +41,8 @@ from servo.command_base import (
|
||||||
)
|
)
|
||||||
from servo.util import delete, get_target_dir
|
from servo.util import delete, get_target_dir
|
||||||
|
|
||||||
|
from python.servo.platform.build_target import SanitizerKind
|
||||||
|
|
||||||
PACKAGES = {
|
PACKAGES = {
|
||||||
"android": [
|
"android": [
|
||||||
"android/aarch64-linux-android/release/servoapp.apk",
|
"android/aarch64-linux-android/release/servoapp.apk",
|
||||||
|
@ -108,9 +110,9 @@ class PackageCommands(CommandBase):
|
||||||
@CommandArgument("--target", "-t", default=None, help="Package for given target platform")
|
@CommandArgument("--target", "-t", default=None, help="Package for given target platform")
|
||||||
@CommandBase.common_command_arguments(build_configuration=False, build_type=True, package_configuration=True)
|
@CommandBase.common_command_arguments(build_configuration=False, build_type=True, package_configuration=True)
|
||||||
@CommandBase.allow_target_configuration
|
@CommandBase.allow_target_configuration
|
||||||
def package(self, build_type: BuildType, flavor=None, with_asan=False):
|
def package(self, build_type: BuildType, flavor=None, sanitizer: Optional[SanitizerKind] = None):
|
||||||
env = self.build_env()
|
env = self.build_env()
|
||||||
binary_path = self.get_binary_path(build_type, asan=with_asan)
|
binary_path = self.get_binary_path(build_type, sanitizer=sanitizer)
|
||||||
dir_to_root = self.get_top_dir()
|
dir_to_root = self.get_top_dir()
|
||||||
target_dir = path.dirname(binary_path)
|
target_dir = path.dirname(binary_path)
|
||||||
if self.is_android():
|
if self.is_android():
|
||||||
|
@ -184,6 +186,11 @@ class PackageCommands(CommandBase):
|
||||||
"-p",
|
"-p",
|
||||||
f"buildMode={build_mode}",
|
f"buildMode={build_mode}",
|
||||||
]
|
]
|
||||||
|
if sanitizer.is_asan():
|
||||||
|
hvigor_command.extend(["-p", "ohos-debug-asan=true"])
|
||||||
|
elif sanitizer.is_tsan():
|
||||||
|
hvigor_command.extend(["-p", "ohos-enable-tsan=true"])
|
||||||
|
|
||||||
# Detect if PATH already has hvigor, or else fallback to npm installation
|
# Detect if PATH already has hvigor, or else fallback to npm installation
|
||||||
# provided via HVIGOR_PATH
|
# provided via HVIGOR_PATH
|
||||||
if "HVIGOR_PATH" not in env:
|
if "HVIGOR_PATH" not in env:
|
||||||
|
@ -388,17 +395,19 @@ class PackageCommands(CommandBase):
|
||||||
@CommandArgument("--target", "-t", default=None, help="Install the given target platform")
|
@CommandArgument("--target", "-t", default=None, help="Install the given target platform")
|
||||||
@CommandBase.common_command_arguments(build_configuration=False, build_type=True, package_configuration=True)
|
@CommandBase.common_command_arguments(build_configuration=False, build_type=True, package_configuration=True)
|
||||||
@CommandBase.allow_target_configuration
|
@CommandBase.allow_target_configuration
|
||||||
def install(self, build_type: BuildType, emulator=False, usb=False, with_asan=False, flavor=None):
|
def install(
|
||||||
|
self, build_type: BuildType, emulator=False, usb=False, sanitizer: Optional[SanitizerKind] = None, flavor=None
|
||||||
|
):
|
||||||
env = self.build_env()
|
env = self.build_env()
|
||||||
try:
|
try:
|
||||||
binary_path = self.get_binary_path(build_type, asan=with_asan)
|
binary_path = self.get_binary_path(build_type, sanitizer=sanitizer)
|
||||||
except BuildNotFound:
|
except BuildNotFound:
|
||||||
print("Servo build not found. Building servo...")
|
print("Servo build not found. Building servo...")
|
||||||
result = Registrar.dispatch("build", context=self.context, build_type=build_type, flavor=flavor)
|
result = Registrar.dispatch("build", context=self.context, build_type=build_type, flavor=flavor)
|
||||||
if result:
|
if result:
|
||||||
return result
|
return result
|
||||||
try:
|
try:
|
||||||
binary_path = self.get_binary_path(build_type, asan=with_asan)
|
binary_path = self.get_binary_path(build_type, sanitizer=sanitizer)
|
||||||
except BuildNotFound:
|
except BuildNotFound:
|
||||||
print("Rebuilding Servo did not solve the missing build problem.")
|
print("Rebuilding Servo did not solve the missing build problem.")
|
||||||
return 1
|
return 1
|
||||||
|
|
|
@ -15,6 +15,7 @@ import platform
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
from packaging.version import parse as parse_version
|
from packaging.version import parse as parse_version
|
||||||
|
@ -24,6 +25,24 @@ import servo.platform
|
||||||
import servo.util as util
|
import servo.util as util
|
||||||
|
|
||||||
|
|
||||||
|
class SanitizerKind(Enum):
|
||||||
|
NONE = 0
|
||||||
|
ASAN = 1
|
||||||
|
TSAN = 2
|
||||||
|
|
||||||
|
# Apparently enums don't always compare across modules, so we define
|
||||||
|
# helper methods.
|
||||||
|
def is_asan(self) -> bool:
|
||||||
|
return self is self.ASAN
|
||||||
|
|
||||||
|
def is_tsan(self) -> bool:
|
||||||
|
return self is self.TSAN
|
||||||
|
|
||||||
|
# Returns true if a sanitizer is enabled.
|
||||||
|
def is_some(self) -> bool:
|
||||||
|
return self is not self.NONE
|
||||||
|
|
||||||
|
|
||||||
class BuildTarget(object):
|
class BuildTarget(object):
|
||||||
def __init__(self, target_triple: str):
|
def __init__(self, target_triple: str):
|
||||||
self.target_triple = target_triple
|
self.target_triple = target_triple
|
||||||
|
@ -350,9 +369,8 @@ class OpenHarmonyTarget(CrossBuildTarget):
|
||||||
env[f"CXX_{clang_target_triple_underscore}"] = ndk_clangxx
|
env[f"CXX_{clang_target_triple_underscore}"] = ndk_clangxx
|
||||||
# rustc linker
|
# rustc linker
|
||||||
env[f"CARGO_TARGET_{rust_target_triple.upper()}_LINKER"] = ndk_clang
|
env[f"CARGO_TARGET_{rust_target_triple.upper()}_LINKER"] = ndk_clang
|
||||||
# We could also use a cross-compile wrapper
|
|
||||||
env["RUSTFLAGS"] += f" -Clink-arg=--target={clang_target_triple}"
|
link_args = ["-fuse-ld=lld", f"--target={clang_target_triple}", f"--sysroot={ohos_sysroot_posix}"]
|
||||||
env["RUSTFLAGS"] += f" -Clink-arg=--sysroot={ohos_sysroot_posix}"
|
|
||||||
|
|
||||||
env["HOST_CFLAGS"] = ""
|
env["HOST_CFLAGS"] = ""
|
||||||
env["HOST_CXXFLAGS"] = ""
|
env["HOST_CXXFLAGS"] = ""
|
||||||
|
@ -398,6 +416,65 @@ class OpenHarmonyTarget(CrossBuildTarget):
|
||||||
bindgen_extra_clangs_args = bindgen_extra_clangs_args + " " + ohos_cflags_str
|
bindgen_extra_clangs_args = bindgen_extra_clangs_args + " " + ohos_cflags_str
|
||||||
env[bindgen_extra_clangs_args_var] = bindgen_extra_clangs_args
|
env[bindgen_extra_clangs_args_var] = bindgen_extra_clangs_args
|
||||||
|
|
||||||
|
sanitizer: SanitizerKind = config["build"]["sanitizer"]
|
||||||
|
san_compile_flags = []
|
||||||
|
if sanitizer.is_some():
|
||||||
|
# Lookup `<sdk>/native/llvm/lib/clang/15.0.4/lib/aarch64-linux-ohos/libclang_rt.asan.so`
|
||||||
|
lib_clang = llvm_toolchain.joinpath("lib", "clang")
|
||||||
|
children = [f.path for f in os.scandir(lib_clang) if f.is_dir()]
|
||||||
|
if len(children) != 1:
|
||||||
|
raise RuntimeError(f"Expected exactly 1 libclang version: `{children}`")
|
||||||
|
lib_clang_version_dir = pathlib.Path(children[0])
|
||||||
|
libclang_arch = lib_clang_version_dir.joinpath("lib", clang_target_triple).resolve()
|
||||||
|
# Use the clangrt from the NDK to use the same library for both C++ and Rust.
|
||||||
|
env["RUSTFLAGS"] += " -Zexternal-clangrt"
|
||||||
|
san_compile_flags.append("-fno-omit-frame-pointer")
|
||||||
|
|
||||||
|
# On OpenHarmony we add some additional flags when asan is enabled
|
||||||
|
if sanitizer.is_asan():
|
||||||
|
libasan_so_path = libclang_arch.joinpath("libclang_rt.asan.so")
|
||||||
|
libasan_preinit_path = libclang_arch.joinpath("libclang_rt.asan-preinit.a")
|
||||||
|
if not libasan_so_path.exists():
|
||||||
|
raise RuntimeError(f"Couldn't find ASAN runtime library at {libasan_so_path}")
|
||||||
|
link_args.extend(
|
||||||
|
[
|
||||||
|
"-fsanitize=address",
|
||||||
|
"--rtlib=compiler-rt",
|
||||||
|
"-shared-libasan",
|
||||||
|
str(libasan_so_path),
|
||||||
|
"-Wl,--whole-archive",
|
||||||
|
"-Wl," + str(libasan_preinit_path),
|
||||||
|
"-Wl,--no-whole-archive",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
san_compile_flags.extend([ "-fsanitize=address", "-shared-libasan", "-fsanitize-recover=address"])
|
||||||
|
|
||||||
|
arch_asan_ignore_list = lib_clang_version_dir.joinpath("share", "asan_ignorelist.txt")
|
||||||
|
if arch_asan_ignore_list.exists():
|
||||||
|
san_compile_flags.append("-fsanitize-system-ignorelist=" + str(arch_asan_ignore_list))
|
||||||
|
else:
|
||||||
|
print(f"Warning: Couldn't find system ASAN ignorelist at `{arch_asan_ignore_list}`")
|
||||||
|
elif sanitizer.is_tsan():
|
||||||
|
libtsan_so_path = libclang_arch.joinpath("libclang_rt.tsan.so")
|
||||||
|
builtins_path = libclang_arch.joinpath("libclang_rt.builtins.a")
|
||||||
|
|
||||||
|
link_args.extend(
|
||||||
|
[
|
||||||
|
"-fsanitize=thread",
|
||||||
|
"--rtlib=compiler-rt",
|
||||||
|
"-shared-libsan",
|
||||||
|
str(libtsan_so_path),
|
||||||
|
str(builtins_path)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
san_compile_flags.append("-shared-libsan")
|
||||||
|
|
||||||
|
link_args = [f"-Clink-arg={arg}" for arg in link_args]
|
||||||
|
env["RUSTFLAGS"] += " " + " ".join(link_args)
|
||||||
|
env["TARGET_CFLAGS"] += " " + " ".join(san_compile_flags)
|
||||||
|
env["TARGET_CXXFLAGS"] += " " + " ".join(san_compile_flags)
|
||||||
|
|
||||||
def binary_name(self) -> str:
|
def binary_name(self) -> str:
|
||||||
return "libservoshell.so"
|
return "libservoshell.so"
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue