Skip to content

Commit

Permalink
Fix support for post-libs.
Browse files Browse the repository at this point in the history
  • Loading branch information
hiker committed Dec 3, 2024
1 parent 7b189e8 commit d084f20
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 10 deletions.
45 changes: 38 additions & 7 deletions source/fab/tools/linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Linker(CompilerSuiteTool):

def __init__(self, compiler: Optional[Compiler] = None,
linker: Optional[Linker] = None,
exec_name: Optional[str] = None,
name: Optional[str] = None):

if linker and compiler:
Expand All @@ -53,9 +54,13 @@ def __init__(self, compiler: Optional[Compiler] = None,
assert final_compiler
name = f"linker-{final_compiler.name}"

if not exec_name:
# This will search for the name in linker or compiler
exec_name = self.get_exec_name()

super().__init__(
name=name or f"linker-{name}",
exec_name=self.exec_name,
exec_name=exec_name,
suite=self.suite,
category=Category.LINKER)

Expand All @@ -67,22 +72,30 @@ def __init__(self, compiler: Optional[Compiler] = None,
self._pre_lib_flags: List[str] = []
self._post_lib_flags: List[str] = []

def check_available(self):
def check_available(self) -> bool:
''':returns: whether this linker is available by asking the wrapped
linker or compiler.
'''
return (self._compiler or self._linker).check_available()

@property
def exec_name(self) -> str:
def get_exec_name(self) -> str:
''':returns: the name of the executable by asking the wrapped
linker or compiler.'''
if self._compiler:
return self._compiler.exec_name
assert self._linker # make mypy happy
return self._linker.exec_name

@property
def suite(self) -> str:
''':returns: the suite this linker belongs to by getting it from
the wrapper compiler or linker.'''
return cast(CompilerSuiteTool, (self._compiler or self._linker)).suite

@property
def mpi(self) -> bool:
''':returns" whether this linker supports MPI or not by checking
with the wrapper compiler or linker.'''
if self._compiler:
return self._compiler.mpi
assert self._linker
Expand Down Expand Up @@ -158,7 +171,7 @@ def add_post_lib_flags(self, flags: List[str]):

def get_pre_link_flags(self) -> List[str]:
'''Returns the list of pre-link flags. It will concatenate the
flags for this instance with all potentially wrapper linkers.
flags for this instance with all potentially wrapped linkers.
This wrapper's flag will come first - the assumption is that
the pre-link flags are likely paths, so we need a wrapper to
be able to put a search path before the paths from a wrapped
Expand All @@ -178,6 +191,25 @@ def get_pre_link_flags(self) -> List[str]:
params.extend(self._linker.get_pre_link_flags())
return params

def get_post_link_flags(self) -> List[str]:
'''Returns the list of post-link flags. It will concatenate the
flags for this instance with all potentially wrapped linkers.
This wrapper's flag will be added to the end.
:returns: List of post-link flags of this linker and all
wrapped linkers
'''
params: List[str] = []
if self._linker:
# If we are wrapping a linker, get the wrapped linker's
# pre-link flags and append them to the end (so the linker
# wrapper's settings come before the setting from the
# wrapped linker).
params.extend(self._linker.get_post_link_flags())
if self._post_lib_flags:
params.extend(self._post_lib_flags)
return params

def link(self, input_files: List[Path], output_file: Path,
openmp: bool,
libs: Optional[List[str]] = None) -> str:
Expand Down Expand Up @@ -214,8 +246,7 @@ def link(self, input_files: List[Path], output_file: Path,
for lib in (libs or []):
params.extend(self.get_lib_flags(lib))

if self._post_lib_flags:
params.extend(self._post_lib_flags)
params.extend(self.get_post_link_flags())
params.extend([self.output_flag, str(output_file)])

return self.run(params)
1 change: 1 addition & 0 deletions source/fab/tools/tool_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ def add_tool(self, tool: Tool):
name=f"linker-{compiler.compiler.name}")
other_linker = cast(Linker, other_linker)
linker = Linker(linker=other_linker,
exec_name=compiler.exec_name,
name=f"linker-{compiler.name}")
self[linker.category].append(linker)
else:
Expand Down
9 changes: 6 additions & 3 deletions tests/unit_tests/tools/test_linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,10 +316,12 @@ def test_linker_nesting(mock_c_compiler):
linker1.add_pre_lib_flags(["pre_lib1"])
linker1.add_lib_flags("lib_a", ["a_from_1"])
linker1.add_lib_flags("lib_c", ["c_from_1"])
linker1.add_post_lib_flags(["post_lib1"])
linker2 = Linker(linker=linker1)
linker2.add_pre_lib_flags(["pre_lib2"])
linker2.add_lib_flags("lib_b", ["b_from_2"])
linker2.add_lib_flags("lib_c", ["c_from_2"])
linker1.add_post_lib_flags(["post_lib2"])

mock_result = mock.Mock(returncode=0)
with mock.patch("fab.tools.tool.subprocess.run",
Expand All @@ -328,9 +330,10 @@ def test_linker_nesting(mock_c_compiler):
[Path("a.o")], Path("a.out"),
libs=["lib_a", "lib_b", "lib_c"],
openmp=True)
tool_run.assert_called_with(['mock_c_compiler.exe', '-fopenmp',
'a.o', "pre_lib2", "pre_lib1", "a_from_1",
"b_from_2", "c_from_2", '-o', 'a.out'],
tool_run.assert_called_with(["mock_c_compiler.exe", "-fopenmp",
"a.o", "pre_lib2", "pre_lib1", "a_from_1",
"b_from_2", "c_from_2",
"post_lib1", "post_lib2", "-o", "a.out"],
capture_output=True, env=None, cwd=None,
check=False)

Expand Down

0 comments on commit d084f20

Please sign in to comment.