Testing a Rust crate outside of the source package - rust

I have created my Rust crate. It's a very trivial affair. It built fine and when tested within it's own source directory works just fine (I just included extern crate my_first_crate; in my test file).
I want to now test the crate in a totally different application.
If I add the same extern crate line to my new application, the compiler tells me that it can't find the crate. I expected this (I'd get the same in C if I told the compiler to link to a library it has no clue about!)
Do I need to copy the my_first_crate.rlib file from the source to the application target/debug folder or is there a way to tell cargo that it needs to link to the rlib file?

You need to add your crate as a dependency for your application. Add this to your application's Cargo.toml:
[dependencies]
my_first_crate = { path = "/path/to/crate" }
"/path/to/crate" is the path to the root of the crate's source (i.e. the directory that contains its Cargo.toml). You can use either a relative or an absolute path (but avoid absolute paths if you intend on publishing your code!).

Related

Is it possible to have example-specific build.rs file?

In my library I have few examples -- (normally) each one is represented by a single x<N>.rs file living in examples directory.
One example uses a .proto file -- this file needs to be compiled during build (of said example) and it's generated output is used by example itself.
I've tried this in my Cargo.toml:
[[example]]
name = "x1"
path = "examples/x1/main.rs"
build = "examples/x1/build.rs"
but build key gets ignored when I run cargo build --example x1
Is it possible to have example-specific build.rs file?
If not -- what is the correct way to deal with this situation?
Edit: I ended up processing that .proto file in crate's build.rs (even though it is not required to build that crate) and using artefacts in the example like this:
pub mod my_proto {
include!(concat!(env!("OUT_DIR"), "/my_proto.rs"));
}
This is not possible. This issue explains why, but in a nutshell build scripts are used for whole crate. So you could move your example into separate crate.

Can I apply a crate attribute only to the crate itself?

I have a Rust project that needs a few binaries with TitleCaseNames. So I created source files like src/bin/MyFooBinary.rs and src/bin/MyBarBinary.rs. The compiler warns that these binary crates should have snake case names, and I want to suppress that warning.
I can add #![allow(non_snake_case)] to the crate, but that then applies to the crate's entire contents as well. Not ideal. I really only want to suppress the warning for the crate name. Is that possible?
I'd suggest to follow the usual snake_name convention for the source file and crate names. Since you need to move the binaries elsewhere during deployment or packaging anyway, you can rename them at that point.
In the nightly compiler build, you can also specify a filename that is different from the crate name in Cargo.toml:
cargo-features = ["different-binary-name"]
[package]
# ...
[[bin]]
name = "foo_bar"
filename = "FooBar"
path = "src/bin/foo_bar.rs"

Can not create rust library for python

I am trying to make a python module in rust. I am continuing to fail to get the files that I need to generate. I followed this tutorial almost exactly.
https://mycognosist.github.io/tutorial-rust-python-lib.html
Here is my toml file.
name = "pylib"
version = "0.1.0"
authors = ["Atops"]
edition = "2018"
[lib]
name = "status"
crate-type = ["cdylib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies.cpython]
version = "0.5"
features = ["extension-module"]
Here is the code for lib.rs
extern crate cpython;
use cpython::{PyResult, Python, py_fn, py_module_initializer};
pub extern fn hello(_py: Python, val: String) -> PyResult<String> {
match &*val {
"hello" => Ok("world".to_string()),
_ => Ok("afdfs".to_string()),
}
}
py_module_initializer!(status, initstatus, Pyinit_status, |py, m|{
m.add(py, "__doc__", "asdhgdfs")?;
m.add(py, "hello", py_fn!(py, hello(val: String)))?;
Ok(())
});
I navigate to the appropriate folder with my cargo.toml file and use cargo build --release, as specified in the tutorial. It finishes with a few warnings about certain things being "not FFI-safe". When it finishes a new folder is created called "target". I go through there to where the files for the library should be, but the appropriate files don't seem to have been generated. I have these.
target\release
These don't seem to be usable for me. I am not sure what I have done wrong.
I copied every single one of these files to another folder and tried importing them in python. This did not work. I tried changing them to .so files, this did not work. It seems that windows is supposed to output a dll here, but the dll file did not work when attempting to import. It did not work as a dll file or a so file. I am not sure what to do here. Also, it seems that when these files are generated in every other tutorial or guide I see, there is a "lib" prefix on the name of each. I get no such prefix.
A dll file contains shared object code for COFF systems (like Windows) while a so file generally contains shared object code for ELF (and other) systems like Linux.
Renaming them will not work under any circumstance. If you have one and need the other, you need to rebuild them on the correct, matching, operating system.
I think you might be following instructions for Linux (due to the lib prefixes) on a Windows machine and then expecting some of the instructions to work. They might work, if you can identify all the "changes" between the platform and modify the Linux instructions to match the Windows platform; but until you know how to translate one environment's instructions to the other, it might be easier if you just find a set of Windows instructions that only refer to dll files and don't mention so files.

What is a Rust systest?

I sometimes see that a Rust crate has a folder called systest. I guess that the name stands for "system test", but I can't find any documentation of this.
My questions are:
What is the purpose of a systest? Just testing that a crate compiles fine, or also testing that some code in another crate runs fine?
What are the rules to follow when writing a systest? Is it just a crate in a folder called systest?
Why does the lib.rs in systest/src seem to always include a file all.rs generated from build.rs?
systest is not a standard name used in Rust or Cargo. However, it is the name suggested by the documentation for ctest, which performs automated testing for FFI bindings. build.rs uses ctest to generate the all.rs file which contains the tests, and this is included from the main file.
According to the documentation, the tests generate include ensuring that all function signatures, constant values, struct layout/alignment, type size/alignment, etc., all match their C equivalent.

Figure out code from what module is "use"d in a large rust project (servo)

I'm trying to read the code of servo. As an example, I'm looking at this code in layout_task.rs:
use url::Url;
..and I want to know which code this refers to (the answer is rust-url).
Per the Rust reference §6.1.2.2 Use declarations,
the paths contained in use items are relative to the crate root [...]
It is also possible to use self and super at the beginning of a use item to refer to the current and direct parent modules respectively.
All rules regarding accessing declared modules in use declarations apply to both module declarations and extern crate declarations.
The reference (§5 Crates and source files) does not explicitly say what a "crate root" is, but it does share that:
A crate contains a tree of nested module scopes. The top level of this tree is a module that is anonymous [...] The Rust compiler is always invoked with a single source file as input, and always produces a single output crate. The processing of that source file may result in other source files being loaded as modules.
So it seems that to find the crate root that the current file (layout_task.rs) belongs to, we need to figure out what source file rustc is invoked with when building the crate. With Cargo this is specified in Cargo.toml and defaults to src/lib.rs:
[lib]
path = "src/lib.rs"
In my case, here's Cargo.toml and the lib.rs has:
extern crate url;
pub mod layout_task;
So far so good. To find out what the extern crate refers to, we need to look at Cargo.toml again:
[dependencies.url]
version = "0.2"
The cargo docs claim that "Dependencies from crates.io are not declared with separate sections", but apparently they can be... So we look the package up on crates.io: https://crates.io/crates/url

Resources