-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Linker flags for common libraries #19
Changes from 17 commits
d7c66c6
0340a27
4cc5485
f017eed
4f62bfd
1caf110
dd81dbe
8d72ccd
b3021d6
c9b4183
390a2fb
d8c9db1
c612aae
649b9ff
b0e5842
0645816
728089e
76322a1
58007e8
7286200
c6e3b42
f7e40f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,8 @@ | |
|
||
import os | ||
from pathlib import Path | ||
from typing import cast, List, Optional | ||
from typing import cast, Dict, List, Optional | ||
import warnings | ||
|
||
from fab.tools.category import Category | ||
from fab.tools.compiler import Compiler | ||
|
@@ -51,6 +52,14 @@ def __init__(self, name: Optional[str] = None, | |
self._compiler = compiler | ||
self.flags.extend(os.getenv("LDFLAGS", "").split()) | ||
|
||
# Maintain a set of flags for common libraries. | ||
self._lib_flags: Dict[str, List[str]] = {} | ||
# Include netcdf as an example, since it is reasonable portable | ||
self.add_lib_flags( | ||
'netcdf', | ||
['$(nf-config --flibs)', '($nc-config --libs)'] | ||
) | ||
|
||
@property | ||
def mpi(self) -> bool: | ||
''':returns: whether the linker supports MPI or not.''' | ||
|
@@ -66,16 +75,61 @@ def check_available(self) -> bool: | |
|
||
return super().check_available() | ||
|
||
def get_lib_flags(self, lib: str) -> List[str]: | ||
'''Gets the standard flags for a standard library | ||
|
||
:param lib: the library name | ||
|
||
:returns: a list of flags | ||
|
||
:raises RuntimeError: if lib is not recognised | ||
''' | ||
try: | ||
return self._lib_flags[lib] | ||
except KeyError: | ||
raise RuntimeError(f"Unknown library name: '{lib}'") | ||
|
||
def add_lib_flags(self, lib: str, flags: List[str], | ||
silent_replace: bool = False): | ||
'''Add a set of flags for a standard library | ||
|
||
:param lib: the library name | ||
:param flags: the flags to use with the library | ||
:param silent_replace: if set, no warning will be printed when an | ||
existing lib is overwritten. | ||
''' | ||
if lib in self._lib_flags and not silent_replace: | ||
warnings.warn(f"Replacing existing flags for library {lib}: " | ||
f"'{self._lib_flags[lib]}' with " | ||
f"'{flags}'.") | ||
|
||
# Make a copy to avoid modifying the caller's list | ||
self._lib_flags[lib] = flags[:] | ||
|
||
def remove_lib_flags(self, lib: str): | ||
'''Add a set of flags for a standard library | ||
|
||
:param lib: the library name | ||
''' | ||
try: | ||
del self._lib_flags[lib] | ||
except KeyError: | ||
pass | ||
|
||
def link(self, input_files: List[Path], output_file: Path, | ||
openmp: bool, | ||
add_libs: Optional[List[str]] = None) -> str: | ||
pre_lib_flags: Optional[List[str]] = None, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like we had a misunderstanding :( I want to have the pre- and post-flags for the linker object, not the link step (since the link step ideally should be as independent from the linker and site used as possible, we now would have to specify site- and linker/compiler-specific paths here. I'll add more details to the actual ticket #7 (it's just more convenient to write there :) ) |
||
libs: Optional[List[str]] = None, | ||
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 add_libs: additional linker flags. | ||
: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 | ||
''' | ||
|
@@ -88,7 +142,12 @@ def link(self, input_files: List[Path], output_file: Path, | |
params = [] | ||
# TODO: why are the .o files sorted? That shouldn't matter | ||
params.extend(sorted(map(str, input_files))) | ||
if add_libs: | ||
params += add_libs | ||
|
||
if pre_lib_flags: | ||
params.extend(pre_lib_flags) | ||
for lib in (libs or []): | ||
params.extend(self.get_lib_flags(lib)) | ||
if post_lib_flags: | ||
params.extend(post_lib_flags) | ||
params.extend([self._output_flag, str(output_file)]) | ||
return self.run(params) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My mistake, but the second entry should be
$(nc-config...)
(i.e. switch $ and (.But even worse: this actually does not work, because atm we don't use a shell when starting a process, we only fork ... and as a result the (shell)
$(...)
is not executed.It's easy enough to add that flat (and instead of a list of parameters, we supply a string), but I better check that with Matthew. It might break something subtly (because parameters that contain a string now need quoting ... not that I think we have any spaces anywhere :) ).
So for now, just remove the whole setting of netcdf. I will add this using a proper shell script in the site-specific/default config. and discuss this with Matthew.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See MetOffice#337