/ algorithms / cuda / build.rs
build.rs
 1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
 2  // This file is part of the deltavm library.
 3  
 4  // Licensed under the Apache License, Version 2.0 (the "License");
 5  // you may not use this file except in compliance with the License.
 6  // You may obtain a copy of the License at:
 7  
 8  // http://www.apache.org/licenses/LICENSE-2.0
 9  
10  // Unless required by applicable law or agreed to in writing, software
11  // distributed under the License is distributed on an "AS IS" BASIS,
12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  // See the License for the specific language governing permissions and
14  // limitations under the License.
15  
16  use std::{env, path::PathBuf};
17  
18  fn main() {
19      let curve = "FEATURE_BLS12_377";
20  
21      // Set CC environment variable to choose an alternative C compiler.
22      // Optimization level depends on whether or not --release is passed
23      // or implied.
24      let mut cc = cc::Build::new();
25  
26      let c_src_dir = PathBuf::from("src");
27      let files = vec![c_src_dir.join("lib.c")];
28      let mut cc_opt = None;
29  
30      match cfg!(feature = "portable") {
31          true => {
32              println!("Compiling in portable mode without ISA extensions");
33              cc_opt = Some("__BLST_PORTABLE__");
34          }
35          false => {
36              #[cfg(target_arch = "x86_64")]
37              {
38                  // account for cross-compilation [by examining environment variable]
39                  let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
40                  if target_arch.eq("x86_64") && std::is_x86_feature_detected!("adx") {
41                      println!("Enabling ADX because it was detected on the host");
42                      cc_opt = Some("__ADX__");
43                  }
44              }
45          }
46      }
47  
48      cc.flag_if_supported("-mno-avx") // avoid costly transitions
49          .flag_if_supported("-fno-builtin")
50          .flag_if_supported("-Wno-unused-command-line-argument");
51      if !cfg!(debug_assertions) {
52          cc.opt_level(2);
53      }
54      if let Some(def) = cc_opt {
55          cc.define(def, None);
56      }
57      if let Some(include) = env::var_os("DEP_BLST_C_SRC") {
58          cc.include(include);
59      }
60      cc.files(&files).compile("blst_msm");
61  
62      if cfg!(target_os = "windows") && !cfg!(target_env = "msvc") {
63          return;
64      }
65      // Detect if there is CUDA compiler and engage "cuda" feature accordingly
66      let nvcc = match env::var("NVCC") {
67          Ok(var) => which::which(var),
68          Err(_) => which::which("nvcc"),
69      };
70  
71      if nvcc.is_ok() {
72          let mut nvcc = cc::Build::new();
73          nvcc.cuda(true);
74          nvcc.flag("-g");
75          nvcc.flag("-arch=sm_70");
76          nvcc.flag("-maxrregcount=255");
77          nvcc.flag("-Xcompiler").flag("-Wno-unused-function");
78          nvcc.flag("-Xcompiler").flag("-Wno-subobject-linkage");
79          nvcc.define("TAKE_RESPONSIBILITY_FOR_ERROR_MESSAGE", None);
80          nvcc.define(curve, None);
81          if let Some(def) = cc_opt {
82              nvcc.define(def, None);
83          }
84          if let Some(include) = env::var_os("DEP_BLST_C_SRC") {
85              nvcc.include(include);
86          }
87          if let Some(include) = env::var_os("DEP_SPPARK_ROOT") {
88              nvcc.include(include);
89          }
90          nvcc.file("cuda/deltavm_api.cu").compile("deltavm_algorithms_cuda");
91  
92          println!("cargo:rustc-cfg=feature=\"cuda\"");
93          println!("cargo:rerun-if-changed=cuda");
94          println!("cargo:rerun-if-env-changed=CXXFLAGS");
95      } else {
96          println!("nvcc must be in the path. Consider adding /usr/local/cuda/bin.");
97          // panic!();
98      }
99  }