From e696e2cbdf8959a761b228ce23957690a141ab56 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Thu, 5 Aug 2021 13:55:09 +1200 Subject: [PATCH 1/3] add user settings to BuildConfig and expose them to cli args via structopt --- src/bin/tvm-build.rs | 5 +- src/core.rs | 428 +++++++++++++++++++++++++++++++++++-------- src/lib.rs | 2 +- 3 files changed, 359 insertions(+), 76 deletions(-) diff --git a/src/bin/tvm-build.rs b/src/bin/tvm-build.rs index c80f834..e5936d4 100644 --- a/src/bin/tvm-build.rs +++ b/src/bin/tvm-build.rs @@ -1,6 +1,6 @@ use structopt::StructOpt; use tracing_subscriber; -use tvm_build::{self, build, BuildConfig}; +use tvm_build::{self, build, BuildConfig, UserSettings}; #[derive(StructOpt, Debug)] #[structopt()] @@ -13,6 +13,8 @@ struct InstallCommand { clean: bool, #[structopt(short, long)] verbose: bool, + #[structopt(flatten)] + settings: UserSettings, } #[derive(StructOpt, Debug)] @@ -49,6 +51,7 @@ fn main() -> anyhow::Result<()> { config.clean = install_cmd.clean; config.repository = install_cmd.repository; config.verbose = install_cmd.verbose; + config.settings = install_cmd.settings; build(config)?; Ok(()) } diff --git a/src/core.rs b/src/core.rs index 18e9020..8b86090 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,4 +1,5 @@ -use std::path::PathBuf; +use std::{ascii::AsciiExt, path::PathBuf, str::FromStr}; +use structopt::StructOpt; use cmake; use dirs; @@ -31,121 +32,209 @@ pub enum Error { /// /// This enumeration represents all cases in a more Rust friendly way. #[derive(Debug)] -pub enum TVMCMakeSetting { +pub enum CMakeSetting { On, Off, Path(PathBuf), } -#[derive(Debug)] -pub struct BuildConfig { - pub repository: Option, - pub repository_path: Option, - pub output_path: Option, - pub branch: Option, - pub verbose: bool, - pub clean: bool, +impl FromStr for CMakeSetting { + type Err = std::convert::Infallible; + + fn from_str(s: &str) -> Result { + match s.to_ascii_lowercase().as_str() { + "on" => Ok(CMakeSetting::On), + "off" => Ok(CMakeSetting::Off), + _ => Ok(CMakeSetting::Path(PathBuf::from_str(s)?)), + } + } +} + +/// Convert something into a value that can be used in `cmake::Config::define`. +trait CMakeSettingValue { + fn as_string_value(&self) -> String; +} + +impl CMakeSettingValue for &bool { + fn as_string_value(&self) -> String { + if **self { "ON" } else { "OFF" }.to_string() + } +} + +impl CMakeSettingValue for &PathBuf { + fn as_string_value(&self) -> String { + format!("{}", self.display()) + } +} + +impl CMakeSettingValue for &String { + fn as_string_value(&self) -> String { + self.to_string() + } +} + +impl CMakeSettingValue for &CMakeSetting { + fn as_string_value(&self) -> String { + match self { + CMakeSetting::On => "ON".to_string(), + CMakeSetting::Off => "OFF".to_string(), + CMakeSetting::Path(path) => path.as_string_value(), + } + } +} +#[derive(Debug, Default, StructOpt)] +pub struct UserSettings { // TVM Build Configuration Options /// Build with the CUDA support enabled. - pub use_cuda: Option, + #[structopt(long)] + pub use_cuda: Option, /// Build with the CUDA runtime enabled. - pub use_opencl: Option, + #[structopt(long)] + pub use_opencl: Option, // Build with Vulkan runtime enabled. - pub use_vulkan: Option, - pub use_metal: Option, - pub use_rocm: Option, + #[structopt(long)] + pub use_vulkan: Option, + #[structopt(long)] + pub use_metal: Option, + #[structopt(long)] + pub use_rocm: Option, /// The path to ROCM. + #[structopt(long)] pub rocm_path: Option, /// Build with Hexagon device support in TVM runtime. + #[structopt(long)] pub use_hexagon_device: Option, /// Path to the Hexagon SDK root (required for Hexagon support in TVM runtime or for building TVM runtime for Hexagon. + #[structopt(long)] pub use_heaxgon_dsk: Option, /// Whether to enable TVM RPC. + #[structopt(long)] pub use_rpc: Option, /// Build with threading support. + #[structopt(long)] pub use_threads: Option, /// Build with LLVM, can also be set to specific llvm-config path. - pub use_llvm: Option, + #[structopt(long)] + pub use_llvm: Option, /// Enable TVM's stackvm in the runtime. + #[structopt(long)] pub use_stackvm_runtime: Option, /// Build with graph runtime, defaults to ON. + #[structopt(long)] pub use_graph_runtime: Option, /// Build with graph runtime debug mode, defaults to OFF. + #[structopt(long)] pub use_graph_runtime_debug: Option, /// Build with OpenMP thread pool implementation, defaults to OFF. + #[structopt(long)] pub use_openmp: Option, /// Build Relay in debug mode, defaults to OFF. + #[structopt(long)] pub use_relay_debug: Option, /// Build with RTTI, defaults to ON. + #[structopt(long)] pub use_rtti: Option, /// Build with multi-threaded MSCV runtime. + #[structopt(long)] pub use_mscv_mt: Option, /// Build with Micro TVM support. + #[structopt(long)] pub use_micro: Option, /// Install compiler infrastructure, defaults to OFF. + #[structopt(long)] pub use_install_dev: Option, /// Compile with -fvisibility=hidden. + #[structopt(long)] pub hide_private_symbols: Option, /// Use TVM's POD compatible Map, defaults to OFF. + #[structopt(long)] pub use_fallback_stl_map: Option, /// tvm_option(USE_ETHOSN "Build with Arm Ethos-N" OFF) + #[structopt(long)] pub use_ethosn: Option, /// Defaults the index datatype to int64. + #[structopt(long)] pub use_index_default_i64: Option, /// Build with TensorFlow TVMDSOOp. + #[structopt(long)] pub use_tf_tvmdsoop: Option, // Contrib library options. /// Build with BYODT software emulated posit custom datatype. + #[structopt(long)] pub use_byodt_posit: Option, /// The blas library to be linked. + #[structopt(long)] pub use_blas: Option, // tvm_option(USE_MKL "MKL root path when use MKL blas" OFF) - pub use_mkl: Option, + #[structopt(long)] + pub use_mkl: Option, /// "Build with MKLDNN" - pub use_mkldnn: Option, + #[structopt(long)] + pub use_mkldnn: Option, /// Enable MKLDNN (DNNL) codegen. + #[structopt(long)] pub use_dnnl_codegen: Option, // tvm_opt"Build with cuDNN" OFF) + #[structopt(long)] pub use_cudnn: Option, // tvm_option(USE_CUBLAS "Build with cuBLAS" OFF) + #[structopt(long)] pub use_cublas: Option, // tvm_option(USE_THRUST "Build with Thrust" OFF) + #[structopt(long)] pub use_thrust: Option, // tvm_option(USE_MIOPEN "Build with ROCM:MIOpen" OFF) + #[structopt(long)] pub use_miopen: Option, // tvm_option(USE_ROCBLAS "Build with ROCM:RoCBLAS" OFF) + #[structopt(long)] pub use_rocblas: Option, // tvm_option(USE_SORT "Build with sort support" ON) + #[structopt(long)] pub use_sort: Option, // tvm_option(USE_NNPACK "Build with nnpack support" OFF) + #[structopt(long)] pub use_nnpack: Option, // tvm_option(USE_RANDOM "Build with random support" ON) + #[structopt(long)] pub use_random: Option, // tvm_option(USE_MICRO_STANDALONE_RUNTIME "Build with micro.standalone_runtime support" OFF) + #[structopt(long)] pub use_micro_standalone_runtime: Option, // tvm_option(USE_CPP_RPC "Build CPP RPC" OFF) + #[structopt(long)] pub use_cpp_rpc: Option, // tvm_option(USE_TFLITE "Build with tflite support" OFF) + #[structopt(long)] pub use_tflite: Option, // tvm_option(USE_TENSORFLOW_PATH "TensorFlow root path when use TFLite" none) + #[structopt(long)] pub use_tensorflow_path: Option, // tvm_option(USE_COREML "Build with coreml support" OFF) + #[structopt(long)] pub use_coreml: Option, // tvm_option(USE_TARGET_ONNX "Build with ONNX Codegen support" OFF) + #[structopt(long)] pub use_target_onnx: Option, // tvm_option(USE_ARM_COMPUTE_LIB "Build with Arm Compute Library" OFF) + #[structopt(long)] pub use_arm_compute_lib: Option, // tvm_option(USE_ARM_COMPUTE_LIB_GRAPH_RUNTIME "Build with Arm Compute Library graph runtime" OFF) - pub use_arm_compute_lib_graph_runtime: Option, + #[structopt(long)] + pub use_arm_compute_lib_graph_runtime: Option, /// Build with TensorRT Codegen support, defaults to OFF> + #[structopt(long)] pub use_tensorrt_codegen: Option, /// Build with TensorRT runtime, defaults to OFF. - pub use_tensorrt_runtime: Option, + #[structopt(long)] + pub use_tensorrt_runtime: Option, /// Build with Rust based compiler extensions, defaults to OFF. + #[structopt(long)] pub use_rust_ext: Option, /// Build with VITIS-AI Codegen support, defaults to OFF. + #[structopt(long)] pub use_vitis_ai: Option, // Note(@jroesch): these options are supported by TVM but not exposed by this interface // we instead use defaults. @@ -156,6 +245,22 @@ pub struct BuildConfig { // tvm_option(RANG_PATH "Path to RANG" "3rdparty/rang/include") // tvm_option(COMPILER_RT_PATH "Path to COMPILER-RT" "3rdparty/compiler-rt") // tvm_option(PICOJSON_PATH "Path to PicoJSON" "3rdparty/picojson") + + /// Whether to build static libtvm_runtime.a, the default is to build the dynamic + /// version: libtvm_runtime.so. + #[structopt(long)] + build_static_runtime: Option, +} + +#[derive(Debug)] +pub struct BuildConfig { + pub repository: Option, + pub repository_path: Option, + pub output_path: Option, + pub branch: Option, + pub verbose: bool, + pub clean: bool, + pub settings: UserSettings, } impl std::default::Default for BuildConfig { @@ -167,64 +272,11 @@ impl std::default::Default for BuildConfig { branch: None, verbose: false, clean: false, - use_cuda: None, - use_opencl: None, - use_vulkan: None, - use_metal: None, - use_rocm: None, - rocm_path: None, - use_hexagon_device: None, - use_heaxgon_dsk: None, - use_rpc: None, - use_threads: None, - use_llvm: None, - use_stackvm_runtime: None, - use_graph_runtime: None, - use_graph_runtime_debug: None, - use_openmp: None, - use_relay_debug: None, - use_rtti: None, - use_mscv_mt: None, - use_micro: None, - use_install_dev: None, - hide_private_symbols: None, - use_fallback_stl_map: None, - use_ethosn: None, - use_index_default_i64: None, - use_tf_tvmdsoop: None, - use_byodt_posit: None, - use_blas: None, - use_mkl: None, - use_mkldnn: None, - use_dnnl_codegen: None, - use_cudnn: None, - use_cublas: None, - use_thrust: None, - use_miopen: None, - use_rocblas: None, - use_sort: None, - use_nnpack: None, - use_random: None, - use_micro_standalone_runtime: None, - use_cpp_rpc: None, - use_tflite: None, - use_tensorflow_path: None, - use_coreml: None, - use_target_onnx: None, - use_arm_compute_lib: None, - use_arm_compute_lib_graph_runtime: None, - use_tensorrt_codegen: None, - use_tensorrt_runtime: None, - use_rust_ext: None, - use_vitis_ai: None, + settings: UserSettings::default(), } } } -pub struct Revision { - revision: String, -} - // convert to lazy? pub(crate) fn tvm_build_directory() -> PathBuf { let home_dir = dirs::home_dir().expect("requires a home directory"); @@ -277,6 +329,229 @@ impl BuildConfig { Ok(revision) } + + fn setting_key_value(k: &str, value: T) -> (String, String) { + (k.to_string(), value.as_string_value()) + } + + // Returns any user settings to be "set" as cmake definitions. + pub fn as_cmake_define_key_values(&self) -> impl Iterator { + let UserSettings { + use_cuda, + use_opencl, + use_vulkan, + use_metal, + use_rocm, + rocm_path, + use_hexagon_device, + use_heaxgon_dsk, + use_rpc, + use_threads, + use_llvm, + use_stackvm_runtime, + use_graph_runtime, + use_graph_runtime_debug, + use_openmp, + use_relay_debug, + use_rtti, + use_mscv_mt, + use_micro, + use_install_dev, + hide_private_symbols, + use_fallback_stl_map, + use_ethosn, + use_index_default_i64, + use_tf_tvmdsoop, + use_byodt_posit, + use_blas, + use_mkl, + use_mkldnn, + use_dnnl_codegen, + use_cudnn, + use_cublas, + use_thrust, + use_miopen, + use_rocblas, + use_sort, + use_nnpack, + use_random, + use_micro_standalone_runtime, + use_cpp_rpc, + use_tflite, + use_tensorflow_path, + use_coreml, + use_target_onnx, + use_arm_compute_lib, + use_arm_compute_lib_graph_runtime, + use_tensorrt_codegen, + use_tensorrt_runtime, + use_rust_ext, + use_vitis_ai, + build_static_runtime + } = &self.settings; + + vec![ + use_cuda + .as_ref() + .map(|s| Self::setting_key_value("USE_CUDA", s)), + use_opencl + .as_ref() + .map(|s| Self::setting_key_value("USE_OPENCL", s)), + use_vulkan + .as_ref() + .map(|s| Self::setting_key_value("USE_VULKAN", s)), + use_metal + .as_ref() + .map(|s| Self::setting_key_value("USE_METAL", s)), + use_rocm + .as_ref() + .map(|s| Self::setting_key_value("USE_ROCM", s)), + rocm_path + .as_ref() + .map(|s| Self::setting_key_value("ROCM_PATH", s)), + use_hexagon_device + .as_ref() + .map(|s| Self::setting_key_value("USE_HEXAGON_DEVICE", s)), + use_heaxgon_dsk + .as_ref() + .map(|s| Self::setting_key_value("USE_HEAXGON_DSK", s)), + use_rpc + .as_ref() + .map(|s| Self::setting_key_value("USE_RPC", s)), + use_threads + .as_ref() + .map(|s| Self::setting_key_value("USE_THREADS", s)), + use_llvm + .as_ref() + .map(|s| Self::setting_key_value("USE_LLVM", s)), + use_stackvm_runtime + .as_ref() + .map(|s| Self::setting_key_value("USE_STACKVM_RUNTIME", s)), + use_graph_runtime + .as_ref() + .map(|s| Self::setting_key_value("USE_GRAPH_RUNTIME", s)), + use_graph_runtime_debug + .as_ref() + .map(|s| Self::setting_key_value("USE_GRAPH_RUNTIME_DEBUG", s)), + use_openmp + .as_ref() + .map(|s| Self::setting_key_value("USE_OPENMP", s)), + use_relay_debug + .as_ref() + .map(|s| Self::setting_key_value("USE_RELAY_DEBUG", s)), + use_rtti + .as_ref() + .map(|s| Self::setting_key_value("USE_RTTI", s)), + use_mscv_mt + .as_ref() + .map(|s| Self::setting_key_value("USE_MSCV_MT", s)), + use_micro + .as_ref() + .map(|s| Self::setting_key_value("USE_MICRO", s)), + use_install_dev + .as_ref() + .map(|s| Self::setting_key_value("USE_INSTALL_DEV", s)), + hide_private_symbols + .as_ref() + .map(|s| Self::setting_key_value("HIDE_PRIVATE_SYMBOLS", s)), + use_fallback_stl_map + .as_ref() + .map(|s| Self::setting_key_value("USE_FALLBACK_STL_MAP", s)), + use_ethosn + .as_ref() + .map(|s| Self::setting_key_value("USE_ETHOSN", s)), + use_index_default_i64 + .as_ref() + .map(|s| Self::setting_key_value("USE_INDEX_DEFAULT_I64", s)), + use_tf_tvmdsoop + .as_ref() + .map(|s| Self::setting_key_value("USE_TF_TVMDSOOP", s)), + use_byodt_posit + .as_ref() + .map(|s| Self::setting_key_value("USE_BYODT_POSIT", s)), + use_blas + .as_ref() + .map(|s| Self::setting_key_value("USE_BLAS", s)), + use_mkl + .as_ref() + .map(|s| Self::setting_key_value("USE_MKL", s)), + use_mkldnn + .as_ref() + .map(|s| Self::setting_key_value("USE_MKLDNN", s)), + use_dnnl_codegen + .as_ref() + .map(|s| Self::setting_key_value("USE_DNNL_CODEGEN", s)), + use_cudnn + .as_ref() + .map(|s| Self::setting_key_value("USE_CUDNN", s)), + use_cublas + .as_ref() + .map(|s| Self::setting_key_value("USE_CUBLAS", s)), + use_thrust + .as_ref() + .map(|s| Self::setting_key_value("USE_THRUST", s)), + use_miopen + .as_ref() + .map(|s| Self::setting_key_value("USE_MIOPEN", s)), + use_rocblas + .as_ref() + .map(|s| Self::setting_key_value("USE_ROCBLAS", s)), + use_sort + .as_ref() + .map(|s| Self::setting_key_value("USE_SORT", s)), + use_nnpack + .as_ref() + .map(|s| Self::setting_key_value("USE_NNPACK", s)), + use_random + .as_ref() + .map(|s| Self::setting_key_value("USE_RANDOM", s)), + use_micro_standalone_runtime + .as_ref() + .map(|s| Self::setting_key_value("USE_MICRO_STANDALONE_RUNTIME", s)), + use_cpp_rpc + .as_ref() + .map(|s| Self::setting_key_value("USE_CPP_RPC", s)), + use_tflite + .as_ref() + .map(|s| Self::setting_key_value("USE_TFLITE", s)), + use_tensorflow_path + .as_ref() + .map(|s| Self::setting_key_value("USE_TENSORFLOW_PATH", s)), + use_coreml + .as_ref() + .map(|s| Self::setting_key_value("USE_COREML", s)), + use_target_onnx + .as_ref() + .map(|s| Self::setting_key_value("USE_TARGET_ONNX", s)), + use_arm_compute_lib + .as_ref() + .map(|s| Self::setting_key_value("USE_ARM_COMPUTE_LIB", s)), + use_arm_compute_lib_graph_runtime + .as_ref() + .map(|s| Self::setting_key_value("USE_ARM_COMPUTE_LIB_GRAPH_RUNTIME", s)), + use_tensorrt_codegen + .as_ref() + .map(|s| Self::setting_key_value("USE_TENSORRT_CODEGEN", s)), + use_tensorrt_runtime + .as_ref() + .map(|s| Self::setting_key_value("USE_TENSORRT_RUNTIME", s)), + use_rust_ext + .as_ref() + .map(|s| Self::setting_key_value("USE_RUST_EXT", s)), + use_vitis_ai + .as_ref() + .map(|s| Self::setting_key_value("USE_VITIS_AI", s)), + build_static_runtime + .as_ref() + .map(|s| Self::setting_key_value("BUILD_STATIC_RUNTIME", s)), + ] + .into_iter() + .flatten() + } +} + +pub struct Revision { + revision: String, } impl Revision { @@ -316,6 +591,11 @@ impl Revision { .host(&target.host) .profile("Debug"); + for (key, value) in build_config.as_cmake_define_key_values() { + println!("setting {}={}", key, value); + let _ = cmake_config.define(key, value); + } + if build_config.verbose { cmake_config.very_verbose(true); } diff --git a/src/lib.rs b/src/lib.rs index 01abbbe..a62cdef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ mod targets; use targets::local_target; -pub use self::core::BuildConfig; +pub use self::core::{BuildConfig, UserSettings}; #[derive(Serialize, Deserialize)] pub struct VersionConfig { From a5b3c4fa08abfcfd3df7eab7868974520f08ad38 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Thu, 5 Aug 2021 14:29:29 +1200 Subject: [PATCH 2/3] build_static_runtime is pub --- src/core.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.rs b/src/core.rs index 8b86090..92613bf 100644 --- a/src/core.rs +++ b/src/core.rs @@ -249,7 +249,7 @@ pub struct UserSettings { /// Whether to build static libtvm_runtime.a, the default is to build the dynamic /// version: libtvm_runtime.so. #[structopt(long)] - build_static_runtime: Option, + pub build_static_runtime: Option, } #[derive(Debug)] From 3c5323fb6cd8fc41877d4e7a95e1ff02e7a06e3b Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Thu, 5 Aug 2021 14:53:58 +1200 Subject: [PATCH 3/3] CMakeSettings is exported --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index a62cdef..50320c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ mod targets; use targets::local_target; -pub use self::core::{BuildConfig, UserSettings}; +pub use self::core::{BuildConfig, UserSettings, CMakeSetting}; #[derive(Serialize, Deserialize)] pub struct VersionConfig {