From 478ebe034f22e5c28bf06d9cbbc6dda6f62530ca Mon Sep 17 00:00:00 2001 From: Meagan Lang Date: Fri, 23 Feb 2024 12:50:29 -0500 Subject: [PATCH] Control linker language via class attribute Link fortran as C++ Add standard libraries for fortran compilation based on the linking language --- yggdrasil/drivers/CompiledModelDriver.py | 10 ++++-- yggdrasil/drivers/FortranModelDriver.py | 46 +++++++++++++----------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/yggdrasil/drivers/CompiledModelDriver.py b/yggdrasil/drivers/CompiledModelDriver.py index b988a1e58..fa5add52f 100644 --- a/yggdrasil/drivers/CompiledModelDriver.py +++ b/yggdrasil/drivers/CompiledModelDriver.py @@ -1489,7 +1489,10 @@ def linker(cls): linker = getattr(cls, '_linker', cls.default_linker) linker_flags = getattr(cls, '_linker_flags', cls.default_linker_flags) if linker is None: - linker = find_compilation_tool('linker', cls.languages[0]) + linker_language = getattr(cls, 'default_linker_language', None) + if linker_language is None: + linker_language = cls.languages[0] + linker = find_compilation_tool('linker', linker_language) if linker: out = get_compilation_tool('linker', linker, return_instance=True, @@ -1511,7 +1514,10 @@ def archiver(cls): archiver = getattr(cls, '_archiver', cls.default_archiver) archiver_flags = getattr(cls, '_archiver_flags', cls.default_archiver_flags) if archiver is None: - archiver = find_compilation_tool('archiver', cls.languages[0]) + archiver_language = getattr(cls, 'default_archiver_language', None) + if archiver_language is None: + archiver_language = cls.languages[0] + archiver = find_compilation_tool('archiver', archiver_language) out = archiver if archiver: out = get_compilation_tool('archiver', archiver, diff --git a/yggdrasil/drivers/FortranModelDriver.py b/yggdrasil/drivers/FortranModelDriver.py index f00bb64df..015fe4b9f 100644 --- a/yggdrasil/drivers/FortranModelDriver.py +++ b/yggdrasil/drivers/FortranModelDriver.py @@ -34,14 +34,16 @@ class FortranCompilerBase(CompilerBase): default_executable = None default_archiver = None product_exts = ['.mod'] + default_linker_language = 'c++' @classmethod def call(cls, args, **kwargs): r"""Call the compiler with the provided arguments. For |yggdrasil| C models will always be linked using the C++ linker since some parts of the interface library are written in C++.""" - if not kwargs.get('dont_link', False): - kwargs.setdefault('linker_language', 'c++') + if (((not kwargs.get('dont_link', False)) + and cls.default_linker_language is not None)): + kwargs.setdefault('linker_language', cls.default_linker_language) return super(FortranCompilerBase, cls).call(args, **kwargs) @classmethod @@ -170,7 +172,7 @@ class FortranModelDriver(CompiledModelDriver): zmq={'libraries': [('c', x) for x in CModelDriver.CModelDriver.supported_comm_options[ 'zmq']['libraries']]}) - standard_libraries = ['c', 'gfortran'] + standard_libraries = [] external_libraries = {'cxx': {'include': 'stdlib.h', 'libtype': 'shared', 'language': 'c'}} @@ -184,8 +186,7 @@ class FortranModelDriver(CompiledModelDriver): [('c', 'ygg'), 'c_wrappers']), 'external_dependencies': ( [('c', x) for x in - _c_internal_libs['ygg']['external_dependencies']] - + ['c', 'gfortran']), + _c_internal_libs['ygg']['external_dependencies']]), 'include_dirs': ( _c_internal_libs['ygg']['include_dirs'])}, c_wrappers={'source': os.path.join(_incl_interface, @@ -431,28 +432,33 @@ def before_registration(cls): # elif platform._is_win: # pragma: windows # cls.default_compiler = 'flang' CompiledModelDriver.before_registration(cls) - cxx_orig = cls.external_libraries.pop('cxx', None) - if cxx_orig is not None: + orig_standards = {} + orig_standards['c++'] = cls.external_libraries.pop('cxx', None) + add_standard_libraries = {} + if FortranCompilerBase.default_linker_language == 'c++': + if cls.default_compiler == 'gfortran': + add_standard_libraries['fortran'] = 'gfortran' + elif orig_standards['c++'] is not None: + # add_standard_libraries['c'] = 'c' c_compilers = get_compilation_tool_registry( 'compiler', init_languages=['c++'])['by_language'].get('c++', {}) - add_cxx_lib = None for k, v in c_compilers.items(): if not v.is_installed(): continue if k == 'clang++': - if not add_cxx_lib: - add_cxx_lib = 'c++' + if not add_standard_libraries.get('c++', None): + add_standard_libraries['c++'] = 'c++' else: - # GNU takes precedence when present - add_cxx_lib = 'stdc++' - if add_cxx_lib and (add_cxx_lib not in cls.standard_libraries): - cls.standard_libraries.append(add_cxx_lib) - cls.internal_libraries['fygg']['external_dependencies'].append( - add_cxx_lib) - # if add_cxx_lib and (add_cxx_lib not in cls.external_libraries): - # cls.external_libraries[add_cxx_lib] = copy.deepcopy(cxx_orig) - # cls.internal_libraries['fygg']['external_dependencies'].append( - # add_cxx_lib) + # GNU takes precedence when present even if already + # set from clang + add_standard_libraries['c++'] = 'stdc++' + for k, v in add_standard_libraries.items(): + # if v not in cls.external_libraries: + # cls.external_libraries[v] = copy.deepcopy(orig_standards.get(k, v)) + # cls.internal_libraries['fygg']['external_dependencies'].append(v) + if v not in cls.standard_libraries: + cls.standard_libraries.append(v) + cls.internal_libraries['fygg']['external_dependencies'].append(v) if platform._is_win: # pragma: windows cl_compiler = get_compilation_tool('compiler', 'cl') if not cl_compiler.is_installed(): # pragma: debug