cargo build of the same code: spurious compile time errors? - rust

I have crate A that depend on B and B depend on rust-nmea crate.
If I build crate A I got bunch of errors (all of them that missed use std::error::Error;) during build of rust-nmea dependency:
error[E0599]: no method named `description` found for type `nom::Err<&[u8]>` in the current scope
--> /home/evgeniy/.cargo/registry/src/github.com-1ecc6299db9ec823/nmea-0.0.6/src/parse.rs:100:44
|
100 | IError::Error(e) => e.description().to_string(),
| ^^^^^^^^^^^
|
= help: items from traits can only be used if the trait is in scope
= note: the following trait is implemented but not in scope, perhaps add a `use` for it:
candidate #1: `use std::error::Error;`
But if I go to source tree of B crate and run cargo build,
all build without any error (if you follow me A depend on B and B depend on rust-nmea),
also if go to /home/evgeniy/.cargo/registry/src/github.com-1ecc6299db9ec823/nmea-0.0.6/ (see compile error) and run cargo build then all good.
cargo tree show for A:
│ ├── chrono v0.4.0
│ │ ├── num v0.1.40
│ │ │ ├── num-integer v0.1.35
│ │ │ │ └── num-traits v0.1.40
│ │ │ ├── num-iter v0.1.34
│ │ │ │ ├── num-integer v0.1.35 (*)
│ │ │ │ └── num-traits v0.1.40 (*)
│ │ │ └── num-traits v0.1.40 (*)
│ │ └── time v0.1.38
│ │ └── libc v0.2.27
├── nmea v0.0.6
│ ├── chrono v0.4.0 (*)
│ └── nom v3.2.0
│ └── memchr v1.0.1 (*)
and for cached by cargo rust-nmea:
├── chrono v0.4.0
│ ├── num v0.1.40
│ │ ├── num-integer v0.1.35
│ │ │ └── num-traits v0.1.40
│ │ ├── num-iter v0.1.34
│ │ │ ├── num-integer v0.1.35 (*)
│ │ │ └── num-traits v0.1.40 (*)
│ │ └── num-traits v0.1.40 (*)
│ └── time v0.1.38
│ └── libc v0.2.27
└── nom v3.2.0
└── memchr v1.0.1
└── libc v0.2.27 (*)
so for both good and bad case used the same dependencies.
If run cargo build -v -j1, I got rustc command line for both cases.
The only difference for good and bad case is this part:
-L dependency=/home/evgeniy/.cargo/registry/src/github.com-1ecc6299db9ec823/nmea-0.0.6/target/debug/deps --extern chrono=/home/evgeniy/.cargo/registry/src/github.com-1ecc6299db9ec823/nmea-0.0.6/target/debug/deps/libchrono-8e9e54e691d9b988.rlib --extern nom=/home/evgeniy/.cargo/registry/src/github.com-1ecc6299db9ec823/nmea-0.0.6/target/debug/deps/libnom-b72336f662b090c1.rlib
bad case have different path to libraries and libnom-e2ec53418967eac0.rlib instead of libnom-b72336f662b090c1.rlib, while libchrono-8e9e54e691d9b988.rlib match.
The crates A and B are close sourced and I can not reduce problem to more simple case. nom crates not used in A and B except via rust-nmea.
rust-nmea is used in simple way, just nmea = 0.0.6 in Cargo.toml.
No flags or so on things.
Any idea why crate dependecy with the same flags (no flags at all)
may produce or not produce syntax error?

I found source of problem,
crate A has second level dependicies with cexpr,
cexpr has nom = {version = "^3", features = ["verbose-errors"] } in Cargo.toml,
rust-nmea also depend on nom, so we have compile time error.

Related

How to import a lib from one cabal package to another

So my folder structure is like this
.
├── eulerlibs
│ ├── EulerLibs
│ └── eulerlibs.cabal
├── flake.lock
├── flake.nix
├── p001
│ ├── Main.hs
│ └── p001.cabal
├── p002
│ ├── Main.hs
│ └── p002.cabal
├── p003
│ ├── Main.hs
│ └── p003.cabal
├── p004
│ ├── Main.hs
│ └── p004.cabal
├── p005
│ ├── Main.hs
│ └── p005.cabal
What I am trying to do is import the library modules in the ./eulerlibs (library) cabal directory to lets say ./p005(executable) cabal directory
I do understand that I can include built libraries (*.so), but can find no way of linking two cabal projects
I'm very new to cabal as well as haskell so some insight will be much appreciated. If nothing works out I'll have to add the library to p005 itself which I really want to avoid.
You can do this with a cabal.project file. Place it at the top level (in the . directory) with these contents:
packages: */*.cabal
Then you will be able to use all those libraries in each other's cabal files in the build-dependencies, e.g. in p001.cabal:
...
library
...
build-depends: base, eulerlibs
...
...
Here is the full documentation of cabal.project files: https://cabal.readthedocs.io/en/latest/cabal-project.html

How can I load an image from a changing path environment after building an .app with cargo-bundle?

I'm using cargo-bundle to create an .app bundle for my Rust application built with fltk-rs.
There are assets in the application like images. While I'm developing, accessing these assets is no problem.
main.rs:
let mut my_img = SharedImage::load("imgs/smiley.png").unwrap();
.
├── Cargo.lock
├── Cargo.toml
├── app_icon_design.psd
├── imgs
│ └── smiley.PNG <--get this image
├── src
│ ├── app_icon.png
│ ├── app_icon#2x.png
│ ├── icon32x32.png
│ └── main.rs
└── target
├── CACHEDIR.TAG
├── debug
└── release
I then bundle to an .app with cargo build --release which gives me the following directory structure inside of my .app:
.
├── Info.plist
├── MacOS
│ └── build_to_app_bundle <--my executable
└── Resources
└── imgs
└── smiley.PNG<--get this image now
Now my application needs to get the image file from the /Resources folder:
println!("my resources folder is: {:?}", std::env::current_exe().unwrap().parent().unwrap().join(Path::new("Resources")));
let my_resources_path = std::env::current_exe().unwrap().parent().unwrap().join(Path::new("Resources"));
How can I make it so that every time I want to load an image from a path I do not need to explicitly reference the Resources value?

How to fix the following warning: `WARN: The resource for '' is not found, drilling down to the details of this test won't be possible.`

My abridged sonar-project.properties files is as follows:
# Sources
sonar.sources=felix
sonar.sources.inclusions=**/**.py
sonar.exclusions=**/test_*.py,**/**.pyc,felix/utils/*,**/*.iml
# Linter
sonar.python.pylint=/usr/local/bin/pylint
sonar.python.pylint_config=.pylintrc
sonar.python.pylint.reportPath=pylint-report.txt
# Coverage / Unit Tests
sonar.tests=./tests
sonar.test.inclusions=**/test_**.py
sonar.python.xunit.skipDetails=false
#DEFAULT VALUES: sonar.python.xunit.reportPath=xunit-reports/xunit-result-*.xml
#DEFAULT VALUES: sonar.python.coverage.reportPath=coverage-reports/*coverage-*.xml
The abridged source code tree is like so:
├── felix
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── process.cpython-35.pyc
│ │ └── spark.cpython-35.pyc
│ ├── felix.iml
│ ├── process.py
│ ├── spark.py
│ └── utils
│ └── utils.py
├── requirements.txt
├── setup.py
├── sonar-project.properties
├── tests
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ └── test_process.cpython-35-PYTEST.pyc
│ ├── cia-spark.iml
│ ├── data
│ └── test_process.py
└── tox.ini
I'm getting the following warning, though, when I run the sonar-scanner: WARN: The resource for '' is not found, drilling down to the details of this test won't be possible
Could someone, please, let me know why I'm getting this warning and how can I get rid of / fix it? Thanks.
I received this warning because I was excluding test files from analysis. I see than in your properties you are excluding your tests as well:
sonar.exclusions=**/test_*.py,**/**.pyc,felix/utils/*,**/*.iml
This will prevent sonar from calculating the number of tests and their pass/fail status as shown in the open source here
The issue turned out to be with the Pylint integrated into the Pytest call.
The parent Pytest call generated a unit testing report, which had empty classnames for additional "empty" tests that Pylint came up with.
SonarQube warned about those empty classnames.
I ended up removing Pylint Pytest integration and just running Pylint as a separate step from Pytest.

What are examples and what are they used for?

The directory layout of a Rust project should look like this (source)
.
├── 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
What is the file simple.rs under examples? How do I execute it? How should the file look like?
Examples are useful in library crates to show how the crate is used.
An example can be an executable with a main method or a library; it can either be in a single file examples/example-name.rs or consist of several files in a subdirectory examples/example-name/, with the main method in main.rs. To compile a library example you need to specify its crate type in Cargo.toml:
[[example]]
name = "example-name"
crate-type = ["lib"]
Examples are compiled by cargo test to ensure that they are up to date with the crate. You can run a specific executable example by
cargo run --example <example-name>
and selectively build any example with
cargo build --example <example-name>
This is documented in the Cargo Reference.

Can I specify a repository structure with a single Cargo.toml but multiple versions of the code, each with separate main.rs files?

I'm writing a book about embedded Rust using mdbook as one git repository and then I have another repository created by cargo where I place the code.
I'd like to structure the code so it corresponds with the chapters in the book and therefore is in separate directory.
The structure for the book:
├── book
├── book.toml
└── src
├── chapter_1.md
├── chapter_2.md
├── chapter_3.md
├── chapter_4.md
├── chapter_5.md
├── chapter_6.md
└── SUMMARY.md
And the structure for the code:
├── aarch64-unknown-none.json
├── Cargo.lock
├── Cargo.toml
├── layout.ld
├── Readme.md
├── chapter1
│   └── main.rs
├── chapter2
│ ├── boot.rs
│ └── main.rs
└── chapter3
├── boot.rs
├── console.rs
└── main.rs
I'd prefer this structure as the reader can then look directly at the code for the chapter and not search git commits. I also sometimes need to modify something later therefore git commits are not a solution.
Is there a way to specify this format in Cargo.toml? To either build all the directories or specify which one on the command line.
The exact solution can be found in the second edition of the Rust book with an example.
I restructured the repository like this:
├── aarch64-unknown-none.json
├── Cargo.lock
├── Cargo.toml
├── layout.ld
├── Readme.md
├── chapter1
│ ├── Cargo.toml
│ └── main.rs
├── chapter2
│ ├── boot.rs
│ ├── Cargo.toml
│ └── main.rs
└── chapter3
├── boot.rs
├── Cargo.toml
├── console.rs
└── main.rs
Cargo.toml files in the chapter directories remain without any modification. Only the Cargo.toml in the root is modified to contain the following:
[workspace]
members = ["chapter1", "chapter2", "chapter3"]
One small drawback to this solution is that the members must have different crate names in their Cargo.toml as the output of all members is stored in the target dir in the root of the workspace. This is only a small issue and I appreciate the flexibility Cargo offers.

Resources