On Fri, 08 Sep 2023 13:35:44 -0400 Andres Salomon <dilin...@queued.net>
wrote:
>
>
> On Fri, Sep 8 2023 at 10:36:48 AM +02:00:00, Fabian Grünbichler
> <fabian@gruenbichler.email> wrote:
> >> On Tue, Aug 8 2023 at 06:22:28 PM -04:00:00, Andres Salomon
> >>
> [...]
> >>
> >> This patch adds
> >> "cargo:rustc-link-search=/usr/lib/clang/15/lib/linux/" and
> >> "cargo:rustc-link-lib=static=clang_rt.profile-x86_64" (or
whatever
> >> architecture it happens to be building on) to the
profiler_builtins
> >> build
> >> flags when the target matches the host. In the case where the
> >> target is
> >> different from the host, it assumes a wasm build and sets
> >> "rustc-link-lib=static=clang_rt.builtins-wasm32" or
> >> "cargo:rustc-link-lib=static=clang_rt.builtins-wasm64" depending
> >> upon
> >> whether the target is 32 or 64 bits, respectively.
> >
> > Thanks for the patch! the Windows part in d/rules looks wrong to
me -
> > that is built with mingw, not wasi. I assume you are not
interested in
> > that part, so maybe it would also be an option to guard it based on
> > target and just build it for the regular one (or regular+wasm, but
not
> > windows/mingw)?
>
After you pointed out the upstream patch on IRC
(https://github.com/rust-lang/rust/pull/114069), I backported it to
1.70 and tried building it. It gets pretty far, but fails late in the
build on some tests. I'm going to do some more building (starting with
rustc by itself without the profiler stuff, to ensure that the test
failure I'm seeing is actually related to profiler). But in the
meantime, here's the backported patch. If I can get it fully built,
I'll follow up with the full debian patch or a merge request.
From d0b58f40a0e669897fafb614299d2a989997eda7 Mon Sep 17 00:00:00 2001
From: Josh Stone <jist...@redhat.com>
Date: Tue, 25 Jul 2023 13:11:50 -0700
Subject: [PATCH] Allow using external builds of the compiler-rt profile lib
This changes the bootstrap config `target.*.profiler` from a plain bool
to also allow a string, which will be used as a path to the pre-built
profiling runtime for that target. Then `profiler_builtins/build.rs`
reads that in a `LLVM_PROFILER_RT_LIB` environment variable.
---
config.example.toml | 6 ++++--
library/profiler_builtins/build.rs | 6 ++++++
src/bootstrap/compile.rs | 4 ++++
src/bootstrap/config.rs | 30 ++++++++++++++++++++++++------
4 files changed, 38 insertions(+), 8 deletions(-)
--- a/config.example.toml
+++ b/config.example.toml
@@ -745,8 +745,10 @@ changelog-seen = 2
# This option will override the same option under [build] section.
#sanitizers = build.sanitizers (bool)
-# Build the profiler runtime for this target(required when compiling with options that depend
-# on this runtime, such as `-C profile-generate` or `-C instrument-coverage`).
+# When true, build the profiler runtime for this target(required when compiling
+# with options that depend on this runtime, such as `-C profile-generate` or
+# `-C instrument-coverage`). This may also be given a path to an existing build
+# of the profiling runtime library from LLVM's compiler-rt.
# This option will override the same option under [build] section.
#profiler = build.profiler (bool)
--- a/library/profiler_builtins/build.rs
+++ b/library/profiler_builtins/build.rs
@@ -6,6 +6,12 @@ use std::env;
use std::path::Path;
fn main() {
+ println!("cargo:rerun-if-env-changed=LLVM_PROFILER_RT_LIB");
+ if let Ok(rt) = env::var("LLVM_PROFILER_RT_LIB") {
+ println!("cargo:rustc-link-lib=static:+verbatim={rt}");
+ return;
+ }
+
let target = env::var("TARGET").expect("TARGET was not set");
let cfg = &mut cc::Build::new();
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -314,6 +314,10 @@ pub fn std_cargo(builder: &Builder<'_>,
cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
}
+ if let Some(path) = builder.config.profiler_path(target) {
+ cargo.env("LLVM_PROFILER_RT_LIB", path);
+ }
+
// Determine if we're going to compile in optimized C intrinsics to
// the `compiler-builtins` crate. These intrinsics live in LLVM's
// `compiler-rt` repository, but our `src/llvm-project` submodule isn't
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -454,7 +454,7 @@ pub struct Target {
pub linker: Option<PathBuf>,
pub ndk: Option<PathBuf>,
pub sanitizers: Option<bool>,
- pub profiler: Option<bool>,
+ pub profiler: Option<StringOrBool>,
pub crt_static: Option<bool>,
pub musl_root: Option<PathBuf>,
pub musl_libdir: Option<PathBuf>,
@@ -715,9 +715,9 @@ define_config! {
}
}
-#[derive(Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
-enum StringOrBool {
+pub enum StringOrBool {
String(String),
Bool(bool),
}
@@ -728,6 +728,12 @@ impl Default for StringOrBool {
}
}
+impl StringOrBool {
+ fn is_string_or_true(&self) -> bool {
+ matches!(self, Self::String(_) | Self::Bool(true))
+ }
+}
+
define_config! {
/// TOML representation of how the Rust build is configured.
struct Rust {
@@ -799,7 +805,7 @@ define_config! {
llvm_libunwind: Option<String> = "llvm-libunwind",
android_ndk: Option<String> = "android-ndk",
sanitizers: Option<bool> = "sanitizers",
- profiler: Option<bool> = "profiler",
+ profiler: Option<StringOrBool> = "profiler",
crt_static: Option<bool> = "crt-static",
musl_root: Option<String> = "musl-root",
musl_libdir: Option<String> = "musl-libdir",
@@ -1616,12 +1622,24 @@ impl Config {
self.target_config.values().any(|t| t.sanitizers == Some(true)) || self.sanitizers
}
+ pub fn profiler_path(&self, target: TargetSelection) -> Option<&str> {
+ match self.target_config.get(&target)?.profiler.as_ref()? {
+ StringOrBool::String(s) => Some(s),
+ StringOrBool::Bool(_) => None,
+ }
+ }
+
pub fn profiler_enabled(&self, target: TargetSelection) -> bool {
- self.target_config.get(&target).map(|t| t.profiler).flatten().unwrap_or(self.profiler)
+ self.target_config
+ .get(&target)
+ .and_then(|t| t.profiler.as_ref())
+ .map(StringOrBool::is_string_or_true)
+ .unwrap_or(self.profiler)
}
pub fn any_profiler_enabled(&self) -> bool {
- self.target_config.values().any(|t| t.profiler == Some(true)) || self.profiler
+ self.target_config.values().any(|t| matches!(&t.profiler, Some(p) if p.is_string_or_true()))
+ || self.profiler
}
pub fn llvm_enabled(&self) -> bool {