I just noticed the CLI flag to build your Roc app as a C library - that sounds cool! I don't remember that from Roc marketing or training materials, though. Could we build Zig libraries, too? Rust? (Context: I'm uninformed on most low-level language stuff)
That probably doesn't mean what you think it means. You mean --lib
, right? IIRC, that just builds a dynamic library.
It talks c abi. Which is probably why it says a c library, but it really is just a standard dynamic/shared library
It can be loaded by zig or c or rust and talked to with cffi like normal
We are not emitting c or anything.
Ah, yes, I did not envision it outputting uncompiled C source code. However, I maintain that this is super cool and (maybe) undersold in Roc's story!
So far I've envisioned Roc as a valuable tool for any teams who want a lang upgrade or simply want to script/control an existing engine... but this opens a third category of use cases - incremental Roc-ification of a codebase!
It sounds like one could have a dozen product features implemented in Rust/Zig/C and decide to implement the 13th feature in Roc???
I mean it really is no different that current Roc really. It would be the exact same api. It just lives in a dynamic library instead of being surgically linked into the host.
I guess a tad more dynamic
My realization is that Roc doesn't have to own the entrypoint/callsite
/executable
What do you mean?
Roc currently doesn't own the executable entry point. It is defined in rust or zig or c
I guess we tend to currently have roc control the build process, but that isn't required.
It sounds like we could take an existing codebase that doesn't use Roc, sprinkle some Roc goodness on it, and continue to run the service/product the same way (same entrypoint, same executable build pipeline, same everything external/interface-y) but with part of the compiled code sourcing Roc
In my opinion, this is a massive boon for Roc's adoptability
I guess? We also can emit a .o
file. Which is probably better than a library in most cases
I've never used Lua, so maybe analogies to Lua were supposed to elicit this realization earlier for me
But yeah, long term, platforms should have more control on specifying the build process. That will likely help a lot. The current situation is all manually hacked into the compiler. When I targeted a microcontroller, I just used the .o
file and an external build process
Is there precedent for this style of language interop? All of cffi maybe, which I never looked into? All of these JVM-based FPLangs like Scala?
I'm not sure I understand these questions.
Can an existing Rust codebase call any compiled Roc app though not import from it?
I might need to watch some videos on what cffi and .o are
I'm coming from an understanding that scripting languages call systems languages, not the other way around.
This breaks that distinction for me, in a very promising way :D
When using the dynamic lib or .o
, must of the rust code would not change. It still needs to define all of the roc_
functions. It also needs to define all of the headers to know how to call roc code. Roc require bidirectional communication
(Note: I've known that Roc apps are actually called by Roc platforms, not the other way around at all. However, I assumed that Roc platforms could call same-lang codebases but not the other way around, due to a crude understanding of executable entrypoint.)
Ah, so an existing codebase would need to do the minimal enhancements required to become a Roc platform?
That helpfully erodes at my idea of Roc platforms being codebases focused on Roc... rather than just codebases that happen to have implemented the adaptations necessary to call Roc
Your last comment hits the nail on the head. For example, you may work on a game and just use Roc as a scripting language, but you still implement an entire game. This is super specialized and would be fine without roc. Roc is just a nice addition.
Let's see. The best way to think about this is probably to just consider Roc another package/library in the host language (even though it clearly isn't).
It is a package with a really weird api that imports a few functions (roc_alloc
, roc_memcpy
, ..., roc_fx_DoSometing
) and exposes a few functions roc_main_for_host
, etc.
Yes, but critically, adding Roc doesn't make your codebase Roc-y and it doesn't create a scoped Roc zone that can't benefit existing code elsewhere
The first example I heard about game dev was that devs could add a scripting language for game players/modders to use... but that didn't make me think that the game developers might want to refactor some of the game engine into Roc for maintainability or stability/security reasons
So, following that simplification, if Roc is basically a Rust/Zig/C library... then a Roc app is basically a particular single data transformation plugin that the library can perform for a Rust/Zig/C codebase?
If a Rust codebase calls 3 different Roc apps, will it need 3 "really weird api"s?
It would be, but roc can also call effects. That enables it to do more than just transform data
True, I suppose the Roc app is a data transformation but the Roc "library" uses the result of that data transformation to call effects on behalf of the codebase
Also, roc is really not made with the idea of using multiple apps, though since they are just object files, I guess you could. You would probably have to be careful around name conflicts
But yeah, you would need to define all effects expected from all roc apps. Though you would only define things like roc_alloc
once.
Also, you would have to deal with all the function calling code, but in the future hopefully glue will generate most of that
I suppose it'd be easier to either have the main function switch on a tag or expose a record of functions, rather than using multiple apps
Also, long term, roc should be able to expose multiple function directly rather than through main
To summarize, any existing Rust/Zig/C(/C++?) codebase can add a few specific IO/memory-related (effect-related) functions and start adding new business logic features in Roc instead of in Rust/Zig/C (or refactoring old business logic into a superior language for it)
#BigIfTrue
Yeah
That enables such a clear incremental adoption/upgrade/refactor story
Haha :joy: you make it sound so simple
Hahahaha
yeah check out examples/ruby-interop
- that incremental adoption thing is how we're working on using it at work!
How simple can step 1 become? Can we create+publish+maintain libraries/codegen for that "setup step" (platformification) to become trivial? Is it already trivial by virtue of it requiring only copy/paste of less than 50 lines of code?
I don't know how Rust/Zig/C/Ruby libraries work, but a two-liner like
import Roc
Roc.initializePlatform({ ... })
would be super cool
The goal of roc glue
is to make that step trivial!
Last updated: Jul 06 2025 at 12:14 UTC