"""Module for functions relating to make."""importloggingimportreimporttempfilefrompathlibimportPathfromtypingimportIterable,List,Set,Tuplefrome3_build_tools.utilsimportrun_make
[docs]defparse_file_for_cxx_stds(f:Iterable)->List[str]:"""Return all c++ std definitions in a makefile."""stds=[]forlineinf:match=re.match(CXX_FLAGS_REGEX,line)ifmatch:logger.debug(f"Found {match.group(1)} with -std={match.group(2)}")stds.append(match.group(2))returnstds
[docs]deffind_cxx_stds(wrapper_path:Path)->List[Tuple[Path,List[str]]]:"""Return all c++ std definitions in all makefiles."""stds=[]forfnameinwrapper_path.glob("*.Makefile"):logger.debug(f"Checking file {fname} for CXX std definitions")withfname.open()asf:file_stds=parse_file_for_cxx_stds(f)iffile_stds:stds.append((fname,file_stds))forfname,file_stdsinstds:logger.info(f"{fname} contains the c++ standards {file_stds}")returnstds
[docs]defcreate_tmp_makefile(tmp_path:Path,wrapper_path:Path)->None:"""Create a temporary makefile to try to determine which variables are undefined."""makefile_path=tmp_path/"Makefile"withopen(makefile_path,"w")asf:f.write("VARS_EXCLUDE:=$(.VARIABLES)\n")# Read in the configure files from the actual module in order to catch# the *_DEP_VERSION, etc. definitionsforcfileinfilter(lambdax:x.is_file(),[wrapper_path/"configure"/cfforcfinCONFIG_FILES],):f.write(f"include {cfile.absolute()}\n")# Read in the actual makefile(s)forfnameinwrapper_path.glob("*.Makefile"):f.write(f"include {fname.absolute()}\n")# We need to force `make` to actually evaluate all of the variables in order to# test for them being undefinedf.write("$(foreach v,$(filter-out $(VARS_EXCLUDE),$(.VARIABLES)),$(eval $v:=$($v)))\n")withopen(makefile_path,"r")asf:logger.debug("Generated makefile:\n"+f.read())
[docs]deffind_undefined_vars(wrapper_path:Path)->Set[str]:"""Run `make` to see which variables have not been defined. Compile CONFIG_MODULE, CONFIG_OPTIONS, and all *.Makefiles into a single dummy file. Test this using the flag --warn-undefined-variables """undefined=set()withtempfile.TemporaryDirectory()asd:tmp_dir=Path(d)create_tmp_makefile(tmp_dir,wrapper_path)result=run_make(tmp_dir,"-n","--warn-undefined-variables")forlineinresult.stderr.split("\n"):match=re.match(UNDEF_REGEX,line)ifmatch:logger.debug(match.group(0))ifmatch.group(1)notinEXCEPTIONS:undefined.add(match.group(1))ifundefined:logger.info("Undefined variables: "+str(undefined))returnundefined