Understanding compiler flags and more modularizing/rlibs

Hello,

i want to make my project/code more modular. I want to code a program that has first an n/pancursed based userinterface and then sometime and gui (when i have found and gui-crate that don’t need external c-compiler and are rust-core) and a few isolated functions.

I want to say the compiler that he should make an executable with all functions, only a specified function or an build with all functions but with one executable for one function.

And how can i use rlibs or build completly a executable was has for every functions an rlib and check the rlib presence. Like the dlls/sos for c/c++ executables.

So i hope anybody can help me, when my project are growing i can at the first steps keep an simple order and use the compiler flags more.

Greetz

PS: By the way, how can i control what name gives cargo/rustc the rustr std-lib when i compile its dynamic and how can i control names for the points aboeve?

The standard solution is to have a Cargo project with both binaries and a library, and have binaries import the common part as a library (in bin targets your lib is visible as an extern crate of your package name).

lib.rs:

pub fn foo() {}

main.rs

fn main() {
   yourcratename::foo();
}

You can also use Cargo Workspaces to have more separate crates, each with its own dependencies.

Each binary will still include the library statically. You can use LTO to trim unused parts.

Rust’s .rlib doesn’t have a stable ABI, so it’s not recommended to use it externally. If you wanted to have a true shared library, you’d have to build cdylib type (.so/.dylib/.dll) with only a C interface.

@kornel thx, good start point, cargo workspace are great to for me. I will use LTO in the future and don’t use rlibs.

Do I understand this in the right manner that i compile a Lib into an .so/.dll and then rust must go the way over an C Interface crutch? Internally for my projects all are pure rust but only when i build the project rust use the crutch for an shared project build, looks like some little performances losts or that does not matter?

Okay when i use fully shared library projects i must accept that rust are not go and the ABI are not stable at the moment. How can i say cargo/rustc that he some Libs compile as an shared Library?

Give it some good doc where i can show all the compiler-flags and statements for cargo/rustc?

Greetz

The crate-type setting decides whether Cargo builds something as .rlib/.a/.so.

I suppose for your private use you could ship .rlib. I just think it’s uncommon to do so, and I haven’t seen it officially recommended anywhere, so there’s a risk you’d run into some problems. Static linking and .so with C ABI are well-tested. Going through the C ABI is a hassle, so do it only if you really need to have a shared library.

@kornel cool thx for the link, very useful.

At the moment i try to order my project with [lib] and [bin] statements in the cargo.toml.

The [lib] i use when i include the library in my main.rs that uses functions from that lib and [bin] plus the -p argument when i want the library as an standalone executable.

I’m an very old coder;) and i’m started for decades with an .c file and coded all in what i need and then run the c compiler over that single c file. Long time ago. Then i used the make and projects files. Then i’m switched to internet development:) and now i’m back at low level coding and my brain-patterns from php-mvc developments says everytime No one single executables and outsource all functions in a single file;).

But the times where i use rustc are over, now i’m only use cargo to manage my project.

Shared linking was only an option for memory optimisation in my brain and low level coding has bringing me back to such problems. But at the moment my executables don’t trigger an out of memory error on no machines;).

But thx at this moment now i can bring an cool order in my project.

ps: how can i control the paths and names of shared librarys and project executables? Are this only possible with an build.rs? And when yes how can i use the build script only on the name changer level? I mean in the docs all are use build.rs to inject new code but i’m only that fine granular control the outputet names from my project?

With Cargo you don’t control names or locations of the products beyond the project name. After they’re built, you copy them out of target/ where you want them.

@kornel

Ah okay then give it no mechanism in cargo after build. A pity so no full makefile mechanism or gradlew mechanism. A pity i thought i can set the name of the executable outside the standard mechnisms (like name of the cargo project or name of the libs/bin cargo-section). Only a 1to1 representation of the files in the cargo project.

Hmm another situation i use rlibs or better i use .so/.dll, cargoi and rustc only copy this in the target root and i want that cargo represent a structure like this

target/exe
target/libs/exe_lib_1.so
target/libs/exe_lib_2.so

i hope its understandable, first i don’t want the logic that librarys are searched in path or in the project-root, i want a discreet path with all shared librarys. Is there any compiler statement for this reason?

Cargo has a very strong preference for convention over configuration. It’s not a traditional build system where you write the entire build process from scratch and design a unique setup that you want. Cargo does everything itself, out of the box, the Cargo way.

The downside is that you won’t be able to do what you want. The upside is that anyone coming to your project, and you using anyone else’s project, can run cargo build and it will build the same way.

So you get:

  • target[/<platform>]/<profile>/projectname
  • target[/<platform>]/<profile>/projectname.so
  • target[/<platform>]/<profile>/projectname.a

and that’s it. This directory is not yours, and you don’t decide what goes where. There are some env variables that let you configure where the target directory is, but generally it’s not something that you manage.

There are no search paths for Rust dependencies. They’re managed by Cargo automatically.

In general, you don’t touch the rustc compiler. Cargo tries to abstract it away (it’s a leaky abstraction, so some hacky setups try to influence compiler flags, but that’s fragile).

The only search paths that Cargo lets you influence is for searching non-Rust libraries, intended for linking system’s C libraries and C code in sys crates using build.rs. These scripts are necessary evil for C interoperability and are never used for native Rust libraries.