How do I include extern functions from dependency crates? - rust

I had some extern "C" functions in my Rust library; then I decided to split the library up into a bunch of crates and make one workspace crate that just re-exports everything from its members. However, now that I have done this, the symbols for these extern "C" functions are missing from the generated .so file. How can I fix this?
I tried re-exporting the extern "C" functions individually; this did not work. I also tried setting crate-type = ["cdylib"] on the crate containing the functions, and this didn't work either.

According to this GitHub issue, the behaviour I'm seeing is a bug and there doesn't seem to be any known solution besides wrapping the functions that I want to re-export.

Related

What is proc_macro2 vs. proc-macro2?

Trying to learn procedural macros as part of internalizing Rust. I don't need competing crates. What is going on here?
proc-macro2:
https://crates.io/crates/proc-macro2
proc_macro2:
https://docs.rs/proc-macro2/latest/proc_macro2/
WTH is going on here? It's causing all sorts of issue trying to run "cargo upgrade" and somehow get cargo.toml and main.rs to agree on underscore vs dash. Seems very silly, what am I missing?
The crate name is with dash and that's how it needs to be specified in Cargo.toml.
But crate names with dashes become underscores for imports.
That's why docs.rs uses first dash - this is the crate name in crates.io - and second underscore - this is the crate name in Rust.

How to make an item visible in my binary crate targets but not any other crates?

I would like to generate multiple binaries using a lot of the same common code. If I write everything in src/main.rs I can simply mark items at pub(crate) and access the code without exporting it. However if I put the binary in src/bin/foo.rs then I can not find a way to access this without marking everything pub. I would not like to mark everything pub not only because I don't want others to depend on it but also because it renders visibility checking ineffective.
The only workaround I have found is to put the file inside of the src directory then put a simple shim in bin/foo-bar.rs that just calls my_crate::bin_foo_bar::main(). This isn't very tidy and requires a bunch of overhead.
Inside your package you may define a single lib crate and multiple binary crates. If you declare a type inside your library crate as pub(crate) it will obviously unvisible from your binary crates. So revise the definitions. A package is not a crate, it is a package of crates. And pub(crate) types are only visible inside the crate they belong to.

Why can actix_rt be used directly in the code, even if it wasn't declared?

I just added actix_rt in Cargo.toml and didn't declare it at the first line with the use keyword. Then I could use it in the code. I know some frequently used functions are included in the prelude of Rust, but I had no idea 3rd party libraries could do the some thing. Can I create a crate like that?
Any one could tell me why or give me some tips or some reference links? I'd appreciate it.
[dependencies]
actix-rt = "0.2.5"
actix-web = "1.0.8"
use std::io;
fn main() -> io::Result<()> {
let sys = actix_rt::System::new("basic");
sys.run()
}
In the Rust 2018 Edition, extern crate is no longer required. Putting a crate as a dependency allows it to be accessed as a module. There's nothing you need to do to make your crate accessible like this.
This is very different from the standard library prelude, which uses all the items in the prelude implicitly (with use std::prelude::v1::*;). With extern crate or adding an external crate as a dependency, the types, functions and traits have to be qualified. In your example, you have to use actix_rt::System::new("basic") rather than simply System::new("basic"). Compare this to std::prelude::v1::Option, which can be used as Option<T> without any prefix.

Is there a way of resolving a crate naming conflict? [duplicate]

I have a crate foo_sys. In Rust 2015 I used extern crate foo_sys as foo for convenience, but in Rust 2018 extern crate isn't needed anymore and I don't want to use it only for aliasing. When dropping extern crate, I get
error[E0463]: can't find crate for foo
This can be achieved with the rename-dependency Cargo feature, available in Rust 1.31. With this feature, it's possible to provide a package attribute to the dependencies:
The rename-dependency feature allows you to import a dependency with a different name from the source. This can be useful in a few scenarios:
Depending on crates with the same name from different registries.
Depending on multiple versions of a crate.
Avoid needing extern crate foo as bar in Rust source.
Instead of writing
[dependencies]
foo_sys = "0.2"
the package key can be added to the dependency in Cargo.toml:
[dependencies]
foo = { package = "foo_sys", version = "0.2" }
WARNING: Cargo prior to Rust 1.26.0 may download the wrong dependency when using this feature!
The idiomatic solution is to rename the crate in Cargo.toml. See the answer by Tim Diekmann for more information about that.
But if you don't want to use Cargo.toml renaming for some reason, you can still use the old syntax. It's soft-deprecated, but not removed. So this still works:
extern crate foo_sys as foo;
(Playground example)

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