Hacker News new | ask | show | jobs
by berkut 1639 days ago
One of the things I really find limiting in Rust compared to C/C++ is conditional compilation, i.e. for different architectures: yes, the C/C++ pre-processor does suck in many ways and is masochistic if you're not careful, but it's also incredibly flexible.

Conditional compilation in Rust can be done per module, so in theory you can have different archs in different .rs files, each imported conditionally, but that then seems to mean duplication of things like structs, method/function signatures in different implementations, which is pretty annoying in many cases (i.e. you'd just want the inner bits of functions to be different, or optionally call certain subsets for certain archs). You can abstract some of this to 'common' modules to a limited degree, but not much in my experience, and that comes with additional 'plumbing' complexity anyway.

Rust has cfg attributes, and the cfg_if crate which in theory is a bit closer to the pre-processor functionality (and to a degree allows nesting/cascading like in C/C++), but in my experience these are just as annoying and limiting but in different ways: it's a macro, which is annoying in other ways (needs braces, has some issues with formatting, etc).

cfgs also seem to be exclusive, so I've found it incredibly messy getting a balance right between code re-use for common parts (i.e. function/method signatures) which need to be shared by multiple cfgs, and duplication.

Maybe I'm missing something?

4 comments

I just checked. You can also add those same conditionals to functions and structs. So you don't have to in- or exclude whole modules. You can even use it in an if-statement, as seen in the example main function on the page I linked.

See here: https://doc.rust-lang.org/rust-by-example/attribute/cfg.html

Yes, but now try nesting or chaining them...

It's do-able with cfg_if crate macro, but I really don't think much of the result in many complex situations, compared to what can be done in C/C++.

Also, using the cfg! macro (which you need to do to use it in logic) I think is stripped out at link time (I had all sorts of issues with this), so if you've got intrinsics which don't compile on the current platform, that's not helpful (maybe I did something wrong here, but I've googled it a lot, and asked for help several times on the Rust Discord server).

That’s trivial to do with cfg-if and similar crates.

There are many Rust libraries that support dozen different hardware architectures using conditional compilation.

Rust has many pain points, but conditional compilation isn’t one.

What ever weird constraint or desire you have, a macro would solve it nicely for your case.

It's do-able, but you seem to have to go out of your way organise code or modules in sub-optimal ways to compensate in many cases.

Most of the crates which I've seen which do that kind of thing in my experience seem to use features or conditional modules, which as I've discussed above have other downsides. Others like Vek seem to just get LLVM to do the work.

I think that's a bit disingenuous: I've certainly found Rust's infrastructure in this area quite limiting and a pain point for myself.

Conditional modules are a nice solution to this problem.
There are many examples out there of ways to deal with conditional compilation in Rust, and I find it much more straightforward and simple than my own personal experience with C.

Take a look at the socket2 crate as a nice way to deal with different platforms.

The rule of thumb I would use is encode logic as much as possible into traits, and then abstract out specific arch details like fields etc. You can combine conditional compilation units with trait based support as well to reduce the annotations and instead provide functionality only for types that implement certain traits.

Are you able to provide a barebones specific code example (either in C/C++ or Rust) of the issue(s) you're describing (e.g. nesting/chaining) where Rust conditional compilation is limiting?

A specific example is likely to lead to a more educational discussion in terms of learning about a solution to issues that you've observed or highlighting currently unsolved issues with Rust's implementation.

Either of which would be valuable.

> yes, the C/C++ pre-processor does suck in many ways and is masochistic if you're not careful, but it's also incredibly flexible.

Why not just use it as-is for Rust ? There are plenty of non-C/C++ things which use cpp. X11 uses it for config files (.Xresources for instance afaik). I think that polkit or something like that uses it too for its config files. I've seen it used in Java.