From 16bc8b6f7998204a48c56be7fed6e9324d5d9796 Mon Sep 17 00:00:00 2001 From: Scott Wales Date: Mon, 11 Dec 2023 12:44:03 +1100 Subject: [PATCH 1/4] Support full paths in FC --- source/fab/cli.py | 14 ++++++++++---- source/fab/steps/compile_fortran.py | 4 ++-- .../zero_config/test_zero_config.py | 17 +++++++++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/source/fab/cli.py b/source/fab/cli.py index 3c0811e9..d940328a 100644 --- a/source/fab/cli.py +++ b/source/fab/cli.py @@ -6,6 +6,7 @@ import sys from pathlib import Path from typing import Dict, Optional +import os from fab.steps.analyse import analyse from fab.steps.c_pragma_injector import c_pragma_injector @@ -20,6 +21,7 @@ from fab.steps.grab.folder import grab_folder from fab.steps.preprocess import preprocess_c, preprocess_fortran from fab.util import common_arg_parser +from fab.tools import get_tool def _generic_build_config(folder: Path, kwargs=None) -> BuildConfig: @@ -61,15 +63,19 @@ def calc_linker_flags(): # todo: test this and get it running # 'ifort': (..., [...]) } + try: - linker, linker_flags = linkers[fc] - except KeyError: - raise NotImplementedError(f"Fab's zero configuration mode does not yet work with compiler '{fc}'") + linker, linker_flags = get_tool(os.environ.get("LD", None)) + except ValueError: + try: + linker, linker_flags = linkers[fc] + except KeyError: + raise NotImplementedError(f"Fab's zero configuration mode does not yet work with compiler '{fc}'") return linker, linker_flags -def cli_fab(folder: Path, kwargs: Optional[Dict] = None): +def cli_fab(folder: Path = None, kwargs: Optional[Dict] = None): """ Running Fab from the command line will attempt to build the project in the current or given folder. The following params are used for testing. When run normally any parameters will be caught diff --git a/source/fab/steps/compile_fortran.py b/source/fab/steps/compile_fortran.py index 71329430..41c4e380 100644 --- a/source/fab/steps/compile_fortran.py +++ b/source/fab/steps/compile_fortran.py @@ -136,7 +136,7 @@ def handle_compiler_args(common_flags=None, path_flags=None): # Do we know this compiler? If so we can manage the flags a little, to avoid duplication or misconfiguration. # todo: This has been raised for discussion - we might never want to modify incoming flags... - known_compiler = COMPILERS.get(compiler) + known_compiler = COMPILERS.get(os.path.basename(compiler)) if known_compiler: common_flags = remove_managed_flags(compiler, common_flags) else: @@ -342,7 +342,7 @@ def compile_file(analysed_file, flags, output_fpath, mp_common_args): # tool command = [mp_common_args.compiler] - known_compiler = COMPILERS.get(mp_common_args.compiler) + known_compiler = COMPILERS.get(os.path.basename(mp_common_args.compiler)) # Compile flag. # If it's an unknown compiler, we rely on the user config to specify this. diff --git a/tests/system_tests/zero_config/test_zero_config.py b/tests/system_tests/zero_config/test_zero_config.py index 952dec17..704c0b93 100644 --- a/tests/system_tests/zero_config/test_zero_config.py +++ b/tests/system_tests/zero_config/test_zero_config.py @@ -1,6 +1,9 @@ from pathlib import Path from fab.cli import cli_fab +import shutil +import os +from unittest import mock class TestZeroConfig(object): @@ -25,3 +28,17 @@ def test_c_fortran_interop(self, tmp_path): kwargs=kwargs) assert (config.project_workspace / 'main').exists() + + def test_fortran_explicit_gfortran(self, tmp_path): + # test the sample project in the fortran dependencies system test + kwargs = {'project_label': 'fortran explicit gfortran', 'fab_workspace': tmp_path, 'multiprocessing': False} + + cc = shutil.which('gcc') + fc = shutil.which('gfortran') + + with mock.patch.dict(os.environ, CC=cc, FC=fc, LD=fc): + config = cli_fab( + folder=Path(__file__).parent.parent / 'CFortranInterop', + kwargs=kwargs) + + assert (config.project_workspace / 'main').exists() From 7f49c1bebb7bc8c204489db9db5f447f2147a1b1 Mon Sep 17 00:00:00 2001 From: Scott Wales Date: Mon, 11 Dec 2023 15:07:59 +1100 Subject: [PATCH 2/4] Fallback linker to /usr/bin/gfortran --- source/fab/cli.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source/fab/cli.py b/source/fab/cli.py index d940328a..c7385c6b 100644 --- a/source/fab/cli.py +++ b/source/fab/cli.py @@ -65,12 +65,11 @@ def calc_linker_flags(): } try: + # Get linker from $LD linker, linker_flags = get_tool(os.environ.get("LD", None)) except ValueError: - try: - linker, linker_flags = linkers[fc] - except KeyError: - raise NotImplementedError(f"Fab's zero configuration mode does not yet work with compiler '{fc}'") + # Get linker from linkers, or else just use $FC + linker, linker_flags = linkers.get(os.path.basename(fc), (fc, [])) return linker, linker_flags From af2badde21ba94647519ed5cf63dfdf05b6aaa6a Mon Sep 17 00:00:00 2001 From: Scott Wales Date: Wed, 20 Dec 2023 19:45:47 +1100 Subject: [PATCH 3/4] Add Optional --- source/fab/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/fab/cli.py b/source/fab/cli.py index c7385c6b..0396b1c4 100644 --- a/source/fab/cli.py +++ b/source/fab/cli.py @@ -74,7 +74,7 @@ def calc_linker_flags(): return linker, linker_flags -def cli_fab(folder: Path = None, kwargs: Optional[Dict] = None): +def cli_fab(folder: Optional[Path] = None, kwargs: Optional[Dict] = None): """ Running Fab from the command line will attempt to build the project in the current or given folder. The following params are used for testing. When run normally any parameters will be caught From d4bceca0a9b7a3b13796de6896393a7a3c3da263 Mon Sep 17 00:00:00 2001 From: Scott Wales Date: Mon, 15 Jan 2024 10:09:06 +1100 Subject: [PATCH 4/4] Fix typing --- source/fab/cli.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/fab/cli.py b/source/fab/cli.py index 0396b1c4..7080b542 100644 --- a/source/fab/cli.py +++ b/source/fab/cli.py @@ -93,8 +93,11 @@ def cli_fab(folder: Optional[Path] = None, kwargs: Optional[Dict] = None): if Path(sys.argv[0]).parts[-1] == 'fab': arg_parser = common_arg_parser() kwargs = vars(arg_parser.parse_args()) + _folder = kwargs.pop('folder') + else: + # Required when testing + assert folder is not None + _folder = folder - folder = folder or kwargs.pop('folder', '.') - - config = _generic_build_config(folder, kwargs) + config = _generic_build_config(_folder, kwargs) return config