Skip to content

Conversation

@jonmeow
Copy link
Contributor

@jonmeow jonmeow commented Nov 6, 2025

  • Change the look-and-feel of the carbon compilation command set to use
    compile, link, and build.
  • Build library-to-file discovery for Core, but support it in a general
    manner.

Drafted in Docs

@jonmeow jonmeow added proposal A proposal proposal draft Proposal in draft, not ready for review labels Nov 6, 2025
@jonmeow jonmeow marked this pull request as ready for review November 6, 2025 18:45
@jonmeow jonmeow requested a review from a team as a code owner November 6, 2025 18:45
@jonmeow jonmeow requested review from zygoloid and removed request for a team November 6, 2025 18:45
@github-actions github-actions bot added proposal rfc Proposal with request-for-comment sent out and removed proposal draft Proposal in draft, not ready for review labels Nov 6, 2025
Comment on lines 57 to 59
Right now, `carbon compile` produces an object file per input file. This has a
few issues, for example when it comes to compiling prelude files: it's not clear
how to get a prelude `.o` file.
Copy link
Contributor

Choose a reason for hiding this comment

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

Also maybe worth calling out: we only support one --output-file per compilation, but always compile a file and all of its interface dependencies together, so we end up creating and then repeatedly overwriting the output file.

The upshot of this is that our carbon_library rule passes all of the carbon files to every compile, putting "the one it's building" last so that its object file is the one left behind as the --output-file after all the overwriting happens. And that means that our compile times are scaling quadratically with the number of files we build. Fortunately our builds are so fast that we're getting away with this, but it clearly won't scale, and is a cause of our -c dbg //examples/... builds being slow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adjusting/reformatting.

Additionally, the compilation setup doesn't work well with the prelude because
symbols don't get emitted for prelude files. Right now, we generally don't
notice this because the prelude has been implemented in a way that typically
doesn't require separate object files, but it will likely become an issue.
Copy link
Contributor

Choose a reason for hiding this comment

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

For what it's worth, this does work these days with the existing carbon_library rule, because it adds all the prelude files to the list of sources. Some of our examples depend on that. But as you mention in the next paragraph, that doesn't really apply to real-world build scenarios where it won't be easy to get a list of the prelude files and build them manually.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a note that carbon_binary has a workaround, but I don't think that's someone using carbon compile can make use of.

- Run the equivalent of `carbon link` over produced inputs.

While the build command will default to providing an executable `program`, we'll
also want it to be capable of producing `.a` and `.so` files.
Copy link
Contributor

Choose a reason for hiding this comment

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

@chandlerc I think you had some particular plans around .so files. Should we include or exclude them as possible carbon build outputs for now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm updating the doc to suggest that these be decided as an implementation detail instead of design. Like maybe we really want carbon build to be more demo-y, and .so files are a little too non-demo-y.

Comment on lines 206 to 211
- For `lib`, we'll delegate to `carbon build`:
- Examine the four files, and determine a compile order.
- Invoke the four `carbon compile` behaviors, producing a `.o` file.
- For `bin`, we'll again delegate to `carbon build`:
- Given one file, determine the trivial compile order.
- Invoke `carbon compile` to produce a `.o`
Copy link
Contributor

Choose a reason for hiding this comment

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

The phrasing here leaves me unsure whether we're invoking carbon build, or whether we're invoking carbon compile directly, or some hybrid such as running carbon build in a "tell me what you would have done" mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this is a mistake and doesn't reflect how we're likely to want to write this. Rewriting it all. :)

without relying on user decisions.
- This makes the `srcs` versus `apis` difference less meaningful.

Disadvantages:
Copy link
Contributor

Choose a reason for hiding this comment

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

Another disadvantage: once we have separate compilation to some kind of precompiled artifact, having all the files in srcs would mean the set of precompilation actions isn't knowable from just the build rules -- bazel would need to read the package / library declaration in the file to determine whether it's an impl file or not, and hence whether it produces a precompiled Carbon unit that downstream compilations might want to consume.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why is this the case? For a source file, the extension is either .carbon or .impl.carbon, and from that we can tell whether it's an impl file. For a precompiled unit, shouldn't there be some way to map between the source file it was built from?

inclusive of C++ code. Hopefully then people can learn that the new thing works
with both.

What's really missing is a better name for this than "carbon".
Copy link
Contributor

