77# -------------------------------------------------------------------------
88
99
10- from collections import namedtuple
10+ from dataclasses import dataclass
1111from shutil import which
1212from enum import Enum
1313from functools import lru_cache
@@ -322,9 +322,25 @@ class ImplicitCompilerInfo:
322322 # attributes to the implicit settings. In the future we may find that some
323323 # other attributes are also dependencies of implicit compiler info in which
324324 # case this tuple should be extended.
325- ImplicitInfoSpecifierKey = namedtuple (
326- 'ImplicitInfoSpecifierKey' ,
327- ['compiler' , 'language' , 'compiler_flags' ])
325+ @dataclass
326+ class ImplicitInfoSpecifierKey :
327+ compiler : str
328+ language : str
329+ compiler_flags : list [str ]
330+
331+ def __str__ (self ):
332+ return json .dumps ([
333+ self .compiler ,
334+ self .language ,
335+ self .compiler_flags ])
336+
337+ def __eq__ (self , other ):
338+ return (self .compiler , self .language , self .compiler_flags ) == \
339+ (other .compiler , other .language , other .compiler_flags )
340+
341+ def __hash__ (self ):
342+ return hash (
343+ (self .compiler , self .language , tuple (self .compiler_flags )))
328344
329345 compiler_info : Dict [ImplicitInfoSpecifierKey , dict ] = {}
330346 compiler_isexecutable = {}
@@ -333,14 +349,6 @@ class ImplicitCompilerInfo:
333349 # should be a clang version information object.
334350 compiler_versions = {}
335351
336- @staticmethod
337- def c ():
338- return "c"
339-
340- @staticmethod
341- def cpp ():
342- return "c++"
343-
344352 @staticmethod
345353 def is_executable_compiler (compiler ):
346354 if compiler not in ImplicitCompilerInfo .compiler_isexecutable :
@@ -378,11 +386,9 @@ def __get_compiler_err(cmd: List[str]) -> Optional[str]:
378386 _ , err = proc .communicate ("" )
379387 return err
380388 except OSError as oerr :
381- # TODO: shlex.join(cmd) would be more elegant after upgrading to
382- # Python 3.8.
383389 LOG .error (
384390 "Error during process execution: %s\n %s\n " ,
385- ' ' .join (map ( shlex . quote , cmd ) ), oerr .strerror )
391+ shlex .join (cmd ), oerr .strerror )
386392 return None
387393
388394 @staticmethod
@@ -437,11 +443,7 @@ def get_compiler_includes(compiler, language, compiler_flags):
437443 """
438444 cmd = [compiler , * compiler_flags , '-E' , '-x' , language , '-' , '-v' ]
439445
440- # TODO: shlex.join(cmd) would be more elegant after upgrading to
441- # Python 3.8.
442- LOG .debug (
443- "Retrieving default includes via %s" ,
444- ' ' .join (map (shlex .quote , cmd )))
446+ LOG .debug ("Retrieving default includes via %s" , shlex .join (cmd ))
445447 include_dirs = ImplicitCompilerInfo .__parse_compiler_includes (cmd )
446448
447449 return list (map (os .path .normpath , include_dirs ))
@@ -551,7 +553,7 @@ def get_compiler_standard(compiler, language):
551553 @staticmethod
552554 def dump_compiler_info (file_path : str ):
553555 dumpable = {
554- json . dumps (k ): v for k , v
556+ str (k ): v for k , v
555557 in ImplicitCompilerInfo .compiler_info .items ()}
556558
557559 with open (file_path , 'w' , encoding = "utf-8" , errors = "ignore" ) as f :
@@ -976,8 +978,7 @@ def parse_options(compilation_db_entry,
976978
977979 if 'arguments' in compilation_db_entry :
978980 gcc_command = compilation_db_entry ['arguments' ]
979- details ['original_command' ] = \
980- ' ' .join ([shlex .quote (x ) for x in gcc_command ])
981+ details ['original_command' ] = shlex .join (gcc_command )
981982 elif 'command' in compilation_db_entry :
982983 details ['original_command' ] = compilation_db_entry ['command' ]
983984 gcc_command = shlex .split (compilation_db_entry ['command' ])
@@ -1223,7 +1224,6 @@ def _process_entry_worker(args):
12231224
12241225
12251226def parse_unique_log (compilation_database ,
1226- report_dir ,
12271227 compile_uniqueing = "none" ,
12281228 compiler_info_file = None ,
12291229 keep_gcc_include_fixed = False ,
@@ -1251,8 +1251,6 @@ def parse_unique_log(compilation_database,
12511251 by "arguments" which is a split command. Older
12521252 versions of intercept-build provide the build
12531253 command this way.
1254- report_dir -- The output report directory. The compiler infos
1255- will be written to <report_dir>/compiler.info.json.
12561254 compile_uniqueing -- Compilation database uniqueing mode.
12571255 If there are more than one compile commands for a
12581256 target file, only a single one is kept.
@@ -1312,6 +1310,13 @@ def parse_unique_log(compilation_database,
13121310 keep_gcc_intrin )
13131311 for entry in entries )
13141312
1313+ # Here we overwrite ImplicitCompilerInfo.compiker_info with a dict type
1314+ # that can be used in multiprocess environment, since the next section
1315+ # is executed in a process pool.
1316+ manager = multiprocessing .SyncManager ()
1317+ manager .start ()
1318+ ImplicitCompilerInfo .compiler_info = manager .dict ()
1319+
13151320 # Process entries in parallel using imap_unordered with chunk size 1024
13161321 with multiprocessing .Pool (jobs ) as pool :
13171322 # Convert generator to list for map function
@@ -1390,9 +1395,6 @@ def parse_unique_log(compilation_database,
13901395 compile_uniqueing )
13911396 sys .exit (1 )
13921397
1393- ImplicitCompilerInfo .dump_compiler_info (
1394- os .path .join (report_dir , "compiler_info.json" ))
1395-
13961398 LOG .debug ('Parsing log file done.' )
13971399 return list (uniqued_build_actions .values ()), skipped_cmp_cmd_count
13981400
0 commit comments