From c80915eb7450d579acc1f276a4f3cab0fe277825 Mon Sep 17 00:00:00 2001 From: Jesper Brynolf Date: Fri, 27 Oct 2023 23:10:57 +0200 Subject: [PATCH] Adds support for non pkg-config tpm2-tss installs. - Adds support for specifying path to the tpm2-tss libraries and header files using the environment variable ```TPM2_TSS_PATH```. The specified path is expected to have the following layout: | -> | | -> include | | -> tss2 | | -> tss2_esys.h | | | -> lib | | -> tss2_esys.lib (or .so) Signed-off-by: Jesper Brynolf --- .github/workflows/ci.yml | 24 +- tss-esapi-sys/Cargo.toml | 2 +- tss-esapi-sys/build.rs | 455 ++++++++++++++++++++++-------- tss-esapi/tests/Dockerfile-ubuntu | 12 +- tss-esapi/tests/all-ubuntu.sh | 7 +- 5 files changed, 366 insertions(+), 134 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9957690a..548e96c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Build the container - run: docker build -t ubuntucontainer tss-esapi/tests/ --file tss-esapi/tests/Dockerfile-ubuntu + run: docker build -t ubuntucontainer tss-esapi/tests/ --file tss-esapi/tests/Dockerfile-ubuntu --target tpm2-tools - name: Run the container run: docker run -v $(pwd):/tmp/rust-tss-esapi -w /tmp/rust-tss-esapi/tss-esapi --env RUST_TOOLCHAIN_VERSION=1.66.0 ubuntucontainer /tmp/rust-tss-esapi/tss-esapi/tests/all-ubuntu.sh # All in one job as I think it is a big overhead to build and run the Docker @@ -38,19 +38,29 @@ jobs: steps: - uses: actions/checkout@v2 - name: Build the container - run: docker build -t ubuntucontainer tss-esapi/tests/ --file tss-esapi/tests/Dockerfile-ubuntu + run: docker build -t ubuntucontainer tss-esapi/tests/ --file tss-esapi/tests/Dockerfile-ubuntu --target tpm2-tools - name: Run the container run: docker run -v $(pwd):/tmp/rust-tss-esapi -w /tmp/rust-tss-esapi/tss-esapi ubuntucontainer /tmp/rust-tss-esapi/tss-esapi/tests/all-ubuntu.sh - name: Run the cross-compilation script run: docker run -v $(pwd):/tmp/rust-tss-esapi -w /tmp/rust-tss-esapi/tss-esapi ubuntucontainer /tmp/rust-tss-esapi/tss-esapi/tests/cross-compile.sh - tests-ubuntu-v4: - name: Ubuntu tests on v4.x.y of tpm2-tss + tests-ubuntu-v4-pkg: + name: Ubuntu tests on v4.x.y of tpm2-tss libraries found using pkg-config --target tpm2-tools runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Build the container - run: docker build -t ubuntucontainer tss-esapi/tests/ --build-arg TPM2_TSS_VERSION=4.0.1 --file tss-esapi/tests/Dockerfile-ubuntu + run: docker build -t ubuntucontainer tss-esapi/tests/ --build-arg TPM2_TSS_VERSION=4.0.1 --file tss-esapi/tests/Dockerfile-ubuntu --target tpm2-tools + - name: Run the container + run: docker run -v $(pwd):/tmp/rust-tss-esapi -w /tmp/rust-tss-esapi/tss-esapi ubuntucontainer /tmp/rust-tss-esapi/tss-esapi/tests/all-ubuntu.sh + + test-ubuntu-v4-path: + name: Ubuntu tests on v4.x.y of tpm2-tss libraries found using a path + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Build the container + run: docker build -t ubuntucontainer tss-esapi/tests/ --build-arg TPM2_TSS_VERSION=4.0.1 --file tss-esapi/tests/Dockerfile-ubuntu --target tpm2-tss-install-dir - name: Run the container run: docker run -v $(pwd):/tmp/rust-tss-esapi -w /tmp/rust-tss-esapi/tss-esapi ubuntucontainer /tmp/rust-tss-esapi/tss-esapi/tests/all-ubuntu.sh @@ -82,7 +92,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Build the container - run: docker build -t ubuntucontainer tss-esapi/tests/ --file tss-esapi/tests/Dockerfile-ubuntu + run: docker build -t ubuntucontainer tss-esapi/tests/ --file tss-esapi/tests/Dockerfile-ubuntu --target tpm2-tools - name: Run the tests run: docker run -v $(pwd):/tmp/rust-tss-esapi -w /tmp/rust-tss-esapi/tss-esapi ubuntucontainer /tmp/rust-tss-esapi/tss-esapi/tests/valgrind.sh @@ -93,7 +103,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Build the container - run: docker build -t ubuntucontainer tss-esapi/tests/ --file tss-esapi/tests/Dockerfile-ubuntu + run: docker build -t ubuntucontainer tss-esapi/tests/ --file tss-esapi/tests/Dockerfile-ubuntu --target tpm2-tools - name: Check documentation run: docker run -v $(pwd):/tmp/rust-tss-esapi -w /tmp/rust-tss-esapi/tss-esapi -e RUSTDOCFLAGS="-Dwarnings" ubuntucontainer cargo doc --document-private-items --no-deps diff --git a/tss-esapi-sys/Cargo.toml b/tss-esapi-sys/Cargo.toml index 0e8615fc..42f67b40 100644 --- a/tss-esapi-sys/Cargo.toml +++ b/tss-esapi-sys/Cargo.toml @@ -14,7 +14,7 @@ links = "tss2-esys" rust-version = "1.66.0" [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 94413963..b7525193 100644 --- a/tss-esapi-sys/build.rs +++ b/tss-esapi-sys/build.rs @@ -1,8 +1,6 @@ // Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 -//#[cfg(feature = "generate-bindings")] - fn main() { if std::env::var("DOCS_RS").is_ok() { // Nothing to be done for docs.rs builds. @@ -12,51 +10,56 @@ 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); } } } pub mod target { use std::str::FromStr; - use target_lexicon::{Architecture, OperatingSystem, Triple}; + use target_lexicon::{Architecture, OperatingSystem, Triple}; const TARGET_ENV_VAR_NAME: &str = "TARGET"; /// Ensures that the `TARGET` is valid for cross compilation. pub fn ensure_supported() { - let target = Triple::from_str( - &std::env::var(TARGET_ENV_VAR_NAME) - .unwrap_or_else(|_| { - panic!("Missing environment variable `{}`.", TARGET_ENV_VAR_NAME); - })) - .expect("Failed to parse target triple."); + let target = Triple::from_str(&std::env::var(TARGET_ENV_VAR_NAME).unwrap_or_else(|_| { + panic!("Missing environment variable `{}`.", TARGET_ENV_VAR_NAME); + })) + .expect("Failed to parse target triple."); match (target.architecture, target.operating_system) { - (Architecture::Arm(_), OperatingSystem::Linux) | - (Architecture::Aarch64(_), OperatingSystem::Linux) | - (Architecture::X86_64, OperatingSystem::Darwin) | - (Architecture::X86_64, OperatingSystem::Linux) | - (Architecture::X86_64, OperatingSystem::Windows) => {} + (Architecture::Arm(_), OperatingSystem::Linux) + | (Architecture::Aarch64(_), OperatingSystem::Linux) + | (Architecture::X86_64, OperatingSystem::Darwin) + | (Architecture::X86_64, OperatingSystem::Linux) => {} (arch, os) => { panic!( - "Compilation target (architecture, OS) tuple ({}, {}) is not part of the supported tuples. Please compile with the \"generate-bindings\" feature or add support for your platform.", - arch, - os); + "Compilation target (architecture, OS) tuple ({}, {}) is not part \ + of the supported tuples. Please compile with the \"generate-bindings\" \ + feature or add support for your platform.", + arch, os + ); } } } } pub mod tpm2_tss { - use std::path::{PathBuf, Path}; use semver::{Version, VersionReq}; + use std::{ + fs::read_dir, + path::{Path, PathBuf}, + }; const MINIMUM_VERSION: &str = "3.2.2"; const PATH_ENV_VAR_NAME: &str = "TPM2_TSS_PATH"; /// 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,65 +68,109 @@ 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, + ), } } - /// Generates bindings for the Installation. - pub fn generate_bindings(&self, esapi_out: &Path) { - self.bindgen_builder() - .generate() - .expect("Unable to generate bindings to TSS2 ESYS APIs.") - .write_to_file(esapi_out) - .expect("Couldn't write ESYS bindings!"); - } + 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() + .generate() + .expect("Unable to generate bindings to TSS2 ESYS APIs.") + .write_to_file(esapi_out) + .expect("Couldn't write ESYS bindings!"); + } - /// The bindgen builder to use. - fn bindgen_builder(&self) -> bindgen::Builder { - let mut builder = bindgen::Builder::default() - .size_t_is_usize(false) - .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) - .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) - .derive_default(true); - if let Some(tss2_tcti_tbs) = &self.tss2_tcti_tbs { - builder = builder - .clang_arg(tss2_tcti_tbs.include_dir_arg()) - .header(tss2_tcti_tbs.header_file_arg()); + /// The bindgen builder to use. + fn bindgen_builder(&self) -> bindgen::Builder { + let mut builder = bindgen::Builder::default() + .size_t_is_usize(false) + .clang_arg(self.tss2_esys.include_dir_arg()) + .clang_arg(self.tss2_tctildr.include_dir_arg()) + .clang_arg(self.tss2_mu.include_dir_arg()) + .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 + .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 + .clang_arg(tss2_tcti_tbs.include_dir_arg()) + .header(tss2_tcti_tbs.header_file_arg()); + } + builder + } } - 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| { - match e { + std::env::var(PATH_ENV_VAR_NAME).map_or_else( + |e| match e { std::env::VarError::NotUnicode(invalid_value) => { - panic!("Invalid `{}` env var: `{:?}`.", PATH_ENV_VAR_NAME, invalid_value); - }, + panic!( + "Invalid `{}` env var: `{:?}`.", + PATH_ENV_VAR_NAME, invalid_value + ); + } std::env::VarError::NotPresent => None, - } - }, |var| { - Some(Installation::ensure_valid_installation_path(var)) - }) + }, + |var| Some(Installation::ensure_valid_installation_path(var)), + ) } /// Ensures that the installation path is valid. - /// + /// /// # Details /// In order to be considered valid the following /// requirements needs to be full filled: @@ -131,145 +178,307 @@ pub mod tpm2_tss { /// 2. Sub directories `include` and `lib` must exist. /// 3. A `VERSION` file must be present in the directory and it needs to be /// be specifying a version that is greater then the minimum supported version. - /// + /// + /// The function is also responsible for reporting the library search path the rust compiler + /// should use. + /// /// # Arguments /// env_var - The value of the environment variable that contains the installation path. - /// + /// /// # Returns /// A tuple containing the validated installation path and the version associated with it. fn ensure_valid_installation_path(env_var: String) -> (PathBuf, String) { let install_path = PathBuf::from(env_var); if !install_path.is_dir() { - panic!("`{}` specifies a path `{}`, that does not exist", PATH_ENV_VAR_NAME, install_path.to_string_lossy()); + panic!( + "`{}` specifies a path `{}`, that does not exist", + PATH_ENV_VAR_NAME, + install_path.to_string_lossy() + ); } if !install_path.join("include").is_dir() { - panic!("`{}` specifies a path `{}`, that does not contain an `include` directory", PATH_ENV_VAR_NAME, install_path.to_string_lossy()); + panic!( + "`{}` specifies a path `{}`, that does not contain an `include` directory", + PATH_ENV_VAR_NAME, + install_path.to_string_lossy() + ); } if !install_path.join("lib").is_dir() { - panic!("`{}` specifies a path `{}`, that does not contain an `lib` directory", PATH_ENV_VAR_NAME, install_path.to_string_lossy()); + panic!( + "`{}` specifies a path `{}`, that does not contain an `lib` directory", + PATH_ENV_VAR_NAME, + install_path.to_string_lossy() + ); } let version_str = std::fs::read_to_string(install_path.join("VERSION")) .expect("Failed to read VERSION file."); - let version = Version::parse(version_str.as_str()) + let version = Version::parse(version_str.trim()) .expect("Failed to parse the content of the VERSION file."); - let min_version_req_str = format!(">={}",MINIMUM_VERSION); + let min_version_req_str = format!(">={}", MINIMUM_VERSION); let min_version_req = VersionReq::parse(&min_version_req_str) .expect("Failed to parse minimum version requirement."); if !min_version_req.matches(&version) { - panic!("Minimum supported version is {}, found installed version {}", MINIMUM_VERSION, version_str); + panic!( + "Minimum supported version is {}, found installed version {}", + MINIMUM_VERSION, version_str + ); } + println!( + "cargo:rustc-link-search=native={}", + install_path.join("lib").to_string_lossy() + ); (install_path, version_str) } } - /// Struct holding the information for a library. struct Library { - header_file: PathBuf, + header_file: Option, version: String, name: String, } impl Library { - /// Probes the different options for a required library. - /// + /// 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. + /// `report_version` - Flag indicating if the version of the library should + /// be reported to Cargo. /// /// # Returns /// The detected installed library. - /// # Panics + /// # 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. - /// + /// 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 { - install_path - .map(|(path, version)| { - Self::probe_install_path(lib_name, &path, &version) - }) - .or_else(|| Self::probe_pkg_config_optional(lib_name)) + pub fn probe_optional( + lib_name: &str, + install_path: Option<&(PathBuf, String)>, + with_header_files: bool, + ) -> Option { + if let Some((path, version)) = install_path { + return Self::probe_install_path_optional( + lib_name, + path, + version, + with_header_files, + ); + } + 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() .to_str() - .map_or_else(|| { - panic!("Error converting OsString to &str when processing `{}` include dir.", self.name); - }, |v| format!("-I{}", v)) + .map_or_else( + || { + panic!( + "Error converting OsString to &str when processing `{}` include dir.", + self.name + ); + }, + |v| format!("-I{}", v), + ) } /// The header file path to a `header` bindgen argument. - /// + /// /// # Panics /// - 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)) - } + self.header_file.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 include_path = pkg_config.include_paths[0].join("tss2"); + let header_file = Self::header_file(lib_name, &include_path, with_header_files); + Self { + header_file, + version: pkg_config.version, + name: lib_name.to_string(), } - Self {header_file, version: pkg_config.version, name: lib_name.to_string()} }) } /// Probe the install path for a library. - /// + /// + /// # Details + /// Will report then name of the library to Cargo for + /// static linking purposes. + /// /// # Arguments /// `lib_name` - The name of the library to probe for. /// `path` - The path to probe for the library. /// `version` - The version of the library. - /// + /// /// # Returns - /// A `Library` object containing the information retrieved. - /// + /// A `Library` object containing the information retrieved if one + /// was found that matched the library name. + /// /// # Panics - /// - If no `.lib` file for the library was found. + /// - If no `.lib` or `.so` 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")); - if !lib_file.is_file() { - panic!("Lib file `{}`, does not exist.", lib_file.to_string_lossy()); + fn probe_install_path_optional( + lib_name: &str, + path: &Path, + version: &str, + with_header_files: bool, + ) -> Option { + let lib_path = path.join("lib"); + if Self::lib_file(lib_name, &lib_path).is_none() { + return None; + } + // If the lib file was found then the name is reported to Cargo. + println!("cargo:rustc-link-lib={}", lib_name); + + let include_path = path.join("include/tss2"); + Some(Self { + header_file: Self::header_file(lib_name, &include_path, with_header_files), + version: version.to_string(), + name: lib_name.to_string(), + }) + } + + /// Finds the path for the lib file. + /// + /// # Arguments + /// `lib_name` - The name of the library to probe for. + /// `lib_path` - The path to probe for the library. + /// + /// # Returns + /// The lib file path if it was found. + /// + /// # Panics + /// - If the `lib_path` cannot be read using `read_dir`. + /// - If more then one file matches the lib_name. + fn lib_file(lib_name: &str, lib_path: &Path) -> Option { + let mut hit_iter = read_dir(lib_path) + .expect("The call to read_dir failed.") + .filter_map(|e| e.ok()) + .map(|e| e.path()) + .filter(|file| { + file.extension() + .and_then(|ext| ext.to_str()) + .map_or(false, |file_ext| ["so", "lib"].contains(&file_ext)) + && file + .file_stem() + .and_then(|stem| stem.to_str()) + .map_or(false, |file_name| file_name.contains(lib_name)) + }) + .peekable(); + + let result = hit_iter.next(); + // Ensure it is a unique hit + if let Some(hit) = result.as_ref() { + if hit_iter.peek().is_some() { + let mut associated_files = hit_iter.collect::>(); + associated_files.push(hit.clone()); + panic!( + "More then one match found for library `{}`: {:?}", + lib_name, associated_files + ); + } } - let header_file = path.join("include").join(file_name.with_extension("h")); - if !header_file.is_file() { - panic!("Header file `{}`, does not exist.", header_file.to_string_lossy()); + result + } + + /// 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 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) } } } diff --git a/tss-esapi/tests/Dockerfile-ubuntu b/tss-esapi/tests/Dockerfile-ubuntu index 44e52d11..0ce923ed 100644 --- a/tss-esapi/tests/Dockerfile-ubuntu +++ b/tss-esapi/tests/Dockerfile-ubuntu @@ -7,7 +7,8 @@ ENV PATH="/root/.cargo/bin:${PATH}" FROM rust-toolchain AS tpm2-tss # Download and install the TSS library -ARG TPM2_TSS_VERSION=3.2.2 +ENV TPM2_TSS_BINDINGS_VERSION=3.2.2 +ARG TPM2_TSS_VERSION=$TPM2_TSS_BINDINGS_VERSION ENV TPM2_TSS_VERSION=$TPM2_TSS_VERSION ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig RUN git clone https://github.com/tpm2-software/tpm2-tss.git --branch $TPM2_TSS_VERSION @@ -25,3 +26,12 @@ RUN cd tpm2-tools \ && ./bootstrap \ && ./configure \ && make install + +FROM tpm2-tools AS tpm2-tss-install-dir +# TPM2_TSS_PATH is the env variable build.rs looks for +# an installation. +ENV TPM2_TSS_PATH=/tpm2-tss-install-dir +RUN mkdir -p /tpm2-tss-install-dir/lib /tpm2-tss-install-dir/include +COPY --from=tpm2-tss tpm2-tss/src/tss2-*/.libs/libtss2-*.so /tpm2-tss-install-dir/lib/ +COPY --from=tpm2-tss tpm2-tss/include/* /tpm2-tss-install-dir/include/ +COPY --from=tpm2-tss tpm2-tss/VERSION /tpm2-tss-install-dir/ \ No newline at end of file diff --git a/tss-esapi/tests/all-ubuntu.sh b/tss-esapi/tests/all-ubuntu.sh index 27c71301..41dae611 100755 --- a/tss-esapi/tests/all-ubuntu.sh +++ b/tss-esapi/tests/all-ubuntu.sh @@ -23,12 +23,15 @@ fi ################################################# # Generate bindings for non-"standard" versions # ################################################# -if [[ "$TPM2_TSS_VERSION" != "3.2.2" ]]; then +if [[ "${TPM2_TSS_VERSION}" != "${TPM2_TSS_BINDINGS_VERSION}" ]]; then FEATURES="generate-bindings integration-tests" else FEATURES="integration-tests" fi +if [[ ! -z ${TPM2_TSS_PATH:+x} ]]; then + export LD_LIBRARY_PATH="${TPM2_TSS_PATH}" +fi ################################# # Run the TPM simulation server # ################################# @@ -44,4 +47,4 @@ RUST_BACKTRACE=1 cargo build --features "$FEATURES" ################# # Run the tests # ################# -TEST_TCTI=mssim: RUST_BACKTRACE=1 RUST_LOG=info cargo test --features "$FEATURES" -- --test-threads=1 --nocapture +TEST_TCTI=mssim: RUST_BACKTRACE=1 RUST_LOG=info cargo test --features "${FEATURES}" -- --test-threads=1 --nocapture