Choose a reason for hiding this comment

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

We could invent a name for the C, C++, and Carbon ecosystem, and then use that here. Just to throw out an idea, maybe the "CX ecosystem"? (as in, /C.*/) -- so cx_library, cx_binary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Per open discussion today, probably keeping with carbon_* and saying it's essentially the "carbon" ecosystem.

Copy link
Contributor Author

@jonmeow jonmeow left a comment

Choose a reason for hiding this comment

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

Per discussion, pulled out a lot of the Bazel mentions out separately and trying to avoid making design choices for it here. (trying to just use it for illustrative purposes)

Additionally, the compilation setup doesn't work well with the prelude because
symbols don't get emitted for prelude files. Right now, we generally don't
notice this because the prelude has been implemented in a way that typically
doesn't require separate object files, but it will likely become an issue.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a note that carbon_binary has a workaround, but I don't think that's someone using carbon compile can make use of.

Comment on lines 57 to 59
Right now, `carbon compile` produces an object file per input file. This has a
few issues, for example when it comes to compiling prelude files: it's not clear
how to get a prelude `.o` 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.

Adjusting/reformatting.

At the end, it should be possible to:

- Run `carbon build main.carbon` (or even just `carbon build`) with
non-prelude `Core` imports, and get an executable `program`.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

program was suggested by chandlerc:

https://docs.google.com/document/d/19UvmU0znIFDj32hMj7TvE_WkZ_zEHygQHfOiFELKiMU/edit?disco=AAABfcNoIWQ

I think saying get an executable `main` would also be confusing because "main" is also a term... I've dropped the backticks, do you think that's okay?

- Run the equivalent of `carbon link` over produced inputs.

While the build command will default to providing an executable `program`, we'll
also want it to be capable of producing `.a` and `.so` files.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm updating the doc to suggest that these be decided as an implementation detail instead of design. Like maybe we really want carbon build to be more demo-y, and .so files are a little too non-demo-y.

Comment on lines 206 to 211
- For `lib`, we'll delegate to `carbon build`:
- Examine the four files, and determine a compile order.
- Invoke the four `carbon compile` behaviors, producing a `.o` file.
- For `bin`, we'll again delegate to `carbon build`:
- Given one file, determine the trivial compile order.
- Invoke `carbon compile` to produce a `.o`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this is a mistake and doesn't reflect how we're likely to want to write this. Rewriting it all. :)

Comment on lines 379 to 380
- `apis` more clearly reflects the design intent of "API". `hdrs` is an opaque
naming choice for Carbon when considered independently of C++.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added the note.

without relying on user decisions.
- This makes the `srcs` versus `apis` difference less meaningful.

Disadvantages:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why is this the case? For a source file, the extension is either .carbon or .impl.carbon, and from that we can tell whether it's an impl file. For a precompiled unit, shouldn't there be some way to map between the source file it was built from?

Comment on lines 353 to 356
- Some other name for `public_deps`
- I'm not really sure `public_deps` is the best name, but it's my best
thought for something to reflect the transitive nature of API exposure
being proposed.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

See #6333 (comment), I think this is commenting about the same naming

inclusive of C++ code. Hopefully then people can learn that the new thing works
with both.

What's really missing is a better name for this than "carbon".
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Per open discussion today, probably keeping with carbon_* and saying it's essentially the "carbon" ecosystem.


Because we'll build this for Core, it would probably be straightforward to
expose this for other packages, too. So for example, we will support
`--package_path=MyPackage:/my/package`.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm hedging this mention a bit more, are you okay with that? I'd in particular expect any support along these lines to mirror Core... for example, maybe you still need to compile the package's files to produce objects, and link it; it's just pulling API files in an easy way (as it would for Core).

sounds a little fragile for an environment like bazel

I think it's too fragile for a fully hermetic environment. However, some users use bazel in a fully hermetic way, and others cut corners (e.g. we don't use a fully hermetic python in Carbon, but we definitely could).

For a fully hermetic setup where even Core is explicitly built through build rules, I would expect them not to use this feature at all. For something like carbon build and users just trying to do something quickly, or for someone using a slightly non-hermetic setup (perhaps custom bazel rules, or their CMake setup), does it make a little more sense to provide?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

proposal rfc Proposal with request-for-comment sent out proposal A proposal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants