Use rust-s3 without tokio? - rust

I want to use the rust-s3 crate in the simplest & lightest possible way (w/o async). By default this crate uses tokio. So I followed what's written in rust-s3's README:
With default-features = false
sync - no async runtime, attohttpc is used for HTTP requests
So in my Cargo.toml I added this:
[dependencies]
rust-s3 = { version = "0.28.1", default-features = false, features = ["sync"] }
When I read "no async runtime", I don't expect to see tokio added as a dependency. However, tokio is still being added. And looking at the crate's Cargo.toml, I see it has a (non-optional) dependency on tokio-stream, which, in turn, depends on tokio. This is from cargo tree's output in my project:
├── tokio-stream v0.1.8
│ ├── futures-core v0.3.19
│ ├── pin-project-lite v0.2.8
│ └── tokio v1.15.0
│ └── pin-project-lite v0.2.8
So it seems to me it's actually not possible to avoid adding tokio as a dependency, the way this crate is written. Am I right or am I missing something here?

I kinda reached the conclusion tokio in its default mode has almost nothing (no runtime, etc.), so maybe that's why, even though it is included as a dependency, it shouldn't add much of a baggage in itself.

Related

Cargo Publish uses different dependency version

When I do cargo publish of my library it fails to compile the project because for a some reason it uses different version of a dependency. But if I do cargo build it works fine.
I see that for cargo publish it uses two different version of one of the dependencies:
Compiling bitcoin v0.27.1
Compiling bitcoin v0.28.1
And it fails later because one of the dependencies uses 0.27.1 and another 0.28.1.
The dependency is specified as bitcoin = "=0.27.1" in Cargo.toml. If I look into Cargo.lock file I see only version 0.27.1. I.e. only one entry, no other versions in Cargo.lock. cargo tree shows only version 0.27.1 as well. And cargo build uses only 0.27.1 for compilation.
It's absolutely unclear where from the 0.28.1 comes from during the cargo publish
How I can tell cargo publish to not use 0.28.1 and stick to version in the Cargo.lock? I tried --locked and --frozen but I doesn't make any effect.
UPDATE
One of the dependencies has defined bitcoin = ">= 0.27" and it seems that Cargo tries to use the most up-to-date version 0.28.1 only because it fits that criteria for that lib. And 0.27.1 for others. That obviously would not work. How to enforce it to use one version?
UPDATE 2:
There is the whole tree of the conflicting versions cargo tree --all-features:
├── bitcoin v0.27.1
.
├── emerald-hwkey v0.2.0
│ ├── bitcoin v0.27.1 (*)
│ ├── hdpath v0.6.1
│ │ ├── bitcoin v0.28.1
Where hdpath:0.6.1's Crate.toml accepts any version via:
bitcoin = { version = ">= 0.27", optional = true }
So it's unclear why Cargo tries to upgrade this particular version and makes everything incompatible to each other.
UPDATE 3:
It seems that it works if I use a local version of hdpath with enforced ">= 0.27, < 0.28". But I don't want that because hdpath by itself doesn't have a reason for such restriction and works fine with any of the versions.
So I just need to make sure it uses the version compatible with the parent project. Is there any way?

Local crate not found when trying to update edition via cargo fix

Context:
I have a local C library called 'libmaths' that then uses Bindgen to create a 'libmaths-sys' crate that is locally stored in the same directory as my project.
Issue:
I want to use some of the features in the 2021 edition of Rust and currently my project is built off 2018. I am trying to update the project by following the instructions at:
https://doc.rust-lang.org/cargo/commands/cargo-fix.html
Run cargo fix --edition. Consider also using the --all-features flag if your project has multiple features. You may also want to run cargo
fix --edition multiple times with different --target flags if your
project has platform-specific code gated by cfg attributes.
Modify Cargo.toml to set the edition field to the new edition.
Run your project tests to verify that everything still works. If new
warnings are issued, you may want to consider running cargo fix again
(without the --edition flag) to apply any suggestions given by the
compiler.
To run cargo fix --edition I am told by the compiler to remove the edition="2018" in cargo toml. Following this I receive a compile error stating that libmaths-sys cannot be found. The code compiles and executes normally in 2018 but not without this edition tag.
I can not find anyone with a similar issue, this is my first stackoverflow question so not sure how best to show my code given its a context of a small project.
Error code
error[E0432]: unresolved import `libmaths_sys`
--> src/main.rs:1:5
|
1 | use libmaths_sys::*; // lib.rs in sys crate
| ^^^^^^^^^^^^ maybe a missing crate `libmaths_sys`?
File Structure and general overview of project
.
├── Cargo.lock
├── Cargo.toml
├── libmaths
│   ├── add.c
│   ├── add.h
│   └── subtract.c
├── libmaths-sys
│   ├── build.rs
│   ├── Cargo.lock
│   ├── Cargo.toml
│   ├── src
│   │   └── lib.rs
│   └── wrapper.h
├── README.md
└── src
  ├── lib.rs
  └── main.rs
