Skip to content

Commit

Permalink
backends, compilers: move Fortran-specific handling out of ninjabackend
Browse files Browse the repository at this point in the history
All Fortran-specific handling of "objects:" is for now in generate_target();
parts of it can be reused for Rust.

Even though Rust is only supported by the ninja backend, move the Fortran
handling entirely outside ninjabackend.py: it's not specific to Ninja,
it can be implemented easily using inheritance, and it also gets better
typing this way.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
bonzini committed Dec 20, 2024
1 parent 3b9fa9a commit 6b29548
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 19 deletions.
10 changes: 10 additions & 0 deletions mesonbuild/backend/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,16 @@ def relpath(todir: str, fromdir: str) -> str:
return os.path.relpath(os.path.join('dummyprefixdir', todir),
os.path.join('dummyprefixdir', fromdir))

def get_compiler_order_deps(self, target: build.BuildTarget, compiler: Compiler) -> T.List[str]:
return [
os.path.join(self.get_target_dir(lt), lt.get_filename())
for lt in compiler.get_extra_order_deps(target)
]

def get_fortran_order_deps(self, deps: T.List[build.BuildTarget]) -> T.List[File]:
return [File(True, *os.path.split(self.get_target_filename(t))) for t in deps
if t.uses_fortran()]

def flatten_object_list(self, target: build.BuildTarget, proj_dir_to_build_root: str = ''
) -> T.Tuple[T.List[str], T.List[build.BuildTargetTypes]]:
obj_list, deps = self._flatten_object_list(target, target.get_objects(), proj_dir_to_build_root)
Expand Down
21 changes: 3 additions & 18 deletions mesonbuild/backend/ninjabackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -1016,14 +1016,13 @@ def generate_target(self, target) -> None:
pch_objects = []

o, od = self.flatten_object_list(target)
obj_targets = [t for t in od if t.uses_fortran()]
obj_list.extend(o)

fortran_order_deps = [File(True, *os.path.split(self.get_target_filename(t))) for t in obj_targets]
fortran_order_deps = self.get_fortran_order_deps(od)
fortran_inc_args: T.List[str] = []
if target.uses_fortran():
fortran_inc_args = mesonlib.listify([target.compilers['fortran'].get_include_args(
self.get_target_private_dir(t), is_system=False) for t in obj_targets])
self.get_target_private_dir(t), is_system=False) for t in od if t.uses_fortran()])

# Generate compilation targets for sources generated by transpilers.
#
Expand Down Expand Up @@ -3073,7 +3072,7 @@ def generate_single_compile(self, target: build.BuildTarget, src,
d = os.path.join(self.get_target_private_dir(target), d)
element.add_orderdep(d)
element.add_dep(pch_dep)
for i in self.get_fortran_orderdeps(target, compiler):
for i in self.get_compiler_order_deps(target, compiler):
element.add_orderdep(i)
if dep_file:
element.add_item('DEPFILE', dep_file)
Expand Down Expand Up @@ -3138,20 +3137,6 @@ def has_dir_part(self, fname: FileOrString) -> bool:
return fname.subdir != ''
return has_path_sep(fname)

# Fortran is a bit weird (again). When you link against a library, just compiling a source file
# requires the mod files that are output when single files are built. To do this right we would need to
# scan all inputs and write out explicit deps for each file. That is too slow and too much effort so
# instead just have an ordered dependency on the library. This ensures all required mod files are created.
# The real deps are then detected via dep file generation from the compiler. This breaks on compilers that
# produce incorrect dep files but such is life.
def get_fortran_orderdeps(self, target, compiler):
if compiler.language != 'fortran':
return []
return [
os.path.join(self.get_target_dir(lt), lt.get_filename())
for lt in itertools.chain(target.link_targets, target.link_whole_targets)
]

def generate_msvc_pch_command(self, target, compiler, pch):
header = pch[0]
pchname = compiler.get_pch_name(header)
Expand Down
5 changes: 4 additions & 1 deletion mesonbuild/compilers/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

if T.TYPE_CHECKING:
from .. import coredata
from ..build import BuildTarget, DFeatures
from ..build import BuildTarget, BuildTargetTypes, DFeatures
from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType
from ..envconfig import MachineInfo
from ..environment import Environment
Expand Down Expand Up @@ -1218,6 +1218,9 @@ def get_module_outdir_args(self, path: str) -> T.List[str]:
def module_name_to_filename(self, module_name: str) -> str:
raise EnvironmentException(f'{self.id} does not implement module_name_to_filename')

def get_extra_order_deps(self, target: BuildTarget) -> T.Iterable[BuildTargetTypes]:
return []

def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
"""Arguments to pass the compiler and/or linker for checks.
Expand Down
11 changes: 11 additions & 0 deletions mesonbuild/compilers/fortran.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import typing as T
import functools
import itertools
import os

from .. import options
Expand All @@ -27,6 +28,7 @@
)

if T.TYPE_CHECKING:
from ..build import BuildTarget, BuildTargetTypes
from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType
from ..dependencies import Dependency
from ..envconfig import MachineInfo
Expand Down Expand Up @@ -80,6 +82,15 @@ def get_module_incdir_args(self) -> T.Tuple[str, ...]:
def get_module_outdir_args(self, path: str) -> T.List[str]:
return ['-module', path]

# Fortran is a bit weird (again). When you link against a library, just compiling a source file
# requires the mod files that are output when single files are built. To do this right we would need to
# scan all inputs and write out explicit deps for each file. That is too slow and too much effort so
# instead just have an ordered dependency on the library. This ensures all required mod files are created.
# The real deps are then detected via dep file generation from the compiler. This breaks on compilers that
# produce incorrect dep files but such is life.
def get_extra_order_deps(self, target: BuildTarget) -> T.Iterable[BuildTargetTypes]:
return itertools.chain(target.link_targets, target.link_whole_targets)

def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str],
build_dir: str) -> T.List[str]:
for idx, i in enumerate(parameter_list):
Expand Down

0 comments on commit 6b29548

Please sign in to comment.