-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
cargo or go build alike cross platform build support #1544
Comments
While build systems, and especially as you say good cross-platform self-contained build systems, are a huge area of interest for me personally, I don't think this is really in-scope for the Carbon project. At a very high level, a principle that we have talked about but not yet codified is the idea that Carbon really needs to work with existing C++ build systems rather than trying to provide its own, replace them, or convince everyone to converge on any one build system. We should probably codify this somewhere though and make sure everyone is aware and aligned on that direction. |
That's unfortunate, I actually feel a self-contained build system is what modern c++ needs the most and where go|rust really had some advantages ,i.e. the so-called modern build environment(cargo, go build). Changing some syntax etc alone is not an upgraded c++ to me, if you truly put developers first then toolchain shall be part of the priority. I honestly lost 95% of the interests about carbon now. |
I agree with @chandlerc that Carbon should aim to work with existing build systems. Creating a custom build system for Carbon is not only a very significant, non-trivial undertaking but also makes it a lot more difficult to integrate into large source trees containing code in other languages. C/C++ interop with other languages is a common practice. There are many use cases where C/C++ code is wrapped so that it can be called from other languages such as Python or even Java (via JNI) where the performance of native code is necessary. Many existing build systems are already cross-platform. Bazel and CMake are both available across Linux, macOS, and Windows. I think that in terms of the Carbon developer experience, it is more important to make sure that setting up build files for Carbon code is easy to do with the existing build systems, especially given that one of Carbon's main goals is to seamlessly interop with, and thus integrate into, existing C++ codebases. |
From the official goals:
Doesn't a better build system contribute to this? |
With how many build systems there are out there, especially those used by C/C++ projects, I think that creating Yet Another Build System isn't really the right route. One of Carbon's primary goals is interop, and I think creating a custom build system for Carbon works against that goal. Personally, I have used many different build systems, and Bazel is the only one I have used where I did not feel like I was fighting with the build system all the time. I find that it is much easier to understand all the dependencies between different parts of the source tree with Bazel since all dependencies are explicitly specified. The fact that Bazel builds are fully reproducible and incremental also means you never have to do a 'make clean', which I always had to do with every other build system I've used. Given that it is also designed to be extensible to any language means that it is as close as a universal build system as it gets. |
"With how many build systems there are out there, especially those used by C/C++ projects", this, is one of the biggest pain point for c++. We had way too many options, and none really did what cargo/go-build/zig can do already: self-contained cross-platform(some OS-layer in the library makes that possible). Carbon will attract lots of followers if a true modern build tool becomes one of it goal, which will make creating cross-platform packages a solved problem as well. Otherwise, it just kind feels like a half-baked Rust-for-c++ to me without Cargo, what's the point to use it then. |
The main differences between C++ build systems and these other build systems boils down to two points: A Carbon build system cannot completely reproduce this, due to the huge focus on C++ interopt. But we can make a list of requirements: Maybe one does not need to invent a new build system but rather just bless ONE simple C++ build system maybe in an adapted fork. |
Speaking as a maintainer of a general-purpose build system (in this case, Meson), I'd like to interject with a couple thoughts on build systems. ... What is the plan for supporting project components that aren't written in any programming language at all, but still need to be built? Data files, man pages (asciidoc, help2man, xslt transformations, etc), etc. What about installing static resources to GNU directory variable locations? Default config files, icon themes, mimetypes, manpages again? And of course as mentioned above, many projects need to build code in multiple languages. All these things cry out for, if not a general purpose build system like meson/cmake, then at least the ability to comfortably invoke one build system from another. This is something that both rust and go completely failed at. Rust doesn't have a general purpose build system, and AFAIR this goes hand in hand with being totally unable to install anything anywhere (you cannot even install binaries to /usr/bin in a Linux distro packaging recipe, let alone a cdylib). What you can do is write a build.rs which then open-codes your own build system to run subprocesses that perform tasks, and then dump their output in a mysterious hashed directory deep within cargo's private data. You then get to do unguided pattern matching or Go is in a bit of the same situation, except that it only builds binaries and from what I've seen, people usually then write the simplest homemade build system they can -- Makefiles that call go cannot tell Make (or ninja) when it's necessary to reinvoke Supposedly cargo build plans were supposed to describe the build rules sufficiently that e.g. Meson could then merge cargo's build rules into a build.ninja file and track build edges itself, figure out when rebuilds are necessary, and generally drive rustc as part of a larger superproject. Cargo build plans were apparently broken on arrival, no one really uses them, no one cares about them, they are deprecated, and will probably be deleted. Cache busting of course doesn't work well (especially when the language package manager stores tons of files in arbitrary locations in $HOME instead of the designated build directory). Every programming language wants its own build system, then reinvents the mistakes of the past, only concerns itself with the need to build single-file executables, and fails to implement basic functionality like installing it after you build it. It would be good if carbon could avoid that. This doesn't have to mean that carbon totally eschews having its own native build system, but whatever solution is chosen, it should at least:
|
The issue here is one common problem encountered, when compiling a language that doesn't use header files to share information between dependencies (which will also be true for Carbon): Compilation of upstream compilation units is blocked on metadata generated from compiling downstream ones. These metadata are usually generated halfway through the compilation process. There are 3 solutions here: As far as I know, ninja is currently only capable of modeling strategy a) and b), but not c). Strategy c) is used by cargo, as initial phases of the compilation are often relativly expensive, e.g. due to macro expansion. This might also be a reason, that alternative build systems have a hard time here, as they would immediatly feel a perfomance penilty. |
I think Bazel (which builds the Carbon codebase) could be a good contender for this since it fulfills nearly all of the use cases that @eli-schwartz mentioned in his comment. Bazel is as close to a universal, general-purpose build system as it gets. It is not only used to build Google's entire O(billion) LoC codebase, but also has a vast ecosystem and external adoption:
I think Bazel would also resolve some of the concerns that @nacaclanga described. The way Bazel solves this is by requiring all dependencies to be explicitly listed in
Though, there are some challenges of using Bazel for:
Installing FilesThis is the simplest of the problems to solve. Bazel does not have built-in support for is making any modifications to the source tree or outside of it, but this is by design due to its design goal of being completely hermetic and reproducible. However, it is not difficult to implement this functionality using custom verbs for installing files onto the system. To make this easy, we could implement a build rule that would generate the necessary scripts (perhaps a macro that wraps a genrule and an sh_binary) that would handle installing artifacts on the system: carbon_library(
name = "bar",
srcs = ["bar.cb"],
deps = [
":base",
":util",
…
],
)
carbon_binary(
name = "foo",
srcs = ["foo.cb"],
deps = [
":bar",
…
],
)
carbon_install(
name = "install",
default_prefix = "/usr/local",
binaries = [":foo"],
libraries = [":bar"],
) Then, running External DependenciesBazel has support for pulling in external dependencies, though it has been somewhat similar to the current state of external dependency support of CMake. One main challenge with external dependencies is that many external dependencies use other build systems. This results in some pain points, such as projects needing to write their own BUILD file for the external repository (for example, see Tensorflow’s Though, people have written a number of external repository rules for interfacing with different package and artifact management systems, such as for Maven artifacts (see the Maven category on Awesome Bazel) and rules for Cargo Crates in the Bazel Rust rules. Recent developments such as bzlmod, the new external dependency management system for Bazel, could potentially make this easier. If Carbon standardizes on Bazel from the beginning, then I think implementing external dependency rules for Carbon packages, including support for transitive dependencies, could become a lot simpler than the status quo of C++ projects and be much easier to use. Integration With Other Build SystemsThis is touched on above. Integration with other build systems is currently one of the pain points, especially with bespoke language-specific build systems such as those for Go and Rust. The Go rules contain a significant amount of complexity and workarounds due to In terms of getting Carbon projects built with Bazel to work with repositories using other build systems such as CMake and Meson, one potential solution is to create tooling that would analyze the Bazel build graph for a Carbon project and generate build files for these other build systems if migrating these other projects to Bazel is infeasible. Though, this would require a wider discussion and would also involve members of the Bazel team, but this should certainly be made much better than the status quo. Even if Bazel does not end up being Carbon's standard, official build system, these problems will still nevertheless need to be solved since there will invariably be many Carbon projects that use Bazel. If Carbon ends up with its own build system, I certainly agree that it should interface well with other build systems, including Bazel, both for building source code and managing external dependencies. |
Just gonna throw build2 into the mix. It should cover everything required & more, in a clean & structured way. Inspired by cargo among others. |
I'd tolerate rust learning curve complexity or go's garbage collector over carbon just because of the cross platform build system to be honest. It's a shame that this feature is not high priority in carbon. |
FWIW, I don't think there is really an issue to address here at this time. Our roadmap clearly lays out priorities and while we'd like to dig into build system & ecosystem problems eventually, we need to focus on the critical experimental work on Carbon first. Closing this as not-planned to avoid more distractions here. That said, just as a brief note:
I think once Carbon gets beyond the super early experimental stages, this may well become a much higher priority. =] I think the real point here is that Carbon is in a much earlier project stage than Rust or Go, both of which are mature and ready for business. =] |
if there is one thing needs to do better in c++, it's the cross-platform build, even better, a self-contained cross-platform build like GOOS for go build, so I can build on one and run on all platforms. Please make this a priority.
The text was updated successfully, but these errors were encountered: