Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inject_panic_runtime(): Avoid double negation for 'any non rlib' #133300

Merged
merged 1 commit into from
Nov 24, 2024

Conversation

Enselic
Copy link
Member

@Enselic Enselic commented Nov 21, 2024

This PR originally did more things .Click to expand to see.

By not trying to inject a profiler runtime when only building an rlib. This logic already exists for the panic runtime.

This makes

RUSTFLAGS="-Cinstrument-coverage" cargo build -Zbuild-std=std,profiler_builtins

work. Note that you probably also need
RUST_COMPILER_RT_FOR_PROFILER=$src/llvm-project/compiler-rt in your environment.

cc #79401

Demonstration

Before this fix you get these errors:

$ rm -rf target ; RUST_COMPILER_RT_FOR_PROFILER=/home/martin/src/llvm-project/compiler-rt RUSTFLAGS="-Cinstrument-coverage" cargo +nightly build --release -Zbuild-std=std,profiler_builtins
error: `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
error[E0152]: found duplicate lang item `manually_drop`
    = note: first definition in `core` loaded from /home/martin/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-d453bab70303062c.rlib
    = note: second definition in the local crate (`core`)

With the fix the build succeeds:

$ rm -rf target ; RUST_COMPILER_RT_FOR_PROFILER=/home/martin/src/llvm-project/compiler-rt RUSTFLAGS="-Cinstrument-coverage" cargo +stage1 build --release -Zbuild-std=std,profiler_builtins
    Finished `release` profile [optimized] target(s) in 45.57s

And we can check code coverage. My example program looks like this:

fn main() {
    if std::env::args_os().nth(1) == Some("write-file".into()) {
        std::fs::write("hello.txt", "Hello, world!").unwrap();
    } else {
        println!("Hello, world!");
    }
}

when the program prints to stdout:

$ LLVM_PROFILE_FILE=stdout.profraw ./target/release/hello-world
Hello, world!

we can see that fs::write() is not being used (note the 0's):

$ /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -sparse stdout.profraw -o stdout.profdata
$ /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-cov show target/release/hello-world --sources /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/library/std/src/fs.rs --instr-profile stdout.profdata --color | grep -A 3 'pub fn write(&mut self, write: b
ool) -> &mut Self {'
 1357|      0|    pub fn write(&mut self, write: bool) -> &mut Self {
 1358|      0|        self.0.write(write);
 1359|      0|        self
 1360|      0|    }

but when we print to a file:

$ LLVM_PROFILE_FILE=file.profraw ./target/release/hello-world write-file

the code coverage shows fs::write() as being used (note the 1's):

$ /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -sparse file.profraw -o file.profdata
$ /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-cov show target/release/hello-world --sources /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/library/std/src/fs.rs --instr-profile file.profdata --color | grep -A 3 'pub fn write(&mut self, write: bool) -> &mut Self {'
 1357|      1|    pub fn write(&mut self, write: bool) -> &mut Self {
 1358|      1|        self.0.write(write);
 1359|      1|        self
 1360|      1|    }

@rustbot
Copy link
Collaborator

rustbot commented Nov 21, 2024

r? @lcnr

rustbot has assigned @lcnr.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 21, 2024
@Enselic Enselic changed the title Make cargo -Zbuild-std work with -Cinstrument-coverage Make cargo -Zbuild-std work with -Cinstrument-coverage Nov 21, 2024
@Enselic Enselic added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 21, 2024
@lcnr
Copy link
Contributor

lcnr commented Nov 22, 2024

r? compiler

@rustbot rustbot assigned wesleywiser and unassigned lcnr Nov 22, 2024
@Enselic Enselic force-pushed the build-std-instrument-coverage branch from f9cc5ae to e728236 Compare November 22, 2024 19:13
@rustbot rustbot added the A-run-make Area: port run-make Makefiles to rmake.rs label Nov 22, 2024
@rustbot
Copy link
Collaborator

rustbot commented Nov 22, 2024

This PR modifies tests/run-make/. If this PR is trying to port a Makefile
run-make test to use rmake.rs, please update the
run-make port tracking issue
so we can track our progress. You can either modify the tracking issue
directly, or you can comment on the tracking issue and link this PR.

cc @jieyouxu

@Enselic Enselic added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 22, 2024
@jieyouxu jieyouxu self-assigned this Nov 23, 2024
@Zalathar
Copy link
Contributor

Zalathar commented Nov 23, 2024

I'm not very familiar with the injection of profiler_builtins, but based on my limited understanding I suspect that this might be the wrong fix.

I did some playing around, and this might potentially be the more appropriate solution:

  • Change profiler_builtins from #[no_std] to #[no_core], since it doesn't contain any actual Rust code.
  • Remove the check that refuses to inject profiler_builtins into #[no_core] crates.

EDIT: Draft PR at #133369.

@Zalathar
Copy link
Contributor

Basically, I think the underlying problem is that because profiler_builtins is currently #[no_std], it still has an implicit dependency on core. That causes problems when trying to make it a dependency of core itself.

But I'm pretty sure that:

  • There is no need for profiler_builtins to actually depend on core.
  • When built with -Cinstrument-coverage, core really should have a genuine dependency on profiler_builtins, to make sure the profiler runtime ends up in the final binary even if no other crate in the final binary is built with instrument-coverage.

@Zalathar
Copy link
Contributor

For reference, the error message was added in #79958. It looks like the real issue (profiler doesn't need core) wasn't noticed at that time.

@Enselic Enselic force-pushed the build-std-instrument-coverage branch from e728236 to a0e5aea Compare November 23, 2024 13:20
@Enselic Enselic changed the title Make cargo -Zbuild-std work with -Cinstrument-coverage inject_panic_runtime(): Avoid double negation for 'any non rlib' Nov 23, 2024
@Enselic
Copy link
Member Author

Enselic commented Nov 23, 2024

Your solution is clearly better than mine, and I have confirmed it works for me too. Thanks!

I have now made this PR only fix the double-negation that bjorn3 pointed out.

Copy link
Member

@jieyouxu jieyouxu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, you can r=me after PR CI is green (and probably update PR description).

@jieyouxu
Copy link
Member

@bors delegate+ rollup

@bors
Copy link
Contributor

bors commented Nov 23, 2024

✌️ @Enselic, you can now approve this pull request!

If @jieyouxu told you to "r=me" after making some further change, please make that change, then do @bors r=@jieyouxu

@Enselic
Copy link
Member Author

Enselic commented Nov 23, 2024

@bors r=@jieyouxu

@bors
Copy link
Contributor

bors commented Nov 23, 2024

📌 Commit a0e5aea has been approved by jieyouxu

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 23, 2024
@jieyouxu
Copy link
Member

jieyouxu commented Nov 23, 2024

(I edited the magic Fixes #... comment in PR description out because github will autoclose the linked issue otherwise)

@Zalathar
Copy link
Contributor

By the way, in this sort of situation I would usually suggest creating a new PR rather than changing the scope of an old one, to avoid a confusing PR history.

@Enselic
Copy link
Member Author

Enselic commented Nov 24, 2024

Will do so next time 👍

bors added a commit to rust-lang-ci/rust that referenced this pull request Nov 24, 2024
…iaskrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#133300 (inject_panic_runtime(): Avoid double negation for 'any non rlib')
 - rust-lang#133301 (Add code example for `wrapping_neg` method for signed integers)
 - rust-lang#133371 (remove is_trivially_const_drop)
 - rust-lang#133389 (Stabilize `const_float_methods`)
 - rust-lang#133398 (rustdoc: do not call to_string, it's already impl Display)
 - rust-lang#133405 (tidy: Distinguish between two different meanings of "style file")

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 4ad97f2 into rust-lang:master Nov 24, 2024
6 checks passed
@rustbot rustbot added this to the 1.85.0 milestone Nov 24, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Nov 24, 2024
Rollup merge of rust-lang#133300 - Enselic:build-std-instrument-coverage, r=jieyouxu

inject_panic_runtime(): Avoid double negation for 'any non rlib'

<details>

<summary>This PR originally did more things .Click to expand to see.</summary>

By not trying to inject a profiler runtime when only building an rlib. This logic already exists for the panic runtime.

This makes

    RUSTFLAGS="-Cinstrument-coverage" cargo build -Zbuild-std=std,profiler_builtins

work. Note that you probably also need
`RUST_COMPILER_RT_FOR_PROFILER=$src/llvm-project/compiler-rt` in your environment.

cc rust-lang#79401

# Demonstration

Before this fix you get these errors:

```console
$ rm -rf target ; RUST_COMPILER_RT_FOR_PROFILER=/home/martin/src/llvm-project/compiler-rt RUSTFLAGS="-Cinstrument-coverage" cargo +nightly build --release -Zbuild-std=std,profiler_builtins
error: `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]`
error[E0152]: found duplicate lang item `manually_drop`
    = note: first definition in `core` loaded from /home/martin/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-d453bab70303062c.rlib
    = note: second definition in the local crate (`core`)
