ispc/lib.rs
1//! # ispc-rs
2//!
3//! A small library meant to be used as a build dependency with Cargo for easily
4//! integrating [ISPC](https://ispc.github.io/) code into Rust projects.
5//!
6//! [](https://crates.io/crates/ispc)
7//! [](https://travis-ci.org/Twinklebear/ispc-rs)
8//!
9//! # Documentation
10//!
11//! Rust doc can be found [here](https://docs.rs/ispc/), ISPC documentation can
12//! be found [here](https://ispc.github.io).
13//!
14//! # Using ispc-rs
15//!
16//! With ispc-rs you can compile your ISPC code from your build script to
17//! generate a native library and a Rust module containing bindings to
18//! the exported ISPC functions. ispc-rs will output commands to Cargo to link
19//! the native library, and you can import the Rust bindings into your code using
20//! a provided macro to call into the library. Using ispc-rs in this mode
21//! requires that the ISPC compiler and clang are available when compiling your
22//! crate.
23//!
24//! When writing a crate or program which wants to package and use ISPC
25//! code, but not necessarily require these dependencies on the end user's system,
26//! ispc-rs is actually split into two crates: a compile time crate (`ispc_compile`)
27//! and a runtime crate (`ispc_rt`). The `ispc_compile` crate is used to compile
28//! the ISPC code in a build script, generating the native library and Rust bindings.
29//! The `ispc_rt` crate contains lightweight code to include in the build script
30//! which will find and link against the previously compiled native libraries,
31//! and a macro to import the previously generated Rust bindings. The recommended
32//! use case is to include `ispc_compile` as an optional dependency behind a feature
33//! gate. When building with this feature gate the ISPC code will be built, otherwise
34//! the runtime crate will find and use the existing libraries.
35//!
36//! # Using ispc-rs as a Single Crate
37//!
38//! To use ispc-rs as a single crate, you'll want to add a build script to your
39//! crate (`build.rs`), tell Cargo about it, and add ispc-rs as a build time and
40//! compile time dependency
41//!
42//! ```toml
43//! # Cargo.toml
44//! [package]
45//! # ...
46//! build = "build.rs"
47//!
48//! [dependencies]
49//! ispc = "2.0"
50//!
51//! [build-dependencies]
52//! ispc = "2.0"
53//! ```
54//!
55//! Now you can use `ispc` to compile your code into a static library:
56//!
57//! ```no_run
58//! extern crate ispc;
59//!
60//! fn main() {
61//! // Compile our ISPC library, this call will exit with EXIT_FAILURE if
62//! // compilation fails.
63//! ispc::compile_library("simple", &["src/simple.ispc"]);
64//! }
65//! ```
66//!
67//! Running `cargo build` should now build your ISPC files into a library and link your Rust
68//! application with it. For extra convenience the `ispc_module` macro is provided to import
69//! bindings to the library generated with [rust-bindgen](https://github.com/crabtw/rust-bindgen)
70//! into a module of the same name. Note that all the functions imported will be unsafe as they're
71//! the raw C bindings to your lib.
72//!
73//! ```ignore
74//! #[macro_use]
75//! extern crate ispc;
76//!
77//! // Functions exported from simple will be callable under simple::*
78//! ispc_module!(simple);
79//! ```
80//!
81//! ## Requirements for Compiling ISPC Code
82//!
83//! Both the [ISPC compiler](https://ispc.github.io/) and [libclang](http://clang.llvm.org/)
84//! (for [rust-bindgen](https://github.com/crabtw/rust-bindgen)) must be available in your path
85//! to compile the ISPC code and generate the bindings. These are not required if using `ispc_rt`
86//! to link against a previously compiled library.
87//!
88//! ### Windows Users
89//!
90//! You'll need Visual Studio and will have to use the MSVC ABI version of Rust since ISPC
91//! and Clang link with MSVC on Windows. For bindgen to find libclang you'll need to copy
92//! `libclang.lib` to `clang.lib` and place it in your path.
93//!
94//!
95//! # Using the Separate Compile and Runtime Crates
96//!
97//! The process of using the separate crates is similar to that of the single crate;
98//! however, you'll use the individual `ispc_compile` and `ispc_rt` crates, with the
99//! former marked as an optional dependency. This will allow end users to use the
100//! crate and leverage its ISPC code, without needing to re-build the code on their
101//! machine. For this reason, it's also recommended to build your ISPC code for multiple
102//! vector ISAs, to allow for portability across CPU architectures. You'll also need
103//! to package a compiled ISPC library for each host target triple. This can
104//! be done by building your crate with the ispc feature enabled on each target
105//! host system you want to support users of your library on. Note that users
106//! of your crate on a system you haven't provided a binary for can still compile the ISPC
107//! code themselves, by using your crate with the ispc feature enabled.
108//!
109//! ```toml
110//! # Cargo.toml
111//! [package]
112//! # ...
113//! build = "build.rs"
114//!
115//! [dependencies]
116//! ispc_rt = "2.0"
117//!
118//! [build-dependencies]
119//! ispc_rt = "2.0"
120//! ispc_compile = { "2.0", optional = true }
121//!
122//! [features]
123//! ispc = ["ispc_compile"]
124//! ```
125//!
126//! In the build script we can now use the `ispc` feature to optionally
127//! compile the ispc code using `ispc_compile`, otherwise we'll link the
128//! previously built code with `ispc_rt`. Here we'll also output the
129//! compiled ISPC libraries and bindings into the src/ directory.
130//!
131//! ```no_run
132//! extern crate ispc_rt;
133//! #[cfg(feature = "ispc")]
134//! extern crate ispc_compile;
135//!
136//! #[cfg(feature = "ispc")]
137//! fn link_ispc() {
138//! use ispc_compile::TargetISA;
139//! ispc_compile::Config::new()
140//! .file("src/simple.ispc")
141//! .target_isas(vec![
142//! TargetISA::SSE2i32x4,
143//! TargetISA::SSE4i32x4,
144//! TargetISA::AVX1i32x8,
145//! TargetISA::AVX2i32x8,
146//! TargetISA::AVX512KNLi32x16,
147//! TargetISA::AVX512SKXi32x16])
148//! .out_dir("src/")
149//! .compile("simple");
150//! }
151//!
152//! #[cfg(not(feature = "ispc"))]
153//! fn link_ispc() {
154//! ispc_rt::PackagedModule::new("simple")
155//! .lib_path("src/")
156//! .link();
157//! }
158//!
159//! fn main() {
160//! link_ispc();
161//! }
162//! ```
163//!
164//! Running `cargo build --features ispc` will now build your ISPC files into a library
165//! and generate bindings for your exported ISPC functions. The compiled library and
166//! generated bindings file will be saved under `src/`, to allow packaging with the rest
167//! of the crate. When building with `cargo build`, the previously compiled library
168//! for the host system will be linked against.
169//!
170//! Whether building with or without the ispc feature, you can import the generated
171//! bindings into your rust code with the `ispc_module!` macro as before:
172//!
173//! ```ignore
174//! #[macro_use]
175//! extern crate ispc;
176//!
177//! // Functions exported from simple will be callable under simple::*
178//! ispc_module!(simple);
179//! ```
180//!
181//! Some more complete examples can be found in the
182//! [examples/](https://github.com/Twinklebear/ispc-rs/tree/master/examples) folder.
183//! The separate crates example is [here](https://github.com/Twinklebear/ispc-rs/tree/master/examples/simple)
184
185#![allow(dead_code)]
186
187extern crate ispc_compile;
188extern crate ispc_rt;
189
190pub use ispc_compile::*;
191pub use ispc_rt::*;
192
193/// Convenience macro for generating the module to hold the raw/unsafe ISPC bindings.
194///
195/// In addition to building the library with ISPC we use rust-bindgen to generate
196/// a rust module containing bindings to the functions exported from ISPC. These
197/// can be imported by passing the name of your library to the `ispc_module` macro.
198///
199/// # Example
200///
201/// ```ignore
202/// #[macro_use]
203/// extern crate ispc;
204///
205/// // Functions exported from foo will be callable under foo::*
206/// ispc_module!(foo);
207/// ```
208#[macro_export]
209macro_rules! ispc_module {
210 ($lib:ident) => {
211 include!(concat!(env!("ISPC_OUT_DIR"), "/", stringify!($lib), ".rs"));
212 };
213}