Stream: platform development

Topic: ✔ Building zig and roc


view this post on Zulip Arya Elfren (Aug 14 2022 at 09:53):

I'm new to roc, I've seen quite a bit of the language and its documentation but not about the tooling and the platforms, so I have some questions:

I guess the main thing is that I want control over and knowledge of the build process.

I'd also like to know what a platform needs and how expensive transferring data between the platform and roc is.

I know these are lots of questions for a new language but I'm very excited and have been waiting and thinking about this for a while. I'd be happy to look through some examples or source code if that's all there is.

Thanks for the hard work!

view this post on Zulip Brendan Hansknecht (Aug 14 2022 at 16:06):

Yeah, Roc linking can definitely do a bit of magic. This is to generally make life simpler for people. That being said, I have link Roc for running on an embedded device and had to do it manually. It isn't that bad, but if you can avoid it, I would advise allowing for Roc to just deal with it.

view this post on Zulip Brendan Hansknecht (Aug 14 2022 at 16:07):

Anyway, let me try and answer the individual questions

view this post on Zulip Brendan Hansknecht (Aug 14 2022 at 16:35):

If I extract the files (main.roc, platform/main.roc, platform/platform.zig) from examples/platform-switching/zig-platform and run roc run main.roc I get a compiler bug that wasn't there before (panicked at 'called \Result::unwrap()\` on an \`Err\` value: Any { .. }', crates/cli/src/build.rs:288:46`)

There was a failure to rebuild the zig host, only looking at this error message, it is quite hard to tell why. Based on what you said here, I think it should work, but it is hard to tell what is the issue. Would be useful if you can post and issue to the repo with more details.

How would I build a roc file from a build script? and how does it compile the zig code? can I compile the zig code myself and then statically link them later?

roc build --no-link will output a .o file. That can then be consumed by zig as any other .o would be. So you could use ar rcs roc_app.a roc_app.o to convert it into a static library. Then zig can use it like any other static library.

Is there a way of not generating the dynhost, libapp.so, metadata, preprocessedhost, zig-cache, and executable in the src directory?

There is no config for this to my knowledge. We need to add that, or at least put most of them in a hidden folder or something.

In the platform.zig file it imports builtin and str, where from? can I import them into my code from build.zig myself to compile separately without the roc (build|run) doing everything?

This is a convenience that long term should probably go away. Since our builtin functions are written in zig, we have just directly reused them when building zig hosts. A stripped down version of those files tailored for host use need eventually be built into a zig library/package that would get imported by the zig hosts. We have a proper package for the Rust platforms, but the zig platforms reuse our builtins directly. The files live in crates/compiler/builtins/bitcode/src/. If you were building a zig host a different way, you probably would just copy those files over.

I guess the main thing is that I want control over and knowledge of the build process.

You can get it, but Roc is made to hide that away (at least to some extent). Though a lot of the setup today is at least partially hacked together. Long term, we definitely want platform authors to have more control over how their platform gets built.

I'd also like to know what a platform needs

The platform story currently is not the cleanest. Decent parts of it plan to change long term (mostly around giving platforms more ability to control building/linking, and automatically generating a lot of the API the platform must fulfill). I thought we wrote a doc on the basics of platform dev, but I can't find it at this moment. I would advise building off of existing platforms currently because it leaves less to figure out. The general story is that the platform needs to provide roc with a few special functions roc_alloc, roc_realloc, roc_dealloc, roc_memcpy, roc_memset, and roc_panic. It also needs to provide roc with a function for every effect it can call (roc_fx_*). Lastly, it has to actually call into roc functions when it needs to use them (with some extra complications around closures). All of this is doable manually, but some parts can get painful. Hopefully our bindgen commands will eventually generate most of this for you (at least the function headers/apis).

how expensive transferring data between the platform and roc is.

As expensive as a non-inlined function call (basically free) with the caveat that Roc expects certain types. So if you have a zig string and want to pass it to Roc, you have to convert it into a Roc Str.

view this post on Zulip Brendan Hansknecht (Aug 14 2022 at 16:36):

please feel free to reach out with more questions or for follow up. We are glad to help people build platforms. I think Rust is probably the easiest language to build complex platforms in currently (first bindgen target so more stuff is automatic), but for testing Roc out, any language should work.

view this post on Zulip Arya Elfren (Aug 15 2022 at 13:57):

Brendan Hansknecht said:

Yeah, Roc linking can definitely do a bit of magic. This is to generally make life simpler for people. That being said, I have link Roc for running on an embedded device and had to do it manually. It isn't that bad, but if you can avoid it, I would advise allowing for Roc to just deal with it.

I think having simple defaults is great, but as long as it's possible to change things if you need to.

view this post on Zulip Arya Elfren (Aug 15 2022 at 13:59):

Brendan Hansknecht said:

roc build --no-link will output a .o file. That can then be consumed by zig as any other .o would be. So you could use ar rcs roc_app.a roc_app.o to convert it into a static library. Then zig can use it like any other static library.

That's exactly what I needed! Thank you.

view this post on Zulip Arya Elfren (Aug 15 2022 at 14:00):

There is no config for this to my knowledge. We need to add that, or at least put most of them in a hidden folder or something.

Well it looks like if I do --no-link it doesn't make those files so it's a lot more manageable.

view this post on Zulip Arya Elfren (Aug 15 2022 at 14:06):

Otherwise the rest is perfect! Thanks.

With that I've made a rudimentary zig buildStepthat means I have

    // ...
    exe.addObjectFile("zig-cache/roc/rocLovesZig.o");
    // and
    const roc = RocBuildStep.create(b, "rocLovesZig");
    roc.setBuildMode(mode);
    roc.install();

Which currently copies all of the files into a cache directory, compiles it into a .o, then links it. It's slightly hardcoded right now but I'd love to get it out to a build library so that anyone can just add a roc file in a build.zig and have it "just work" (including caching etc...).

I also just copied over the builtin zig definitions but I'd like to make that a package too.

Anyway, I got it to do:

$ zig build run
rebuilding host...
// ...

Roc <3 Zig!
runtime: 0.000ms

view this post on Zulip Notification Bot (Aug 18 2022 at 10:46):

Arya Elfren has marked this topic as resolved.


Last updated: Jul 06 2025 at 12:14 UTC