```

With the fix the build succeeds:

```console
$ rm -rf target ; RUST_COMPILER_RT_FOR_PROFILER=/home/martin/src/llvm-project/compiler-rt RUSTFLAGS="-Cinstrument-coverage" cargo +stage1 build --release -Zbuild-std=std,profiler_builtins
    Finished `release` profile [optimized] target(s) in 45.57s
```

And we can check code coverage. My example program looks like this:

```rs
fn main() {
    if std::env::args_os().nth(1) == Some("write-file".into()) {
        std::fs::write("hello.txt", "Hello, world!").unwrap();
    } else {
        println!("Hello, world!");
    }
}
```

when the program prints to stdout:

```
$ LLVM_PROFILE_FILE=stdout.profraw ./target/release/hello-world
Hello, world!
```

we can see that `fs::write()` is not being used (note the `0`'s):

```console
$ /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -sparse stdout.profraw -o stdout.profdata
$ /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-cov show target/release/hello-world --sources /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/library/std/src/fs.rs --instr-profile stdout.profdata --color | grep -A 3 'pub fn write(&mut self, write: b
ool) -> &mut Self {'
 1357|      0|    pub fn write(&mut self, write: bool) -> &mut Self {
 1358|      0|        self.0.write(write);
 1359|      0|        self
 1360|      0|    }
```

but when we print to a file:

```console
$ LLVM_PROFILE_FILE=file.profraw ./target/release/hello-world write-file
```

the code coverage shows `fs::write()` as being used (note the `1`'s):

```console
$ /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -sparse file.profraw -o file.profdata
$ /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-cov show target/release/hello-world --sources /home/martin/src/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/library/std/src/fs.rs --instr-profile file.profdata --color | grep -A 3 'pub fn write(&mut self, write: bool) -> &mut Self {'
 1357|      1|    pub fn write(&mut self, write: bool) -> &mut Self {
 1358|      1|        self.0.write(write);
 1359|      1|        self
 1360|      1|    }
```
</summary>
bors added a commit to rust-lang-ci/rust that referenced this pull request Nov 24, 2024
…r=jieyouxu

Allow injecting a profiler runtime into `#![no_core]` crates

An alternative to rust-lang#133300, allowing `-Cinstrument-coverage` to be used with `-Zbuild-std`.

The incompatibility between `profiler_builtins` and `#![no_core]` crates appears to have been caused by profiler_builtins depending on core, and therefore conflicting with core (or minicore).

But that's a false dependency, because the profiler doesn't contain any actual Rust code. So we can just mark the profiler itself as `#![no_core]`, and remove the incompatibility error.

---

For context, the error was originally added by rust-lang#79958.
bors added a commit to rust-lang-ci/rust that referenced this pull request Nov 27, 2024
…r=jieyouxu

Allow injecting a profiler runtime into `#![no_core]` crates

An alternative to rust-lang#133300, allowing `-Cinstrument-coverage` to be used with `-Zbuild-std`.

The incompatibility between `profiler_builtins` and `#![no_core]` crates appears to have been caused by profiler_builtins depending on core, and therefore conflicting with core (or minicore).

But that's a false dependency, because the profiler doesn't contain any actual Rust code. So we can just mark the profiler itself as `#![no_core]`, and remove the incompatibility error.

---

For context, the error was originally added by rust-lang#79958.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants