diff --git a/tss-esapi-sys/Cargo.toml b/tss-esapi-sys/Cargo.toml index 9e5d22e8..3b7b0dcb 100644 --- a/tss-esapi-sys/Cargo.toml +++ b/tss-esapi-sys/Cargo.toml @@ -13,7 +13,7 @@ documentation = "https://docs.rs/crate/tss-esapi-sys" links = "tss2-esys" [build-dependencies] -bindgen = { version = "0.66.1", optional = true } +bindgen = { version = "0.69.1", optional = true } pkg-config = "0.3.18" target-lexicon = "0.12.0" cfg-if = "1.0.0" diff --git a/tss-esapi-sys/build.rs b/tss-esapi-sys/build.rs index aa183b85..c2e985e0 100644 --- a/tss-esapi-sys/build.rs +++ b/tss-esapi-sys/build.rs @@ -12,8 +12,11 @@ fn main() { cfg_if::cfg_if! { if #[cfg(feature = "generate-bindings")] { let installation = tpm2_tss::Installation::probe(true); + let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap()); + installation.generate_bindings(&out_dir.join("tss_esapi_bindings.rs")); } else { - let installation = tpm2_tss::Installation::probe(false); + target::ensure_supported(); + let _ = tpm2_tss::Installation::probe(false); } } } @@ -56,7 +59,7 @@ pub mod tpm2_tss { /// The installed tpm2-tss libraries that are of /// interest. pub struct Installation { - tss2_sys: Library, + _tss2_sys: Library, tss2_esys: Library, tss2_tctildr: Library, tss2_mu: Library, @@ -65,17 +68,20 @@ pub mod tpm2_tss { impl Installation { /// Probes the system for an installation. - pub fn probe(with_headers: bool) -> Self { + pub fn probe(with_header_files: bool) -> Self { let install_path = Installation::installation_path_from_env_var(); Installation { - tss2_sys: Library::probe_required("tss2-sys", install_path.as_ref()), - tss2_esys: Library::probe_required("tss2-esys", install_path.as_ref()), - tss2_tctildr: Library::probe_required("tss2-tctildr", install_path.as_ref()), - tss2_mu: Library::probe_required("tss2-mu", install_path.as_ref()), - tss2_tcti_tbs: Library::probe_optional("tss2-tcti-tbs", install_path.as_ref()), + _tss2_sys: Library::probe_required("tss2-sys", install_path.as_ref(), with_header_files, false), + tss2_esys: Library::probe_required("tss2-esys", install_path.as_ref(), with_header_files, true), + tss2_tctildr: Library::probe_required("tss2-tctildr", install_path.as_ref(), with_header_files, false), + tss2_mu: Library::probe_required("tss2-mu", install_path.as_ref(), with_header_files, false), + tss2_tcti_tbs: Library::probe_optional("tss2-tcti-tbs", install_path.as_ref(), with_header_files), } } +cfg_if::cfg_if! { + if #[cfg(feature = "generate-bindings")] { + /// Generates bindings for the Installation. pub fn generate_bindings(&self, esapi_out: &Path) { self.bindgen_builder() @@ -92,13 +98,27 @@ pub mod tpm2_tss { .clang_arg(self.tss2_esys.include_dir_arg()) .clang_arg(self.tss2_tctildr.include_dir_arg()) .clang_arg(self.tss2_mu.include_dir_arg()) - .rustfmt_bindings(true) + .formatter(bindgen::Formatter::Rustfmt) .header(self.tss2_esys.header_file_arg()) .header(self.tss2_tctildr.header_file_arg()) .header(self.tss2_mu.header_file_arg()) //See this issue: https://github.com/parallaxsecond/rust-cryptoki/issues/12 - .blocklist_type("max_align_t") .generate_comments(false) + .blocklist_type("max_align_t") + // Needed for windows + .blocklist_type("IMAGE_TLS_DIRECTORY") + .blocklist_type("PIMAGE_TLS_DIRECTORY") + .blocklist_type("IMAGE_TLS_DIRECTORY64") + .blocklist_type("PIMAGE_TLS_DIRECTORY64") + .blocklist_type("_IMAGE_TLS_DIRECTORY64") + .blocklist_type("MONITORINFOEX") + .blocklist_type("MONITORINFOEXA") + .blocklist_type("MONITORINFOEXW") + .blocklist_type("tagMONITORINFOEXA") + .blocklist_type("tagMONITORINFOEXW") + .blocklist_type("LPMONITORINFOEX") + .blocklist_type("LPMONITORINFOEXA") + .blocklist_type("LPMONITORINFOEXW") .derive_default(true); if let Some(tss2_tcti_tbs) = &self.tss2_tcti_tbs { builder = builder @@ -107,7 +127,8 @@ pub mod tpm2_tss { } builder } - + } +} /// Retrieves the installation path from the environment variable and validates it. fn installation_path_from_env_var() -> Option<(PathBuf, String)> { std::env::var(PATH_ENV_VAR_NAME).map_or_else(|e| { @@ -165,7 +186,7 @@ pub mod tpm2_tss { /// Struct holding the information for a library. struct Library { - header_file: PathBuf, + header_file: Option, version: String, name: String, } @@ -174,41 +195,53 @@ pub mod tpm2_tss { /// Probes the different options for a required library. /// /// # Arguments - /// lib_name - The name of the library. - /// install_path - Optional path and version of installation. + /// `lib_name` - The name of the library. + /// `install_path` - Optional path and version of installation. + /// `with_header_files` - Flag indicating if header files are required. /// /// # Returns /// The detected installed library. /// # Panics /// - If the library is not found. - pub fn probe_required(lib_name: &str, install_path: Option<&(PathBuf, String)>) -> Self { - Self::probe_optional(lib_name, install_path) - .unwrap_or_else(|| panic!("Failed to find {} library.", lib_name)) + pub fn probe_required(lib_name: &str, install_path: Option<&(PathBuf, String)>, with_header_files: bool, report_version: bool) -> Self { + Self::probe_optional(lib_name, install_path, with_header_files) + .map_or_else( + || panic!("Failed to find {} library.", lib_name), + |lib| { + if report_version { + println!("cargo:version={}", lib.version); + } + lib + }) } /// Probes the different options for an optional library. /// /// # Arguments - /// lib_name - The name of the library. - /// install_path - Optional path and version of installation. + /// `lib_name` - The name of the library. + /// `install_path` - Optional path and version of installation. + /// `with_header_files` - Flag indicating if header files are required. /// /// # Returns /// The detected installed library or None if no library was found. - pub fn probe_optional(lib_name: &str, install_path: Option<&(PathBuf, String)>) -> Option { + pub fn probe_optional(lib_name: &str, install_path: Option<&(PathBuf, String)>, with_header_files: bool) -> Option { install_path .map(|(path, version)| { - Self::probe_install_path(lib_name, &path, &version) + Self::probe_install_path(lib_name, path, version, with_header_files) }) - .or_else(|| Self::probe_pkg_config_optional(lib_name)) + .or_else(|| Self::probe_pkg_config_optional(lib_name, with_header_files)) } /// The include dir `clang_arg` bindgen builder argument. /// /// # Panics + /// - If the library was probe without requiring header files. /// - If the library specifies a header file does not have a parent directory. /// - If the library specifies a header file path that contain invalid utf-8 characters. pub fn include_dir_arg(&self) -> String { self.header_file + .as_ref() + .unwrap_or_else(|| panic!("No header file present for `{}`.", self.name)) .parent() .unwrap_or_else(|| panic!("Inconsistent `{}` header file path.", self.name)) .as_os_str() @@ -224,24 +257,34 @@ pub mod tpm2_tss { /// - If the library specifies a header file path that contain invalid utf-8 characters. pub fn header_file_arg(&self) -> &str { self.header_file - .as_os_str() - .to_str() - .unwrap_or_else(|| panic!("Error converting OsString to &str when processing `{}` include dir.", self.name)) + .as_ref() + .map_or_else( + || { + panic!("No header file present for `{}`.", self.name); + }, + |v| { + v.as_os_str() + .to_str() + .unwrap_or_else(|| panic!("Error converting OsString to &str when processing `{}` include dir.", self.name)) + }) } /// Probe the system for an optional library using pkg-config. - fn probe_pkg_config_optional(lib_name: &str) -> Option { + /// + /// # Args + /// `lib_name` - The name of the library. + /// `with_header_files` - Flag indicating if header files are required. + fn probe_pkg_config_optional(lib_name: &str, with_header_files: bool) -> Option { pkg_config::Config::new() .atleast_version(MINIMUM_VERSION) .probe(lib_name) .ok() .map(|pkg_config| { - let header_file = pkg_config.include_paths[0] - .join("tss2") - .join(lib_name.replace("-", "_") + ".h"); - if !header_file.is_file() { - panic!("Header file `{}` does not exist.", header_file.to_string_lossy()); + if !with_header_files { + return Self {header_file: None, version: pkg_config.version, name: lib_name.to_string()} } + //let file_name = PathBuf::from(lib_name.replace("-", "_")); + let header_file = Self::header_file(lib_name, &pkg_config.include_paths[0], with_header_files); Self {header_file, version: pkg_config.version, name: lib_name.to_string()} }) } @@ -259,17 +302,46 @@ pub mod tpm2_tss { /// # Panics /// - If no `.lib` file for the library was found. /// - If no `.h` file for the library was found. - fn probe_install_path(lib_name: &str, path: &Path, version: &str) -> Self { - let file_name = PathBuf::from(lib_name.replace("-", "_")); - let lib_file = path.join("lib").join(file_name.with_extension("lib")); + fn probe_install_path(lib_name: &str, path: &Path, version: &str, with_header_files: bool) -> Self { + let lib_path = path.join("lib"); + Self::ensure_lib_file_exist(lib_name, &lib_path); + + let include_path = path.join("include/tss2"); + let header_file = Self::header_file(lib_name, &include_path, with_header_files); + + Self {header_file, version: version.to_string(), name: lib_name.to_string()} + } + + fn ensure_lib_file_exist(lib_name: &str, lib_path: &Path) { + let lib_file = lib_path.join(PathBuf::from(lib_name).with_extension("lib")); if !lib_file.is_file() { - panic!("Lib file `{}`, does not exist.", lib_file.to_string_lossy()); + panic!("Lib name: {}\n Lib file `{}`, does not exist.", lib_name, lib_file.to_string_lossy()); + } + } + + /// Creates a PathBuf object for the header file. + /// + /// # Args + /// `lib_name` - Name of the library. + /// `include_path` - The include path to the header file. + /// `with_header_files` - Flag indicating if header files are required. + /// + /// # Returns + /// An optional PathBuf object. + /// + /// # Panics + /// - If `with_header_files` but the combination of `file_name` and `include_path` + /// does not point to an existing file. + fn header_file(lib_name: &str, include_path: &Path, with_header_files: bool) -> Option { + if !with_header_files { + return None; } - let header_file = path.join("include").join(file_name.with_extension("h")); - if !header_file.is_file() { + let file_name = PathBuf::from(lib_name.replace('-', "_")); + let header_file = include_path.join(file_name.with_extension("h")); + if with_header_files && !header_file.is_file() { panic!("Header file `{}`, does not exist.", header_file.to_string_lossy()); } - Self {header_file, version: version.to_string(), name: lib_name.to_string()} + Some(header_file) } } }