I was wondering how are Rust crates are implemented.
For example, there is a crate named num_cpus. This crate has this basic method num_cpus::get() which tells number of CPUs in your computer.
My questions:
How is the method num_cpus::get() implemented (is it done using another language?)
Can the same result be achieved with plain Rust code without using any crates?
... in Rust. There's no reason to believe it'd be anything else.
You can also check this by just looking at the source code, easily done by:
Search crates.io for "num_cpus"..
Select the num_cpus crate.
Select "Repository" for the source code.
Open the only .rs source file in the repository, src/lib.rs.
Related
When I document my project by 'cargo doc' then it can happen that the name of my own project shadows a dependend crate which is then invisible.
So I do not see that a crate with the same name exists and this crate then keeps undocumented.
How can I tackle this problem?
The best workaround is to just avoid this situation from the beginning. Just make sure you're not shadowing any public crates names. You can check on crates.io if your desired name is available, if it's not I strongly recommend you choose a different name since if you ever want to publish it you'd have to rename it anyways.
With Rust Procedural macros, developer are able to parse the TokenTree of Rust code, such as the contents of a struct. But if this struct is from another crate there does not seem to be a direct solution to implement a macro to parse it.
There is an incredibly verbose thread on the Rust Forum here related to the orphan-impl problem in Rust which does not seem to have an official conclusion. There are libraries out in the wild which do their best given the tools provided by the Rust ecosystem such as serde's remote-derive with relevant code. This though necessitates the user to define structs from external crates in their own, which makes coupling with other crates very fragile.
Example usage for serde's remote linting can be found here:
serde remote linting
Wondering if there are any different methods to solve this use case in the rust ecosystem or if there are plans in the rust core team for the future.
I want to extract all nightly features used by a crate for some research purposes.
Just to be clear, "nightly features" means codes like #![feature(...)]", but not crate provided optional features.
I tried using regex, and it works, but not accurate enough. cfg defined features may not be detected: #![cfg_attr(target_os = "macos", feature(...))].
So I turn to rustc compiler, I wish to modify some source code and print out what features crate uses. Now I'm still trying to find out how rustc deals with nightly features.
I hope someone can give me some tips and help about the process of rustc dealing with nightly features. I'm almost lost in codes.
Access to enabled features is done via rustc_session::Session::features. You can add code after they are set in rustc_interface, or look at how they're computed.
If you are at a later stage, you probably have access to the Session of the compiled crate. For example, TyCtxt has a sess() method (but also a features() method for direct access using the query system), and InferCtxt has a tcx member to access the TyCtxt.
I come from a Java background and have recently started with Rust.
The official Rust doc is pretty self-explanatory except the chapter that explains Crates and Packages.
The official doc complicates it with so many ORs and ANDs while explaining the two.
This reddit post explains it a little better, but is not thorough.
What is the exact difference between a Crate and Package in Rust? Where/When do we use them?
Much thanks!
Crates
From the perspective of the Rust compiler, "crate" is the name of the compilation unit. A crate consists of an hierarchy of modules in one or multiple files. This is in contrast to most "traditional" compiled languages like Java, C or C++, where the compilation unit is a single file.
From the perspective of an user, this definition isn't really helpful. Indeed, in most cases, you will need to distinguish between two types of crates:
binary crates can be compiled to executables by the Rust compiler. For example, Cargo, the Rust package manager, is a binary crate translated by the Rust compiler to the executable that you use to manage your project.
library crates are what you'd simply call libraries in other languages. A binary crate can depend on library crates to use functionality supplied by the libraries.
Packages
The concept of packages does not originate in the Rust compiler, but in Cargo, the Rust package manager. At least for simple projects, a package is also what you will check into version control.
A package consists of one or multiple crates, but no more than one library crate.
Creating packages
to create a new package consisting of one binary crate, you can run cargo new
to create a new package consisting of one library crate, you can run cargo new --lib
to create a package consisting of a library as well as one or multiple binaries, you can run either cargo new or cargo new --lib and then modify the package directory structure to add the other crate
When should you use crates, and when should you use packages?
As you can see now, this question doesn't really make sense – you should and must always use both. A package can't exist without at least one crate, and a crate is (at least if you are using Cargo) always part of a package.
Therefore, a better question is this:
When should you put multiple crates into one package?
There are multiple reasons to have more than one crate in a package. For example:
If you have a binary crate, it is idiomatic to have the "business logic" in a library in the same package. This has multiple advantages:
Libraries can be integration tested while binaries can't
If you later decide that the business logic needs to also be used in another binary, it is trivial to add this second binary to the package and also use the library
If you have a library crate that generates some files (a database engine or something like that), you may want to have a helper binary to inspect those files
Note that if you have a very big project, you may instead want to use the workspace feature of Cargo in these cases.
On crates.io we can easily see the direct dependencies of a crate by just clicking on the Dependencies tab. Is there a way to also easily see the sub-dependencies of a crate? Perhaps in a tree-like view, similar to what cargo tree would display. Or at least the number of all (sub)dependencies.
I think that can be helpful, for example, when we need to decide which crate to use among alternatives. By having an indicator of the total number of (sub)dependencies, we would have a better idea on how "heavy" a library actually is. I think that can be especially useful for a language like Rust where the build speed seems to heavily depend on the number of dependencies.