Local crate in Rust - rust

I am currently learning Rust, and for that purpose I wanted to create my own crate and use it. However, Rust can't find this crate.
I have the following file structure:
├───minimal
│ ├───Cargo.toml
│ └───src
│ └───main.rs
└───util
└───win
├───Cargo.toml
└───src
└───lib.rs
In folder minimal I have my main project. It looks like this:
Cargo.toml
[package]
name = "minimal"
version = "0.1.0"
[dependecies]
win = { path = "../util/win"}
main.rs
extern crate win; // ERROR: "Can't find crate for 'win' rustc(E0463)"
fn main() {
println!("Hello, World!");
}
My library in folder win looks like this:
File Cargo.toml
[package]
name = "win"
version = "0.1.0"
File lib.rs
pub type TestType = String;
My first assumption was that I somehow had a mistake in specifying the path in the dependency of the Cargo.toml file. So I tried to wiggle it around a bit, but it does not seem to work.
Rust reports
can't find crate for 'win' rustc(E0463)
I feel like I am making a very basic error here, however, when looking at similar questions (e.g., How do I "use" or import a local Rust file?) I can't seem to find it.

After having a good night's sleep and looking at this problem again, I have managed to find the error.
I used [dependecies] instead of [dependencies] in the Cargo.toml file.
On the one hand, I feel kind of dumb for this error, but on the other hand I now know that Cargo will not warn about unknown tags in the TOML file.

Related

cargo would not build even when src/main.rs is available

