Skip to content

Commit 17478d9

Browse files
uglyoldbobFirstyear
authored andcommitted
Add bundled feature and improve support for windows.
Signed-off-by: Thomas Epperson <[email protected]>
1 parent aa0e1ea commit 17478d9

File tree

5 files changed

+226
-3
lines changed

5 files changed

+226
-3
lines changed

Diff for: tss-esapi-sys/Cargo.toml

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@ links = "tss2-esys"
1414
rust-version = "1.66.0"
1515

1616
[build-dependencies]
17-
bindgen = { version = "0.66.1", optional = true }
17+
autotools = { version = "0.2.6", optional = true }
18+
bindgen = { version = "0.69.4", optional = true }
1819
pkg-config = "0.3.18"
1920
target-lexicon = "0.12.0"
2021
cfg-if = "1.0.0"
2122
semver = "1.0.7"
2223

24+
[target.'cfg(windows)'.build-dependencies]
25+
msbuild = { git = "https://github.com/uglyoldbob/msbuild.git", optional = true }
26+
winreg = {version = "0.52", optional = true }
27+
2328
[features]
2429
generate-bindings = ["bindgen"]
30+
bundled = ["dep:autotools", "dep:msbuild", "dep:winreg"]

Diff for: tss-esapi-sys/build.rs

