summaryrefslogtreecommitdiff
path: root/mesonbuild/scripts
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2024-03-29 23:54:06 +0200
committerGitHub <noreply@github.com>2024-03-29 23:54:06 +0200
commit516a485136f871a15bba3889182a3795178ccba1 (patch)
tree91b2b3e354abf1be0ca31c84e9636a45cbb731ea /mesonbuild/scripts
parent27caa765ff33e1343546ea026f341f60d2fb05c0 (diff)
parent2171a017be671283c7d68b60efba4404bedf5e64 (diff)
downloadmeson-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.py73
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()