@@ -29,6 +29,8 @@ use quote::ToTokens;
29
29
use std:: borrow:: Cow ;
30
30
use std:: cell:: { Cell , RefCell } ;
31
31
use std:: collections:: { BTreeSet , HashMap as StdHashMap } ;
32
+ use std:: fs:: OpenOptions ;
33
+ use std:: io:: Write ;
32
34
use std:: mem;
33
35
use std:: path:: Path ;
34
36
@@ -2081,55 +2083,82 @@ If you encounter an error missing from this list, please file an issue or a PR!"
2081
2083
2082
2084
let index = clang:: Index :: new ( false , false ) ;
2083
2085
2084
- let mut c_args = Vec :: new ( ) ;
2085
- let mut pch_paths = Vec :: new ( ) ;
2086
- for input_header in self . options ( ) . input_headers . iter ( ) {
2086
+ let mut header_names_to_compile = Vec :: new ( ) ;
2087
+ let mut header_paths = Vec :: new ( ) ;
2088
+ let mut header_contents = String :: new ( ) ;
2089
+ for input_header in self . options . input_headers . iter ( ) {
2087
2090
let path = Path :: new ( input_header. as_ref ( ) ) ;
2088
- let header_name = path
2089
- . file_name ( )
2090
- . and_then ( |hn| hn. to_str ( ) )
2091
- . map ( |s| s. to_owned ( ) ) ;
2092
- let header_path = path
2093
- . parent ( )
2094
- . and_then ( |hp| hp. to_str ( ) )
2095
- . map ( |s| s. to_owned ( ) ) ;
2096
-
2097
- let ( header, pch) = if let ( Some ( ref hp) , Some ( hn) ) =
2098
- ( header_path, header_name)
2099
- {
2100
- let header_path = if hp. is_empty ( ) { "." } else { hp } ;
2101
- let header = format ! ( "{header_path}/{hn}" ) ;
2102
- let pch_path = if let Some ( ref path) =
2103
- self . options ( ) . clang_macro_fallback_build_dir
2104
- {
2105
- path. as_os_str ( ) . to_str ( ) ?
2091
+ if let Some ( header_path) = path. parent ( ) {
2092
+ if header_path == Path :: new ( "" ) {
2093
+ header_paths. push ( "." ) ;
2106
2094
} else {
2107
- header_path
2108
- } ;
2109
- ( header, format ! ( "{pch_path}/{hn}.pch" ) )
2095
+ header_paths. push ( header_path. as_os_str ( ) . to_str ( ) ?) ;
2096
+ }
2110
2097
} else {
2111
- return None ;
2112
- } ;
2113
-
2114
- let mut tu = clang:: TranslationUnit :: parse (
2115
- & index,
2116
- & header,
2117
- & [
2118
- "-x" . to_owned ( ) . into_boxed_str ( ) ,
2119
- "c-header" . to_owned ( ) . into_boxed_str ( ) ,
2120
- ] ,
2121
- & [ ] ,
2122
- clang_sys:: CXTranslationUnit_ForSerialization ,
2123
- ) ?;
2124
- tu. save ( & pch) . ok ( ) ?;
2125
-
2126
- c_args. push ( "-include-pch" . to_string ( ) . into_boxed_str ( ) ) ;
2127
- c_args. push ( pch. clone ( ) . into_boxed_str ( ) ) ;
2128
- pch_paths. push ( pch) ;
2098
+ header_paths. push ( "." ) ;
2099
+ }
2100
+ let header_name = path. file_name ( ) ?. to_str ( ) ?;
2101
+ header_names_to_compile
2102
+ . push ( header_name. split ( ".h" ) . next ( ) ?. to_string ( ) ) ;
2103
+ header_contents +=
2104
+ format ! ( "\n #include <{header_name}>" ) . as_str ( ) ;
2129
2105
}
2106
+ let header_to_precompile = format ! (
2107
+ "{}/{}" ,
2108
+ match self . options( ) . clang_macro_fallback_build_dir {
2109
+ Some ( ref path) => path. as_os_str( ) . to_str( ) ?,
2110
+ None => "." ,
2111
+ } ,
2112
+ header_names_to_compile. join( "-" ) + "-precompile.h"
2113
+ ) ;
2114
+ let pch = header_to_precompile. clone ( ) + ".pch" ;
2115
+
2116
+ let mut header_to_precompile_file = OpenOptions :: new ( )
2117
+ . create ( true )
2118
+ . truncate ( true )
2119
+ . write ( true )
2120
+ . open ( & header_to_precompile)
2121
+ . ok ( ) ?;
2122
+ header_to_precompile_file
2123
+ . write_all ( header_contents. as_bytes ( ) )
2124
+ . ok ( ) ?;
2130
2125
2126
+ let mut c_args = Vec :: new ( ) ;
2127
+ c_args. push ( "-x" . to_string ( ) . into_boxed_str ( ) ) ;
2128
+ c_args. push ( "c-header" . to_string ( ) . into_boxed_str ( ) ) ;
2129
+ for header_path in header_paths {
2130
+ c_args. push ( format ! ( "-I{header_path}" ) . into_boxed_str ( ) ) ;
2131
+ }
2132
+ let mut need_next = false ;
2133
+ for arg in self . options . clang_args . iter ( ) {
2134
+ if need_next {
2135
+ c_args. push ( arg. clone ( ) ) ;
2136
+ need_next = false ;
2137
+ } else if arg. as_ref ( ) == "-I" || arg. as_ref ( ) == "-isystem" {
2138
+ c_args. push ( arg. clone ( ) ) ;
2139
+ need_next = true ;
2140
+ } else if arg. starts_with ( "-I" ) || arg. starts_with ( "-isystem" ) {
2141
+ c_args. push ( arg. clone ( ) ) ;
2142
+ }
2143
+ }
2144
+ let mut tu = clang:: TranslationUnit :: parse (
2145
+ & index,
2146
+ & header_to_precompile,
2147
+ & c_args,
2148
+ & [ ] ,
2149
+ clang_sys:: CXTranslationUnit_ForSerialization ,
2150
+ ) ?;
2151
+ tu. save ( & pch) . ok ( ) ?;
2152
+
2153
+ let c_args = vec ! [
2154
+ "-include-pch" . to_string( ) . into_boxed_str( ) ,
2155
+ pch. clone( ) . into_boxed_str( ) ,
2156
+ ] ;
2131
2157
self . fallback_tu = Some ( clang:: FallbackTranslationUnit :: new (
2132
- file, pch_paths, & c_args,
2158
+ file,
2159
+ header_to_precompile,
2160
+ pch,
2161
+ & c_args,
2133
2162
) ?) ;
2134
2163
}
2135
2164
0 commit comments