Summary: Allow backend to trigger compilation of extra files when it needs them. This will allow infer to capture less files initally and possibly speed up compilation Reviewed By: cristianoc, jberdine Differential Revision: D4231581 fbshipit-source-id: 181abeamaster
							parent
							
								
									f0498a77f9
								
							
						
					
					
						commit
						c9d254c084
					
				| @ -0,0 +1,64 @@ | |||||||
|  | (* | ||||||
|  |  * Copyright (c) 2016 - present Facebook, Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * This source code is licensed under the BSD style license found in the | ||||||
|  |  * LICENSE file in the root directory of this source tree. An additional grant | ||||||
|  |  * of patent rights can be found in the PATENTS file in the same directory. | ||||||
|  |  *) | ||||||
|  | open! Utils | ||||||
|  | 
 | ||||||
|  | let compilation_db = lazy (CompilationDatabase.from_json_files !Config.clang_compilation_db_files) | ||||||
|  | 
 | ||||||
|  | (** Given proc_attributes try to produce proc_attributes' where proc_attributes'.is_defined = true | ||||||
|  |     It may trigger capture of extra files to do so and when it does, it waits for | ||||||
|  |     frontend to finish before returning *) | ||||||
|  | let try_capture (attributes : ProcAttributes.t) : ProcAttributes.t option = | ||||||
|  |   let lazy cdb = compilation_db in | ||||||
|  |   if Option.is_none | ||||||
|  |       (AttributesTable.load_defined_attributes ~cache_none:false attributes.proc_name) then ( | ||||||
|  |     let decl_file = attributes.loc.file in | ||||||
|  |     let definition_file_opt = SourceFile.of_header decl_file in | ||||||
|  |     let try_compile definition_file = | ||||||
|  |       let source_dir = DB.source_dir_from_source_file definition_file in | ||||||
|  |       (* Use cfg_filename as a proxy to find out whether definition_file was already captured. | ||||||
|  |          If it was, there is no point in trying to capture it again. | ||||||
|  |          Treat existance of cfg_filename as a barrier - if it exists it means that | ||||||
|  |          all attributes files have been created - write logic is defined in | ||||||
|  |          Cfg.store_cfg_to_file *) | ||||||
|  |       let cfg_filename = DB.source_dir_get_internal_file source_dir ".cfg" in | ||||||
|  |       if not (DB.file_exists cfg_filename) then ( | ||||||
|  |         CaptureCompilationDatabase.capture_file_in_database cdb definition_file; | ||||||
|  |         if Config.debug_mode && | ||||||
|  |            Option.is_none | ||||||
|  |              (AttributesTable.load_defined_attributes ~cache_none:false attributes.proc_name) then ( | ||||||
|  |           (* peek at the results to know if capture succeeded, but only in debug mode *) | ||||||
|  |           Logging.out | ||||||
|  |             "Captured file %a to get procedure %a but it wasn't found there@." | ||||||
|  |             SourceFile.pp definition_file | ||||||
|  |             Procname.pp attributes.proc_name | ||||||
|  |         ) | ||||||
|  |       ) else ( | ||||||
|  |         Logging.out | ||||||
|  |           "Wanted to capture file %a to get procedure %a but file was already captured@." | ||||||
|  |           SourceFile.pp definition_file | ||||||
|  |           Procname.pp attributes.proc_name | ||||||
|  |       ) | ||||||
|  |     in | ||||||
|  |     Option.may try_compile definition_file_opt | ||||||
|  |   ); | ||||||
|  |   (* It's important to call load_defined_attributes again in all cases to make sure we try | ||||||
|  |      reading from disk again no matter which condition happened. If previous call to | ||||||
|  |      load_defined_attributes is None, it may mean couple of things: | ||||||
|  |      - proc_name hasn't been captured yet, so it needs to get captured (most likely scenario) | ||||||
|  |      - there was a race and proc_name got captured by the time we checked whether | ||||||
|  |        cfg_filename exists. In this case it's important to refetch attributes from disk because | ||||||
|  |        contents may have changed (attributes file for proc_name may be there now) | ||||||
|  |      - proc_name can't be captured (there is no definition we know of). In that case | ||||||
|  |        result will stay None. At this point we know(?) we won't be able to find definition | ||||||
|  |        for it ever so we can cache None. | ||||||
|  |        Caveat: it's possible that procedure will be captured in some other unrelated file | ||||||
|  |                later - infer may ignore it then. | ||||||
|  |      It also relies on retry mechanism in deserialization code to deal with half-written | ||||||
|  |      attributes files *) | ||||||
|  |   AttributesTable.load_defined_attributes ~cache_none:true attributes.proc_name | ||||||
					Loading…
					
					
				
		Reference in new issue