Structuring a project that generates two similarly-named executables

I'm in the process of converting an existing project from C to Rust. The actual conversion is straightforward, and has resulted in code that's 10% of the size of the C version, more robust and easier to understand. So that's absolutely awesome :slightly_smiling_face: But one thing I'm having trouble deciding how to handle is the project structure.

My initial Rust implementation is a simple main.rs containing all the code, that builds project.exe. But my C code generates two executables, project.exe and projectw.exe, which are essentially the same but the -w version is a Windows GUI executable.

I can make this happen by writing a bin/projectw.rs containing a copy of the code from main.rs, plus an attribute setting to make it a GUI subsystem build. So far, so good. There's a lot of shared code, but I should be able to move that into a private module (I need to read up on modules, I've not used them yet, but they seem like what I want here).

But I'm a little concerned about the lack of symmetry between the two versions - if I want to change the name of project.exe, I do that in Cargo.toml, but if I want to change the name of the -w version, I rename the source file. In my C version, I just built the source file twice, with different compiler flags.

Is there a better way of doing this? I thought about having both bin/project.rs and bin/projectw.rs, with no main.rs at all. Is that allowed? It makes the project name in Cargo.toml irrelevant, which seems odd. Or is there a way to derive the filename for the bin/projectw.rs build from the name of the project (by adding a "w") rather than from the source filename? Or can I do like I do in C, and have all the source in main.rs with the differences handled by features (which seem to cover what I use C defines for - another thing I need to read up on!) and have the executable filename calculated based on what features I enable?

I'm probably over-thinking all of this, but I'd like to start my first non-trivial Rust project with a reasonably "best practice" project structure, and learn how to do things right from the start :slight_smile:

I would put them both in bin. Then instead of a main.rs, use lib.rs as the root of your module tree, and refer to shared code in lib.rs as, for example, crate_name::f().

Edit to add: with this structure, you wouldn't put any mod declarations in your bin/ files.

1 Like

Cool. If I do that, am I allowed to call the crate the same as one of the files in bin? I tried that but I got some weird complaints from VS Code (that I can't reproduce right now) which suggested that this was invalid. The project built OK, though.

You may get a warning about .pdb files colliding if you build both dynamic library and exe of the same name on Windows.

But apart from that it's fine to have a binary and a Rust library with the same name, even in the same package.

That shouldn't be an issue, as I'm not building a DLL (if I were, I'd probably rename the project so the DLL had a different name anyway). The warning was from the VS Code rust extension - I've reported it there on the assumption that it's an extension bug, as the build seems OK.

Thanks for the help.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.