Skip to content

Commit

Permalink
Configure pre- and post-lib flags on the Linker object
Browse files Browse the repository at this point in the history
Previously they were passed into the Linker.link() function
  • Loading branch information
lukehoffmann committed Sep 23, 2024
1 parent 58007e8 commit 7286200
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 24 deletions.
9 changes: 5 additions & 4 deletions source/fab/steps/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ def link_exe(config,
logger.info(f'Linker is {linker.name}')

libs = libs or []
flags = flags or []
if flags:
linker.add_post_lib_flags(flags)
source_getter = source or DefaultLinkerSource()

target_objects = source_getter(config.artefact_store)
for root, objects in target_objects.items():
exe_path = config.project_workspace / f'{root}'
linker.link(objects, exe_path, openmp=config.openmp, libs=libs,
post_lib_flags=flags)
linker.link(objects, exe_path, openmp=config.openmp, libs=libs)
config.artefact_store.add(ArtefactSet.EXECUTABLES, exe_path)


Expand Down Expand Up @@ -122,4 +122,5 @@ def link_shared_object(config, output_fpath: str, flags=None,

objects = target_objects[None]
out_name = Template(output_fpath).substitute(output=config.build_output)
linker.link(objects, out_name, openmp=config.openmp, post_lib_flags=flags)
linker.add_post_lib_flags(flags)
linker.link(objects, out_name, openmp=config.openmp)
33 changes: 23 additions & 10 deletions source/fab/tools/linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ def __init__(self, name: Optional[str] = None,

# Maintain a set of flags for common libraries.
self._lib_flags: Dict[str, List[str]] = {}
# Allow flags to include before or after any library-specific flags.
self._pre_lib_flags: List[str] = []
self._post_lib_flags: List[str] = []

@property
def mpi(self) -> bool:
Expand Down Expand Up @@ -102,7 +105,7 @@ def add_lib_flags(self, lib: str, flags: List[str],
self._lib_flags[lib] = flags[:]

def remove_lib_flags(self, lib: str):
'''Add a set of flags for a standard library
'''Remove any flags configured for a standard library
:param lib: the library name
'''
Expand All @@ -111,20 +114,30 @@ def remove_lib_flags(self, lib: str):
except KeyError:
pass

def add_pre_lib_flags(self, flags: List[str]):
'''Add a set of flags to use before any library-specific flags
:param flags: the flags to include
'''
self._pre_lib_flags.extend(flags)

def add_post_lib_flags(self, flags: List[str]):
'''Add a set of flags to use after any library-specific flags
:param flags: the flags to include
'''
self._post_lib_flags.extend(flags)

def link(self, input_files: List[Path], output_file: Path,
openmp: bool,
pre_lib_flags: Optional[List[str]] = None,
libs: Optional[List[str]] = None,
post_lib_flags: Optional[List[str]] = None) -> str:
libs: Optional[List[str]] = None) -> str:
'''Executes the linker with the specified input files,
creating `output_file`.
:param input_files: list of input files to link.
:param output_file: output file.
:param openm: whether OpenMP is requested or not.
:param pre_lib_flags: additional linker flags to use before libs.
:param libs: additional libraries to link with.
:param post_lib_flags: additional linker flags to use after libs.
:returns: the stdout of the link command
'''
Expand All @@ -138,11 +151,11 @@ def link(self, input_files: List[Path], output_file: Path,
# TODO: why are the .o files sorted? That shouldn't matter
params.extend(sorted(map(str, input_files)))

if pre_lib_flags:
params.extend(pre_lib_flags)
if self._pre_lib_flags:
params.extend(self._pre_lib_flags)
for lib in (libs or []):
params.extend(self.get_lib_flags(lib))
if post_lib_flags:
params.extend(post_lib_flags)
if self._post_lib_flags:
params.extend(self._post_lib_flags)
params.extend([self._output_flag, str(output_file)])
return self.run(params)
16 changes: 6 additions & 10 deletions tests/unit_tests/tools/test_linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,11 @@ def test_linker_c_with_libraries_and_post_flags(mock_c_compiler):
specified."""
linker = Linker(compiler=mock_c_compiler)
linker.add_lib_flags("customlib", ["-q", "/tmp", "-j"])
linker.add_post_lib_flags(["-extra-flag"])

with mock.patch.object(linker, "run") as link_run:
linker.link(
[Path("a.o")], Path("a.out"),
libs=["customlib"], post_lib_flags=["-extra-flag"],
openmp=False,
)
[Path("a.o")], Path("a.out"), libs=["customlib"], openmp=False)
link_run.assert_called_with([
"a.o",
"-q", "/tmp", "-j", "-extra-flag",
Expand All @@ -231,13 +229,11 @@ def test_linker_c_with_libraries_and_pre_flags(mock_c_compiler):
specified."""
linker = Linker(compiler=mock_c_compiler)
linker.add_lib_flags("customlib", ["-q", "/tmp", "-j"])
linker.add_pre_lib_flags(["-extra-flag"])

with mock.patch.object(linker, "run") as link_run:
linker.link(
[Path("a.o")], Path("a.out"),
pre_lib_flags=["-extra-flag"], libs=["customlib"],
openmp=False,
)
[Path("a.o")], Path("a.out"), libs=["customlib"], openmp=False)
link_run.assert_called_with([
"a.o",
"-extra-flag", "-q", "/tmp", "-j",
Expand Down Expand Up @@ -299,17 +295,17 @@ def test_linker_all_flag_types(mock_c_compiler):

mock_c_compiler.flags.extend(["-compiler-flag1", "-compiler-flag2"])
linker.flags.extend(["-linker-flag1", "-linker-flag2"])
linker.add_pre_lib_flags(["-prelibflag1", "-prelibflag2"])
linker.add_lib_flags("customlib1", ["-lib1flag1", "lib1flag2"])
linker.add_lib_flags("customlib2", ["-lib2flag1", "lib2flag2"])
linker.add_post_lib_flags(["-postlibflag1", "-postlibflag2"])

mock_result = mock.Mock(returncode=0)
with mock.patch("fab.tools.tool.subprocess.run",
return_value=mock_result) as tool_run:
linker.link([
Path("a.o")], Path("a.out"),
pre_lib_flags=["-prelibflag1", "-prelibflag2"],
libs=["customlib2", "customlib1"],
post_lib_flags=["-postlibflag1", "-postlibflag2"],
openmp=True)

tool_run.assert_called_with([
Expand Down

0 comments on commit 7286200

Please sign in to comment.