diff options
| author | Jussi Pakkanen <jpakkane@gmail.com> | 2024-03-29 23:54:06 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-29 23:54:06 +0200 |
| commit | 516a485136f871a15bba3889182a3795178ccba1 (patch) | |
| tree | 91b2b3e354abf1be0ca31c84e9636a45cbb731ea /mesonbuild/scripts | |
| parent | 27caa765ff33e1343546ea026f341f60d2fb05c0 (diff) | |
| parent | 2171a017be671283c7d68b60efba4404bedf5e64 (diff) | |
| download | meson-516a485136f871a15bba3889182a3795178ccba1.tar.gz | |
Merge pull request #13021 from dcbaker/submit/depscanner-fixes-and-speedups
Cleanups, fixes, and speedups for the depscanner
Diffstat (limited to 'mesonbuild/scripts')
| -rw-r--r-- | mesonbuild/scripts/depscan.py | 73 |
1 files changed, 24 insertions, 49 deletions
diff --git a/mesonbuild/scripts/depscan.py b/mesonbuild/scripts/depscan.py index d5b8a0734..44e805447 100644 --- a/mesonbuild/scripts/depscan.py +++ b/mesonbuild/scripts/depscan.py @@ -1,20 +1,20 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2020 The Meson development team +# Copyright © 2023 Intel Corporation from __future__ import annotations -import json +import collections import os import pathlib import pickle import re -import sys import typing as T from ..backend.ninjabackend import ninja_quote -from ..compilers.compilers import lang_suffixes if T.TYPE_CHECKING: + from typing_extensions import Literal from ..backend.ninjabackend import TargetDependencyScannerInfo CPP_IMPORT_RE = re.compile(r'\w*import ([a-zA-Z0-9]+);') @@ -30,26 +30,21 @@ FORTRAN_SUBMOD_RE = re.compile(FORTRAN_SUBMOD_PAT, re.IGNORECASE) FORTRAN_USE_RE = re.compile(FORTRAN_USE_PAT, re.IGNORECASE) class DependencyScanner: - def __init__(self, pickle_file: str, outfile: str, sources: T.List[str]): + def __init__(self, pickle_file: str, outfile: str): with open(pickle_file, 'rb') as pf: self.target_data: TargetDependencyScannerInfo = pickle.load(pf) self.outfile = outfile - self.sources = sources + self.sources = self.target_data.sources self.provided_by: T.Dict[str, str] = {} self.exports: T.Dict[str, str] = {} - self.needs: T.Dict[str, T.List[str]] = {} + self.needs: collections.defaultdict[str, T.List[str]] = collections.defaultdict(list) self.sources_with_exports: T.List[str] = [] - def scan_file(self, fname: str) -> None: - suffix = os.path.splitext(fname)[1][1:] - if suffix != 'C': - suffix = suffix.lower() - if suffix in lang_suffixes['fortran']: + def scan_file(self, fname: str, lang: Literal['cpp', 'fortran']) -> None: + if lang == 'fortran': self.scan_fortran_file(fname) - elif suffix in lang_suffixes['cpp']: - self.scan_cpp_file(fname) else: - sys.exit(f'Can not scan files with suffix .{suffix}.') + self.scan_cpp_file(fname) def scan_fortran_file(self, fname: str) -> None: fpath = pathlib.Path(fname) @@ -63,10 +58,7 @@ class DependencyScanner: # In Fortran you have an using declaration also for the module # you define in the same file. Prevent circular dependencies. if needed not in modules_in_this_file: - if fname in self.needs: - self.needs[fname].append(needed) - else: - self.needs[fname] = [needed] + self.needs[fname].append(needed) if export_match: exported_module = export_match.group(1).lower() assert exported_module not in modules_in_this_file @@ -97,10 +89,7 @@ class DependencyScanner: # submodule (a1:a2) a3 <- requires a1@a2.smod # # a3 does not depend on the a1 parent module directly, only transitively. - if fname in self.needs: - self.needs[fname].append(parent_module_name_full) - else: - self.needs[fname] = [parent_module_name_full] + self.needs[fname].append(parent_module_name_full) def scan_cpp_file(self, fname: str) -> None: fpath = pathlib.Path(fname) @@ -109,10 +98,7 @@ class DependencyScanner: export_match = CPP_EXPORT_RE.match(line) if import_match: needed = import_match.group(1) - if fname in self.needs: - self.needs[fname].append(needed) - else: - self.needs[fname] = [needed] + self.needs[fname].append(needed) if export_match: exported_module = export_match.group(1) if exported_module in self.provided_by: @@ -121,14 +107,8 @@ class DependencyScanner: self.provided_by[exported_module] = fname self.exports[fname] = exported_module - def objname_for(self, src: str) -> str: - objname = self.target_data.source2object[src] - assert isinstance(objname, str) - return objname - - def module_name_for(self, src: str) -> str: - suffix = os.path.splitext(src)[1][1:].lower() - if suffix in lang_suffixes['fortran']: + def module_name_for(self, src: str, lang: Literal['cpp', 'fortran']) -> str: + if lang == 'fortran': exported = self.exports[src] # Module foo:bar goes to a file name foo@bar.smod # Module Foo goes to a file name foo.mod @@ -138,23 +118,20 @@ class DependencyScanner: else: extension = 'mod' return os.path.join(self.target_data.private_dir, f'{namebase}.{extension}') - elif suffix in lang_suffixes['cpp']: - return '{}.ifc'.format(self.exports[src]) - else: - raise RuntimeError('Unreachable code.') + return '{}.ifc'.format(self.exports[src]) def scan(self) -> int: - for s in self.sources: - self.scan_file(s) + for s, lang in self.sources: + self.scan_file(s, lang) with open(self.outfile, 'w', encoding='utf-8') as ofile: ofile.write('ninja_dyndep_version = 1\n') - for src in self.sources: - objfilename = self.objname_for(src) + for src, lang in self.sources: + objfilename = self.target_data.source2object[src] mods_and_submods_needed = [] module_files_generated = [] module_files_needed = [] if src in self.sources_with_exports: - module_files_generated.append(self.module_name_for(src)) + module_files_generated.append(self.module_name_for(src, lang)) if src in self.needs: for modname in self.needs[src]: if modname not in self.provided_by: @@ -167,7 +144,7 @@ class DependencyScanner: for modname in mods_and_submods_needed: provider_src = self.provided_by[modname] - provider_modfile = self.module_name_for(provider_src) + provider_modfile = self.module_name_for(provider_src, lang) # Prune self-dependencies if provider_src != src: module_files_needed.append(provider_modfile) @@ -190,9 +167,7 @@ class DependencyScanner: return 0 def run(args: T.List[str]) -> int: - assert len(args) == 3, 'got wrong number of arguments!' - pickle_file, outfile, jsonfile = args - with open(jsonfile, encoding='utf-8') as f: - sources = json.load(f) - scanner = DependencyScanner(pickle_file, outfile, sources) + assert len(args) == 2, 'got wrong number of arguments!' + outfile, pickle_file = args + scanner = DependencyScanner(pickle_file, outfile) return scanner.scan() |
