I think my approach would be to move things in steps over to Rust instead of just trying to rewrite everything. For example the Plugins for the debugger uses a C API (not C++) in order to make it easy to interface with other langs so I can perhaps move some of that over first.
Now would it be best to.
Move away from Tundra to use Cargo for everything. What worries me a bit here is incremental builds which are very fast in Tundra (uses Lua for config and C++ for building)
Add Cargo support to Tundra.
Skip Cargo and focus on just using rustc and have it as a "regular" compiler for the rest of the C/C++ code.
If anyone else has done something similar I would love to hear about which approach you have taken and the pros and cons with it.
If you move to cargo, you can split up your project into many small crates to retain incremental building. You can slowly move to cargo by using build scripts to call into you regular build system.
One issue with #3 I ran into recently: Cargo projects tend to play nicer with tools like multirust, because dependencies get compiled into a per-Rust directory. I recently used a Rust project which used plain old make, and thought I found a Rust bug when I switched between nightly and stable, causing a crash because the project put dependencies in its own deps/ directory...
Thanks. Good to know for sure. I think the approach of having Cargo calling my other build system and then work from there is the approach I will try to take as suggested by @oli_obk
Cargo looks alike package system, not a comprehensive build system. Don't forgive you can use rustc directly from other systems like Tundra. In our projects we use Cargo for builds Rust only, Erlang parts we build with Rebar, C parts and whole project with SCons. Sounds excessive, but not a problem.
Some time later we'll rewrite many parts with Rust, because we plan it. As example, we've test Rust a reimplementation of our Erlang's service now. It works 9x faster, and we'll drop Erlang's part, I think. But the main reason is not a speed. Rust has more active community with fast developing external libs. We can solve more comlicated tasks with Rust. That's a reason. But some things changes too fast and sometimes it would be better to rewrite project fully from scratch, because you can take advantages of many cool language features and follow the rapid improvements.
Do you then have some "master" script that builds all the various parts (calls Cargo, Rebar and SCons) and how do you deal with dependencies between them?
You have a great point about features and such. I think I will start with rewriting some plugin in Rust. The good thing is that the plugins are quite standalone in my project while it still needs to talk with C code (I also still want to keep that to allow other langs for plugins in the future)
I don't have shared example of a build scripts, but we use similar like:
# SConstruct example
import os
cargo = Builder(action="cargo build", chdir=1)
# and another builders
env = Environment(
ENV=os.environ,
BUILDERS=dict(
Luac=luac,
Jade=jade,
Less=less,
Cargo=cargo,
Rebar=rebar,
)
)
RUST_SOURCES = ['src/main.rs']
env_cargo = env.Clone()
env_cargo.Cargo('target/debug/program', RUST_SOURCES)
SCons is never forget how-to build system ) It's automatically check file's versions and never build twice.
Some builders we've implemented internally as SCons extensions.
To resolve external dependencies we use Bower, Rebar, etc. with bootstrap shell script. It also possible to implement as build routine, but we decide never mix it. Cargo do it (deps and build) automatically. It's a nice bonus which works fine.
In another words: dependency resolving is a task for package managers, testing for test tools, assembing for build systems, deployment for devops toolchain, benchmarking for another tools. Cargo has an one button for the multiple of this tasks, but It's Rust oriented: test, benches, etc.
I think for native or system projects like your Cargo will be a deliverance
Brining this back to life as I have started to look at this.
I have it up and running now using Cargo that builds my main project and some plugins and that all works fine. The main project also has a build.rs which kicks off tundra to build the native code. Now some issues.
It seems that Cargo 'eats' all the std output from Tundra. Is there a way to disable that?
If I change some native code and do cargo build I want it to build all the native code again. Is there some way to tell Cargo to always execute build.rs? (Or can I fool it is some way)
Right now I worked around the problem by having the bash script calling the tundra build step first and then Cargo to build the Rust code. I think that should work fine as most people will use that script when building anyway.
Yeah that is what I currently use but it really doesn't work the way I want it.
It depends on a dynamic lib which actually isn't built correctly and it generates a file in deps/ but the actual dynamic lib isn't built (or at least now written to the output directory) but if I got to "foo/bar" and do cargo build there it builds it correct (and generates the dynamic lib in the correct directory)