I am trying to build using cargo build. The following is the project structure
tree
.
├── Cargo.toml
└── src
└── main.rs
The content of Cargo.toml
[package]
name = "server"
version = "0.1.0"
authors = ["Lokanath Mohanty <lokanath.mohanty#adcolony.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
The content of src/main.rs
use std::io::{ErrorKind, Read, Write};
use std::net::TcpListener;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
const LOCAL_IP: &str = "127.0.0.1:6001";
const MSG_SIZE: usize = 32;
fn main() {
...
}
I am getting the following error -
error: failed to parse manifest at `/home/debashishc/Downloads/Cargo.toml`
Caused by:
no targets specified in the manifest
either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present
Cargo looks for and tries to parse Cargo.toml in parent directories, because it checks whether your crate is part of a larger workspace.
Remove the broken Cargo.toml from the parent directory. Alternatively, make your crate's Cargo.toml a workspace to stop cargo from searching further.

Refactoring to workspace structure causes extern crate imports to not work

I need different parts of my project to use different versions of the same extern crate so I'm refactoring my Rust project to be divided into multiple packages via the workspaces system using this as a guide. Doing so is causing all my pub extern crate imports to not work.
This post is very similar to one I created very recently and then deleted - this version contains a minimal, complete, and verifiable example.
Here's my project structure
workspace_test/
root/
src/
main.rs
Cargo.toml
Cargo.toml
workspace_test/Cargo.toml:
[package]
name = "workspace_test"
version = "0.1.0"
authors = ["Phoenix <kahlo.phoenix#gmail.com>"]
[workspace]
members = [
"root"
]
[[bin]]
name = "root"
path = "root/src/main.rs"
workspace_test/root/Cargo.toml:
[package]
name = "root"
version = "0.1.0"
authors = ["Phoenix <kahlo.phoenix#gmail.com>"]
[dependencies]
time = "0.1"
workspace_test/root/src/main.rs:
pub extern crate time;
fn main() {
println!("Hello, world!");
}
This is also on github, so it can easily be cloned and cargo run'd.
This is the error:
error[E0463]: can't find crate for `time`
--> root/src/main.rs:1:1
|
1 | pub extern crate time;
| ^^^^^^^^^^^^^^^^^^^^^^ can't find crate
error: aborting due to previous error
error: Could not compile `workspace_test`.
In workspace_test/Cargo.toml you create a package with the binary root. If you execute cargo run, it runs the main.rs, but since you didn't state the dependencies in this manifest file, the error occurs. The dependency is only specified in workspace_test/root/Cargo.toml, which is not used at this point.
I assume you want to use the workspaces proposed by the RFC. You can create a workspace with virtual manifests, which must neither specify a [package] nor [[bin]], so just remove them. workspace_test/Cargo.toml now looks like this:
[workspace]
members = [
"root"
]
If you only have one executable, you can now pass the package: -p/--package
cargo run -p root
or specify the manifest path manually:
cargo run --manifest-path root/Cargo.toml
If root/Cargo.toml contains multiple targets, you can just append the --lib or --bin flags as usual. E.g. this would execute the abc-binary specified in workspace_test/root/Cargo.toml:
cargo run -p root --bin abc

How to import a crate dependency when the library name is different from the package name?

I have a crate that is imported straight off of GitHub, as per Cargo's documentation:
[dependencies]
libfoo = { git = "ssh://git#github.com/me/libfoo", branch = "dev" }
[lib]
path = "src/rust/lib.rs"
name = "myprj"
crate-type = ["cdylib"]
Running cargo build works fine here, Cargo fetches libfoo and builds it in the ~/.cargo directory. When I try to use (import) it in lib.rs:
extern crate libfoo; //also tried foo
Cargo chokes:
error[E0463]: can't find crate for `libfoo`
--> src/rust/lib.rs:1:1
|
1 | extern crate libfoo;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
Interestingly, IntelliJ's Rust plugin does find the crate when I click on it in lib.rs – it navigates to the downloaded source in ~/.cargo...
In the dependency libfoo, the lib section of the Cargo.toml file is specified as:
[package]
name = "libfoo"
[lib]
name = "foo"
crate-type = ["cdylib"]
I have tried all permutations of libfoo and foo to see if Cargo is getting confused between the lib name and the package/directory name.
It also fails if I specify a local path to the dependency. (Cargo compiles the dependency but then claims not to find it when it is declared/imported in lib.rs.)
[dependencies]
libfoo = { path = "/Users/me/dev/libfoo" }
If I include a crate from git or the file system that has the same [lib] name as the [package] name, it works fine. So it appears the problem is with crates that have a have a library ([lib]) name that is different from the package ([package]) name.
If I remove the [lib] section from the dependency's Cargo.toml file, it works.
Update: if crate-type = ["cdylib"] is removed from libfoo, this works with foo imported. If that is there, I get the same error with extern crate foo;.
Cargo is interested in package names when it comes to dependencies, while the compiler (rustc) is interested in library names when it comes to loading their metadata and linking with them.
Let's take a look again at this Cargo.toml excerpt:
[package]
name = "libfoo"
[lib]
name = "foo"
Here, the package name is libfoo and the library name is foo.
When you want to declare a dependency on libfoo in your project, you need to write the package name (libfoo) in the [dependencies] table. For example:
[dependencies]
libfoo = { git = "ssh://git#github.com/me/libfoo", branch = "dev" }
This is what you already have, and it's correct.
However, when you want to import the library in your crate, you need to write the library name in the extern crate item, i.e.
extern crate foo;
How did I figure this out? First, I wrote libfoo in both Cargo.toml and the extern crate item, as you described. When I ran cargo build, I noticed that libfoo was built successfully, indicating that Cargo correctly resolved the dependency. But I also noticed that the compiler couldn't find libfoo, as you experienced.
I then inspected the command line passed to rustc by running cargo build --verbose. This is what I saw (irrelevant parts omitted):
Running `rustc [...] --extern foo=/[path]/target/debug/deps/libfoo-5cf876c5c8ac1bfb.rlib`
The --extern name=path argument tells rustc that the crate named name is located in path. The name here is foo, so we must write extern crate foo; in the code to reference it.

Importing non-root module from multiple non-root binaries

I am learning Rust and decided to write a simple client/server program. Both the client and the server will be using a very simple module I've already written. Knowing that this code might grow, I decided to compartmentalize my source for clarity. Right now my current hierarchy looks as follows:
├── Cargo.lock
├── Cargo.toml
├── README.md
├── src
│   ├── client
│   │   └── main.rs
│   ├── common
│   │   ├── communicate.rs
│   │   └── mod.rs
│   ├── lib.rs
│   └── server
│   └── main.rs
Many of the examples I found on Stack Overflow and the net provide great samples for when the main.rs is in the project root directory. Unfortunately I'm trying to do something different as shown above.
communicate.rs contains all of the network code I have written. Eventually I will add other Rust files here and include their public mod statement in mod.rs. Currently common/mod.rs all I have is
pub mod communicate;
Focusing on just the client folder, all I have is main.rs as shown. The file "header" lists
extern crate common;
use std::thread;
use std::time;
use std::net;
use std::mem;
use common::communicate;
pub fn main() {
// ...
}
Besides the fundamental [package] section, all I have in Cargo.toml is
[[bin]]
name = "server"
path = "src/server/main.rs"
[[bin]]
name = "client"
path = "src/client/main.rs"
When I try to build the client binary, the compiler complains that the common crate could not be found.
$ cargo build
Compiling clientserver v0.1.0 (file:///home/soplu/rust/RustClientServer)
client/main.rs:1:1: 1:21 error: can't find crate for `common` [E0463]
client/main.rs:1 extern crate common;
^~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
error: Could not compile `clientserver`.
To learn more, run the command again with --verbose.
I think this is because it is looking for a common crate within the client/ folder. I had this same problem when I tried the mod statement instead of extern crate statement.
use std::thread;
use std::time;
use std::net;
use std::mem;
mod common;
Gave me:
client/main.rs:6:5: 6:11 error: file not found for module `common`
client/main.rs:6 mod common;
^~~~~~
client/main.rs:6:5: 12:11 help: name the file either common.rs or common/mod.rs inside the directory "client"
I also tried (using the extern crate...) adding a lib.rs in the client whose contents are pub mod common; but I still get the same error as the first.
One potential solution I found to model it like this project, but this would require a Cargo.toml in every folder, something which I'd like to avoid.
I feel like I am close but am missing something.
You are not building common as a crate right now. The crates being built are the library clientserver (the default name for the library is the package name) and the binaries client and server.
Normally, extern crate clientserver; should work. However, if you want to name your library differently, you can do so by specifying a different name in a [lib] section in Cargo.toml. In this section, you can also specify a different source path for the library's main source file. In your case, it will probably be better, otherwise you'll end up with a crate named common and all of its contents would be in a module named common, so you'd have to access everything as common::common::foo. For example, by adding this to your Cargo.toml:
[lib]
name = "common"
path = "src/common/lib.rs"
you could combine src/lib.rs and src/common/mod.rs into src/common/lib.rs. Then, extern crate common; should work in your binaries.

How to link main.rs to lib.rs dynamically?

I have a crate with both src/lib.rs and src/main.rs.
main.rs is just using extern crate programname (which is lib.rs) and uses certain functions from lib.rs and it's submodules.
The documentation on linking says:
Pure-Rust dependencies are statically linked by default so you can use created binaries and libraries without installing Rust everywhere.
How can I change this behavior so a binary created from main.rs will be dynamically linked to library produced by lib.rs?
I've added the following to Cargo.toml
[lib]
path = "src/lib.rs"
crate-type = ["dylib"]
[[bin]]
name = "programname"
path = "src/main.rs"
But it does not compile and gives me errors like:
error: cannot satisfy dependencies so `std` only shows up once
help: having upstream crates all available in one format will likely make this go away
If I add "rlib" to lib section, it compiles, but the binary is not linked against libprogramname.so

Resources