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


#![allow(dead_code)]

extern crate ispc_compile;
extern crate ispc_rt;

pub use ispc_compile::*;
pub use ispc_rt::*;

/// Convenience macro for generating the module to hold the raw/unsafe ISPC bindings.
///
/// In addition to building the library with ISPC we use rust-bindgen to generate
/// a rust module containing bindings to the functions exported from ISPC. These
/// can be imported by passing the name of your library to the `ispc_module` macro.
///
/// # Example
///
/// ```ignore
/// #[macro_use]
/// extern crate ispc;
///
/// // Functions exported from foo will be callable under foo::*
/// ispc_module!(foo);
/// ```
#[macro_export]
macro_rules! ispc_module {
    ($lib:ident) => (
        include!(concat!(env!("ISPC_OUT_DIR"), "/", stringify!($lib), ".rs"));
    )
}