Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kali committed May 19, 2018
0 parents commit 44ffb5b
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

/target
**/*.rs.bk
Cargo.lock
20 changes: 20 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
authors = ["Mathieu Poumeyrol <[email protected]>"]
name = "blis-sys"
version = "0.1.0"

[build-dependencies]
flate2 = "1.0.1"
git2 = "0.7"
reqwest = "0.8.5"
tar = "0.4.15"

[features]
default = ["cblas"]

cblas = []
static = []
system = []

[dependencies]
libc = "0.2.40"
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Blis-sys

This crate provides BLAS and/or CBLAS function using [BLIS](https://github.com/flame/blis).

Features:

* `cblas`: includes cblas binding (on by default)
* `static`: prefer static link (be very careful with this one on Apple platforms)
* `system`: do not compile blis, link it from a system-wide installation instead


93 changes: 93 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
extern crate flate2;
extern crate git2;
extern crate reqwest;
extern crate tar;

const BLIS_VERSION:&str = "0.3.2";

use std::{fs, path, process};

fn env(k: &str) -> Option<String> {
match std::env::var(k) {
Ok(v) => Some(v),
Err(_) => None,
}
}

fn obtain_source(out_dir:&path::Path) {
let blis_build = out_dir.join("src");
if !blis_build.exists() {
if env("BLIS_SYS_FROM_GITHUB").is_some() {
git_clone(out_dir);
} else {
download_release(out_dir);
}
}
}

fn git_clone(out_dir:&path::Path) {
git2::Repository::clone("https://github.com/flame/blis", out_dir.join("src")).unwrap();
}

fn download_release(out_dir:&path::Path) {
let blis_release = format!("https://github.com/flame/blis/archive/{}.tar.gz", BLIS_VERSION);
let stream = reqwest::get(&blis_release).unwrap();
let stream = flate2::read::GzDecoder::new(stream);
tar::Archive::new(stream).unpack(&out_dir).unwrap();
fs::rename(
out_dir.join(format!("blis-{}", BLIS_VERSION)),
out_dir.join("src"),
).unwrap();
}

fn compile(out_dir: &path::Path) {
let blis_build = out_dir.join("src");
let mut configure = process::Command::new(blis_build.join("configure"));
configure.current_dir(&blis_build)
.arg(format!("--prefix={}", out_dir.to_string_lossy()))
.arg("--enable-cblas")
.arg("--enable-shared")
.arg("--enable-threading=pthreads");
if let Some(cc) = env("TARGET_CC") {
configure.arg(format!("CC={}", cc));
}
if let Some(ranlib) = env("TARGET_RANLIB") {
configure.arg(format!("RANLIB={}", ranlib));
}
let arch = match &*env("CARGO_CFG_TARGET_ARCH").unwrap() {
"x86_64" => "x86_64",
"arm"|"armv7" => "arm32",
"aarch64" => "arm64",
_ => "generic"
};
configure.arg(arch);
assert!(configure
.status()
.unwrap()
.success()
);
assert!(
process::Command::new("make")
.arg("-j").arg("8")
.arg("install")
.current_dir(&blis_build)
.status()
.unwrap()
.success()
);
}

fn main() {
let out_dir = path::PathBuf::from(env("OUT_DIR").unwrap());
if env("CARGO_FEATURE_SYSTEM").is_none() {
let lib_dir = out_dir.join("lib");
let lib = lib_dir.join("libblis.a");
if !lib.exists() {
obtain_source(&out_dir);
compile(&out_dir);
}
println!("cargo:rustc-link-search=native={}", lib_dir.to_string_lossy());
}
let kind = if env("CARGO_FEATURE_STATIC").is_some() { "static" } else { "dylib" };
println!("cargo:rustc-link-lib={}=blis", kind);
}
54 changes: 54 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@

#[cfg(test)]
mod tests {

extern crate libc;
use self::libc::*;

extern {
pub fn bli_info_get_version_str() -> *const c_char;
pub fn sgemm_(
transa: *const c_char,
transb: *const c_char,
m: *const c_int,
n: *const c_int,
k: *const c_int,
alpha: *const c_float,
a: *const c_float,
lda: *const c_int,
b: *const c_float,
ldb: *const c_int,
beta: *const c_float,
c: *mut c_float,
ldc: *const c_int,
);
}

#[test]
fn it_links() {
use std::ffi::CStr;
unsafe {
let s = CStr::from_ptr(bli_info_get_version_str());
println!("blis version: {:?}", s);
}
}

#[test]
fn sgemm() {
let a = [ 1.0 ];
let b = [ 2.0 ];
let mut c = [ 12.0 ];

unsafe {
sgemm_(
&(b'N' as i8), &(b'N' as i8),
&1, &1, &1,
&1.0,
a.as_ptr(), &1,
b.as_ptr(), &1,
&0.0,
c.as_mut_ptr(), &1);
}
assert_eq!(&c, &[2.0]);
}
}
48 changes: 48 additions & 0 deletions tests/gemm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
extern crate libc;
extern crate blis_sys;

use libc::*;

extern "C" {
pub fn sgemm_(
transa: *const c_char,
transb: *const c_char,
m: *const c_int,
n: *const c_int,
k: *const c_int,
alpha: *const c_float,
a: *const c_float,
lda: *const c_int,
b: *const c_float,
ldb: *const c_int,
beta: *const c_float,
c: *mut c_float,
ldc: *const c_int,
);
}

#[test]
fn gemm() {
let a = [1.0];
let b = [2.0];
let mut c = [12.0];

unsafe {
sgemm_(
&(b'N' as i8),
&(b'N' as i8),
&1,
&1,
&1,
&1.0,
a.as_ptr(),
&1,
b.as_ptr(),
&1,
&0.0,
c.as_mut_ptr(),
&1,
);
}
assert_eq!(&c, &[2.0]);
}

0 comments on commit 44ffb5b

Please sign in to comment.