-
Notifications
You must be signed in to change notification settings - Fork 24
Re: Auto-generate CUDA bindings using Bindgen #4
Changes from all commits
25775f7
0fe3d4f
d0fc682
8b7a2ae
ee1e8bd
104a387
93a53d1
a75a427
a25340c
39f4731
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,146 @@ | ||
| extern crate bindgen; | ||
|
|
||
| use std::env; | ||
| use std::path::PathBuf; | ||
|
|
||
| fn find_library_paths() -> Vec<String> { | ||
| fn read_env() -> Vec<String> { | ||
| match env::var("CUDA_LIBRARY_PATH") { | ||
| Ok(path) => { | ||
| let split_char = if cfg!(target_os = "windows") { ";" } else { ":" }; | ||
| let split_char = if cfg!(target_os = "windows") { | ||
| ";" | ||
| } else { | ||
| ":" | ||
| }; | ||
|
|
||
| path.split(split_char).map(|s| s.to_owned()).collect::<Vec<_>>() | ||
| path.split(split_char) | ||
| .map(|s| s.to_owned()) | ||
| .collect::<Vec<_>>() | ||
| } | ||
| Err(_) => vec![], | ||
| } | ||
| } | ||
|
|
||
| fn main() { | ||
| for p in find_library_paths() { | ||
| println!("cargo:rustc-link-search=native={}", p); | ||
| fn find_cuda() -> PathBuf { | ||
| let mut candidates = read_env(); | ||
| candidates.push("/usr/local/cuda".to_string()); | ||
| candidates.push("/opt/cuda".to_string()); | ||
| for base in &candidates { | ||
| let base = PathBuf::from(base); | ||
| let path = base.join("include/cuda.h"); | ||
| if path.is_file() { | ||
| return base; | ||
| } | ||
| } | ||
| panic!("CUDA cannot find"); | ||
| } | ||
|
|
||
| fn main() { | ||
| let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); | ||
| let cuda_path = find_cuda(); | ||
|
|
||
| bindgen::builder() | ||
| .header("wrapper/cuda.h") | ||
| .clang_arg(format!("-I{}/include", cuda_path.display())) | ||
| .whitelist_recursively(false) | ||
| .whitelist_type("^CU.*") | ||
| .whitelist_type("^cuuint(32|64)_t") | ||
| .whitelist_type("^cudaError_enum") | ||
| .whitelist_type("^cudaMem.*") | ||
| .whitelist_var("^CU.*") | ||
| .whitelist_function("^CU.*") | ||
| .whitelist_function("^cu.*") | ||
| .default_enum_style(bindgen::EnumVariation::Rust) | ||
| .generate() | ||
| .expect("Unable to generate CUDA bindings") | ||
| .write_to_file(out_path.join("cuda_bindings.rs")) | ||
| .expect("Unable to write CUDA bindings"); | ||
|
|
||
| bindgen::builder() | ||
| .header("wrapper/cublas.h") | ||
| .clang_arg(format!("-I{}/include", cuda_path.display())) | ||
| .whitelist_recursively(false) | ||
| .whitelist_type("^cublas.*") | ||
| .whitelist_var("^cublas.*") | ||
| .whitelist_function("^cublas.*") | ||
| .default_enum_style(bindgen::EnumVariation::Rust) | ||
| .generate() | ||
| .expect("Unable to generate CUBLAS bindings") | ||
| .write_to_file(out_path.join("cublas_bindings.rs")) | ||
| .expect("Unable to write CUBLAS bindings"); | ||
|
|
||
| bindgen::builder() | ||
| .header("wrapper/cucomplex.h") | ||
| .clang_arg(format!("-I{}/include", cuda_path.display())) | ||
| .whitelist_recursively(false) | ||
| .whitelist_type("^cu.*Complex$") | ||
| .default_enum_style(bindgen::EnumVariation::Rust) | ||
| .generate() | ||
| .expect("Unable to generate CUComplex bindings") | ||
| .write_to_file(out_path.join("cucomplex_bindings.rs")) | ||
| .expect("Unable to write CUComplex bindings"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like this generates bindings for CUComplex and CUBLAS, but only links to CUBLAS. Was that intended? It seems like it should either link to CUComplex as well, or it should not generate bindings for it. I'd prefer to have separate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks only pub type cuFloatComplex = float2;
pub type cuDoubleComplex = double2;
pub type cuComplex = cuFloatComplex;are generated from CUComplex.h
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bheisler Thanks for the review! I can add one more problem to the list. cublas doesn't compile using CUDA 8. It's missing the __half and __half2 types. Unfortunately, I couldn't get Bindgen to detect those types in cuda_fp16.h. As a work-around, I've added them manually in LutzCle/accel@74a82a4.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've create an issue to track *-sys crate separation #9 |
||
|
|
||
| bindgen::builder() | ||
| .header("wrapper/cudart.h") | ||
| .clang_arg(format!("-I{}/include", cuda_path.display())) | ||
| .whitelist_recursively(false) | ||
| .whitelist_type("^cuda.*") | ||
| .whitelist_type("^surfaceReference") | ||
| .whitelist_type("^textureReference") | ||
| .whitelist_var("^cuda.*") | ||
| .whitelist_function("^cuda.*") | ||
| .default_enum_style(bindgen::EnumVariation::Rust) | ||
| .generate() | ||
| .expect("Unable to generate CUDA RT bindings") | ||
| .write_to_file(out_path.join("cudart_bindings.rs")) | ||
| .expect("Unable to write CUDA RT bindings"); | ||
|
|
||
| bindgen::builder() | ||
| .header("wrapper/driver_types.h") | ||
| .clang_arg(format!("-I{}/include", cuda_path.display())) | ||
| .whitelist_recursively(false) | ||
| .whitelist_type("^CU.*") | ||
| .whitelist_type("^cuda.*") | ||
| .default_enum_style(bindgen::EnumVariation::Rust) | ||
| .generate() | ||
| .expect("Unable to generate driver types bindings") | ||
| .write_to_file(out_path.join("driver_types_bindings.rs")) | ||
| .expect("Unable to write driver types bindings"); | ||
|
|
||
| bindgen::builder() | ||
| .header("wrapper/library_types.h") | ||
| .clang_arg(format!("-I{}/include", cuda_path.display())) | ||
| .whitelist_recursively(false) | ||
| .whitelist_type("^cuda.*") | ||
| .whitelist_type("^libraryPropertyType.*") | ||
| .default_enum_style(bindgen::EnumVariation::Rust) | ||
| .generate() | ||
| .expect("Unable to generate library types bindings") | ||
| .write_to_file(out_path.join("library_types_bindings.rs")) | ||
| .expect("Unable to write library types bindings"); | ||
|
|
||
| bindgen::builder() | ||
| .header("wrapper/vector_types.h") | ||
| .clang_arg(format!("-I{}/include", cuda_path.display())) | ||
| // .whitelist_recursively(false) | ||
| .whitelist_type("^u?char[0-9]$") | ||
| .whitelist_type("^dim[0-9]$") | ||
| .whitelist_type("^double[0-9]$") | ||
| .whitelist_type("^float[0-9]$") | ||
| .whitelist_type("^u?int[0-9]$") | ||
| .whitelist_type("^u?long[0-9]$") | ||
| .whitelist_type("^u?longlong[0-9]$") | ||
| .whitelist_type("^u?short[0-9]$") | ||
| .default_enum_style(bindgen::EnumVariation::Rust) | ||
| .derive_copy(true) | ||
| .generate() | ||
| .expect("Unable to generate vector types bindings") | ||
| .write_to_file(out_path.join("vector_types_bindings.rs")) | ||
| .expect("Unable to write vector types bindings"); | ||
|
|
||
| println!( | ||
| "cargo:rustc-link-search=native={}/lib64", | ||
| cuda_path.display() | ||
| ); | ||
| println!("cargo:rustc-link-lib=dylib=cuda"); | ||
| println!("cargo:rustc-link-lib=dylib=cudart"); | ||
| println!("cargo:rustc-link-lib=dylib=cublas"); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On Windows, I normally have to set my CUDA_LIBRARY_PATH to
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.1\lib\x64. It would be nice if it could find that for me. I can send a pull request later adding this feature though.A better error message would be:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, hey, I addressed your issue with Windows in #6