Skip to content

Commit

Permalink
Add pre- and post- lib flags to link function
Browse files Browse the repository at this point in the history
  • Loading branch information
lukehoffmann committed Sep 11, 2024
1 parent 0645816 commit 728089e
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 10 deletions.
4 changes: 2 additions & 2 deletions source/fab/steps/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def link_exe(config,
for root, objects in target_objects.items():
exe_path = config.project_workspace / f'{root}'
linker.link(objects, exe_path, openmp=config.openmp, libs=libs,
add_flags=flags)
post_lib_flags=flags)
config.artefact_store.add(ArtefactSet.EXECUTABLES, exe_path)


Expand Down Expand Up @@ -122,4 +122,4 @@ 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, add_flags=flags)
linker.link(objects, out_name, openmp=config.openmp, post_lib_flags=flags)
12 changes: 8 additions & 4 deletions source/fab/tools/linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,18 @@ def remove_lib_flags(self, lib: str):

def link(self, input_files: List[Path], output_file: Path,
openmp: bool,
pre_lib_flags: Optional[List[str]] = None,
libs: Optional[List[str]] = None,
add_flags: Optional[List[str]] = None) -> str:
post_lib_flags: 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 add_flags: additional linker flags.
:param post_lib_flags: additional linker flags to use after libs.
:returns: the stdout of the link command
'''
Expand All @@ -141,9 +143,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)
for lib in (libs or []):
params.extend(self.get_lib_flags(lib))
if add_flags:
params.extend(add_flags)
if post_lib_flags:
params.extend(post_lib_flags)
params.extend([self._output_flag, str(output_file)])
return self.run(params)
59 changes: 55 additions & 4 deletions tests/unit_tests/tools/test_linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,40 @@ def test_linker_c_with_libraries(mock_c_compiler):
"-o", "a.out"])


def test_linker_c_with_libraries_and_post_flags(mock_c_compiler):
"""Test the link command line when a library and additional flags are
specified."""
linker = Linker(compiler=mock_c_compiler)
with mock.patch.object(linker, "run") as link_run:
linker.link(
[Path("a.o")], Path("a.out"),
libs=["netcdf"], post_lib_flags=["-extra-flag"],
openmp=False,
)
link_run.assert_called_with([
"a.o",
"$(nf-config --flibs)", "($nc-config --libs)", "-extra-flag",
"-o", "a.out",
])


def test_linker_c_with_libraries_and_pre_flags(mock_c_compiler):
"""Test the link command line when a library and additional flags are
specified."""
linker = Linker(compiler=mock_c_compiler)
with mock.patch.object(linker, "run") as link_run:
linker.link(
[Path("a.o")], Path("a.out"),
pre_lib_flags=["-extra-flag"], libs=["netcdf"],
openmp=False,
)
link_run.assert_called_with([
"a.o",
"-extra-flag", "$(nf-config --flibs)", "($nc-config --libs)",
"-o", "a.out",
])


def test_linker_c_with_custom_libraries(mock_c_compiler):
"""Test the link command line when additional libraries are specified."""
linker = Linker(compiler=mock_c_compiler)
Expand Down Expand Up @@ -270,14 +304,31 @@ def test_linker_all_flag_types(mock_c_compiler):
with mock.patch.dict("os.environ", {"LDFLAGS": "-ldflag"}):
linker = Linker(compiler=mock_c_compiler)

mock_c_compiler.flags.extend(["-compiler-flag1", "-compiler-flag2"])
linker.flags.extend(["-linker-flag1", "-linker-flag2"])
linker.add_lib_flags("customlib", ["-libflag1", "libflag2"])

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"), openmp=False)
linker.link([
Path("a.o")], Path("a.out"),
pre_lib_flags=["-prelibflag1", "-prelibflag2"],
libs=["customlib", "netcdf"],
post_lib_flags=["-postlibflag1", "-postlibflag2"],
openmp=True)

tool_run.assert_called_with([
"mock_c_compiler.exe",
"-ldflag",
"-linker-flag1", "-linker-flag2",
"a.o", "-o", "a.out"],
# Note: compiler flags and linker flags will be switched when the Linker
# becomes a CompilerWrapper in a following PR
"-ldflag", "-linker-flag1", "-linker-flag2",
"-compiler-flag1", "-compiler-flag2",
"-fopenmp",
"a.o",
"-prelibflag1", "-prelibflag2",
"-libflag1", "libflag2",
"$(nf-config --flibs)", "($nc-config --libs)",
"-postlibflag1", "-postlibflag2",
"-o", "a.out"],
capture_output=True, env=None, cwd=None, check=False)

0 comments on commit 728089e

Please sign in to comment.