Skip to content

Conversation

@chandlerc
Copy link
Contributor

Previously, the Clang runtimes building only considered building the target resource directory, and was only internally asynchronous. Because the asynchrony was only internal, it could use the function frame as a context object throughout the build of the resource dir. This is simple but doesn't generalize well to more runtimes: if we want to add 2 or 3 more runtimes, we want them to all build asynchronously. That means using some asynchronous builder that maintains the context and allows them to proceed concurrently with other work.

This also factors all the runtimes building code into a separate set of files. These aren't separate libraries at this point due to the ClangRunner in some cases wanting to build runtimes on-demand, but it at least lets us organize the code more cleanly.

Because this splits code between clang_runner.* and clang_runtimes.*, it also works to update the #includes for both to be roughly accurate. I used ClangD's include cleaner for this and it probably also did some latent cleaning as it went, but that's the reason for the churn of #include lines.

The archive building is also factored out into a re-usable helper. This is a bit "over factored" in this PR, but supports the next PR that uses the same code to build archives for other runtimes.

This also overhauls the synchronization used -- it uses a simple Latch construct introduced in a previous PR to coordinate between the steps of building the runtimes.

Last but not least, it factors the "enable leaking" state out of a boolean in the runner to a parameter. This is important in the face of concurrent calls as otherwise toggling this boolean can create a race.

The next PR will layer building more runtimes on top of this new factoring.

@chandlerc chandlerc requested a review from a team as a code owner November 16, 2025 11:09
@chandlerc chandlerc requested review from dwblaikie and removed request for a team November 16, 2025 11:09
Previously, the Clang runtimes building only considered building the
target resource directory, and was only _internally_ asynchronous.
Because the asynchrony was only internal, it could use the function
frame as a context object throughout the build of the resource dir. This
is simple but doesn't generalize well to more runtimes: if we want to
add 2 or 3 more runtimes, we want them to _all_ build asynchronously.
That means using some asynchronous builder that maintains the context
and allows them to proceed concurrently with other work.

This also factors all the runtimes building code into a separate set of
files. These aren't separate libraries at this point due to the
`ClangRunner` in some cases wanting to build runtimes on-demand, but it
at least lets us organize the code more cleanly.

Because this splits code between `clang_runner.*` and
`clang_runtimes.*`, it also works to update the `#include`s for both to
be roughly accurate. I used ClangD's include cleaner for this and it
probably also did some latent cleaning as it went, but that's the reason
for the churn of `#include` lines.

The archive building is also factored out into a re-usable helper. This
is a bit "over factored" in this PR, but supports the next PR that uses
the same code to build archives for other runtimes.

This also overhauls the synchronization used -- it uses a simple `Latch`
construct introduced in a previous PR to coordinate between the steps of
building the runtimes.

Last but not least, it factors the "enable leaking" state out of
a boolean in the runner to a parameter. This is important in the face of
concurrent calls as otherwise toggling this boolean can create a race.

The next PR will layer building more runtimes on top of this new
factoring.
llvm::fmt_consume(obj_result.takeError())));
}

// Unlink the object file once we've read it. However, we log and ignore
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe say why we're unlinking the file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, done.

}
}

result_ = (*std::move(runtimes_builder_)).Commit();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
result_ = (*std::move(runtimes_builder_)).Commit();
result_ = std::move(runtimes_builder_)->Commit();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

weirdly, I don't think this works. Because Commit needs its LHS to be R-value qualified, and you can't do that with the overloaded operator-> (which has to return a pointer), but you can with operator* (which can return an R-value ref or by-value)... =[

return Success();
}

std::scoped_lock lock{obj_dirs_mu_};
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there some convention for () v {} in ctor init in Carbon? Usually I expect to see () for ctor calls (or = x if the ctor's implicit).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The usual Google style guide conventions -- for some reason I thought this hit the vexing parse and needed {}s, but it doesn't. Switched back to ()s.

Copy link
Contributor Author

@chandlerc chandlerc left a comment

Choose a reason for hiding this comment

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

Thanks for the review! I think all addressed so merging. Lemme know if you'd like any follow-ups.

}
}

result_ = (*std::move(runtimes_builder_)).Commit();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

weirdly, I don't think this works. Because Commit needs its LHS to be R-value qualified, and you can't do that with the overloaded operator-> (which has to return a pointer), but you can with operator* (which can return an R-value ref or by-value)... =[

return Success();
}

std::scoped_lock lock{obj_dirs_mu_};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The usual Google style guide conventions -- for some reason I thought this hit the vexing parse and needed {}s, but it doesn't. Switched back to ()s.

llvm::fmt_consume(obj_result.takeError())));
}

// Unlink the object file once we've read it. However, we log and ignore
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, done.

@chandlerc chandlerc enabled auto-merge November 18, 2025 04:34
@chandlerc chandlerc added this pull request to the merge queue Nov 18, 2025
Merged via the queue into carbon-language:trunk with commit 77808cd Nov 18, 2025
11 of 12 checks passed
@chandlerc chandlerc deleted the push-uxkynytsypqq branch November 18, 2025 06:28
chandlerc added a commit to chandlerc/carbon-lang that referenced this pull request Nov 18, 2025
The review of carbon-language#6380 suggested an expanded comment that I wrote but
apparently didn't hit "save" in the editor for. Doh! This adds it.
github-merge-queue bot pushed a commit that referenced this pull request Nov 18, 2025
The review of #6380 suggested an expanded comment that I wrote but
apparently didn't hit "save" in the editor for. Doh! This adds it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants