-
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
Conversation
source/fab/steps/link.py
Outdated
@@ -65,7 +65,7 @@ def link_exe(config, flags=None, source: Optional[ArtefactsGetter] = None): | |||
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, add_libs=flags) | |||
linker.link(objects, exe_path, openmp=config.openmp, add_flags=flags) |
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.
Should I include support for libs up at this level?
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.
Yes please. Keep the flags parameter, while I can't think of a real good use case, you never know if an app might want/need to provide additional flags (hmm - maybe ask for linker mapping file or so ... there are enough linker options :) )
@hiker please let me know if I've misunderstood what you had in mind, or if not can you review please? |
Looks perfect. Bring it up to the link_exe (and link_shared_object), and this is ready to go. |
source/fab/tools/linker.py
Outdated
except KeyError: | ||
raise RuntimeError(f"Unknown library name: '{lib}'") | ||
|
||
def add_lib_flags(self, lib: str, flags: List[str]): |
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.
Hmm - I just remembered: during the code review of the tool box, I was asked to add a silent_replace
option: if there is already an entry defined that is overwritten, do a warnings.warn(...)
to indicate that library settings get replaced (but if there is no entry, just add it as well).
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.
Wasn't sure if you meant both the warning and the silent option, but I've added both since it's fairly simple
I've merged bom_masters into this and resolved the conflicts. I detected one test failure only triggered when the tests were executed in a certain order (in steps/archive) - I switched this test to use mock_c_compiler (which is always available), instead of the default in the tool box (which somehow changed when things were executed in a certain oder). I also noticed that linesn66 and 147 are not covered by a test in
I don't think this is an official requirement (line 66 is covered if we run all tests in unit_tests/tools, and line 147 somewhere from unit_tests/steps), but imho this is quite useful. Now, line 66 is actually my fault I think (unless it was a side-effect of conflicts when merging??), and looking at it, this code is actually wrong (it relies on linker._compiler to exist, which atm does not have to be the case ... though de-facto it is). With #20 this will actually be fixed, so ... just ignore line 66 for now, but covering 147 looks useful |
I think we need two extensions:
|
Currently the Do you want to also put these pre/post flags into the linker.link(..., prelib_flags=[..], libs=[..], postlib_flags[..], ...) Or should the be properties of the linker, linker.prelib_flags = [ ... ]
linker.postlib_flags = [ ... ]
...
linker.link(..., libs=[..], ...) Or do you want both options? Currently we can technically do both with
But the first is configured on the linker object, while the second is passed into |
I decided to go with the option of adding both arguments to the |
I admit I can't decide, and am happy with either (as long as these flags are all optional, since typically you won't need them). The only thing I did notice: flags that go before the source code (linker.flags) seems pretty useless. Any 'generic' linker flag can go anywhere (e.g. to ask for a symbol map file or so, or adding a search path), but any library must come after the .o files. |
Yeah the linker.flags is just built-in behaviour of the |
source/fab/tools/linker.py
Outdated
# Include netcdf as an example, since it is reasonable portable | ||
self.add_lib_flags( | ||
'netcdf', | ||
['$(nf-config --flibs)', '($nc-config --libs)'] |
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
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.
Back to you due to the misunderstanding of where to add the pre/post flag.
def test_linker_add_lib_flags(mock_c_compiler): | ||
"""Linker should provide a way to add a new set of flags for a library""" | ||
linker = Linker(compiler=mock_c_compiler) | ||
linker.add_lib_flags("xios", ["-L", "xios/lib", "-I", "xios/inc"]) |
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.
Nit picking, but -I is not required for linking (it's the include path for compilation). Instead use "-l", "xios"
together with -L...
).
linker = Linker(compiler=mock_c_compiler) | ||
# netcdf is built in to the linker, since it is reasonable portable | ||
result = linker.get_lib_flags("netcdf") | ||
assert result == ["$(nf-config --flibs)", "($nc-config --libs)"] |
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.
That will affect quite a few tests, so I'll mention it only here: As mentioned above, remove netcdf lib. Instead modify the mock_linker in conftest.py to add some libraries there.
# Replace them with another set of flags. | ||
warn_message = 'Replacing existing flags for library netcdf' | ||
with pytest.warns(UserWarning, match=warn_message): | ||
linker.add_lib_flags("netcdf", ["-L", "netcdf/lib", "-I", "netcdf/inc"]) |
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.
Same, replace with -l netcdf or so
source/fab/tools/linker.py
Outdated
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 comment
The 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 :) )
Bash-style substitution is not currently handled
Previously they were passed into the Linker.link() function
No problem, as I said I was weighing up both options, and just picked one option to implement for you to review. I've switched to configure the additional flags on the Linker itself now. |
That looks good now, thanks. I'll port our lfric build to see if any other issue pops up :) |
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.
Looks nice, and works perfectly with our LFRic_atm-fab builds.
Add support for libraries in the
Linker
class. As per issue #7: