Could not find `Options` in `getopts` - rust

I am trying to use the Options struct in the getopts crate, which exists according to the Rust book.
The code I am running is this.
let mut opts = getopts::Options::new();
While building the project the compiler gives the error
let mut opts = getopts::Options::new();
^^^^^^^^^^^^^^^^^^^^^ Could not find `Options in `getopts`
How do I resolve this? I am using the nightly version of Rust.

You need to use the crates.io version instead. You can see here that the built-in version of getopts has been flagged as a compiler internal with rustc_private. The version on crates.io is basically the same crate. The compiler-internal version is just kept segregated for various reasons.

Related

How to protect nightly feature 'extended_key_value_attributes' behind a crate feature?

I run code using stable and document it using nightly, mostly because of the automatic links.
I tried to include a long inner documentation by #![doc = include_str!("doc.md")] in the code, but only use it if using nightly, as it is unstable. The standard way to do it seems to be with an explicit feature.
I declared a nightly feature on my Cargo.toml, and tried:
#![cfg_attr(feature = "nightly",
feature(extended_key_value_attributes),
doc = include_str!("doc.md"))]
which works as expected with cargo +nightly doc --features nightly, but is not supported by stable:
> cargo +stable build
[...]
error[E0658]: arbitrary expressions in key-value attributes are unstable
I suspect the cfg_attr has to parse all its arguments even if not using them, so the macro syntax within the #[]makes things more complicated.
How can I do this correctly?

How to programmatically compile Rust programs?

Given metadata about the library I am trying to create in the form of an expression tree, I would like to be able to convert this into some sort of Rust-specific syntax tree that can be given to the Rust compiler.
I found a related question but it is outdated.
Yes there is. The Rust compiler itself. The entire compiler is a library and rustc is just a small crate that calls into the compiler. As an example there's the stupid-stats crate. It runs the rust compiler to generate some statistics about the code.
All you need is to import the rustc and rustc_driver crates (with extern crate) and implement the rustc_driver::CompilerCalls trait for a type (lets call it MyDriver). Then you can run rustc like this:
let args: Vec<_> = std::env::args().collect();
let mut my_driver = MyDriver::new();
rustc_driver::run_compiler(&args, &mut my_driver);
You need to make sure that the path to the standard library and core library is passed. In my case I added
"-L $HOME/.multirust/toolchains/nightly/lib/rustlib/x86_64-unknown-linux-gnu/lib"
to the command line. You cannot simply add this to the args vector, because $HOME isn't parsed here. So you need some more code that extracts the $HOME env var and builds your command.

Issue when replacing a crates dependency with a local version

So I am trying to serialize a struct using bincode following these instructions, and I was able to get that to work.
But then I wanted to serialize a struct with an IpAddr enum. Since IpAddr doesn't implement the Encodable trait needed, I downloaded the rustc_serialize crate from git and implemented encodable for IpAddr myself. I then changed my Cargo.toml file to:
[dependencies]
# rustc-serialize = "0.3"
byteorder = "0.3"
bincode = "0.4"
[dependencies.rustc-serialize]
path = "src/rustc-serialize-master"
But now, the same code from the struct I was using doesn't compile saying that
rustc_serialize::serialize::Encodable is not implemented for my struct even though i have #[derive(RustcEncodable)] above the struct.
Even when I get rid of the code I added to the local version of rustc_serialize, I still get that error.
I think it might be due to something being screwed up with the way bincode and a local rustc_serialize interact, but I'm not sure.
Please review the Cargo documentation on overriding dependencies:
To specify overrides, create a .cargo/config file in some ancestor of your project's directory (common places to put it is in the root of your code directory or in your home directory).
Inside that file, put this:
paths = ["/path/to/project/rand"]
Going deeper, you are likely running into issue 22750 - two different versions of a crate interacting leads to unhelpful error messages. When you add rustc-serialize to your dependencies, you aren't replacing the old version, you are adding a new one.
In general, this is a good feature. If my project relies on crates A and B and they both rely on crate Z but with different versions, Rust can handle that just fine. The problem arises when they re-export items from those crates.

How to get a crate's version number? [duplicate]

How do you access a Cargo package's metadata (e.g. version) from the Rust code in the package? In my case, I am building a command line tool that I'd like to have a standard --version flag, and I'd like the implementation to read the version of the package from Cargo.toml so I don't have to maintain it in two places. I can imagine there are other reasons someone might want to access Cargo metadata from the program as well.
Cargo passes some metadata to the compiler through environment variables, a list of which can be found in the Cargo documentation pages.
The compiler environment is populated by fill_env in Cargo's code. This code has become more complex since earlier versions, and the entire list of variables is no longer obvious from it because it can be dynamic. However, at least the following variables are set there (from the list in the docs):
CARGO_MANIFEST_DIR
CARGO_PKG_AUTHORS
CARGO_PKG_DESCRIPTION
CARGO_PKG_HOMEPAGE
CARGO_PKG_NAME
CARGO_PKG_REPOSITORY
CARGO_PKG_VERSION
CARGO_PKG_VERSION_MAJOR
CARGO_PKG_VERSION_MINOR
CARGO_PKG_VERSION_PATCH
CARGO_PKG_VERSION_PRE
You can access environment variables using the env!() macro. To insert the version number of your program you can do this:
const VERSION: &str = env!("CARGO_PKG_VERSION");
// ...
println!("MyProgram v{}", VERSION);
If you want your program to compile even without Cargo, you can use option_env!():
const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION");
// ...
println!("MyProgram v{}", VERSION.unwrap_or("unknown"));
The built-crate helps with serializing a lot of Cargo's environment without all the boilerplate.
At build-time (as in build.rs), cargo_metadata may be useful. For example:
let path = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let meta = MetadataCommand::new()
.manifest_path("./Cargo.toml")
.current_dir(&path)
.exec()
.unwrap();
let root = meta.root_package().unwrap();
let option = root.metadata["my"]["option"].as_str().unwrap();
let version = &root.version;
...

How can a Rust program access metadata from its Cargo package?

How do you access a Cargo package's metadata (e.g. version) from the Rust code in the package? In my case, I am building a command line tool that I'd like to have a standard --version flag, and I'd like the implementation to read the version of the package from Cargo.toml so I don't have to maintain it in two places. I can imagine there are other reasons someone might want to access Cargo metadata from the program as well.
Cargo passes some metadata to the compiler through environment variables, a list of which can be found in the Cargo documentation pages.
The compiler environment is populated by fill_env in Cargo's code. This code has become more complex since earlier versions, and the entire list of variables is no longer obvious from it because it can be dynamic. However, at least the following variables are set there (from the list in the docs):
CARGO_MANIFEST_DIR
CARGO_PKG_AUTHORS
CARGO_PKG_DESCRIPTION
CARGO_PKG_HOMEPAGE
CARGO_PKG_NAME
CARGO_PKG_REPOSITORY
CARGO_PKG_VERSION
CARGO_PKG_VERSION_MAJOR
CARGO_PKG_VERSION_MINOR
CARGO_PKG_VERSION_PATCH
CARGO_PKG_VERSION_PRE
You can access environment variables using the env!() macro. To insert the version number of your program you can do this:
const VERSION: &str = env!("CARGO_PKG_VERSION");
// ...
println!("MyProgram v{}", VERSION);
If you want your program to compile even without Cargo, you can use option_env!():
const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION");
// ...
println!("MyProgram v{}", VERSION.unwrap_or("unknown"));
The built-crate helps with serializing a lot of Cargo's environment without all the boilerplate.
At build-time (as in build.rs), cargo_metadata may be useful. For example:
let path = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let meta = MetadataCommand::new()
.manifest_path("./Cargo.toml")
.current_dir(&path)
.exec()
.unwrap();
let root = meta.root_package().unwrap();
let option = root.metadata["my"]["option"].as_str().unwrap();
let version = &root.version;
...

Resources