Hey everyone, I'm a computational physicist and have been working with C and Rust on molecular and Brownian dynamics simulations. I'm a big fan of Rust, especially for its memory safety over C.
Right now, I'm tackling a big project: converting openmm from C++ to Rust. It's a huge repo and I know it's going to be tough, but my biggest hurdle is figuring out how to start this whole thing.
There are tons of classes and methods in openmm, spread across many files, and I don't really get their structure or how they depend on each other. Setting up the crate structure seems crucial, so any tips on that?
Also, is there a good tool for mapping out the dependency tree of a big C++ repo? I’m trying out cflow right now. And what’s the big difference between Rust and C++ in terms of structure? Is it better to go class by class, or should I rethink the whole dependency setup?
Any advice to get this project rolling would be awesome.
There is no such thing as the proper structure of a large program. It always depends on what the code actually is.
Therefore, be prepared to change the structure as you develop. Move items and create modules (or crates) as needed; as you discover that a module is too big — or too small — or just doesn't make as much sense as you thought previously.
Or did you mean “how should I arrange my files to create the project at all?” To that, I say: Cargo and rustc has defaults. The first rule for starting a project is to not gratuitously override the defaults. If you find yourself writing a path = "foo.rs", don't unless you know exactly why there is no other option.
It is very often the case that Rust requires (or prefers) a different organization of data into types than C++, particularly when the C++ types involve e.g. pointers to a “parent” object. You should be prepared to encounter such differences and adjust as you go. Therefore, try to approach the problem at first as a slice of functionality, rather than per class: translate enough code at enough layers of the system to actually use the library for a toy problem, see whether you had to make any structural changes, and use that to inform how you work on the rest of the library.
There are also likely to be cases where something that is a single class in C++ is most naturally several structs in Rust, or vice versa — an entire class hierarchy might be replaced with a single enum.
I knew there were no shortcuts, but I thought I'd ask just in case. It seems like the best strategy to start with right now is to move things over one functionality at a time and update them step by step. Thanks.
Lastly, when organizing C++ code by functionality and checking their dependencies to determine the minimum range to migrate to Rust, is there any tool other than something like cflow + dot? Cflow automatically finds the main function and creates a tree with that function as the root, but I just want to obtain a calling graph from the perspective of the library.
I'm not doing this for any commercial purpose or with a clear utility in mind. MD (Molecular Dynamics) is a tool widely used in my field of study, and creating an MD package by linking the functions I use while working with Rust has been my personal project so far. However, as it turns out, there are limitations in terms of efficiency and functionality implementation, so my intention now is just to learn by porting an already well-developed project for personal study.