I'm new at rust and just finished the book. I'm trying to understand whether everything in rust must be distributed in the form of source code, like golang perhaps. This may not be the accurate way to ask but here's what I want to know about:
In the age of C/C++ I can compile code into some library (xx.a or xx.so) and distribute it with header files to someone who can link their code with as long as we are using about the same compiler/os/platform. Now with Rust every dependency is pulled from crates.io in the form of source code and locally built and linked. However if for some reason I do not want to publish the source code but only the target platform's library can this be done though manipulating the tool chain? I believe this cannot be done because of some Rust's inherent design. For example I can write code like this in a rust library:
pub trait Summary {
// snip
}
fn returns_summarizable() -> impl Summary {
// snip
}
If the code that depend on the library calls returns_summarizable then the compiler must be able to determine the size of the return value to allocate space on stack for the result variable. This means although the code only care that it returns some type that implements the Summary trait but the compiler actually has to know the concrete type it returns. This can not be done without the library's source code, not even with some equivalent thing like header files because the header file (if exists) should only contain the trait declaration other than any inner type the function could possibly return.
I'm curious about it not because I want to distribute crates without source but it occurs to me that the borrow checker and compiler never looks at the body of a function or method where it's called but only the signature. This seems not to be the case when a function returns impl xxx as above, because Rust has to look at the implementation type that's actually returned to determine the return type size, right?
The main problem here is that the Rust ABI is not stable yet. So it's hard to properly distribute "Rust binary files" since they are only known to work with the exact same compiler you compiled them with. Even a minor version change might break them.
The safe bet for now is to distribute a
staticliband/orcdylibby setting the crates type inCargo.tomlwich will produce a static library file
*.aand a dynamic library file*.so/*.dylib/*.dllrespectively, see the reference article on linkage.The disadvantage is that this uses the FFI interface and as a result you loose some of Rusts expressiveness and can only use C compatible types which rules out things like generics.
If you don't mind breaking/rebuilding every Rust minor release you can use a Rust
dylib:which will produce a
lib<your_crate_name>.soon Linux. You can then tell cargo to link that file with a build script or similar:You'll also have to provide the function signatures in an extern block either directly where you use it or in a stub library:
Note that since generics are implemented by monomorphization, that still doesn't allow them, but you can at least use the rest of Rusts expressive type system though all functions in an
externblock are implicitlyunsafe.