libmaths contains add.c that returns a + b and subtract.c which returns a - b, with a header add.h directing to both .c files
The Rust code generated by bindgen is attached via lib.rs in the libmath-sys crate which links to the OUT DIR which I have omitted from the tree to save 200 lines of file names.
Try updating edition="2018" to edition="2021"; otherwise it defaults to edition="2015" which requires usage of extern crate.
As #Solomon Ucko directed me to, rustup update held the key.
Running rustup update produced:
info: syncing channel updates for 'stable-x86_64-unknown-linux-gnu'
info: syncing channel updates for '1.48-x86_64-unknown-linux-gnu'
info: checking for self-updates
stable-x86_64-unknown-linux-gnu unchanged - rustc 1.59.0 (9d1b2106e 2022-02-23)
1.48-x86_64-unknown-linux-gnu unchanged - rustc 1.48.0 (7eac88abb 2020-11-16)
info: cleaning up downloads & tmp directories
In the end, rustup was using the old 1.48 version and not the installed 1.59 version.
To switch to the newer vesion I ran:
rustup default stable
I then could follow the instructions from the link in the original question to change the edition.

"Unresolved import" when linking with [lib] in Cargo.toml [duplicate]

I'm trying to create a module in Rust and then use it from a different file. This is my file structure:
matthias#X1:~/projects/bitter-oyster$ tree
.
├── Cargo.lock
├── Cargo.toml
├── Readme.md
├── src
│   ├── liblib.rlib
│   ├── lib.rs
│   ├── main.rs
│   ├── main.rs~
│   └── plot
│   ├── line.rs
│   └── mod.rs
└── target
└── debug
├── bitter_oyster.d
├── build
├── deps
├── examples
├── libbitter_oyster.rlib
└── native
8 directories, 11 files
This is Cargo.toml:
[package]
name = "bitter-oyster"
version = "0.1.0"
authors = ["matthias"]
[dependencies]
This is main.rs:
extern crate plot;
fn main() {
println!("----");
plot::line::test();
}
This is lib.rs:
mod plot;
this is plot/mod.rs
mod line;
and this is plot/line.rs
pub fn test(){
println!("Here line");
}
When I try to compile my program using: cargo run I get:
Compiling bitter-oyster v0.1.0 (file:///home/matthias/projects/bitter-oyster)
/home/matthias/projects/bitter-oyster/src/main.rs:1:1: 1:19 error: can't find crate for `plot` [E0463]
/home/matthias/projects/bitter-oyster/src/main.rs:1 extern crate plot;
How do I compile my program? As far as I can tell from online documentations this should work, but it doesn't.
To add to the given answers, a library compiled as a cdylib (docs) can generate this error when you try to reference it in another project. I solved it by separating the code I wished to reuse in a regular lib project.
If you see this error:
error[E0463]: can't find crate for `PACKAGE`
|
1 | extern crate PACKAGE;
| ^^^^^^^^^^^^^^^^^^^^^ can't find crate
it could be that you haven't added the desired crate to the dependencies list in your Cargo.toml:
[dependencies]
PACKAGE = "1.2.3"
See specifying dependencies in the Cargo docs.
You have the following problems:
you have to use extern crate bitter_oyster; in main.rs, because the produced binary uses your crate, the binary is not a part of it.
Also, call bitter_oyster::plot::line::test(); in main.rs instead of plot::line::test();. plot is a module in the bitter_oyster crate, such as line. You are referring to the test function with its fully qualified name.
Make sure, that every module is exported in the fully qualified name. You can make a module public with the pub keyword, like pub mod plot;
You can find more information about Rust's module system here: https://doc.rust-lang.org/book/crates-and-modules.html
A working copy of your module structure is as follows:
src/main.rs:
extern crate bitter_oyster;
fn main() {
println!("----");
bitter_oyster::plot::line::test();
}
src/lib.rs:
pub mod plot;
src/plot/mod.rs:
pub mod line;
src/plot/line.rs :
pub fn test(){
println!("Here line");
}
I got this issue when I had imported my crate in [dev-dependencies] instead of [dependencies]
This can also happen when you don't enable certain "feature flags" for specific crates. Unfortunately, these feature flags can sometimes be undocumented. When feature flags are missing when required, they show the same error ("Can't find crate")
I was using diesel, and was trying to use BigInteger:
Wrong
diesel = { version = "2.0.3", features = ["postgres", "chrono", "r2d2", "serde_json", "biginteger"] }
Correct:
diesel = { version = "2.0.3", features = ["postgres", "chrono", "r2d2", "serde_json", "numeric"] }

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.

What is the recommended directory structure for a Rust project?

Where should one put the sources, examples, documentation, unit tests, integration tests, license, benchmarks etc?
Cargo, the official package manager for Rust, defines some conventions regarding the layout of a Rust crate:
.
├── Cargo.lock
├── Cargo.toml
├── benches
│ └── large-input.rs
├── examples
│ └── simple.rs
├── src
│ ├── bin
│ │ └── another_executable.rs
│ ├── lib.rs
│ └── main.rs
└── tests
└── some-integration-tests.rs
Cargo.toml and Cargo.lock are stored in the root of your project.
Source code goes in the src directory.
The default library file is src/lib.rs.
The default executable file is src/main.rs.
Other executables can be placed in src/bin/*.rs.
Integration tests go in the tests directory (unit tests go in each file they're testing).
Example executable files go in the examples directory.
Benchmarks go in the benches directory.
These are explained in more detail in the manifest description.
By following this standard layout, you'll be able to use Cargo's commands to build, run and test your project easily. Run cargo new to set up a new executable project or cargo new --lib to set up a new library project.
Additionally, documentation for libraries is often written in documentation comments (comments that start with /// before any item, or //! to document the parent item). Also, the license is usually put at the root.
Unit tests, as mentioned above, are written in the same module as the functions they're testing. Usually, they're put in an inner module. It looks like this (this is what Cargo generates for a new library with cargo new --lib):
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
}
}

Resources