@@ -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
0 commit comments