@@ -9,11 +9,21 @@ fn main() {
9
9
10
10
cfg_if:: cfg_if! {
11
11
if #[ cfg( feature = "generate-bindings" ) ] {
12
+ #[ cfg( feature = "bundled" ) ]
13
+ let installation = tpm2_tss:: Installation :: bundled( ) ;
14
+ #[ cfg( not( feature = "bundled" ) ) ]
12
15
let installation = tpm2_tss:: Installation :: probe( true ) ;
13
16
let out_dir = std:: path:: PathBuf :: from( std:: env:: var( "OUT_DIR" ) . unwrap( ) ) ;
14
17
installation. generate_bindings( & out_dir. join( "tss_esapi_bindings.rs" ) ) ;
18
+ installation. output_linker_arguments( ) ;
15
19
} else {
16
20
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" ) ) ]
17
27
let _ = tpm2_tss:: Installation :: probe( false ) ;
18
28
}
19
29
}
@@ -59,19 +69,158 @@ pub mod tpm2_tss {
59
69
/// The installed tpm2-tss libraries that are of
60
70
/// interest.
61
71
pub struct Installation {
62
- _tss2_sys : Library ,
72
+ tss2_sys : Library ,
63
73
tss2_esys : Library ,
64
74
tss2_tctildr : Library ,
65
75
tss2_mu : Library ,
66
76
tss2_tcti_tbs : Option < Library > ,
67
77
}
68
78
69
79
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
+
70
219
/// Probes the system for an installation.
71
220
pub fn probe ( with_header_files : bool ) -> Self {
72
221
let install_path = Installation :: installation_path_from_env_var ( ) ;
73
222
Installation {
74
- _tss2_sys : Library :: probe_required (
223
+ tss2_sys : Library :: probe_required (
75
224
"tss2-sys" ,
76
225
install_path. as_ref ( ) ,
77
226
with_header_files,
@@ -149,10 +298,58 @@ pub mod tpm2_tss {
149
298
. clang_arg( tss2_tcti_tbs. include_dir_arg( ) )
150
299
. header( tss2_tcti_tbs. header_file_arg( ) ) ;
151
300
}
301
+ if let Some ( clang_args) = Self :: platform_args( ) {
302
+ for arg in clang_args {
303
+ builder = builder. clang_arg( arg) ;
304
+ }
305
+ }
152
306
builder
153
307
}
154
308
}
155
309
}
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
+
156
353
/// Retrieves the installation path from the environment variable and validates it.
157
354
fn installation_path_from_env_var ( ) -> Option < ( PathBuf , String ) > {
158
355
std:: env:: var ( PATH_ENV_VAR_NAME ) . map_or_else (
@@ -372,6 +569,16 @@ pub mod tpm2_tss {
372
569
)
373
570
}
374
571
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
+
375
582
/// Probe the system for an optional library using pkg-config.
376
583
///
377
584
/// # Args
0 commit comments