+209-2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,21 @@ fn main() {
99

1010
cfg_if::cfg_if! {
1111
if #[cfg(feature = "generate-bindings")] {
12+
#[cfg(feature = "bundled")]
13+
let installation = tpm2_tss::Installation::bundled();
14+
#[cfg(not(feature = "bundled"))]
1215
let installation = tpm2_tss::Installation::probe(true);
1316
let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
1417
installation.generate_bindings(&out_dir.join("tss_esapi_bindings.rs"));
18+
installation.output_linker_arguments();
1519
} else {
1620
target::ensure_supported();
21+
#[cfg(feature = "bundled")]
22+
{
23+
let installation = tpm2_tss::Installation::bundled();
24+
installation.pkg_config();
25+
}
26+
#[cfg(not(feature = "bundled"))]
1727
let _ = tpm2_tss::Installation::probe(false);
1828
}
1929
}
@@ -59,19 +69,158 @@ pub mod tpm2_tss {
5969
/// The installed tpm2-tss libraries that are of
6070
/// interest.
6171
pub struct Installation {
62-
_tss2_sys: Library,
72+
tss2_sys: Library,
6373
tss2_esys: Library,
6474
tss2_tctildr: Library,
6575
tss2_mu: Library,
6676
tss2_tcti_tbs: Option<Library>,
6777
}
6878

6979
impl Installation {
80+
fn platform_args() -> Option<Vec<String>> {
81+
cfg_if::cfg_if! {
82+
if #[cfg(windows)] {
83+
let mut clang_args: Vec<String> = Vec::new();
84+
let hklm = winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE);
85+
let sdk_entry = hklm.open_subkey("SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0").unwrap();
86+
let installation_path: String = sdk_entry.get_value("InstallationFolder").unwrap();
87+
let ip_pb = PathBuf::from(installation_path).join("Include");
88+
let windows_sdk = ip_pb.join("10.0.17134.0");
89+
clang_args.push(format!("-I{}", windows_sdk.join("ucrt").display()));
90+
clang_args.push(format!("-I{}", windows_sdk.join("um").display()));
91+
clang_args.push(format!("-I{}", windows_sdk.join("shared").display()));
92+
Some(clang_args)
93+
}
94+
else {
95+
None
96+
}
97+
}
98+
}
99+
100+
#[cfg(feature = "bundled")]
101+
/// Fetch the given source repo using git
102+
fn fetch_source(
103+
dest_path: impl AsRef<std::path::Path>,
104+
name: &str,
105+
repo: &str,
106+
branch: &str,
107+
) -> std::path::PathBuf {
108+
let parent_path = dest_path.as_ref();
109+
let repo_path = parent_path.join(name);
110+
if !repo_path.join("Makefile.am").exists() {
111+
let output = std::process::Command::new("git")
112+
.args(["clone", repo, "--depth", "1", "--branch", branch])
113+
.current_dir(parent_path)
114+
.output()
115+
.unwrap_or_else(|_| panic!("git clone for {} failed", name));
116+
let status = output.status;
117+
if !status.success() {
118+
panic!(
119+
"git clone for {} returned failure status {}:\n{:?}",
120+
name, status, output
121+
);
122+
}
123+
}
124+
125+
repo_path
126+
}
127+
128+
#[cfg(feature = "bundled")]
129+
fn compile_with_autotools(p: PathBuf) -> PathBuf {
130+
let output1 = std::process::Command::new("./bootstrap")
131+
.current_dir(&p)
132+
.output()
133+
.expect("bootstrap script failed");
134+
let status = output1.status;
135+
if !status.success() {
136+
panic!("bootstrap script failed with {}:\n{:?}", status, output1);
137+
}
138+
139+
let mut config = autotools::Config::new(p);
140+
config.fast_build(true).reconf("-ivf").build()
141+
}
142+
143+
#[cfg(feature = "bundled")]
144+
/// Uses a bundled build for an installation
145+
pub fn bundled() -> Self {
146+
use std::io::Write;
147+
let out_path = std::env::var("OUT_DIR").expect("No output directory given");
148+
let source_path = Self::fetch_source(
149+
out_path,
150+
"tpm2-tss",
151+
"https://github.com/tpm2-software/tpm2-tss.git",
152+
MINIMUM_VERSION,
153+
);
154+
let version_file_name = source_path.join("VERSION");
155+
let mut version_file = std::fs::File::create(version_file_name)
156+
.expect("Unable to create version file for tpm2-tss");
157+
write!(version_file, "{}", MINIMUM_VERSION)
158+
.unwrap_or_else(|e| panic!("Failed to write version file: {}", e));
159+
160+
cfg_if::cfg_if! {
161+
if #[cfg(windows)] {
162+
let mut msbuild = msbuild::MsBuild::find_msbuild(Some("2017")).unwrap();
163+
let profile = std::env::var("PROFILE").unwrap();
164+
let build_string = match profile.as_str() {
165+
"debug" => "",
166+
"release" => "/p:Configuration=Release",
167+
_ => panic!("Unknown cargo profile:"),
168+
};
169+
170+
msbuild.run(source_path.clone(), &[
171+
build_string,
172+
"tpm2-tss.sln"]);
173+
}
174+
else {
175+
let install_path = Self::compile_with_autotools(source_path.clone());
176+
std::env::set_var(
177+
"PKG_CONFIG_PATH",
178+
format!("{}", install_path.join("lib").join("pkgconfig").display()),
179+
);
180+
}
181+
}
182+
std::env::set_var(PATH_ENV_VAR_NAME, source_path.clone());
183+
184+
let include_path = source_path.join("include").join("tss2");
185+
186+
#[cfg(windows)]
187+
let tbs = Some(Library {
188+
header_file: Some(include_path.join("tss2_tcti_tbs.h")),
189+
version: MINIMUM_VERSION.into(),
190+
name: "tss2-tbs".into(),
191+
});
192+
#[cfg(not(windows))]
193+
let tbs = None;
194+
Self {
195+
tss2_sys: Library {
196+
header_file: Some(include_path.join("tss2_sys.h")),
197+
version: MINIMUM_VERSION.into(),
198+
name: "tss2-sys".into(),
199+
},
200+
tss2_esys: Library {
201+
header_file: Some(include_path.join("tss2_esys.h")),
202+
version: MINIMUM_VERSION.into(),
203+
name: "tss2-esys".into(),
204+
},
205+
tss2_tctildr: Library {
206+
header_file: Some(include_path.join("tss2_tctildr.h")),
207+
version: MINIMUM_VERSION.into(),
208+
name: "tss2-tctildr".into(),
209+
},
210+
tss2_mu: Library {
211+
header_file: Some(include_path.join("tss2_mu.h")),
212+
version: MINIMUM_VERSION.into(),
213+
name: "tss2-mu".into(),
214+
},
215+
tss2_tcti_tbs: tbs,
216+
}
217+
}
218+
70219
/// Probes the system for an installation.
71220
pub fn probe(with_header_files: bool) -> Self {
72221
let install_path = Installation::installation_path_from_env_var();
73222
Installation {
74-
_tss2_sys: Library::probe_required(
223+
tss2_sys: Library::probe_required(
75224
"tss2-sys",
76225
install_path.as_ref(),
77226
with_header_files,
@@ -149,10 +298,58 @@ pub mod tpm2_tss {
149298
.clang_arg(tss2_tcti_tbs.include_dir_arg())
150299
.header(tss2_tcti_tbs.header_file_arg());
151300
}
301+
if let Some(clang_args) = Self::platform_args() {
302+
for arg in clang_args {
303+
builder = builder.clang_arg(arg);
304+
}
305+
}
152306
builder
153307
}
154308
}
155309
}
310+
311+
/// Run pkgconfig for bundled installations
312+
#[cfg(feature = "bundled")]
313+
pub fn pkg_config(&self) {
314+
self.tss2_sys.pkg_config();
315+
self.tss2_esys.pkg_config();
316+
self.tss2_tctildr.pkg_config();
317+
self.tss2_mu.pkg_config();
318+
if let Some(lib) = &self.tss2_tcti_tbs {
319+
lib.pkg_config();
320+
}
321+
}
322+
323+
pub fn output_linker_arguments(&self) {
324+
#[cfg(windows)]
325+
{
326+
println!("cargo:rustc-link-lib=dylib=tss2-esys");
327+
println!("cargo:rustc-link-lib=dylib=tss2-mu");
328+
println!("cargo:rustc-link-lib=dylib=tss2-sys");
329+
println!("cargo:rustc-link-lib=dylib=tss2-tctildr");
330+
println!("cargo:rustc-link-lib=dylib=tss2-tcti-tbs");
331+
let profile = std::env::var("PROFILE").unwrap();
332+
let build_string = match profile.as_str() {
333+
"debug" => "Debug",
334+
"release" => "Release",
335+
_ => panic!("Unknown cargo profile:"),
336+
};
337+
let mut source_path = self
338+
.tss2_esys
339+
.header_file
340+
.clone()
341+
.expect("Expected a header file path");
342+
source_path.pop();
343+
source_path.pop();
344+
source_path.pop();
345+
println!("Source path is {}", source_path.display());
346+
println!(
347+
"cargo:rustc-link-search=dylib={}",
348+
source_path.join("x64").join(build_string).display()
349+
);
350+
}
351+
}
352+
156353
/// Retrieves the installation path from the environment variable and validates it.
157354
fn installation_path_from_env_var() -> Option<(PathBuf, String)> {
158355
std::env::var(PATH_ENV_VAR_NAME).map_or_else(
@@ -372,6 +569,16 @@ pub mod tpm2_tss {
372569
)
373570
}
374571

572+
/// Use the pkg config file for a bundled installation
573+
#[cfg(feature = "bundled")]
574+
fn pkg_config(&self) {
575+
pkg_config::Config::new()
576+
.atleast_version(MINIMUM_VERSION)
577+
.statik(true)
578+
.probe(&self.name)
579+
.unwrap_or_else(|_| panic!("Failed to run pkg-config on {}", self.name));
580+
}
581+
375582
/// Probe the system for an optional library using pkg-config.
376583
///
377584
/// # Args

Diff for: tss-esapi/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,4 @@ default = ["abstraction"]
4949
generate-bindings = ["tss-esapi-sys/generate-bindings"]
5050
abstraction = ["oid", "picky-asn1", "picky-asn1-x509"]
5151
integration-tests = ["strum", "strum_macros"]
52+
bundled = [ "tss-esapi-sys/bundled" ]

Diff for: tss-esapi/build.rs

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ fn main() {
99
println!("cargo:rustc-check-cfg=cfg(has_tpmu_sensitive_create)");
1010
println!("cargo:rustc-check-cfg=cfg(has_esys_tr_get_tpm_handle)");
1111

12+
#[cfg(feature = "bundled")]
13+
{
14+
std::env::set_var("DEP_TSS2_ESYS_VERSION", "3.2.2");
15+
}
1216
let tss_version_string = std::env::var("DEP_TSS2_ESYS_VERSION")
1317
.expect("Failed to parse ENV variable DEP_TSS2_ESYS_VERSION as string");
1418

Diff for: tss-esapi/src/tcti_ldr.rs

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const DEVICE: &str = "device";
2121
const MSSIM: &str = "mssim";
2222
const SWTPM: &str = "swtpm";
2323
const TABRMD: &str = "tabrmd";
24+
const TBS: &str = "tbs";
2425

2526
/// TCTI Context created via a TCTI Loader Library.
2627
/// Wrapper around the TSS2_TCTI_CONTEXT structure.
@@ -143,6 +144,8 @@ pub enum TctiNameConf {
143144
///
144145
/// For more information about configuration, see [this page](https://www.mankier.com/3/Tss2_Tcti_Tabrmd_Init)
145146
Tabrmd(TabrmdConfig),
147+
/// Connect to a TPM using windows services
148+
Tbs,
146149
}
147150

148151
impl TctiNameConf {
@@ -174,6 +177,7 @@ impl TryFrom<TctiNameConf> for CString {
174177
TctiNameConf::Mssim(..) => MSSIM,
175178
TctiNameConf::Swtpm(..) => SWTPM,
176179
TctiNameConf::Tabrmd(..) => TABRMD,
180+
TctiNameConf::Tbs => TBS,
177181
};
178182

179183
let tcti_conf = match tcti {
@@ -204,6 +208,7 @@ impl TryFrom<TctiNameConf> for CString {
204208
TctiNameConf::Tabrmd(config) => {
205209
format!("bus_name={},bus_type={}", config.bus_name, config.bus_type)
206210
}
211+
TctiNameConf::Tbs => String::new(),
207212
};
208213

209214
if tcti_conf.is_empty() {

0 commit comments

Comments
 (0)