This is a branch off from the discussion here.
tl;dr - making sure the nice benefits of building with roc also apply when you build with an actual build system would be really good down the line.
I wish for Roc to be as ready for a polyglot/multi-language world as it can be, and Roc is well on its way already of course! Platforms make it entirely plausible for a normal Roc project to actually be polyglot, where you do development on your platform and Roc code in tandem. Or a Roc codebase may just be part of a larger project that all need to depend on one another in various ways (microservices for example). The roc binary is made to work great for single Roc applications or libraries, but it's not a full build system, and we wouldn't want it to be either.
So my rough proposal is to have a very explicit cut off for when you stop using roc alone, and sending users off on a blessed path towards a proper build system when they need it to go beyond roc. For example by having an official rules_roc package for Bazel (which is basically as good as build systems get today), or having a proper guide for setting up roc with make for example (if people find make less daunting than Bazel).
There are multiple benefits to this:
roc capabilities is good.roc. Users probably expect some features to be present (as node or cargo has for example), so would be nice to be able to tell them what to do instead.roc actually plays well with external build systems.Aside from just documentation, the important thing here is that roc should be ready to integrate into something like Bazel. For example, Elm works very well alone, but it was painful for us at work to make it integrate with Bazel, because Elm's command for building code also fetches dependencies. But in Bazel, any build step is generally sandboxed, and relying on network traffic like Elm does, means setting users up for pain. You need to be able to supply dependencies to the compiler without going over the network.
Bazel also does its own caching, meaning it discards caches that roc would build on its own. So without a good Bazel integration, users may be set up for slow(er) build times in Bazel. It would be nice if moving from roc to a proper build system didn't mean degrading the experience, such that the build system is just a natural layer on top of roc.
I know very little about bazel but it does sound like a good idea to make Roc play nice with it. I think @Brendan Hansknecht is very familiar with bazel.
I have used bazel for many years and have a love-hate relationship with it. That said, I have only done very limited rule writing. So I'm not much help here.
Personally, I think a language built in build system is always way nicer than anything bazel could ever do. That said, if you require rebuilding the platform, then a roc project is a multi-language project and that is where bazel makes the most sense.
a pit of success
I have a hard time calling bazel "a pit of success". I feel that most of the time people get it wrong and are fighting it. It is very hard to wrangle and configure correctly. When it is setup correctly and well integrated with the tools used, it can be quite nice, but it is a lot of complexity that many people may not want to ever look into.
Like if I had a zig/rust platform and a roc app and regularly had to rebuild both, I would rather have two separate native build systems and a shell script than deal with setting up bazel.
Having said that, I do think we should try to integrate with bazel nicely. I'm sure some users will already have a bazel base. Then just adding a new roc submodule should be trivial and nice for them.
I think the kinda of things that would make Roc integrate nicely with Bazel would also let Roc integrate nicely with Nix, which is my preferred hermetic build environment (nothing against Bazel, just never tried it :sweat_smile:)
We can separate the two things here:
roc works well with external build systemsFor #1, I can't imagine anyone disagrees :D Whether it's Nix, Bazel, or something else, this is just good to have. The nicest way to achieve it, I think, would probably be to build a "real" Roc plugin for such a system, and either have it used by people on a regular basis or have it verified with automated tests.
For a blessed path, I would keep using roc for as long as it's feasible. A specialized tool is always nicer, so long as you are inside the confines that it the tool is made for. But I think it's common enough to do other stuff as part of building even monoglot codebases, that users would want to reach for something like integrated build scripts eventually. Or workspace management a la cargo, where you combine multiple Rust projects into one. Both of these I would personally keep out of roc, and defer to a proper build system instead.
And I would say that both scripting and Bazel are complex when you are building a complex project, but I would still rather have Bazel in that case. But for building a simple project, I don't think using Bazel is much more complex than scripting, other than you may know one better than the other beforehand. And I would still rather have Bazel in that case too!
But I think scripting tends to break sooner, because it's much more of a "works on my machine" situation. So despite Bazel being a bit more complex up front on small project, I think it pays off later to have started down the path of a proper build system immediately.
Note that I'm not a Bazel super user by any means either, and I also haven't tried Nix, so I can't say much about that. I'm just using Bazel as a substitute for "proper build system", and then Bazel is also well maintained, crossplatform, and so on and so forth, so it seems like as good a candidate as any.
Imagine that we had a convention in the community to build with Bazel when reaching outside roc. For example, if we both have an official Roc plugin for Bazel, and if all our basic platforms were built with Bazel, it would be quite easy to e.g. fork a platform and build it and your Roc code in tandem.
As far as non-specialised build systems go, I'd also see a lot of value in excellent build.zig integration (I vaguely looked into it 1-2 years ago).
Looking more at platform first development in zig, where you want tests of zig code in roc, most of your code is zig, or your primarily integrating with that ecosystem.
On a mostly unrelated front (rather than integrating build.zig, stealing from it) I think lots of the ideas there are perfect for this proposal:
--offline, which means you can split the build into fetch and sandboxedHere is a pretty comprehensive overview/suggestion of build system integration design for the Hylo programming language, which could be relevant for Roc as well, at least some of the points
https://gist.github.com/purpleKarrot/0abd4d9e55fc2f6b35fa33c69d63d9da
Nice! That’s basically a blueprint for great build system integration! :partying_face:
I think it is useful, but following those guidelines fully is very consequential for the programming language design itself, not just the CLI, so that needs to be considered. The listed language properties exclude most programming languages, including roc in its current form (?)
I know this is going back a long way... but can anyone tell my if the old rbt roc tool sits in a similar category to the above tooling?
https://github.com/roc-lang/rbt
Was the intent for the Roc Build Tool to basically be a nice way to configure builds
I've been looking at our CI a bit and what I'm really wanting is fine grained statistics on everything we are running... to help me track down issues and target the biggest problems.
we never got very far with that tool, prob not worth revisiting honestly
Something like rbt is also something I’m trying to avoid with this conversation. I think that it’s very tempting to build language specific build systems (many already exist), and I would rather that, if the roc binary is no longer enough to build your project, you step up to a “proper” build system. Good build systems are complex beasts which it’s better to not try and reinvent, but much better to play into what’s already there.
Last updated: Jun 16 2026 at 16:19 UTC