aboutsummaryrefslogtreecommitdiffstats
path: root/python/servo
diff options
context:
space:
mode:
Diffstat (limited to 'python/servo')
-rw-r--r--python/servo/build_commands.py25
-rw-r--r--python/servo/command_base.py8
-rw-r--r--python/servo/package_commands.py3
-rw-r--r--python/servo/platform/build_target.py48
4 files changed, 71 insertions, 13 deletions
diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py
index e2a5ffc6a1a..e34fa2a2687 100644
--- a/python/servo/build_commands.py
+++ b/python/servo/build_commands.py
@@ -40,6 +40,7 @@ from servo.platform.build_target import BuildTarget
SUPPORTED_ASAN_TARGETS = [
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
+ "aarch64-unknown-linux-ohos",
"x86_64-apple-darwin",
"x86_64-unknown-linux-gnu",
]
@@ -109,6 +110,8 @@ class MachCommands(CommandBase):
opts += ["-v"]
if very_verbose:
opts += ["-vv"]
+ if with_asan:
+ self.config["build"]["with_asan"] = True
env = self.build_env()
self.ensure_bootstrapped()
@@ -136,6 +139,10 @@ class MachCommands(CommandBase):
opts += ["-Zbuild-std"]
kwargs["target_override"] = target_triple
+ # With asan we also want frame pointers
+ 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:
@@ -144,11 +151,14 @@ class MachCommands(CommandBase):
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.
+ env.setdefault("TARGET_CC", target_clang)
+ env.setdefault("TARGET_CXX", target_cxx)
+ 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", "clang")
+ env.setdefault("TARGET_CXX", "clang++")
# 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.
@@ -156,7 +166,6 @@ class MachCommands(CommandBase):
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")
@@ -190,7 +199,9 @@ class MachCommands(CommandBase):
built_binary = self.get_binary_path(build_type, asan=with_asan)
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, with_asan=with_asan
+ )
if rv:
return rv
diff --git a/python/servo/command_base.py b/python/servo/command_base.py
index abd193eda49..f0f28e5488e 100644
--- a/python/servo/command_base.py
+++ b/python/servo/command_base.py
@@ -305,6 +305,7 @@ class CommandBase(object):
self.config["build"].setdefault("incremental", None)
self.config["build"].setdefault("webgl-backtrace", False)
self.config["build"].setdefault("dom-backtrace", False)
+ self.config["build"].setdefault("with_asan", False)
self.config.setdefault("android", {})
self.config["android"].setdefault("sdk", "")
@@ -803,15 +804,16 @@ class CommandBase(object):
"--manifest-path",
path.join(self.context.topdir, "ports", "servoshell", "Cargo.toml"),
]
- if target_override:
- args += ["--target", target_override]
- elif self.target.is_cross_build():
+
+ if self.target.is_cross_build():
args += ["--target", self.target.triple()]
if type(self.target) in [AndroidTarget, OpenHarmonyTarget]:
# 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"
if command == "rustc":
args += ["--lib", "--crate-type=cdylib"]
+ elif target_override:
+ args += ["--target", target_override]
features = []
diff --git a/python/servo/package_commands.py b/python/servo/package_commands.py
index 5e63e6549c0..9bc4d70232d 100644
--- a/python/servo/package_commands.py
+++ b/python/servo/package_commands.py
@@ -184,6 +184,9 @@ class PackageCommands(CommandBase):
"-p",
f"buildMode={build_mode}",
]
+ if with_asan:
+ hvigor_command.extend(["-p", "ohos-debug-asan=true"])
+
# Detect if PATH already has hvigor, or else fallback to npm installation
# provided via HVIGOR_PATH
if "HVIGOR_PATH" not in env:
diff --git a/python/servo/platform/build_target.py b/python/servo/platform/build_target.py
index 5f0f500ad58..536b10a8d3d 100644
--- a/python/servo/platform/build_target.py
+++ b/python/servo/platform/build_target.py
@@ -350,9 +350,8 @@ class OpenHarmonyTarget(CrossBuildTarget):
env[f"CXX_{clang_target_triple_underscore}"] = ndk_clangxx
# rustc linker
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}"
- env["RUSTFLAGS"] += f" -Clink-arg=--sysroot={ohos_sysroot_posix}"
+
+ link_args = ["-fuse-ld=lld", f"--target={clang_target_triple}", f"--sysroot={ohos_sysroot_posix}"]
env["HOST_CFLAGS"] = ""
env["HOST_CXXFLAGS"] = ""
@@ -398,6 +397,49 @@ class OpenHarmonyTarget(CrossBuildTarget):
bindgen_extra_clangs_args = bindgen_extra_clangs_args + " " + ohos_cflags_str
env[bindgen_extra_clangs_args_var] = bindgen_extra_clangs_args
+ # On OpenHarmony we add some additional flags when asan is enabled
+ if config["build"]["with_asan"]:
+ # 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()
+ 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",
+ ]
+ )
+
+ # Use the clangrt from the NDK to use the same library for both C++ and Rust.
+ env["RUSTFLAGS"] += " -Zexternal-clangrt"
+
+ asan_compile_flags = (
+ " -fsanitize=address -shared-libasan -fno-omit-frame-pointer -fsanitize-recover=address"
+ )
+
+ arch_asan_ignore_list = lib_clang_version_dir.joinpath("share", "asan_ignorelist.txt")
+ if arch_asan_ignore_list.exists():
+ asan_compile_flags += " -fsanitize-system-ignorelist=" + str(arch_asan_ignore_list)
+ else:
+ print(f"Warning: Couldn't find system ASAN ignorelist at `{arch_asan_ignore_list}`")
+ env["TARGET_CFLAGS"] += asan_compile_flags
+ env["TARGET_CXXFLAGS"] += asan_compile_flags
+
+ link_args = [f"-Clink-arg={arg}" for arg in link_args]
+ env["RUSTFLAGS"] += " " + " ".join(link_args)
+
def binary_name(self) -> str:
return "libservoshell.so"